混响算法[关闭]
Posted
技术标签:
【中文标题】混响算法[关闭]【英文标题】:Reverb Algorithm [closed] 【发布时间】:2011-07-16 04:40:52 【问题描述】:我正在寻找一种简单或带注释的混响算法,即使是伪代码也会有很大帮助。
我找到了几个,但代码往往相当深奥且难以理解。
【问题讨论】:
这是用于创建实时混响效果,还是将混响效果应用于现有录音(如 WAV 文件)?实时效果的实现要复杂得多,但它们构成了我所见过的大部分示例。 @MusiGenesis 理想情况下是实时的,但修改现有录音可能会有所帮助。 DSP 并不是真正可以通过阅读代码来学习的东西。代码是数学模型的应用,理解这些模型比阅读实现更有效率。除非您只是想插入一些代码来创建混响,否则您不会在这里,对吧? 用外行的话来说混响效果很好soundonsound.com/sos/Oct01/articles/advancedreverb1.asp 这是一个很好的例子,表明编程语言本身只能解决简单的问题。 【参考方案1】:这是一个非常简单的“延迟线”实现,它将在现有数组中产生混响效果(C#,buffer
是 short[]
):
int delayMilliseconds = 500; // half a second
int delaySamples =
(int)((float)delayMilliseconds * 44.1f); // assumes 44100 Hz sample rate
float decay = 0.5f;
for (int i = 0; i < buffer.length - delaySamples; i++)
// WARNING: overflow potential
buffer[i + delaySamples] += (short)((float)buffer[i] * decay);
基本上,您获取每个样本的值,将其乘以衰减参数,然后将结果添加到缓冲区中的值delaySamples
away。
这将产生真正的“混响”效果,因为每个声音都会被多次听到,但幅度会下降。要获得更简单的回声效果(每个声音只重复一次),您使用基本相同的代码,只需反向运行 for
循环。
更新:在这种情况下,“混响”一词有两种常见用法。我上面的代码示例产生了卡通中常见的经典混响效果,而在音乐应用程序中,该术语用于表示混响,或者更普遍地表示人工空间效果的创建。
关于混响的文献如此难以理解的一个重要原因是,创建良好的空间效果需要比我这里的示例方法复杂得多的算法。然而,大多数电子空间效果都是使用多条延迟线构建的,因此这个示例有望说明正在发生的事情的基本原理。为了产生非常好的效果,您可以(或应该)使用 FFT 甚至简单的模糊来混淆混响的输出。
更新 2:以下是多延迟线混响设计的一些技巧:
选择不会相互干扰的延迟值(在波的意义上)。例如,如果您在 500 毫秒处有一个延迟,而在 250 毫秒处有一个延迟,则会有很多点在两条线路上都有回声,从而产生不切实际的效果。通常将基本延迟乘以不同的素数,以帮助确保不会发生这种重叠。
在一个大房间(在现实世界中),当您发出声音时,您往往会听到一些即时(几毫秒)相对不失真的尖锐回声,然后是更大、更微弱的“云” ”的回声。您可以通过使用一些向后运行的延迟线来创建初始回声和一些完整的混响线加上一些模糊来创建“云”,从而以低廉的成本实现这种效果。
绝对最佳技巧(我几乎觉得我不想放弃这个,但到底是什么)只有在您的音频是立体声时才有效。如果您稍微改变左右声道之间的延迟线参数(例如,左声道为 490 毫秒,右声道为 513 毫秒,或者左声道为 0.273 衰减,右声道为 0.2631),您将产生很多更逼真的混响。
【讨论】:
对,所以我这样做了,我如何计算要添加多少延迟线以及将它们放在哪里?感谢您的回答 你只要做听起来不错的事,老实说。这两个网址教会了我在这个主题上学到的一切:ccrma.stanford.edu/~jos/pasp/Artificial_Reverberation.htmlearlevel.com/main/1997/01/19/a-bit-about-reverb【参考方案2】:数字混响通常有两种风格。
卷积混响 convolve 和 impulse response 和输入信号。脉冲响应通常是真实房间或其他混响源的记录。混响的特性由脉冲响应定义。因此,卷积混响通常提供有限的方法来调整混响特性。
算法混响通过延迟、滤波器和反馈网络模拟混响。不同的方案将以不同的方式组合这些基本构建块。许多艺术在于知道如何调整网络。算法混响通常会向最终用户公开几个参数,因此可以调整混响字符以适应。
EarLevel 上的A Bit About Reverb 帖子很好地介绍了该主题。它解释了卷积和算法混响之间的区别,并展示了如何实现它们的一些细节。
Physical Audio Signal Processing by Julius O. Smith 有一章介绍混响算法,其中有一节专门介绍 Freeverb 算法。在搜索一些源代码示例时,略读它可能会有所帮助。
Sean Costello 的 Valhalla 博客充满了有趣的混响花絮。
【讨论】:
【参考方案3】:您需要的是要建模或模拟的房间或混响室的脉冲响应。完整的脉冲响应将包括所有多路径和多路径回波。脉冲响应的长度将大致等于脉冲声音完全衰减到可听阈值或给定本底噪声以下所需的时间长度(以样本为单位)。
给定一个长度为 N 的脉冲向量,您可以通过将输入向量(由当前音频输入样本与之前的 N-1 个输入样本连接而成)乘以脉冲向量来生成音频输出样本,其中适当的缩放。
有些人通过假设脉冲响应中的大多数抽头(除 1 之外的所有抽头)为零来简化这一点,并且只对剩余的回声使用一些缩放的延迟线,然后将其添加到输出中。
要获得更逼真的混响,您可能希望为每只耳朵使用不同的脉冲响应,并让响应随着头部位置而有所不同。小至四分之一英寸的头部移动可能会使脉冲响应中的峰值位置改变 1 个样本(以 44.1k 速率)。
【讨论】:
+1 因为你是对的,但这种解释可能“深奥且难以理解”。 :) +1 因为值得做的事就值得做好。 这种类型的混响被称为Convolution Reverb。卷积混响的替代方案是算法混响。 Freeverb 是算法混响的一个例子。【参考方案4】:您可以使用 GVerb。从here获取代码。GVerb是一个LADSPA插件,想了解LADSPA的可以去here。
Here 是 GVerb 的 wiki,包括参数说明和一些即时混响设置。
我们也可以直接在 Objc 中使用:
ty_gverb *_verb;
_verb = gverb_new(16000.f, 41.f, 40.0f, 7.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f);
AudiosampleType *samples = (AudioSampleType*)dataBuffer.mBuffers[0].mData;//Audio Data from AudioUnit Render or ExtAuidoFileReader
float lval,rval;
for (int i = 0; i< fileLengthFrames; i++)
float value = (float)samples[i] / 32768.f;//from SInt16 to float
gverb_do(_verb, value, &lval, &rval);
samples[i] = (SInt16)(lval * 32767.f);//float to SInt16
GVerb 是一种单声道效果,但如果您想要立体声效果,您可以通过效果单独运行每个通道,然后根据需要平移和混合处理后的信号与干信号
【讨论】:
太棒了!但它是一个昂贵的图书馆。无法实时使用以上是关于混响算法[关闭]的主要内容,如果未能解决你的问题,请参考以下文章