|
发表于 2020-8-18 13:54:01
|
显示全部楼层
哈哈,网上找到个8分频的的算法,好像是用若干个已采样点数据相加取平均,算了下采样时间间隔是变大了,但不知道这样的做法合不合理。
- /**
- * 显示频谱时进行FFT计算
- *
- * @param buf
- * @param samplerate 采样率
- */
- public void spectrogram(int[] buf, double samplerate) {
- first_fft_real[0] = buf[0];
- first_fft_imag[0] = 0;
-
- second_fft_real[0] = buf[0];
- second_fft_imag[0] = 0;
-
- for (int i = 0; i < FFT_SIZE; i++) {
- first_fft_real[i] = buf[i];
- first_fft_imag[i] = 0;
- // 八分频(相当于降低了8倍采样率),这样1024缓存区中的fft频率密度就越大,有利于取低频
- second_fft_real[i] = (buf[i * 8] + buf[i * 8 + 1] + buf[i * 8 + 2]
- + buf[i * 8 + 3] + buf[i * 8 + 4] + buf[i * 8 + 5]
- + buf[i * 8 + 6] + buf[i * 8 + 7]) / 8.0;
- second_fft_imag[i] = 0;
- }
- // 高频部分从原始数据取
- fft(first_fft_real, first_fft_imag, FFT_SIZE);
-
- // 八分频后的1024个数据的FFT,频率间隔为5.512Hz(samplerate / 8),取低频部分
- fft(second_fft_real, second_fft_imag, FFT_SIZE);
- //这里算出的是每一个频点的坐标,对应横坐标的值,因为是定值,所以只需要算一次
- if (loc == null) {
- loc = new int[SPECTROGRAM_COUNT];
- sampleratePoint = new double[SPECTROGRAM_COUNT];
- for (int i = 0; i < loc.length; i++) {
- //20000表示的最大频点20KHZ,这里的20-20K之间坐标的数据成对数关系,这是音频标准
- double F = Math.pow(20000 / 20, 1.0 / SPECTROGRAM_COUNT);//方法中20为低频起点20HZ,31为段数
- sampleratePoint[i] = 20 * Math.pow(F, i);//乘方,30为低频起点
- //这里的samplerate为采样率(samplerate / (1024 * 8))是8分频后点FFT的点密度
- loc[i] = (int) (sampleratePoint[i] / (samplerate / (1024 * 8)));//估算出每一个频点的位置
- }
- }
- //低频部分
- for (int j = 0; j < LowFreqDividing; j++) {
- int k = loc[j];
- // 低频部分:八分频的数据,取31段,以第14段为分界点,小于为低频部分,大于为高频部分
- // 这里的14是需要取数后分析确定的,确保低频有足够的数可取
- real[j] = second_fft_real[k]; //这里的real和imag对应fft运算的实部和虚部
- imag[j] = second_fft_imag[k];
- }
- // 高频部分,高频部分不需要分频
- for (int m = LowFreqDividing; m < loc.length; m++) {
- int k = loc[m];
- real[m] = first_fft_real[k / 8];
- imag[m] = first_fft_imag[k / 8];
- }
- }
复制代码
|
|