Erkennung von Signal-Sprüngen implementiert

This commit is contained in:
Fischlurch 2014-08-31 01:57:05 +02:00
parent 7f6ea5e614
commit 910e85a90a

View file

@ -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 <string>
#include <vector>
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <cmath>
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;
}
}