【问题标题】:Simple reverb alghoritm when buffer is small缓冲区较小时的简单混响算法
【发布时间】:2015-11-29 05:55:20
【问题描述】:

我正在尝试实现这篇文章https://stackoverflow.com/a/5319085/1562784 中描述的简单延迟/混响,但我遇到了一个问题。在我录制 16bit/16khz 样本并在每次录制回调调用时获得 8k 样本的 Windows 上,它工作正常。但是在 linux 上,我从声卡中得到了小得多的块。大约 150 个样本。因此,我修改了延迟/混响代码以缓冲样本:

#define REVERB_BUFFER_LEN 8000

static void reverb( int16_t* Buffer, int N)
{
    int i;
    float decay = 0.5f;
    static int16_t sampleBuffer[REVERB_BUFFER_LEN] = {0};

    //Make room at the end of buffer to append new samples
    for (i = 0; i < REVERB_BUFFER_LEN - N; i++)
        sampleBuffer[ i ] = sampleBuffer[ i + N ] ;     

    //copy new chunk of audio samples at the end of buffer
    for (i = 0; i < N; i++)
        sampleBuffer[REVERB_BUFFER_LEN - N + i ] = Buffer[ i ] ;

    //perform effect
    for (i = 0; i < REVERB_BUFFER_LEN - 1600; i++)
    {
        sampleBuffer[i + 1600] += (int16_t)((float)sampleBuffer[i] * decay);
    }   

    //copy output sample
    for (i = 0; i < N; i++)
        Buffer[ i ] = sampleBuffer[REVERB_BUFFER_LEN - N + i ];


}

这会导致输出出现白噪声,所以很明显我做错了什么。 在 linux 上,我以 16bit/16khz 录制,就像在 Windows 上一样,我在 VMWare 中运行 linux。

谢谢!

更新:

如已回答的帖子中所示,我一遍又一遍地“混响”旧样本。简单的“如果”解决了一个问题:

    for (i = 0; i < REVERB_BUFFER_LEN - 1600; i++)
    {
        if((i + 1600) >= REVERB_BUFFER_LEN - N)
            sampleBuffer[i + 1600] += (int16_t)((float)sampleBuffer[i] * decay);
    }

【问题讨论】:

  • 尝试注释掉reverb函数,看看输出是否还是白噪声。也许问题出在其他地方。
  • 感谢您的建议。我这样做了,没有混响功能输出很好。

标签: c linux audio


【解决方案1】:

执行实际混响效果的循环将在相同的样本上执行多次,对函数的不同调用。这是因为您将旧样本保存在缓冲区中,但每次都对所有样本执行混响。这可能会导致它们在某些时候溢出。

您应该只对新样本执行混响,而不是对已修改的样本执行混响。我还建议检查溢出并裁剪到最小/最大值,而不是在这种情况下换行。

执行混响的一种可能更好的方法(适用于任何输入缓冲区大小)是维护一个大小为 REVERB_SAMPLES(在您的情况下为 1600)的循环缓冲区,其中包含最后的样本。

void reverb( int16_t* buf, int len) {
    static int16_t reverb_buf[REVERB_SAMPLES] = {0};
    static int reverb_pos = 0;

    for (int i=0; i<len; i++) {
        int16_t new_value = buf[i] + reverb_buf[reverb_pos] * decay;
        reverb_buf[reverb_pos] = new_value;
        buf[i] = new_value;
        reverb_pos = (reverb_pos + 1) % REVERB_SAMPLES;
    }
}

【讨论】:

  • 非常感谢您,先生!那正是当时的问题!我在混响循环中放置了简单的“if check”并解决了这个问题。我现在就试试你的实现。
猜你喜欢
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-29
相关资源
最近更新 更多