1 // A small program to try to even out the audio levels within a file
2 // (essentially a compressor with infinite lookahead).
11 // The frequency to filter on, in Hertz. Larger values makes the
12 // compressor react faster, but if it is too large, you'll
13 // ruin the waveforms themselves.
14 #define LPFILTER_FREQ 50.0
16 // A final scalar to get the audio within approximately the right range.
17 // Increase to _lower_ overall volume.
18 #define DAMPENING_FACTOR 5.0
21 #define FILTER_DEPTH 4
23 std::vector<float> level_samples(const std::vector<float> &pcm, float min_level, int sample_rate)
25 // filter forwards, then backwards (perfect phase filtering)
26 std::vector<float> filtered_samples, refiltered_samples, leveled_samples;
27 filtered_samples.resize(pcm.size());
28 refiltered_samples.resize(pcm.size());
29 leveled_samples.resize(pcm.size());
31 Filter filter = Filter::lpf(M_PI * LPFILTER_FREQ / sample_rate);
32 for (unsigned i = 0; i < pcm.size(); ++i) {
33 filtered_samples[i] = filter.update(fabs(pcm[i]));
36 for (unsigned i = pcm.size(); i --> 0; ) {
37 refiltered_samples[i] = filter.update(filtered_samples[i]);
40 for (int i = 1; i < FILTER_DEPTH; ++i) {
42 for (unsigned i = 0; i < pcm.size(); ++i) {
43 filtered_samples[i] = filter.update(refiltered_samples[i]);
46 for (unsigned i = pcm.size(); i --> 0; ) {
47 refiltered_samples[i] = filter.update(filtered_samples[i]);
51 for (unsigned i = 0; i < pcm.size(); ++i) {
52 float f = DAMPENING_FACTOR * std::max<float>(refiltered_samples[i], min_level);
53 leveled_samples[i] = pcm[i] / f;
56 return leveled_samples;