Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- struct fft_sample_8 { s8 r, i; };
- struct fft_sample_16 { s16 r, i; };
- struct fft_sample_32 { s32 r, i; };
- // Fixed-point multiplication & scaling.Scaling ensures that result remains 16-bit
- inline s8 fft_mul_8(s8 a, s8 b) {
- s16 c = ((s16)a * (s16)b) >> 6;
- return (c >> 1) + (c & 0x01);
- }
- inline s16 fft_mul_16(s16 a, s16 b) {
- if ((a == -32768)&&(b == -32768)) a = -32767;
- s32 c = (s32)a * (s32)b;
- return c >> 15;
- }
- //8-bit sine table
- const s8 fft_256_sine_8[192] = {
- 0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 51, 54, 57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 107, 109, 111, 112, 113, 115, 116,
- 117, 118, 120, 121, 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 125, 125, 124, 123, 122, 122, 121, 120, 118, 117, 116, 115, 113, 112, 111, 109, 107, 106, 104, 102, 100, 98, 96, 94, 92,
- 90, 88, 85, 83, 81, 78, 76, 73, 71, 68, 65, 63, 60, 57, 54, 51, 49, 46, 43, 40, 37, 34, 31, 28, 25, 22, 19, 16, 12, 9, 6, 3, 0, -3, -6, -9, -12, -16, -19, -22, -25, -28, -31, -34, -37, -40, -43, -46,
- -49, -51, -54, -57, -60, -63, -65, -68, -71, -73, -76, -78, -81, -83, -85, -88, -90, -92, -94, -96, -98, -100, -102, -104, -106, -107, -109, -111, -112, -113, -115, -116, -117, -118, -120, -121, -122, -122, -123, -124, -125, -125, -126, -126,
- -126, -127, -127, -127
- };
- // Forward FFT
- void fft256_forw_8(struct fft_sample_8 *samples) {
- u16 l = 1, scale = 0;
- u8 nn = 255, k=7;
- // decimation in time - re-order data
- u16 mr = 0;
- for (u8 m=0; m<nn; m++) {
- u16 l = 256;
- do { l >>= 1; } while (mr+l > nn);
- mr = (mr & (l-1)) + l;
- if (mr <= m+1) continue;
- s8 x = samples[m+1].r;
- samples[m+1].r = samples[mr].r;
- samples[mr].r = x;
- x = samples[m+1].i;
- samples[m+1].i = samples[mr].i;
- samples[mr].i = x;
- }
- while (l < 256) {
- u16 istep = l << 1;
- for (u16 m=0; m<l; ++m) {
- u16 j = m << k;
- s8 wr = fft_256_sine_8[j + (256 / 4)];
- s8 wi = -fft_256_sine_8[j];
- wr >>= 1; wi >>= 1;
- for (u16 i=m; i<256; i+=istep) {
- u16 j = i + l;
- s8 qr = samples[j].r, qi = samples[j].i;
- s8 tr = fft_mul_8(wr, qr) - fft_mul_8(wi, qi);
- s8 ti = fft_mul_8(wr, qi) + fft_mul_8(wi, qr);
- qr = samples[i].r; qi = samples[i].i;
- qr >>= 1; qi >>= 1;
- samples[j].r = qr - tr; samples[j].i = qi - ti;
- samples[i].r = qr + tr; samples[i].i = qi + ti;
- }
- }
- k--;
- l = istep;
- }
- }
- const u8 fft256_win_hanning_8[] PROGMEM = {
- 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
- 37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124,
- 127, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170, 173, 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211, 213, 215,
- 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240, 241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
- 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251, 250, 250, 249, 248, 246, 245, 244, 243, 241, 240, 238, 237, 235, 234, 232, 230, 228, 226, 224, 222, 220,
- 218, 215, 213, 211, 208, 206, 203, 201, 198, 196, 193, 190, 188, 185, 182, 179, 176, 173, 170, 167, 165, 162, 158, 155, 152, 149, 146, 143, 140, 137, 134, 131,
- 128, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 93, 90, 88, 85, 82, 79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
- 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0
- };
- const u8 fft256_win_hamming_8[] PROGMEM = {
- 20, 20, 21, 21, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 28, 29, 30, 32, 33, 34, 36, 37, 39, 40, 42, 43, 45, 47, 49, 51, 53,
- 55, 57, 59, 61, 63, 66, 68, 70, 73, 75, 77, 80, 82, 85, 88, 90, 93, 95, 98, 101, 104, 106, 109, 112, 115, 118, 120, 123, 126, 129, 132, 135,
- 138, 141, 143, 146, 149, 152, 155, 158, 161, 163, 166, 169, 172, 174, 177, 180, 183, 185, 188, 190, 193, 196, 198, 200, 203, 205, 208, 210, 212, 214, 216, 219,
- 221, 223, 225, 227, 228, 230, 232, 234, 235, 237, 238, 240, 241, 242, 244, 245, 246, 247, 248, 249, 250, 251, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
- 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251, 251, 250, 249, 248, 247, 246, 245, 244, 242, 241, 240, 238, 237, 235, 234, 232, 230, 228, 227, 225, 223,
- 221, 219, 216, 214, 212, 210, 208, 205, 203, 200, 198, 196, 193, 190, 188, 185, 183, 180, 177, 174, 172, 169, 166, 163, 161, 158, 155, 152, 149, 146, 143, 141,
- 138, 135, 132, 129, 126, 123, 120, 118, 115, 112, 109, 106, 104, 101, 98, 95, 93, 90, 88, 85, 82, 80, 77, 75, 73, 70, 68, 66, 63, 61, 59, 57,
- 55, 53, 51, 49, 47, 45, 43, 42, 40, 39, 37, 36, 34, 33, 32, 30, 29, 28, 27, 26, 25, 25, 24, 23, 23, 22, 22, 21, 21, 21, 21, 20
- };
- const u8 fft256_win_blackman_8[] PROGMEM = {
- 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 21, 22, 23, 25, 26, 28, 29, 31, 33, 34, 36, 38, 40, 42, 44, 46, 49, 51, 53, 56, 58, 61, 63, 66, 69, 71, 74, 77, 80, 83, 86,
- 89, 92, 95, 99, 102, 105, 109, 112, 115, 119, 122, 126, 129, 133, 136, 140, 143, 147, 150, 154, 158, 161, 165, 168, 172, 175, 179, 182, 185, 189, 192, 195,
- 198, 201, 205, 208, 210, 213, 216, 219, 222, 224, 227, 229, 231, 234, 236, 238, 240, 241, 243, 245, 246, 248, 249, 250, 251, 252, 253, 253, 254, 254, 255, 255,
- 255, 255, 255, 254, 254, 253, 253, 252, 251, 250, 249, 248, 246, 245, 243, 241, 240, 238, 236, 234, 231, 229, 227, 224, 222, 219, 216, 213, 210, 208, 205, 201,
- 198, 195, 192, 189, 185, 182, 179, 175, 172, 168, 165, 161, 158, 154, 150, 147, 143, 140, 136, 133, 129, 126, 122, 119, 115, 112, 109, 105, 102, 99, 95, 92,
- 89, 86, 83, 80, 77, 74, 71, 69, 66, 63, 61, 58, 56, 53, 51, 49, 46, 44, 42, 40, 38, 36, 34, 33, 31, 29, 28, 26, 25, 23, 22, 21,
- 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 9, 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2
- };
- const u8 fft256_win_nuttall_8[] PROGMEM = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5,
- 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 22, 23, 25, 27, 28, 30, 32, 34, 36, 39, 41, 43, 46, 48, 51,
- 54, 57, 60, 63, 66, 69, 72, 76, 79, 83, 86, 90, 94, 98, 101, 105, 109, 113, 117, 122, 126, 130, 134, 138, 143, 147, 151, 155, 160, 164, 168, 172,
- 176, 180, 185, 189, 192, 196, 200, 204, 208, 211, 215, 218, 221, 224, 227, 230, 233, 235, 238, 240, 242, 244, 246, 248, 249, 251, 252, 253, 254, 254, 255, 255,
- 255, 255, 255, 254, 254, 253, 252, 251, 249, 248, 246, 244, 242, 240, 238, 235, 233, 230, 227, 224, 221, 218, 215, 211, 208, 204, 200, 196, 192, 189, 185, 180,
- 176, 172, 168, 164, 160, 155, 151, 147, 143, 138, 134, 130, 126, 122, 117, 113, 109, 105, 101, 98, 94, 90, 86, 83, 79, 76, 72, 69, 66, 63, 60, 57,
- 54, 51, 48, 46, 43, 41, 39, 36, 34, 32, 30, 28, 27, 25, 23, 22, 20, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 6,
- 5, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- // amplify by window
- void fft256_win_8(struct fft_sample_8 *samples, const u8 *win){
- u8 i=0;
- do {
- samples->r = ((s16)samples->r * (s16)(*win)) / 256;
- samples++; win++; i++;
- } while (i);
- }
- // square root
- u8 sqrt16( u16 x ){
- u8 b = ((u8)(x >> 8)) ? 0x80 : 8, result=0;
- while (b){
- u8 g = result | b;
- if ((u16)g * g <= x) result = g;
- b >>= 1;
- }
- return result;
- }
- // calculate real amplitudes
- void fft_amp_8(struct fft_sample_8 *samples, u16 n, u8 (*sqrt16)(u16)){
- while (n--){
- samples->r = sqrt16( (s16)samples->r * samples->r + (s16)samples->i * samples->i );
- samples++;
- }
- }
- const s16 fft_256_sine_16[192] PROGMEM = {
- 0, 804, 1608, 2410, 3212, 4011, 4808, 5602, 6393, 7179, 7962, 8739, 9512, 10278, 11039, 11793, 12539, 13279, 14010, 14732, 15446, 16151, 16846, 17530, 18204, 18868, 19519, 20159, 20787, 21403, 22005, 22594,
- 23170, 23731, 24279, 24811, 25329, 25832, 26319, 26790, 27245, 27683, 28105, 28510, 28898, 29268, 29621, 29956, 30273, 30571, 30852, 31113, 31356, 31580, 31785, 31971, 32137, 32285, 32412, 32521, 32609, 32678, 32728, 32757,
- 32767, 32757, 32728, 32678, 32609, 32521, 32412, 32285, 32137, 31971, 31785, 31580, 31356, 31113, 30852, 30571, 30273, 29956, 29621, 29268, 28898, 28510, 28105, 27683, 27245, 26790, 26319, 25832, 25329, 24811, 24279, 23731,
- 23170, 22594, 22005, 21403, 20787, 20159, 19519, 18868, 18204, 17530, 16846, 16151, 15446, 14732, 14010, 13279, 12539, 11793, 11039, 10278, 9512, 8739, 7962, 7179, 6393, 5602, 4808, 4011, 3212, 2410, 1608, 804,
- 0, -804, -1608, -2410, -3212, -4011, -4808, -5602, -6393, -7179, -7962, -8739, -9512, -10278, -11039, -11793, -12539, -13279, -14010, -14732, -15446, -16151, -16846, -17530, -18204, -18868, -19519, -20159, -20787, -21403, -22005, -22594,
- -23170, -23731, -24279, -24811, -25329, -25832, -26319, -26790, -27245, -27683, -28105, -28510, -28898, -29268, -29621, -29956, -30273, -30571, -30852, -31113, -31356, -31580, -31785, -31971, -32137, -32285, -32412, -32521, -32609, -32678, -32728, -32757
- };
- void fft256_forw_16(struct fft_sample_16 *samples) {
- u16 l = 1;
- u8 nn = 255, k=7;
- // decimation in time - re-order data
- u16 mr = 0;
- for (u8 m=0; m<nn; m++) {
- u16 l = 256;
- do { l >>= 1; } while (mr+l > nn);
- mr = (mr & (l-1)) + l;
- if (mr <= m+1) continue;
- s16 x = samples[m+1].r;
- samples[m+1].r = samples[mr].r;
- samples[mr].r = x;
- x = samples[m+1].i;
- samples[m+1].i = samples[mr].i;
- samples[mr].i = x;
- }
- while (l < 256) {
- u16 istep = l << 1;
- for (u16 m=0; m<l; ++m) {
- u16 j = m << k;
- s16 wr = fft_256_sine_16[j + (256 / 4)];
- s16 wi = -fft_256_sine_16[j];
- wr /= 2; wi /= 2;
- for (u16 i=m; i<256; i+=istep) {
- u16 j = i + l;
- s16 qr = samples[j].r, qi = samples[j].i;
- s16 tr = fft_mul_16(wr, qr) - fft_mul_16(wi, qi);
- s16 ti = fft_mul_16(wr, qi) + fft_mul_16(wi, qr);
- qr = samples[i].r; qi = samples[i].i;
- qr /= 2; qi /= 2;
- samples[j].r = qr - tr; samples[j].i = qi - ti;
- samples[i].r = qr + tr; samples[i].i = qi + ti;
- }
- }
- k--;
- l = istep;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement