1 // A small program to try to even out the audio levels within a file
2 // (essentially a compressor with infinite lookahead).
9 // The frequency to filter on, in Hertz. Larger values makes the
10 // compressor react faster, but if it is too large, you'll
11 // ruin the waveforms themselves.
12 #define LPFILTER_FREQ 50.0
14 // A final scalar to get the audio within approximately the right range.
15 // Increase to _lower_ overall volume.
16 #define DAMPENING_FACTOR 5.0
19 #define FILTER_DEPTH 4
21 static float a1, a2, b0, b1, b2;
24 static void filter_init(float cutoff_radians)
26 float resonance = 1.0f / sqrt(2.0f);
27 float sn = sin(cutoff_radians), cs = cos(cutoff_radians);
28 float alpha = float(sn / (2 * resonance));
30 // coefficients for lowpass filter
44 // reset filter delays
48 static float filter_update(float in)
50 float out = b0*in + d0;
51 d0 = b1 * in - a1 * out + d1;
52 d1 = b2 * in - a2 * out;
56 std::vector<float> level_samples(const std::vector<float> &pcm, float min_level, int sample_rate)
58 // filter forwards, then backwards (perfect phase filtering)
59 std::vector<float> filtered_samples, refiltered_samples, leveled_samples;
60 filtered_samples.resize(pcm.size());
61 refiltered_samples.resize(pcm.size());
62 leveled_samples.resize(pcm.size());
64 filter_init(M_PI * LPFILTER_FREQ / sample_rate);
65 for (unsigned i = 0; i < pcm.size(); ++i) {
66 filtered_samples[i] = filter_update(fabs(pcm[i]));
68 filter_init(M_PI * LPFILTER_FREQ / sample_rate);
69 for (unsigned i = pcm.size(); i --> 0; ) {
70 refiltered_samples[i] = filter_update(filtered_samples[i]);
73 for (int i = 1; i < FILTER_DEPTH; ++i) {
74 filter_init(M_PI * LPFILTER_FREQ / sample_rate);
75 for (unsigned i = 0; i < pcm.size(); ++i) {
76 filtered_samples[i] = filter_update(refiltered_samples[i]);
78 filter_init(M_PI * LPFILTER_FREQ / sample_rate);
79 for (unsigned i = pcm.size(); i --> 0; ) {
80 refiltered_samples[i] = filter_update(filtered_samples[i]);
84 for (unsigned i = 0; i < pcm.size(); ++i) {
85 float f = DAMPENING_FACTOR * std::max<float>(refiltered_samples[i], min_level);
86 leveled_samples[i] = pcm[i] / f;
89 return leveled_samples;