#include <vector>
#include <algorithm>
-#define BUFSIZE 4096
-#define WAVE_FREQ 44100.0
-
// The frequency to filter on, in Hertz. Larger values makes the
// compressor react faster, but if it is too large, you'll
// ruin the waveforms themselves.
#define LPFILTER_FREQ 50.0
-// The minimum estimated sound level at any given point.
-// If you decrease this, you'll be able to amplify really silent signals
-// by more, but you'll also increase the level of silent (ie. noise-only) segments,
-// possibly caused misdetected pulses in these segments.
-#define MIN_LEVEL 0.05
-
// A final scalar to get the audio within approximately the right range.
// Increase to _lower_ overall volume.
#define DAMPENING_FACTOR 5.0
// 6dB/oct per round.
#define FILTER_DEPTH 4
-struct stereo_sample {
- short left, right;
-};
-
-inline short clip(int x)
-{
- if (x < -32768) {
- return x;
- } else if (x > 32767) {
- return 32767;
- } else {
- return short(x);
- }
-}
-
static float a1, a2, b0, b1, b2;
static float d0, d1;
static void filter_init(float cutoff_radians)
{
float resonance = 1.0f / sqrt(2.0f);
- float sn, cs;
- sincosf(cutoff_radians, &sn, &cs);
-
+ float sn = sin(cutoff_radians), cs = cos(cutoff_radians);
float alpha = float(sn / (2 * resonance));
// coefficients for lowpass filter
a1 = -2 * cs;
a2 = 1 - alpha;
- float invA0 = 1.0f / a0;
- b0 *= invA0;
- b1 *= invA0;
- b2 *= invA0;
- a1 *= invA0;
- a2 *= invA0;
+ b0 /= a0;
+ b1 /= a0;
+ b2 /= a0;
+ a1 /= a0;
+ a2 /= a0;
// reset filter delays
d0 = d1 = 0.0f;
return out;
}
-int main(int argc, char **argv)
+std::vector<float> level_samples(const std::vector<float> &pcm, float min_level, int sample_rate)
{
- std::vector<short> pcm;
-
- while (!feof(stdin)) {
- short buf[BUFSIZE];
- ssize_t ret = fread(buf, sizeof(short), BUFSIZE, stdin);
- if (ret >= 0) {
- pcm.insert(pcm.end(), buf, buf + ret);
- }
- }
-
// filter forwards, then backwards (perfect phase filtering)
- std::vector<float> filtered_samples, refiltered_samples;
+ std::vector<float> filtered_samples, refiltered_samples, leveled_samples;
filtered_samples.resize(pcm.size());
refiltered_samples.resize(pcm.size());
+ leveled_samples.resize(pcm.size());
- filter_init(M_PI * LPFILTER_FREQ / WAVE_FREQ);
+ filter_init(M_PI * LPFILTER_FREQ / sample_rate);
for (unsigned i = 0; i < pcm.size(); ++i) {
filtered_samples[i] = filter_update(fabs(pcm[i]));
}
- filter_init(M_PI * LPFILTER_FREQ / WAVE_FREQ);
+ filter_init(M_PI * LPFILTER_FREQ / sample_rate);
for (unsigned i = pcm.size(); i --> 0; ) {
refiltered_samples[i] = filter_update(filtered_samples[i]);
}
for (int i = 1; i < FILTER_DEPTH; ++i) {
- filter_init(M_PI * LPFILTER_FREQ / WAVE_FREQ);
+ filter_init(M_PI * LPFILTER_FREQ / sample_rate);
for (unsigned i = 0; i < pcm.size(); ++i) {
filtered_samples[i] = filter_update(refiltered_samples[i]);
}
- filter_init(M_PI * LPFILTER_FREQ / WAVE_FREQ);
+ filter_init(M_PI * LPFILTER_FREQ / sample_rate);
for (unsigned i = pcm.size(); i --> 0; ) {
refiltered_samples[i] = filter_update(filtered_samples[i]);
}
}
for (unsigned i = 0; i < pcm.size(); ++i) {
- float f = DAMPENING_FACTOR * std::max(refiltered_samples[i] * (1.0 / 32768.0), MIN_LEVEL);
- short s = clip(lrintf(pcm[i] / f));
- fwrite(&s, sizeof(s), 1, stdout);
+ float f = DAMPENING_FACTOR * std::max<float>(refiltered_samples[i], min_level);
+ leveled_samples[i] = pcm[i] / f;
}
+
+ return leveled_samples;
}