帮助动态范围压缩function(音频)

我正在编写一个用于进行动态范围压缩的C#function(一种音频效果,基本上可以压缩瞬态峰值并放大其他所有内容以产生整体更响亮的声音)。 我写了一个函数来做到这一点(我认为):

alt text http://sofzh.miximages.com/c%23/www.freeimagehosting.net

public static void Compress(ref short[] input, double thresholdDb, double ratio) { double maxDb = thresholdDb - (thresholdDb / ratio); double maxGain = Math.Pow(10, -maxDb / 20.0); for (int i = 0; i < input.Length; i += 2) { // convert sample values to ABS gain and store original signs int signL = input[i] < 0 ? -1 : 1; double valL = (double)input[i] / 32768.0; if (valL < 0.0) { valL = -valL; } int signR = input[i + 1] < 0 ? -1 : 1; double valR = (double)input[i + 1] / 32768.0; if (valR < 0.0) { valR = -valR; } // calculate mono value and compress double val = (valL + valR) * 0.5; double posDb = -Math.Log10(val) * 20.0; if (posDb  lim) { valL = lim; } if (valR > lim) { valR = lim; } double maxval = 32000.0 / lim; // convert gain values back to sample values input[i] = (short)(valL * maxval); input[i] *= (short)signL; input[i + 1] = (short)(valR * maxval); input[i + 1] *= (short)signR; } } 

我称它的threshold值介于10.0 db和30.0 db之间,比率介于1.5和4.0之间。 此function肯定会产生更响亮的整体声音,但即使在低阈值和低比率时也会产生不可接受的失真水平。

任何人都可以看到这个function有什么问题吗? 我是否正确处理立体声方面(该function假设立体声输入)? 当我(模糊地)理解事物时,我不想单独压缩两个通道,所以我的代码试图压缩“虚拟”单声道样本值,然后分别对L和R样本值应用相同程度的压缩。 但是,不确定我做得对。

我认为问题的一部分可能是我的function的“硬拐点”,当超过阈值时,它突然开始压缩。 我想我可能需要使用这样的“软膝盖”:

alt text http://sofzh.miximages.com/c%23/www.freeimagehosting.net

任何人都可以建议修改我的function来产生柔软的膝盖曲线吗?

我认为你对如何进行压缩的基本理解是错误的(抱歉;))。 这不是关于“压缩”个别样本值; 这将彻底改变波形并产生严重的谐波失真。 您需要评估许多样本的输入信号量(我必须使用Google获取正确的公式),并使用此选项将更多逐渐变化的乘数应用于输入样本以生成输出。

如果您很难找到常用技术,kvraudio.com /论坛上的DSP论坛可能会指出您正确的方向。

开源Skype Voice Changer项目包括一个由Scott Stillwell编写的许多优秀压缩器的C#端口,所有这些压缩器都具有可配置的参数:

  • 快速攻击压缩机
  • 相当幼稚 (压缩机限制器)
  • 活动地平线 (峰值限制器)

第一个看起来它有能力做软膝盖,虽然没有暴露这样做的参数。