From 2116cd5829fafa82e23eb328e01e76c876c7b781 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 12 Mar 2015 00:36:19 +0100 Subject: [PATCH] Integrate the leveler into decode. --- Makefile | 9 +++------ decode.cpp | 25 ++++++++++++++++++++++++- level.cpp | 48 +++++++++++------------------------------------- level.h | 8 ++++++++ 4 files changed, 46 insertions(+), 44 deletions(-) create mode 100644 level.h diff --git a/Makefile b/Makefile index 44e2a5c..fe8c404 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CXXFLAGS=--std=gnu++0x -O2 -fno-math-errno -g -Wall LDLIBS=-lavcodec -lavformat -lavutil -lswresample -all: synth decode sync level cleaner +all: synth decode sync cleaner %.o: %.cpp $(CXX) -MMD -MP $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $< @@ -11,7 +11,7 @@ OBJS=decode.o synth.o synth_main.o interpolate.o sync.o level.o DEPS=$(OBJS:.o=.d) -include $(DEPS) -decode: interpolate.o audioreader.o decode.o +decode: interpolate.o audioreader.o decode.o level.o $(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS) synth: synth.o synth_main.o @@ -20,11 +20,8 @@ synth: synth.o synth_main.o sync: interpolate.o sync.o $(CXX) -o $@ $^ $(LDFLAGS) -level: level.o - $(CXX) -o $@ $^ $(LDFLAGS) - cleaner: cleaner.o $(CXX) -o $@ $^ $(LDFLAGS) clean: - $(RM) synth decode sync level cleaner $(OBJS) $(DEPS) + $(RM) synth decode sync cleaner $(OBJS) $(DEPS) diff --git a/decode.cpp b/decode.cpp index 7def49d..32e2cc3 100644 --- a/decode.cpp +++ b/decode.cpp @@ -9,6 +9,7 @@ #include "audioreader.h" #include "interpolate.h" +#include "level.h" #include "tap.h" #define BUFSIZE 4096 @@ -29,6 +30,8 @@ static float crop_start = 0.0f, crop_end = HUGE_VAL; static float filter_coeff[NUM_FILTER_COEFF] = { 1.0f }; // The rest is filled with 0. static bool output_filtered = false; static bool quiet = false; +static bool do_auto_level = false; +static bool output_leveled = false; // between [x,x+1] double find_zerocrossing(const std::vector &pcm, int x) @@ -151,6 +154,7 @@ void output_tap(const std::vector& pulses, double calibration_factor) } static struct option long_options[] = { + {"auto-level", 0, 0, 'a' }, {"no-calibrate", 0, 0, 's' }, {"plot-cycles", 0, 0, 'p' }, {"hysteresis-limit", required_argument, 0, 'l' }, @@ -166,6 +170,8 @@ void help() { fprintf(stderr, "decode [OPTIONS] AUDIO-FILE > TAP-FILE\n"); fprintf(stderr, "\n"); + fprintf(stderr, " -a, --auto-level automatically adjust amplitude levels throughout the file\n"); + fprintf(stderr, " -A, --output-leveled output leveled waveform to leveled.raw\n"); fprintf(stderr, " -s, --no-calibrate do not try to calibrate on sync pulse length\n"); fprintf(stderr, " -p, --plot-cycles output debugging info to cycles.plot\n"); fprintf(stderr, " -l, --hysteresis-limit VAL change amplitude threshold for ignoring pulses (0..32768)\n"); @@ -181,11 +187,19 @@ void parse_options(int argc, char **argv) { for ( ;; ) { int option_index = 0; - int c = getopt_long(argc, argv, "spl:f:Fc:qh", long_options, &option_index); + int c = getopt_long(argc, argv, "aAspl:f:Fc:qh", long_options, &option_index); if (c == -1) break; switch (c) { + case 'a': + do_auto_level = true; + break; + + case 'A': + output_leveled = true; + break; + case 's': do_calibrate = false; break; @@ -348,6 +362,15 @@ int main(int argc, char **argv) pcm = do_filter(pcm, filter_coeff); } + if (do_auto_level) { + pcm = level_samples(pcm, sample_rate); + if (output_leveled) { + FILE *fp = fopen("leveled.raw", "wb"); + fwrite(pcm.data(), pcm.size() * sizeof(pcm[0]), 1, fp); + fclose(fp); + } + } + #if 0 for (int i = 0; i < LEN; ++i) { in[i] += rand() % 10000; diff --git a/level.cpp b/level.cpp index 3637799..fea5926 100644 --- a/level.cpp +++ b/level.cpp @@ -6,9 +6,6 @@ #include #include -#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. @@ -27,21 +24,6 @@ // 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; @@ -77,46 +59,38 @@ static float filter_update(float in) return out; } -int main(int argc, char **argv) +std::vector level_samples(const std::vector &pcm, int sample_rate) { - std::vector 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 filtered_samples, refiltered_samples; + std::vector 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(refiltered_samples[i], MIN_LEVEL); + leveled_samples[i] = pcm[i] / f; } + + return leveled_samples; } diff --git a/level.h b/level.h new file mode 100644 index 0000000..3f830d7 --- /dev/null +++ b/level.h @@ -0,0 +1,8 @@ +#ifndef _LEVEL_H +#define _LEVEL_H 1 + +#include + +std::vector level_samples(const std::vector &pcm, int sample_rate); + +#endif // !defined(_LEVEL_H) -- 2.39.2