ese 519

Dependents:   PROJECT_3D_AUDIO

Committer:
niv17
Date:
Tue Apr 07 21:09:22 2015 +0000
Revision:
0:2076b4d80327
sonic initial april 7

Who changed what in which revision?

UserRevisionLine numberNew contents of line
niv17 0:2076b4d80327 1 // This file is part of the FXT library.
niv17 0:2076b4d80327 2 // Copyright (C) 2010, 2012 Joerg Arndt
niv17 0:2076b4d80327 3 // License: GNU General Public License version 3 or later,
niv17 0:2076b4d80327 4 // see the file COPYING.txt in the main directory.
niv17 0:2076b4d80327 5
niv17 0:2076b4d80327 6 #include "fxttypes.h"
niv17 0:2076b4d80327 7 #include "cmult.h"
niv17 0:2076b4d80327 8 #include "sumdiff.h"
niv17 0:2076b4d80327 9 #include "constants.h" // COS_1_PI_8, SIN_1_PI_8
niv17 0:2076b4d80327 10 #include "sincos.h"
niv17 0:2076b4d80327 11 #include "revbinpermute.h"
niv17 0:2076b4d80327 12
niv17 0:2076b4d80327 13 #include <cmath> // M_PI, M_SQRT1_2
niv17 0:2076b4d80327 14
niv17 0:2076b4d80327 15 // tuning parameter:
niv17 0:2076b4d80327 16 // define to use trig recurrence:
niv17 0:2076b4d80327 17 // (and possibly lose some precision, see below)
niv17 0:2076b4d80327 18 //#define USE_TRIG_REC
niv17 0:2076b4d80327 19 // with type 'long double' slight speed loss on my machine,
niv17 0:2076b4d80327 20 // with type 'double' little speed gain.
niv17 0:2076b4d80327 21
niv17 0:2076b4d80327 22 #if defined USE_TRIG_REC
niv17 0:2076b4d80327 23 //#warning 'FYI: fht(double *, ulong) uses trig recursion'
niv17 0:2076b4d80327 24 #endif
niv17 0:2076b4d80327 25
niv17 0:2076b4d80327 26 // tuning parameter:
niv17 0:2076b4d80327 27 #define INITIAL_RADIX_16 1 // 0 or 1 (default)
niv17 0:2076b4d80327 28 //
niv17 0:2076b4d80327 29 #if ( INITIAL_RADIX_16==1 )
niv17 0:2076b4d80327 30 //#warning 'FYI: INITIAL_RADIX_16 set in fht_dit(double *, ulong)'
niv17 0:2076b4d80327 31 #else
niv17 0:2076b4d80327 32 #warning 'INITIAL_RADIX_16 is NOT SET in fht_dit(double *, ulong)'
niv17 0:2076b4d80327 33 #endif
niv17 0:2076b4d80327 34
niv17 0:2076b4d80327 35
niv17 0:2076b4d80327 36 void
niv17 0:2076b4d80327 37 fht_dit_core(double *f, ulong ldn)
niv17 0:2076b4d80327 38 // Decimation in time (DIT) FHT.
niv17 0:2076b4d80327 39 // Input data must be in revbin_permuted order.
niv17 0:2076b4d80327 40 // ldn := base-2 logarithm of the array length.
niv17 0:2076b4d80327 41 {
niv17 0:2076b4d80327 42 if ( ldn<=2 )
niv17 0:2076b4d80327 43 {
niv17 0:2076b4d80327 44 if ( ldn==1 ) // two point fht
niv17 0:2076b4d80327 45 {
niv17 0:2076b4d80327 46 sumdiff(f[0], f[1]);
niv17 0:2076b4d80327 47 }
niv17 0:2076b4d80327 48 else if ( ldn==2 ) // four point fht
niv17 0:2076b4d80327 49 {
niv17 0:2076b4d80327 50 double f0, f1, f2, f3;
niv17 0:2076b4d80327 51 sumdiff(f[0], f[1], f0, f1);
niv17 0:2076b4d80327 52 sumdiff(f[2], f[3], f2, f3);
niv17 0:2076b4d80327 53 sumdiff(f0, f2, f[0], f[2]);
niv17 0:2076b4d80327 54 sumdiff(f1, f3, f[1], f[3]);
niv17 0:2076b4d80327 55 }
niv17 0:2076b4d80327 56 return;
niv17 0:2076b4d80327 57 }
niv17 0:2076b4d80327 58
niv17 0:2076b4d80327 59 const ulong n = (1UL<<ldn);
niv17 0:2076b4d80327 60 const double *fn = f + n;
niv17 0:2076b4d80327 61 ulong ldk = ldn & 1;
niv17 0:2076b4d80327 62
niv17 0:2076b4d80327 63 if ( ldk==0 ) // ldn is multiple of 2 => n is a power of 4
niv17 0:2076b4d80327 64 {
niv17 0:2076b4d80327 65 #if ( INITIAL_RADIX_16==1 )
niv17 0:2076b4d80327 66 for (double *fi=f; fi<fn; fi+=16) // radix-16 step
niv17 0:2076b4d80327 67 {
niv17 0:2076b4d80327 68 double f0, f1, f2, f3;
niv17 0:2076b4d80327 69 sumdiff(fi[0], fi[1], f0, f1);
niv17 0:2076b4d80327 70 sumdiff(fi[2], fi[3], f2, f3);
niv17 0:2076b4d80327 71 sumdiff(f0, f2, fi[0], fi[2]);
niv17 0:2076b4d80327 72 sumdiff(f1, f3, fi[1], fi[3]);
niv17 0:2076b4d80327 73
niv17 0:2076b4d80327 74 sumdiff(fi[4], fi[5], f0, f1);
niv17 0:2076b4d80327 75 sumdiff(fi[6], fi[7], f2, f3);
niv17 0:2076b4d80327 76 sumdiff(f0, f2, fi[4], fi[6]);
niv17 0:2076b4d80327 77 sumdiff(f1, f3, fi[5], fi[7]);
niv17 0:2076b4d80327 78
niv17 0:2076b4d80327 79 sumdiff(fi[8], fi[9], f0, f1);
niv17 0:2076b4d80327 80 sumdiff(fi[10], fi[11], f2, f3);
niv17 0:2076b4d80327 81 sumdiff(f0, f2, fi[8], fi[10]);
niv17 0:2076b4d80327 82 sumdiff(f1, f3, fi[9], fi[11]);
niv17 0:2076b4d80327 83
niv17 0:2076b4d80327 84 sumdiff(fi[12], fi[13], f0, f1);
niv17 0:2076b4d80327 85 sumdiff(fi[14], fi[15], f2, f3);
niv17 0:2076b4d80327 86 sumdiff(f0, f2, fi[12], fi[14]);
niv17 0:2076b4d80327 87 sumdiff(f1, f3, fi[13], fi[15]);
niv17 0:2076b4d80327 88
niv17 0:2076b4d80327 89 sumdiff(fi[0], fi[4], f0, f1);
niv17 0:2076b4d80327 90 sumdiff(fi[8], fi[12], f2, f3);
niv17 0:2076b4d80327 91 sumdiff(f0, f2, fi[0], fi[8]);
niv17 0:2076b4d80327 92 sumdiff(f1, f3, fi[4], fi[12]);
niv17 0:2076b4d80327 93
niv17 0:2076b4d80327 94 sumdiff(fi[2], fi[6], f0, f1);
niv17 0:2076b4d80327 95 f3 = M_SQRT2 * fi[14];
niv17 0:2076b4d80327 96 f2 = M_SQRT2 * fi[10];
niv17 0:2076b4d80327 97 sumdiff(f0, f2, fi[2], fi[10]);
niv17 0:2076b4d80327 98 sumdiff(f1, f3, fi[6], fi[14]);
niv17 0:2076b4d80327 99
niv17 0:2076b4d80327 100 double a, b, g0, g1, g2, g3;
niv17 0:2076b4d80327 101 sumdiff(fi[5], fi[7], a, b);
niv17 0:2076b4d80327 102 a *= M_SQRT1_2;
niv17 0:2076b4d80327 103 b *= M_SQRT1_2;
niv17 0:2076b4d80327 104 sumdiff(fi[1], a, f0, f1);
niv17 0:2076b4d80327 105 sumdiff(fi[3], b, g0, g1);
niv17 0:2076b4d80327 106 sumdiff(fi[13], fi[15], a, b);
niv17 0:2076b4d80327 107 a *= M_SQRT1_2;
niv17 0:2076b4d80327 108 b *= M_SQRT1_2;
niv17 0:2076b4d80327 109 sumdiff(fi[9], a, f2, f3);
niv17 0:2076b4d80327 110 sumdiff(fi[11], b, g2, g3);
niv17 0:2076b4d80327 111 double c1 = COS_1_PI_8; // jjkeep
niv17 0:2076b4d80327 112 double s1 = SIN_1_PI_8; // jjkeep
niv17 0:2076b4d80327 113 cmult(s1, c1, f2, g3, b, a);
niv17 0:2076b4d80327 114 sumdiff(f0, a, fi[1], fi[9]);
niv17 0:2076b4d80327 115 sumdiff(g1, b, fi[7], fi[15]);
niv17 0:2076b4d80327 116 cmult(c1, s1, g2, f3, b, a);
niv17 0:2076b4d80327 117 sumdiff(g0, a, fi[3], fi[11]);
niv17 0:2076b4d80327 118 sumdiff(f1, b, fi[5], fi[13]);
niv17 0:2076b4d80327 119 }
niv17 0:2076b4d80327 120 ldk = 4;
niv17 0:2076b4d80327 121 #else // INITIAL_RADIX_16
niv17 0:2076b4d80327 122 for (double *fi=f; fi<fn; fi+=4) // radix-4 step
niv17 0:2076b4d80327 123 {
niv17 0:2076b4d80327 124 double f0, f1, f2, f3;
niv17 0:2076b4d80327 125 sumdiff(fi[0], fi[1], f0, f1);
niv17 0:2076b4d80327 126 sumdiff(fi[2], fi[3], f2, f3);
niv17 0:2076b4d80327 127 sumdiff(f0, f2, fi[0], fi[2]);
niv17 0:2076b4d80327 128 sumdiff(f1, f3, fi[1], fi[3]);
niv17 0:2076b4d80327 129 }
niv17 0:2076b4d80327 130 ldk = 2;
niv17 0:2076b4d80327 131 #endif // INITIAL_RADIX_16
niv17 0:2076b4d80327 132 }
niv17 0:2076b4d80327 133 else // ldk==1, n is no power of 4
niv17 0:2076b4d80327 134 {
niv17 0:2076b4d80327 135 for (double *fi=f; fi<fn; fi+=8) // radix-8 step
niv17 0:2076b4d80327 136 {
niv17 0:2076b4d80327 137 double g0, f0, f1, g1;
niv17 0:2076b4d80327 138 sumdiff(fi[0], fi[1], f0, g0);
niv17 0:2076b4d80327 139 sumdiff(fi[2], fi[3], f1, g1);
niv17 0:2076b4d80327 140
niv17 0:2076b4d80327 141 sumdiff(f0, f1);
niv17 0:2076b4d80327 142 sumdiff(g0, g1);
niv17 0:2076b4d80327 143
niv17 0:2076b4d80327 144 double s1, c1, s2, c2;
niv17 0:2076b4d80327 145 sumdiff(fi[4], fi[5], s1, c1);
niv17 0:2076b4d80327 146 sumdiff(fi[6], fi[7], s2, c2);
niv17 0:2076b4d80327 147
niv17 0:2076b4d80327 148 sumdiff(s1, s2);
niv17 0:2076b4d80327 149
niv17 0:2076b4d80327 150 sumdiff(f0, s1, fi[0], fi[4]);
niv17 0:2076b4d80327 151 sumdiff(f1, s2, fi[2], fi[6]);
niv17 0:2076b4d80327 152
niv17 0:2076b4d80327 153 c1 *= M_SQRT2;
niv17 0:2076b4d80327 154 c2 *= M_SQRT2;
niv17 0:2076b4d80327 155
niv17 0:2076b4d80327 156 sumdiff(g0, c1, fi[1], fi[5]);
niv17 0:2076b4d80327 157 sumdiff(g1, c2, fi[3], fi[7]);
niv17 0:2076b4d80327 158 }
niv17 0:2076b4d80327 159 ldk = 3;
niv17 0:2076b4d80327 160 }
niv17 0:2076b4d80327 161
niv17 0:2076b4d80327 162
niv17 0:2076b4d80327 163 for ( ; ldk<ldn; ldk+=2)
niv17 0:2076b4d80327 164 {
niv17 0:2076b4d80327 165 ulong k = 1UL<<ldk;
niv17 0:2076b4d80327 166 ulong kh = k >> 1;
niv17 0:2076b4d80327 167 ulong k2 = k << 1;
niv17 0:2076b4d80327 168 ulong k3 = k2 + k;
niv17 0:2076b4d80327 169 ulong k4 = k2 << 1;
niv17 0:2076b4d80327 170
niv17 0:2076b4d80327 171 for (double *fi=f, *gi=f+kh; fi<fn; fi+=k4, gi+=k4)
niv17 0:2076b4d80327 172 {
niv17 0:2076b4d80327 173 double f0, f1, f2, f3;
niv17 0:2076b4d80327 174 sumdiff(fi[0], fi[k], f0, f1);
niv17 0:2076b4d80327 175 sumdiff(fi[k2], fi[k3], f2, f3);
niv17 0:2076b4d80327 176 sumdiff(f0, f2, fi[0], fi[k2]);
niv17 0:2076b4d80327 177 sumdiff(f1, f3, fi[k], fi[k3]);
niv17 0:2076b4d80327 178
niv17 0:2076b4d80327 179 sumdiff(gi[0], gi[k], f0, f1);
niv17 0:2076b4d80327 180 f3 = M_SQRT2 * gi[k3];
niv17 0:2076b4d80327 181 f2 = M_SQRT2 * gi[k2];
niv17 0:2076b4d80327 182 sumdiff(f0, f2, gi[0], gi[k2]);
niv17 0:2076b4d80327 183 sumdiff(f1, f3, gi[k], gi[k3]);
niv17 0:2076b4d80327 184 }
niv17 0:2076b4d80327 185
niv17 0:2076b4d80327 186 double tt = M_PI_4/(double)kh; // jjkeep
niv17 0:2076b4d80327 187 #if defined USE_TRIG_REC
niv17 0:2076b4d80327 188 double s1 = 0.0, c1 = 1.0; // jjkeep
niv17 0:2076b4d80327 189 double al = sin(0.5*tt); // jjkeep
niv17 0:2076b4d80327 190 al *= (2.0*al);
niv17 0:2076b4d80327 191 double be = sin(tt); // jjkeep
niv17 0:2076b4d80327 192 #endif // USE_TRIG_REC
niv17 0:2076b4d80327 193
niv17 0:2076b4d80327 194 for (ulong i=1; i<kh; i++)
niv17 0:2076b4d80327 195 {
niv17 0:2076b4d80327 196 #if defined USE_TRIG_REC
niv17 0:2076b4d80327 197 {
niv17 0:2076b4d80327 198 double t1 = c1; // jjkeep
niv17 0:2076b4d80327 199 c1 -= (al*t1+be*s1);
niv17 0:2076b4d80327 200 s1 -= (al*s1-be*t1);
niv17 0:2076b4d80327 201 }
niv17 0:2076b4d80327 202 #else
niv17 0:2076b4d80327 203 double s1, c1; // jjkeep
niv17 0:2076b4d80327 204 SinCos(tt*(double)i, &s1, &c1); // jjkeep
niv17 0:2076b4d80327 205 #endif // USE_TRIG_REC
niv17 0:2076b4d80327 206
niv17 0:2076b4d80327 207 double c2, s2; // jjkeep
niv17 0:2076b4d80327 208 csqr(c1, s1, c2, s2);
niv17 0:2076b4d80327 209
niv17 0:2076b4d80327 210 for (double *fi=f+i, *gi=f+k-i; fi<fn; fi+=k4, gi+=k4)
niv17 0:2076b4d80327 211 {
niv17 0:2076b4d80327 212 double a, b, g0, f0, f1, g1, f2, g2, f3, g3;
niv17 0:2076b4d80327 213 cmult(s2, c2, fi[k], gi[k], b, a);
niv17 0:2076b4d80327 214 sumdiff(fi[0], a, f0, f1);
niv17 0:2076b4d80327 215 sumdiff(gi[0], b, g0, g1);
niv17 0:2076b4d80327 216
niv17 0:2076b4d80327 217 cmult(s2, c2, fi[k3], gi[k3], b, a);
niv17 0:2076b4d80327 218 sumdiff(fi[k2], a, f2, f3);
niv17 0:2076b4d80327 219 sumdiff(gi[k2], b, g2, g3);
niv17 0:2076b4d80327 220
niv17 0:2076b4d80327 221 cmult(s1, c1, f2, g3, b, a);
niv17 0:2076b4d80327 222 sumdiff(f0, a, fi[0], fi[k2]);
niv17 0:2076b4d80327 223 sumdiff(g1, b, gi[k], gi[k3]);
niv17 0:2076b4d80327 224
niv17 0:2076b4d80327 225 cmult(c1, s1, g2, f3, b, a);
niv17 0:2076b4d80327 226 sumdiff(g0, a, gi[0], gi[k2]);
niv17 0:2076b4d80327 227 sumdiff(f1, b, fi[k], fi[k3]);
niv17 0:2076b4d80327 228 }
niv17 0:2076b4d80327 229 }
niv17 0:2076b4d80327 230 }
niv17 0:2076b4d80327 231 }
niv17 0:2076b4d80327 232 // -------------------------
niv17 0:2076b4d80327 233
niv17 0:2076b4d80327 234
niv17 0:2076b4d80327 235 void
niv17 0:2076b4d80327 236 fht_dit(double *f, ulong ldn)
niv17 0:2076b4d80327 237 // Fast Hartley Transform.
niv17 0:2076b4d80327 238 // Split-radix decimation in time (DIT) algorithm.
niv17 0:2076b4d80327 239 // ldn := base-2 logarithm of the array length.
niv17 0:2076b4d80327 240 {
niv17 0:2076b4d80327 241 if ( ldn<=2 )
niv17 0:2076b4d80327 242 {
niv17 0:2076b4d80327 243 if ( ldn==1 ) // two point fht
niv17 0:2076b4d80327 244 {
niv17 0:2076b4d80327 245 sumdiff(f[0], f[1]);
niv17 0:2076b4d80327 246 }
niv17 0:2076b4d80327 247 else if ( ldn==2 ) // four point fht
niv17 0:2076b4d80327 248 {
niv17 0:2076b4d80327 249 double f0, f1, f2, f3;
niv17 0:2076b4d80327 250 sumdiff(f[0], f[2], f0, f1);
niv17 0:2076b4d80327 251 sumdiff(f[1], f[3], f2, f3);
niv17 0:2076b4d80327 252 sumdiff(f0, f2, f[0], f[2]);
niv17 0:2076b4d80327 253 sumdiff(f1, f3, f[1], f[3]);
niv17 0:2076b4d80327 254 }
niv17 0:2076b4d80327 255
niv17 0:2076b4d80327 256 return;
niv17 0:2076b4d80327 257 }
niv17 0:2076b4d80327 258
niv17 0:2076b4d80327 259 revbin_permute(f, 1UL<<ldn);
niv17 0:2076b4d80327 260 fht_dit_core(f, ldn);
niv17 0:2076b4d80327 261 }
niv17 0:2076b4d80327 262 // -------------------------