压缩器简介与实现

时间:2023-04-03 20:15:40

一、简介:压缩器(Compressor)是一种动态范围控制技术,用于减小音频信号的动态范围。它通过降低高音和低音的动态范围来增加信号的平均音量,并将信号的最大值限制在一个可接受的范围内。
压缩器通常被用于音频录制、混音和播放,以及语音处理等领域。压缩器广泛用于音乐制作中,以增加歌曲的整体音量,并保持信号的可听性。在语音处理中,压缩器可以用于增加语音信号的可懂度和清晰度。

二、工作原理:
在信号超过预定阈值后降低信号的增益。压缩器通常具有攻击时间、释放时间、比率等参数来控制其行为。攻击时间指压缩器开始工作的时间,释放时间指压缩器停止工作的时间,比率指压缩器降低信号增益的程度。
压缩器通常与扩展器一起使用,以实现更广泛的动态范围控制。在音乐制作中,压缩器可以用于压缩高音和低音的动态范围,扩展器可以用于在保持中音动态范围不变的情况下增加其可听性。在语音处理中,压缩器可以用于压缩语音信号的动态范围,并使用扩展器提高语音信号的清晰度。
压缩器在音频处理中非常有用,可以增加音频信号的平均音量,保持信号的可听性,并提高信号的可懂度和清晰度。

三、示例代码:
以下代码实现了一个基于包络跟踪的压缩器,其工作原理是在信号超过预定阈值后降低信号的增益。在该代码中,我们使用阈值、压缩比率、攻击时间、释放时间、补偿增益等参数来控制压缩器的行为。我们使用包络来计算适当的增益减少量,并使用增益减少量来计算适当的增益。最后,我们将输出信号打印
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define THRESHOLD -20.0 // 阈值
#define RATIO 3.0 // 压缩比率
#define ATTACK_TIME 0.002 // 攻击时间
#define RELEASE_TIME 0.1 // 释放时间
#define MAKEUP_GAIN 6.0 // 补偿增益
#define SAMPLE_RATE 44100.0
#define PI 3.1415926535

int main() {
float input = 0.0; // 输入信号
float output = 0.0; // 输出信号
float gain = 1.0; // 增益
float attack_coeff = exp(-1.0 / (ATTACK_TIME * SAMPLE_RATE)); // 攻击系数
float release_coeff = exp(-1.0 / (RELEASE_TIME * SAMPLE_RATE)); // 释放系数
float envelope = 0.0; // 包络
float threshold = pow(10.0, THRESHOLD / 20.0); // 将阈值转换为幅度值
float gain_reduction = 0.0; // 增益减少量
float makeup_gain = pow(10.0, MAKEUP_GAIN / 20.0); // 补偿增益的幅度值
float samples = SAMPLE_RATE * 2.0; // 2秒钟的采样数
float dt = 1.0 / SAMPLE_RATE;
for (int i = 0; i < samples; i++) {
// 计算包络
float amplitude = fabs(input);
if (amplitude > envelope) {
envelope = attack_coeff * envelope + (1.0 - attack_coeff) * amplitude;
} else {
envelope = release_coeff * envelope + (1.0 - release_coeff) * amplitude;
}
// 计算增益减少量
if (envelope > threshold) {
gain_reduction = (envelope - threshold) / (RATIO - 1);
gain_reduction = fmin(gain_reduction, amplitude);
gain_reduction = pow(10.0, -gain_reduction / 20.0);
} else {
gain_reduction = 1.0;
}
// 应用压缩器
gain = fmax(gain * gain_reduction, 1.0 / makeup_gain);
output = input * gain;
// 更新输入信号
input += sin(2.0 * PI * 1000.0 * i / SAMPLE_RATE);
// 打印输出信号
printf("%!!(MISSING)f(MISSING)\n", output);
}
return 0;
}