]> git.sesse.net Git - c64tapwav/commitdiff
Make the compressor filter frequency configurable, and up the default to a more aggre...
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 14 Mar 2015 13:49:01 +0000 (14:49 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 14 Mar 2015 13:49:01 +0000 (14:49 +0100)
decode.cpp
level.cpp
level.h

index 5d7669af232af9febb802494df77afa021cf9b36..b90ad218b759a264da739685faecfd328be0db40 100644 (file)
@@ -51,6 +51,11 @@ static bool output_leveled = false;
 static std::vector<float> train_snap_points;
 static bool do_train = false;
 
 static std::vector<float> train_snap_points;
 static bool do_train = false;
 
+// The frequency to filter on (for do_auto_level), in Hertz.
+// Larger values makes the compressor react faster, but if it is too large,
+// you'll ruin the waveforms themselves.
+static float auto_level_freq = 200.0;
+
 // The minimum estimated sound level (for do_auto_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,
 // The minimum estimated sound level (for do_auto_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,
@@ -169,6 +174,7 @@ void output_tap(const std::vector<pulse>& pulses, double calibration_factor)
 
 static struct option long_options[] = {
        {"auto-level",       0,                 0, 'a' },
 
 static struct option long_options[] = {
        {"auto-level",       0,                 0, 'a' },
+       {"auto-level-freq",  required_argument, 0, 'b' },
        {"output-leveled",   0,                 0, 'A' },
        {"min-level",        required_argument, 0, 'm' },
        {"no-calibrate",     0,                 0, 's' },
        {"output-leveled",   0,                 0, 'A' },
        {"min-level",        required_argument, 0, 'm' },
        {"no-calibrate",     0,                 0, 's' },
@@ -188,6 +194,7 @@ 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, "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, "  -b, --auto-level-freq        minimum frequency in Hertz of corrected level changes (default 200 Hz)\n");
        fprintf(stderr, "  -A, --output-leveled         output leveled waveform to leveled.raw\n");
        fprintf(stderr, "  -m, --min-level              minimum estimated sound level (0..32768) for --auto-level\n");
        fprintf(stderr, "  -s, --no-calibrate           do not try to calibrate on sync pulse length\n");
        fprintf(stderr, "  -A, --output-leveled         output leveled waveform to leveled.raw\n");
        fprintf(stderr, "  -m, --min-level              minimum estimated sound level (0..32768) for --auto-level\n");
        fprintf(stderr, "  -s, --no-calibrate           do not try to calibrate on sync pulse length\n");
@@ -208,7 +215,7 @@ void parse_options(int argc, char **argv)
 {
        for ( ;; ) {
                int option_index = 0;
 {
        for ( ;; ) {
                int option_index = 0;
-               int c = getopt_long(argc, argv, "aAm:spl:f:r:Fc:t:qh", long_options, &option_index);
+               int c = getopt_long(argc, argv, "ab:Am:spl:f:r:Fc:t:qh", long_options, &option_index);
                if (c == -1)
                        break;
 
                if (c == -1)
                        break;
 
@@ -217,6 +224,10 @@ void parse_options(int argc, char **argv)
                        do_auto_level = true;
                        break;
 
                        do_auto_level = true;
                        break;
 
+               case 'b':
+                       auto_level_freq = atof(optarg);
+                       break;
+
                case 'A':
                        output_leveled = true;
                        break;
                case 'A':
                        output_leveled = true;
                        break;
@@ -558,7 +569,7 @@ int main(int argc, char **argv)
        }
 
        if (do_auto_level) {
        }
 
        if (do_auto_level) {
-               pcm = level_samples(pcm, min_level, sample_rate);
+               pcm = level_samples(pcm, min_level, auto_level_freq, sample_rate);
                if (output_leveled) {
                        FILE *fp = fopen("leveled.raw", "wb");
                        fwrite(pcm.data(), pcm.size() * sizeof(pcm[0]), 1, fp);
                if (output_leveled) {
                        FILE *fp = fopen("leveled.raw", "wb");
                        fwrite(pcm.data(), pcm.size() * sizeof(pcm[0]), 1, fp);
index 46a494f8ca7070ec26f5d7bd0042331531bab954..504cf0bbf7549170600674140fff7460c14c85f9 100644 (file)
--- a/level.cpp
+++ b/level.cpp
@@ -8,11 +8,6 @@
 
 #include "filter.h"
 
 
 #include "filter.h"
 
-// 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
-
 // A final scalar to get the audio within approximately the right range.
 // Increase to _lower_ overall volume.
 #define DAMPENING_FACTOR 5.0
 // A final scalar to get the audio within approximately the right range.
 // Increase to _lower_ overall volume.
 #define DAMPENING_FACTOR 5.0
@@ -20,7 +15,7 @@
 // 6dB/oct per round.
 #define FILTER_DEPTH 4
 
 // 6dB/oct per round.
 #define FILTER_DEPTH 4
 
-std::vector<float> level_samples(const std::vector<float> &pcm, float min_level, int sample_rate)
+std::vector<float> level_samples(const std::vector<float> &pcm, float min_level, float lpfilter_freq, int sample_rate)
 {
        // filter forwards, then backwards (perfect phase filtering)
        std::vector<float> filtered_samples, refiltered_samples, leveled_samples;
 {
        // filter forwards, then backwards (perfect phase filtering)
        std::vector<float> filtered_samples, refiltered_samples, leveled_samples;
@@ -28,7 +23,7 @@ std::vector<float> level_samples(const std::vector<float> &pcm, float min_level,
        refiltered_samples.resize(pcm.size());
        leveled_samples.resize(pcm.size());
 
        refiltered_samples.resize(pcm.size());
        leveled_samples.resize(pcm.size());
 
-       Filter filter = Filter::lpf(2.0 * M_PI * LPFILTER_FREQ / sample_rate);
+       Filter filter = Filter::lpf(2.0 * M_PI * lpfilter_freq / sample_rate);
        for (unsigned i = 0; i < pcm.size(); ++i) {
                filtered_samples[i] = filter.update(fabs(pcm[i]));
        }
        for (unsigned i = 0; i < pcm.size(); ++i) {
                filtered_samples[i] = filter.update(fabs(pcm[i]));
        }
diff --git a/level.h b/level.h
index 763e617958143c21bbf8c5ee31c84cb5b5751189..3a7f39d1289966b68dae9f18a5321a77d23b5ef0 100644 (file)
--- a/level.h
+++ b/level.h
@@ -3,6 +3,6 @@
 
 #include <vector>
 
 
 #include <vector>
 
-std::vector<float> level_samples(const std::vector<float> &pcm, float min_level, int sample_rate);
+std::vector<float> level_samples(const std::vector<float> &pcm, float min_level, float lpfilter_freq, int sample_rate);
 
 #endif  // !defined(_LEVEL_H)
 
 #endif  // !defined(_LEVEL_H)