我正在编写一个使用 SDL 和 KissFFT 的小程序,它应该打开一个波形文件,播放文件并找到当前采样缓冲区的每个通道的幅度和 dB,这样我就可以在屏幕上直观地显示左通道和右通道。
到目前为止,我已经打开并播放了该文件并编写了一个小函数,该函数将输入当前采样缓冲区并计算所提供缓冲区的幅度和 dB。
我对信号处理和 FFT 非常陌生,但基本概念应该是获取缓冲区,分配数组 IN/OUT。用样本填充 IN 数组并计算 FFT 并将输出存储在 OUT 中。
但据我了解,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 显示时看起来是正确的。但这只会给我一个价值。而且我很确定我在这里搞砸了很多事情。
如何将这些值分成 2 个通道?(我应该分别为每个通道计算 fft 吗?)。