📄 fft.c
字号:
/*** FFT and FHT routines** Copyright 1988, 1993; Ron Mayer** ** fht(fz,n);** Does a hartley transform of "n" points in the array "fz".** ** NOTE: This routine uses at least 2 patented algorithms, and may be** under the restrictions of a bunch of different organizations.** Although I wrote it completely myself; it is kind of a derivative** of a routine I once authored and released under the GPL, so it** may fall under the free software foundation's restrictions;** it was worked on as a Stanford Univ project, so they claim** some rights to it; it was further optimized at work here, so** I think this company claims parts of it. The patents are** held by R. Bracewell (the FHT algorithm) and O. Buneman (the** trig generator), both at Stanford Univ.** If it were up to me, I'd say go do whatever you want with it;** but it would be polite to give credit to the following people** if you use this anywhere:** Euler - probable inventor of the fourier transform.** Gauss - probable inventor of the FFT.** Hartley - probable inventor of the hartley transform.** Buneman - for a really cool trig generator** Mayer(me) - for authoring this particular version and** including all the optimizations in one package.** Thanks,** Ron Mayer; mayer@acuson.com***/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <math.h>#define FLOAT float#define SQRT2 1.4142135623730951454746218587388284504414void fft(FLOAT *x_real, FLOAT *x_imag, FLOAT *energy, FLOAT *phi, int N);void fft2(FLOAT *x_real, FLOAT *energy, int N);static FLOAT costab[20]= { .00000000000000000000000000000000000000000000000000, .70710678118654752440084436210484903928483593768847, .92387953251128675612818318939678828682241662586364, .98078528040323044912618223613423903697393373089333, .99518472667219688624483695310947992157547486872985, .99879545620517239271477160475910069444320361470461, .99969881869620422011576564966617219685006108125772, .99992470183914454092164649119638322435060646880221, .99998117528260114265699043772856771617391725094433, .99999529380957617151158012570011989955298763362218, .99999882345170190992902571017152601904826792288976, .99999970586288221916022821773876567711626389934930, .99999992646571785114473148070738785694820115568892, .99999998161642929380834691540290971450507605124278, .99999999540410731289097193313960614895889430318945, .99999999885102682756267330779455410840053741619428 };static FLOAT sintab[20]= { 1.0000000000000000000000000000000000000000000000000, .70710678118654752440084436210484903928483593768846, .38268343236508977172845998403039886676134456248561, .19509032201612826784828486847702224092769161775195, .09801714032956060199419556388864184586113667316749, .04906767432741801425495497694268265831474536302574, .02454122852291228803173452945928292506546611923944, .01227153828571992607940826195100321214037231959176, .00613588464915447535964023459037258091705788631738, .00306795676296597627014536549091984251894461021344, .00153398018628476561230369715026407907995486457522, .00076699031874270452693856835794857664314091945205, .00038349518757139558907246168118138126339502603495, .00019174759731070330743990956198900093346887403385, .00009587379909597734587051721097647635118706561284, .00004793689960306688454900399049465887274686668768 };/* This is a simplified version for n an even power of 2 *//* MFC: In the case of LayerII encoding, n==1024 always. */static void fht(FLOAT *fz){ int i,k,k1,k2,k3,k4,kx; FLOAT *fi,*fn,*gi; FLOAT t_c,t_s; FLOAT a; static const struct { unsigned short k1, k2; } k1k2tab[8*62] = { {0x020,0x010},{0x040,0x008},{0x050,0x028},{0x060,0x018},{0x068,0x058},{0x070,0x038},{0x080,0x004},{0x088,0x044}, {0x090,0x024},{0x098,0x064},{0x0a0,0x014},{0x0a4,0x094},{0x0a8,0x054},{0x0b0,0x034},{0x0b8,0x074},{0x0c0,0x00c}, {0x0c4,0x08c},{0x0c8,0x04c},{0x0d0,0x02c},{0x0d4,0x0ac},{0x0d8,0x06c},{0x0e0,0x01c},{0x0e4,0x09c},{0x0e8,0x05c}, {0x0ec,0x0dc},{0x0f0,0x03c},{0x0f4,0x0bc},{0x0f8,0x07c},{0x100,0x002},{0x104,0x082},{0x108,0x042},{0x10c,0x0c2}, {0x110,0x022},{0x114,0x0a2},{0x118,0x062},{0x11c,0x0e2},{0x120,0x012},{0x122,0x112},{0x124,0x092},{0x128,0x052}, {0x12c,0x0d2},{0x130,0x032},{0x134,0x0b2},{0x138,0x072},{0x13c,0x0f2},{0x140,0x00a},{0x142,0x10a},{0x144,0x08a}, {0x148,0x04a},{0x14c,0x0ca},{0x150,0x02a},{0x152,0x12a},{0x154,0x0aa},{0x158,0x06a},{0x15c,0x0ea},{0x160,0x01a}, {0x162,0x11a},{0x164,0x09a},{0x168,0x05a},{0x16a,0x15a},{0x16c,0x0da},{0x170,0x03a},{0x172,0x13a},{0x174,0x0ba}, {0x178,0x07a},{0x17c,0x0fa},{0x180,0x006},{0x182,0x106},{0x184,0x086},{0x188,0x046},{0x18a,0x146},{0x18c,0x0c6}, {0x190,0x026},{0x192,0x126},{0x194,0x0a6},{0x198,0x066},{0x19a,0x166},{0x19c,0x0e6},{0x1a0,0x016},{0x1a2,0x116}, {0x1a4,0x096},{0x1a6,0x196},{0x1a8,0x056},{0x1aa,0x156},{0x1ac,0x0d6},{0x1b0,0x036},{0x1b2,0x136},{0x1b4,0x0b6}, {0x1b8,0x076},{0x1ba,0x176},{0x1bc,0x0f6},{0x1c0,0x00e},{0x1c2,0x10e},{0x1c4,0x08e},{0x1c6,0x18e},{0x1c8,0x04e}, {0x1ca,0x14e},{0x1cc,0x0ce},{0x1d0,0x02e},{0x1d2,0x12e},{0x1d4,0x0ae},{0x1d6,0x1ae},{0x1d8,0x06e},{0x1da,0x16e}, {0x1dc,0x0ee},{0x1e0,0x01e},{0x1e2,0x11e},{0x1e4,0x09e},{0x1e6,0x19e},{0x1e8,0x05e},{0x1ea,0x15e},{0x1ec,0x0de}, {0x1ee,0x1de},{0x1f0,0x03e},{0x1f2,0x13e},{0x1f4,0x0be},{0x1f6,0x1be},{0x1f8,0x07e},{0x1fa,0x17e},{0x1fc,0x0fe}, {0x200,0x001},{0x202,0x101},{0x204,0x081},{0x206,0x181},{0x208,0x041},{0x20a,0x141},{0x20c,0x0c1},{0x20e,0x1c1}, {0x210,0x021},{0x212,0x121},{0x214,0x0a1},{0x216,0x1a1},{0x218,0x061},{0x21a,0x161},{0x21c,0x0e1},{0x21e,0x1e1}, {0x220,0x011},{0x221,0x211},{0x222,0x111},{0x224,0x091},{0x226,0x191},{0x228,0x051},{0x22a,0x151},{0x22c,0x0d1}, {0x22e,0x1d1},{0x230,0x031},{0x232,0x131},{0x234,0x0b1},{0x236,0x1b1},{0x238,0x071},{0x23a,0x171},{0x23c,0x0f1}, {0x23e,0x1f1},{0x240,0x009},{0x241,0x209},{0x242,0x109},{0x244,0x089},{0x246,0x189},{0x248,0x049},{0x24a,0x149}, {0x24c,0x0c9},{0x24e,0x1c9},{0x250,0x029},{0x251,0x229},{0x252,0x129},{0x254,0x0a9},{0x256,0x1a9},{0x258,0x069}, {0x25a,0x169},{0x25c,0x0e9},{0x25e,0x1e9},{0x260,0x019},{0x261,0x219},{0x262,0x119},{0x264,0x099},{0x266,0x199}, {0x268,0x059},{0x269,0x259},{0x26a,0x159},{0x26c,0x0d9},{0x26e,0x1d9},{0x270,0x039},{0x271,0x239},{0x272,0x139}, {0x274,0x0b9},{0x276,0x1b9},{0x278,0x079},{0x27a,0x179},{0x27c,0x0f9},{0x27e,0x1f9},{0x280,0x005},{0x281,0x205}, {0x282,0x105},{0x284,0x085},{0x286,0x185},{0x288,0x045},{0x289,0x245},{0x28a,0x145},{0x28c,0x0c5},{0x28e,0x1c5}, {0x290,0x025},{0x291,0x225},{0x292,0x125},{0x294,0x0a5},{0x296,0x1a5},{0x298,0x065},{0x299,0x265},{0x29a,0x165}, {0x29c,0x0e5},{0x29e,0x1e5},{0x2a0,0x015},{0x2a1,0x215},{0x2a2,0x115},{0x2a4,0x095},{0x2a5,0x295},{0x2a6,0x195}, {0x2a8,0x055},{0x2a9,0x255},{0x2aa,0x155},{0x2ac,0x0d5},{0x2ae,0x1d5},{0x2b0,0x035},{0x2b1,0x235},{0x2b2,0x135}, {0x2b4,0x0b5},{0x2b6,0x1b5},{0x2b8,0x075},{0x2b9,0x275},{0x2ba,0x175},{0x2bc,0x0f5},{0x2be,0x1f5},{0x2c0,0x00d}, {0x2c1,0x20d},{0x2c2,0x10d},{0x2c4,0x08d},{0x2c5,0x28d},{0x2c6,0x18d},{0x2c8,0x04d},{0x2c9,0x24d},{0x2ca,0x14d}, {0x2cc,0x0cd},{0x2ce,0x1cd},{0x2d0,0x02d},{0x2d1,0x22d},{0x2d2,0x12d},{0x2d4,0x0ad},{0x2d5,0x2ad},{0x2d6,0x1ad}, {0x2d8,0x06d},{0x2d9,0x26d},{0x2da,0x16d},{0x2dc,0x0ed},{0x2de,0x1ed},{0x2e0,0x01d},{0x2e1,0x21d},{0x2e2,0x11d}, {0x2e4,0x09d},{0x2e5,0x29d},{0x2e6,0x19d},{0x2e8,0x05d},{0x2e9,0x25d},{0x2ea,0x15d},{0x2ec,0x0dd},{0x2ed,0x2dd}, {0x2ee,0x1dd},{0x2f0,0x03d},{0x2f1,0x23d},{0x2f2,0x13d},{0x2f4,0x0bd},{0x2f5,0x2bd},{0x2f6,0x1bd},{0x2f8,0x07d}, {0x2f9,0x27d},{0x2fa,0x17d},{0x2fc,0x0fd},{0x2fe,0x1fd},{0x300,0x003},{0x301,0x203},{0x302,0x103},{0x304,0x083}, {0x305,0x283},{0x306,0x183},{0x308,0x043},{0x309,0x243},{0x30a,0x143},{0x30c,0x0c3},{0x30d,0x2c3},{0x30e,0x1c3}, {0x310,0x023},{0x311,0x223},{0x312,0x123},{0x314,0x0a3},{0x315,0x2a3},{0x316,0x1a3},{0x318,0x063},{0x319,0x263}, {0x31a,0x163},{0x31c,0x0e3},{0x31d,0x2e3},{0x31e,0x1e3},{0x320,0x013},{0x321,0x213},{0x322,0x113},{0x323,0x313}, {0x324,0x093},{0x325,0x293},{0x326,0x193},{0x328,0x053},{0x329,0x253},{0x32a,0x153},{0x32c,0x0d3},{0x32d,0x2d3}, {0x32e,0x1d3},{0x330,0x033},{0x331,0x233},{0x332,0x133},{0x334,0x0b3},{0x335,0x2b3},{0x336,0x1b3},{0x338,0x073}, {0x339,0x273},{0x33a,0x173},{0x33c,0x0f3},{0x33d,0x2f3},{0x33e,0x1f3},{0x340,0x00b},{0x341,0x20b},{0x342,0x10b}, {0x343,0x30b},{0x344,0x08b},{0x345,0x28b},{0x346,0x18b},{0x348,0x04b},{0x349,0x24b},{0x34a,0x14b},{0x34c,0x0cb}, {0x34d,0x2cb},{0x34e,0x1cb},{0x350,0x02b},{0x351,0x22b},{0x352,0x12b},{0x353,0x32b},{0x354,0x0ab},{0x355,0x2ab}, {0x356,0x1ab},{0x358,0x06b},{0x359,0x26b},{0x35a,0x16b},{0x35c,0x0eb},{0x35d,0x2eb},{0x35e,0x1eb},{0x360,0x01b}, {0x361,0x21b},{0x362,0x11b},{0x363,0x31b},{0x364,0x09b},{0x365,0x29b},{0x366,0x19b},{0x368,0x05b},{0x369,0x25b}, {0x36a,0x15b},{0x36b,0x35b},{0x36c,0x0db},{0x36d,0x2db},{0x36e,0x1db},{0x370,0x03b},{0x371,0x23b},{0x372,0x13b}, {0x373,0x33b},{0x374,0x0bb},{0x375,0x2bb},{0x376,0x1bb},{0x378,0x07b},{0x379,0x27b},{0x37a,0x17b},{0x37c,0x0fb}, {0x37d,0x2fb},{0x37e,0x1fb},{0x380,0x007},{0x381,0x207},{0x382,0x107},{0x383,0x307},{0x384,0x087},{0x385,0x287}, {0x386,0x187},{0x388,0x047},{0x389,0x247},{0x38a,0x147},{0x38b,0x347},{0x38c,0x0c7},{0x38d,0x2c7},{0x38e,0x1c7}, {0x390,0x027},{0x391,0x227},{0x392,0x127},{0x393,0x327},{0x394,0x0a7},{0x395,0x2a7},{0x396,0x1a7},{0x398,0x067}, {0x399,0x267},{0x39a,0x167},{0x39b,0x367},{0x39c,0x0e7},{0x39d,0x2e7},{0x39e,0x1e7},{0x3a0,0x017},{0x3a1,0x217}, {0x3a2,0x117},{0x3a3,0x317},{0x3a4,0x097},{0x3a5,0x297},{0x3a6,0x197},{0x3a7,0x397},{0x3a8,0x057},{0x3a9,0x257}, {0x3aa,0x157},{0x3ab,0x357},{0x3ac,0x0d7},{0x3ad,0x2d7},{0x3ae,0x1d7},{0x3b0,0x037},{0x3b1,0x237},{0x3b2,0x137}, {0x3b3,0x337},{0x3b4,0x0b7},{0x3b5,0x2b7},{0x3b6,0x1b7},{0x3b8,0x077},{0x3b9,0x277},{0x3ba,0x177},{0x3bb,0x377}, {0x3bc,0x0f7},{0x3bd,0x2f7},{0x3be,0x1f7},{0x3c0,0x00f},{0x3c1,0x20f},{0x3c2,0x10f},{0x3c3,0x30f},{0x3c4,0x08f}, {0x3c5,0x28f},{0x3c6,0x18f},{0x3c7,0x38f},{0x3c8,0x04f},{0x3c9,0x24f},{0x3ca,0x14f},{0x3cb,0x34f},{0x3cc,0x0cf}, {0x3cd,0x2cf},{0x3ce,0x1cf},{0x3d0,0x02f},{0x3d1,0x22f},{0x3d2,0x12f},{0x3d3,0x32f},{0x3d4,0x0af},{0x3d5,0x2af}, {0x3d6,0x1af},{0x3d7,0x3af},{0x3d8,0x06f},{0x3d9,0x26f},{0x3da,0x16f},{0x3db,0x36f},{0x3dc,0x0ef},{0x3dd,0x2ef}, {0x3de,0x1ef},{0x3e0,0x01f},{0x3e1,0x21f},{0x3e2,0x11f},{0x3e3,0x31f},{0x3e4,0x09f},{0x3e5,0x29f},{0x3e6,0x19f}, {0x3e7,0x39f},{0x3e8,0x05f},{0x3e9,0x25f},{0x3ea,0x15f},{0x3eb,0x35f},{0x3ec,0x0df},{0x3ed,0x2df},{0x3ee,0x1df}, {0x3ef,0x3df},{0x3f0,0x03f},{0x3f1,0x23f},{0x3f2,0x13f},{0x3f3,0x33f},{0x3f4,0x0bf},{0x3f5,0x2bf},{0x3f6,0x1bf}, {0x3f7,0x3bf},{0x3f8,0x07f},{0x3f9,0x27f},{0x3fa,0x17f},{0x3fb,0x37f},{0x3fc,0x0ff},{0x3fd,0x2ff},{0x3fe,0x1ff} }; { int i; for (i = 0; i < sizeof k1k2tab / sizeof k1k2tab[0]; ++i) { k1 = k1k2tab[i].k1; k2 = k1k2tab[i].k2; a = fz[k1]; fz[k1] = fz[k2]; fz[k2] = a; } } for (fi=fz,fn=fz+1024;fi<fn;fi+=4) { FLOAT f0,f1,f2,f3; f1 = fi[0 ]-fi[1 ]; f0 = fi[0 ]+fi[1 ]; f3 = fi[2 ]-fi[3 ]; f2 = fi[2 ]+fi[3 ]; fi[2 ] = (f0-f2); fi[0 ] = (f0+f2); fi[3 ] = (f1-f3); fi[1 ] = (f1+f3); } k=0; do { FLOAT s1,c1; k += 2; k1 = 1 << k; k2 = k1 << 1; k4 = k2 << 1; k3 = k2 + k1; kx = k1 >> 1; fi = fz; gi = fi + kx; fn = fz + 1024; do { FLOAT g0,f0,f1,g1,f2,g2,f3,g3; f1 = fi[0 ] - fi[k1]; f0 = fi[0 ] + fi[k1]; f3 = fi[k2] - fi[k3]; f2 = fi[k2] + fi[k3]; fi[k2] = f0 - f2; fi[0 ] = f0 + f2; fi[k3] = f1 - f3; fi[k1] = f1 + f3; g1 = gi[0 ] - gi[k1]; g0 = gi[0 ] + gi[k1]; g3 = SQRT2 * gi[k3]; g2 = SQRT2 * gi[k2]; gi[k2] = g0 - g2; gi[0 ] = g0 + g2; gi[k3] = g1 - g3; gi[k1] = g1 + g3; gi += k4; fi += k4; } while (fi<fn); t_c = costab[k]; t_s = sintab[k]; c1 = 1; s1 = 0; for (i=1;i<kx;i++) { FLOAT c2,s2; FLOAT t = c1; c1 = t*t_c - s1*t_s; s1 = t*t_s + s1*t_c; c2 = c1*c1 - s1*s1; s2 = 2*(c1*s1); fn = fz + 1024; fi = fz +i; gi = fz +k1-i; do { FLOAT a,b,g0,f0,f1,g1,f2,g2,f3,g3; b = s2*fi[k1] - c2*gi[k1]; a = c2*fi[k1] + s2*gi[k1]; f1 = fi[0 ] - a; f0 = fi[0 ] + a; g1 = gi[0 ] - b; g0 = gi[0 ] + b; b = s2*fi[k3] - c2*gi[k3]; a = c2*fi[k3] + s2*gi[k3]; f3 = fi[k2] - a; f2 = fi[k2] + a; g3 = gi[k2] - b; g2 = gi[k2] + b; b = s1*f2 - c1*g3; a = c1*f2 + s1*g3; fi[k2] = f0 - a; fi[0 ] = f0 + a; gi[k3] = g1 - b; gi[k1] = g1 + b; b = c1*g2 - s1*f3; a = s1*g2 + c1*f3; gi[k2] = g0 - a; gi[0 ] = g0 + a; fi[k3] = f1 - b; fi[k1] = f1 + b; gi += k4; fi += k4; } while (fi<fn); } } while (k4<1024);}void fft(FLOAT *x_real, FLOAT *x_imag, FLOAT *energy, FLOAT *phi, int N){ FLOAT a,b; int i,j; fht(x_real); energy[0] = x_real[0] * x_real[0]; for (i=1,j=N-1;i<N/2;i++,j--) { a = x_real[i]; b = x_real[j]; energy[i]=(a*a + b*b)/2.0; if (energy[i] < 0.0005) { energy[i] = 0.0005; phi[i] = 0; } else /* OPTIMZE this. LAME does without these atan2 calls at all */ phi[i] = 0.7853981 + atan2 (-(double)a, (double)b); } energy[N/2] = x_real[N/2] * x_real[N/2]; phi[N/2] = atan2 (0.0, (double)x_real[N/2]); for (i=1;i<N/2;i++) { energy[N/2+i] = energy[N/2-i]; phi [N/2+i] = -phi[N/2-i]; }}void fft2(FLOAT *x_real, FLOAT *energy, int N){ FLOAT a,b; int i,j; fht(x_real); energy[0] = x_real[0] * x_real[0]; for (i=1,j=N-1;i<N/2;i++,j--) { a = x_real[i]; b = x_real[j]; energy[i]=(a*a + b*b)/2.0; } energy[N/2] = x_real[N/2] * x_real[N/2];}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -