From 910e85a90a5c66b0864338e5996bfaaf2013dd3d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 31 Aug 2014 01:57:05 +0200 Subject: [PATCH] =?UTF-8?q?Erkennung=20von=20Signal-Spr=C3=BCngen=20implem?= =?UTF-8?q?entiert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sauSynKlick/SynKlick.cc | 61 +++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/sauSynKlick/SynKlick.cc b/sauSynKlick/SynKlick.cc index 6348ae5..260ceb4 100644 --- a/sauSynKlick/SynKlick.cc +++ b/sauSynKlick/SynKlick.cc @@ -1,5 +1,5 @@ /* - SynKlick - repair synchronous drop-outs in raw sound recording + SynKlick - repair synchronous skips in raw sound recording (C) Ichthyostega (Hermann Vosseler), 2014 @@ -14,19 +14,25 @@ GNU PUBLIC LICENCE (GPL) Version 2 and above. #include #include +#include #include #include -#include +#include using std::string; using std::vector; using std::cout; using std::cerr; +using std::abs; -const size_t BUFF_SIZE = 20000; //44100; ///TODO for debugging +const size_t CHUNK_SIZE = 20000; //44100; ///TODO for debugging const size_t CONTEXT = 100; -const size_t CHUNK_SIZE = BUFF_SIZE + 2*CONTEXT; +const size_t BUFF_SIZE = CHUNK_SIZE + 2*CONTEXT; +const float EPSILON = 1.0f / (1 << 23); // one normalised sample step for 24bit samples +const float SILENCE_GATE = 1024.0f * EPSILON;// signal below this level (-39dB) is too low to detect jumps +const float TRIGGER_FACTOR = 6.0f; // discontinuity detected by local change compared to average change +const uint AVERAGE_SAMPLES = 50; // number of past samples to use for average delta /* ==== Helpers ==== */ @@ -74,9 +80,10 @@ class Channel SF_INFO info_in_, info_out_; - float buff_[CHUNK_SIZE]; + float buff_[BUFF_SIZE]; size_t numSamples_ = 0; size_t workPos_ = 0; + float ema_ = 1.0f / TRIGGER_FACTOR; public: @@ -120,9 +127,9 @@ class Channel void fillBuffer() { - assert(numSamples_ < CHUNK_SIZE); + assert(numSamples_ < BUFF_SIZE); float* startPos = buff_ + numSamples_; - size_t samplesToRead = CHUNK_SIZE - numSamples_; + size_t samplesToRead = BUFF_SIZE - numSamples_; numSamples_ = sf_read_float(in_, startPos, samplesToRead); if (numSamples_ < samplesToRead) hitEnd = true; // causes the processing to end with this chunk. @@ -170,10 +177,35 @@ class Channel && workPos_ <= i) { workPos_ = i; + float averageDelta = updateMovingAverage(); + float changeFactor = delta() / (averageDelta + EPSILON); + if (event != NO && SILENCE_GATE < abs(sample())) + event = (changeFactor > TRIGGER_FACTOR? YES : NO); } return event; } + private: + float + sample() + { + return buff_[workPos_]; + } + + float + delta() + { + if (0 < workPos_) + return abs(buff_[workPos_] - buff_[workPos_-1]); + else + return 0; + } + + float + updateMovingAverage() + { + return ema_ = (delta() + ema_*(AVERAGE_SAMPLES - 1)) / AVERAGE_SAMPLES; + } }; @@ -199,7 +231,7 @@ class Patch void apply() { - error("TODO"); + cerr << "TODO\n"; } }; @@ -239,21 +271,28 @@ closeStreams() void process() { + size_t absStartPos = 0; // for diagnostic messages + while (!Channel::hitEnd) { for (Channel& channel : streams) channel.fillBuffer(); - for (uint i=0; i < CHUNK_SIZE; ++i) + for (uint i=0; i < BUFF_SIZE; ++i) { Event event = MAYBE; for (Channel& channel : streams) event = channel.visit(i, event); if (YES == event) - for (Channel& channel : streams) - Patch(channel).apply(); + { + cout << "Skip-Event at "<< absStartPos+i <<"\n"; + for (Channel& channel : streams) + Patch(channel).apply(); + } } for (Channel& channel : streams) channel.writeBuffer(); + + absStartPos += CHUNK_SIZE; } }