我正在写一个使用SDL和KissFFT的小程序,它应该打开一个wave文件,播放该文件,并找到当前采样缓冲区中每个通道的幅值和dB,这样我就可以在屏幕上直观地显示左通道和右通道。
到目前为止,我已经打开并播放了文件,并编写了一个小函数,它将输入当前的样本缓冲区,并计算提供的缓冲区的幅值和dB。
我在信号处理和FFT方面是新手,但基本概念应该是获取缓冲区,分配数组IN/OUT。用样本填充IN数组,计算FFT并将输出存储在OUT中。
但据我所知,它是一个频率数组(很多)。所以我现在想找出左声道和右声道的幅值和dB。
这是我现在的代码
void audio_callback(void *userdata, Uint8 *stream, int len)
{
if (audio_len ==0)
return;
SDL_memset(stream, 0, len);
len = ( len > audio_len ? audio_len : len );
SDL_memcpy (stream, ptr_audio_buffer, len);
calc_loudness(ptr_audio_buffer, len); // 8192/2 = 4096 samples
ptr_audio_buffer += len;
audio_len -= len;
}
void calc_loudness(uint8_t *buff, int len)
{
int nfft = len;
double magnitude = 0;
kiss_fft_cfg cfg;
kiss_fft_cpx *cx_in = new kiss_fft_cpx[len];
kiss_fft_cpx *cx_out = new kiss_fft_cpx[len];
int16_t val = NULL;
cfg = kiss_fft_alloc(nfft, 0, 0, 0);
for (int i = 0;i<len;i+=2) // 4096 samples
{
decode_signed16(&buff[i], &val);
cx_in[i].r = (float)val / 32768.0; // I have to do this because values get wild. Why?
cx_in[i].i = 0.0;
}
kiss_fft(cfg, cx_in, cx_out);
int position = len/2-1; // last sample
magnitude = sqrt(pow(cx_out[position].r, 2) + pow(cx_out[position].i, 2));
double dB = 10 * log10(pow(cx_out[position].r, 2) + pow(cx_out[position].i, 2));
printf("magnitude: %9.4f \t dB: %9.4f\n", magnitude,dB);
// ...
// free memory.
}在这一点上,我有了这个任意值,当使用fill_rect显示时,它们看起来是正确的。但这只给了我一个值。我很确定我搞砸了很多事情。
如何将这些值分成两个通道?(我应该为每个通道单独计算fft吗?)
发布于 2020-06-27 01:39:23
看来,虽然响度可以使用FFT来计算,但有一种更简单的方法来计算。据我所知,快速傅立叶变换可以给出不同频率的范围。比如消除信号的歧义。
请看这里:
https://stackoverflow.com/questions/62280477
复制相似问题