|
sin.cos表必须放大成整数. 我的一段代码:
// cos, sin表. 比特倒序表. 共128个点: == sin(2*PI*n/N); cos(2*PI*n/N). 放大128倍 flash char sin_tab[SAMPLE_NUM] = { 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 59, 65, 70, 75, 80, 85, 89, 94, 98, 102, 105, 108, 112, 114, 117, 119, 121, 123, 124, 125, 126, 126, 126, 126, 126, 125, 124, 123, 121, 119, 117, 114, 112, 108, 105, 102, 98, 94, 89, 85, 80, 75, 70, 65, 59, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, -6, -12, -18, -24, -30, -36, -42, -48, -54, -59, -65, -70, -75, -80, -85, -89, -94, -98, -102, -105, -108, -112, -114, -117, -119, -121, -123, -124, -125, -126, -126, -126, -126, -126, -125, -124, -123, -121, -119, -117, -114, -112, -108, -105, -102, -98, -94, -89, -85, -80, -75, -70, -65, -59, -54, -48, -42, -36, -30, -24, -18, -12, -6 }; flash char cos_tab[SAMPLE_NUM] = { 127, 126, 126, 125, 124, 123, 121, 119, 117, 114, 112, 108, 105, 102, 98, 94, 89, 85, 80, 75, 70, 65, 59, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, -6, -12, -18, -24, -30, -36, -42, -48, -54, -59, -65, -70, -75, -80, -85, -89, -94, -98, -102, -105, -108, -112, -114, -117, -119, -121, -123, -124, -125, -126, -126, -126, -126, -126, -125, -124, -123, -121, -119, -117, -114, -112, -108, -105, -102, -98, -94, -89, -85, -80, -75, -70, -65, -59, -54, -48, -42, -36, -30, -24, -18, -12, -6, 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 59, 65, 70, 75, 80, 85, 89, 94, 98, 102, 105, 108, 112, 114, 117, 119, 121, 123, 124, 125, 126, 126 }; flash char inv_tab[SAMPLE_NUM] = { 0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120, 4, 68, 36, 100, 20, 84, 52, 116, 12, 76, 44, 108, 28, 92, 60, 124, 2, 66, 34, 98, 18, 82, 50, 114, 10, 74, 42, 106, 26, 90, 58, 122, 6, 70, 38, 102, 22, 86, 54, 118, 14, 78, 46, 110, 30, 94, 62, 126, 1, 65, 33, 97, 17, 81, 49, 113, 9, 73, 41, 105, 25, 89, 57, 121, 5, 69, 37, 101, 21, 85, 53, 117, 13, 77, 45, 109, 29, 93, 61, 125, 3, 67, 35, 99, 19, 83, 51, 115, 11, 75, 43, 107, 27, 91, 59, 123, 7, 71, 39, 103, 23, 87, 55, 119, 15, 79, 47, 111, 31, 95, 63, 127 };
// 128个整数实部,虚部的累加和 short FftReal[SAMPLE_NUM]; // fft的实部 short FftImage[SAMPLE_NUM]; // fft的虚部
LIGHT_SOUND LightSound; // 发送给计算机的频谱( 单字节频谱 ) UCHAR power; // 平均值
// fft运算时的变量.寄存器/全局变量可以加快运算速度 register UCHAR i,j,k,b,p; // 用寄存器变量,加快速度 register short TR,TI,temp; // 中间变量 ULONG ulReal; // 平方/开方 ULONG ulImage;
// 初始化 void InitFft() { SampAdd = sqrt_16(SampAdd/SAMPLE_NUM); // 功率值 power = SampAdd; // 功率值 for( i=0; i<SAMPLE_NUM; i++ ) { FftReal[i] = SampleValue[i]; // SampleValue里时10位的AD结果 FftImage[i] = 0; } }
/* 128点的FFT运算. 采样数据已经按'比特倒序'放置在FftReal[]里 输出的结果也放在: FftRead[]里 */ void FFT( ) { /************** following code FFT *******************/ for( i=1; i<=NUM_2_LOG; i++) /* for(1) */ { b=1; b <<= (i-1); /*b= 2^(L-1) */ for( j=0; j<=b-1; j++) /* for (2) */ { p=1; p <<= (NUM_2_LOG-i); p = p*j; for( k=j; k<SAMPLE_NUM; k=k+2*b) /* for (3) 2点的dft */ { TR = FftReal[k]; TI = FftImage[k]; temp = FftReal[k+b]; FftReal[k] = FftReal[k] + ((FftReal[k+b]*cos_tab[p])>>7) + ((FftImage[k+b]*sin_tab[p])>>7); FftImage[k] = FftImage[k] - ((FftReal[k+b]*sin_tab[p])>>7) + ((FftImage[k+b]*cos_tab[p])>>7); FftReal[k+b] = TR - ((FftReal[k+b]*cos_tab[p])>>7) - ((FftImage[k+b]*sin_tab[p])>>7); FftImage[k+b] = TI + ((temp*sin_tab[p])>>7) - ((FftImage[k+b]*cos_tab[p])>>7); // 移位.防止溢出. 结果已经是本值的 1/64 FftReal[k] >>= 1; FftImage[k] >>= 1; FftReal[k+b] >>= 1; FftImage[k+b] >>= 1; } /* END for (3) */ } /* END for (2) */ } /* END for (1) */ // 计算复数的模. 结果保存到虚部里, 发送给计算机.同时进行下次的采样,采样数据放入实部里 // FftImage[i] = sqrt( 1.0*FftReal[i]*FftReal[i] + 1.0*FftImage[i]*FftImage[i] ); SoundFrenMax = 0; // 保存频谱的最大值 for( i=0; i<SAMPLE_NUM/2; i++) { ulReal = FftReal[i]; ulReal *= ulReal; ulImage = FftImage[i]; ulImage *= ulImage; LightSound.value[i] = sqrt_16( ulReal + ulImage ); if( i == 0 ) LightSound.value[i] /= 4; // 直流分量的特别处理 if( LightSound.value[i] < FFT_OUT_MIN ) // 太小的值人为是0 LightSound.value[i] = 0; if( LightSound.value[i] > SoundFrenMax ) // 保存最大值 SoundFrenMax = LightSound.value[i]; } }
/****************************************/ /*Function: 开根号处理 */ /*入口参数:被开方数,长整型 */ /*出口参数:开方结果,整型 */ /****************************************/ short sqrt_16( ULONG M) // 快速long型开方 { unsigned int N, i; unsigned long tmp, ttp; // 结果、循环计数 if( M == 0 ) // 被开方数,开方结果也为0 return 0; N = 0; tmp = ( M >> 30 ); // 获取最高位:B[m-1] M <<= 2; if( tmp > 1 ) // 最高位为1 { N ++; // 结果当前位为1,否则为默认的0 tmp -= N; } for( i=15; i>0; i-- ) // 求剩余的15位 { N <<= 1; // 左移一位 tmp <<= 2; tmp += (M >> 30); // 假设 ttp = N; ttp = (ttp<<1)+1; M <<= 2; if( tmp >= ttp ) // 假设成立 { tmp -= ttp; N ++; } } return N; }
|