0

我正在编写一个使用 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 吗?)。

4

1 回答 1

0

似乎虽然可以使用 FFT 计算响度,但有一种更简单的方法可以做到这一点。据我所知,FFT 将为我们提供不同频率的范围。就像信号的消歧一样。

看这里:

如何计算音频 dB 级别?

于 2020-06-26T17:39:23.180 回答