1 // A small program to try to even out the audio levels within a file
2 // (essentially a compressor with infinite lookahead).
10 #define WAVE_FREQ 44100.0
12 // The frequency to filter on, in Hertz. Larger values makes the
13 // compressor react faster, but if it is too large, you'll
14 // ruin the waveforms themselves.
15 #define LPFILTER_FREQ 50.0
17 // The minimum estimated sound level at any given point.
18 // If you decrease this, you'll be able to amplify really silent signals
19 // by more, but you'll also increase the level of silent (ie. noise-only) segments,
20 // possibly caused misdetected pulses in these segments.
21 #define MIN_LEVEL 0.05
23 // A final scalar to get the audio within approximately the right range.
24 // Increase to _lower_ overall volume.
25 #define DAMPENING_FACTOR 5.0
28 #define FILTER_DEPTH 4
30 struct stereo_sample {
34 inline short clip(int x)
38 } else if (x > 32767) {
45 static float a1, a2, b0, b1, b2;
48 static void filter_init(float cutoff_radians)
50 float resonance = 1.0f / sqrt(2.0f);
52 sincosf(cutoff_radians, &sn, &cs);
54 float alpha = float(sn / (2 * resonance));
56 // coefficients for lowpass filter
64 float invA0 = 1.0f / a0;
71 // reset filter delays
75 static float filter_update(float in)
77 float out = b0*in + d0;
78 d0 = b1 * in - a1 * out + d1;
79 d1 = b2 * in - a2 * out;
83 int main(int argc, char **argv)
85 std::vector<short> pcm;
87 while (!feof(stdin)) {
89 ssize_t ret = fread(buf, sizeof(short), BUFSIZE, stdin);
91 pcm.insert(pcm.end(), buf, buf + ret);
95 // filter forwards, then backwards (perfect phase filtering)
96 std::vector<float> filtered_samples, refiltered_samples;
97 filtered_samples.resize(pcm.size());
98 refiltered_samples.resize(pcm.size());
100 filter_init(M_PI * LPFILTER_FREQ / WAVE_FREQ);
101 for (unsigned i = 0; i < pcm.size(); ++i) {
102 filtered_samples[i] = filter_update(fabs(pcm[i]));
104 filter_init(M_PI * LPFILTER_FREQ / WAVE_FREQ);
105 for (unsigned i = pcm.size(); i --> 0; ) {
106 refiltered_samples[i] = filter_update(filtered_samples[i]);
109 for (int i = 1; i < FILTER_DEPTH; ++i) {
110 filter_init(M_PI * LPFILTER_FREQ / WAVE_FREQ);
111 for (unsigned i = 0; i < pcm.size(); ++i) {
112 filtered_samples[i] = filter_update(refiltered_samples[i]);
114 filter_init(M_PI * LPFILTER_FREQ / WAVE_FREQ);
115 for (unsigned i = pcm.size(); i --> 0; ) {
116 refiltered_samples[i] = filter_update(filtered_samples[i]);
120 for (unsigned i = 0; i < pcm.size(); ++i) {
121 float f = DAMPENING_FACTOR * std::max(refiltered_samples[i] * (1.0 / 32768.0), MIN_LEVEL);
122 short s = clip(lrintf(pcm[i] / f));
123 fwrite(&s, sizeof(s), 1, stdout);