Patch-Operation wie geplant implementiert

...funktioniert schön in den sauberen Fällen,
jedoch nicht so gut wenn mehrere Sprünge dicht beieinander liegen,
oder gar eine Strecke von Null-Werten folgt
This commit is contained in:
Fischlurch 2014-08-31 18:44:30 +02:00
parent be57e53479
commit 3260b1d7d8
2 changed files with 94 additions and 23 deletions

View file

@ -13,7 +13,7 @@
#INCLUDES = -I$(XXX_H)
INCLUDES =
LIBRARIES = -lm -lsndfile
CFLAGS = $(INCLUDES) -O0 -ggdb -fPIC
CFLAGS = $(INCLUDES) -O0 -ggdb -DDEBUG -fPIC
#-O2 -fPIC
CXXFLAGS = $(CFLAGS) -std=gnu++11
PROGRAMS = SynKlick

View file

@ -23,6 +23,7 @@ using std::string;
using std::vector;
using std::cout;
using std::cerr;
using std::max;
using std::abs;
const size_t CHUNK_SIZE = 20000; //44100; ///TODO for debugging
@ -35,6 +36,8 @@ const float TRIGGER_FACTOR = 5.0f; // discontinuity detected by local
const float CONFIRMATION_DEGREE = 0.66f; // degree of confirmation by multiple tracks for an event to be accepted
const uint AVERAGE_SAMPLES = 50; // number of past samples to use for average delta
const bool VERBOSE = true;
/* ==== Helpers ==== */
void
@ -75,6 +78,7 @@ class EventScore
{
uint contributions_ = 0;
uint positives_ = 0;
float prevDeg_ = 0.0f;
public:
float
@ -92,13 +96,26 @@ class EventScore
void
recordConfirmation(bool confirmed)
{
prevDeg_ = confirmationDegree(); // record for diagnostics
++contributions_;
if (confirmed)
++positives_;
}
string
showLastUpdate()
{
float deg = confirmationDegree();
return deg == prevDeg_? "neutral"
: (deg > prevDeg_? "conf "
: "rej "
) + std::to_string(deg);
}
};
class Channel
{
SNDFILE *in_ = nullptr,
@ -206,19 +223,20 @@ class Channel
workPos_ = i;
float averageDelta = updateMovingAverage();
float changeFactor = delta() / (averageDelta + EPSILON);
if (SILENCE_GATE < abs(sample()))
event.recordConfirmation(changeFactor > TRIGGER_FACTOR);
if (SILENCE_GATE < sampleLevel())
event.recordConfirmation (changeFactor > TRIGGER_FACTOR);
}
}
private:
float
sample()
sampleLevel()
{
if (0 < workPos_)
return std::max(buff_[workPos_-1], buff_[workPos_]);
else
return buff_[workPos_];
auto curr = abs(buff_[workPos_]);
auto prev = abs(buff_[workPos_ - 1]);
return 0 < workPos_? max(prev, curr)
: curr;
}
float
@ -235,11 +253,22 @@ class Channel
{
return ema_ = (delta() + ema_*(AVERAGE_SAMPLES - 1)) / AVERAGE_SAMPLES;
}
float*
accessCurrentContext()
{
assert(CONTEXT <= workPos_);
assert(CONTEXT + workPos_ <= numSamples_);
return buff_ + (workPos_ - CONTEXT);
}
friend class Patch;
};
/**
* fix a glitch detected in the corresponding channel.
* Fix a glitch detected in the corresponding channel.
* When the Patch is applied, internal work buffers are used
* to create two (partially synthetic) copies of the channel's signal
* which are then cross faded. The result is pushed back into the
@ -247,20 +276,45 @@ class Channel
*/
class Patch
{
float workBuff[2*CONTEXT];
Channel& chan_;
static const size_t LEN = 2 * CONTEXT;
float workBuff[LEN];
float* rawBuff;
void
reconstructMirroredSignal()
{
for (uint i=0; i < LEN; ++i)
workBuff[i] = rawBuff[LEN-1 - i];
}
public:
Patch(Channel& c)
: chan_(c)
Patch (Channel& c)
: rawBuff{c.accessCurrentContext()}
{
reconstructMirroredSignal();
}
void
apply()
{
cerr << "TODO\n";
for (uint i=0; i < LEN; ++i)
{
float fade = (i<CONTEXT) ? CONTEXT - (i+1)
: i - CONTEXT;
fade = 1.0 - fade/CONTEXT;
// i=-1 -> 0
// i=CONTEXT-1 -> 1
// i=CONTEXT -> 1
// i=2*CONTEXT -> 0
float p = fade * 0.5f,
q = 1.0 - p;
rawBuff[i] = q*rawBuff[i] + p*workBuff[i];
}
}
};
@ -297,6 +351,20 @@ closeStreams()
}
void
eventConfirmationDiagnostic(EventScore& event, string name, size_t absPos)
{
static size_t trail = 0;
if (trail && trail != absPos) trail=0;
if (event && !trail) trail = absPos;
if (trail)
cerr <<absPos<<"\t jump? "
<<name<<"\t :: "
<<event.showLastUpdate()
<<"\n";
}
void
process()
{
@ -306,24 +374,24 @@ process()
{
for (Channel& channel : streams)
channel.fillBuffer();
for (uint i=0; i < BUFF_SIZE; ++i)
{
EventScore event;
bool yesss = false;
for (Channel& channel : streams){
channel.visit(i, event);
if (event || yesss){
cerr << "Event ? "<<i<<" "<<channel.name_<<"\t deg "<<event.confirmationDegree()<<"\n";
yesss = true;
for (Channel& channel : streams)
{
channel.visit(i, event);
if (VERBOSE)
eventConfirmationDiagnostic (event, channel.name_, absStartPos+i);
}
}
if (event)
{
cout << "Skip-Event at "<< absStartPos+i <<"\n";
cout << "PATCH at: "<< absStartPos+i <<"\n";
for (Channel& channel : streams)
Patch(channel).apply();
}
}
for (Channel& channel : streams)
channel.writeBuffer();
@ -332,6 +400,9 @@ process()
}
int
main (int argc, char* argv[]) {
if (argc < 3 || string("-h") == argv[1])