diff --git a/sauSynKlick/Makefile b/sauSynKlick/Makefile index 353428c..dc6c35c 100644 --- a/sauSynKlick/Makefile +++ b/sauSynKlick/Makefile @@ -13,7 +13,7 @@ #INCLUDES = -I$(XXX_H) INCLUDES = LIBRARIES = -lm -lsndfile -CFLAGS = $(INCLUDES) -O0 -ggdb -DDEBUG -fPIC +CFLAGS = $(INCLUDES) -ggdb -DDEBUG -fPIC #-O2 -fPIC CXXFLAGS = $(CFLAGS) -std=gnu++11 PROGRAMS = SynKlick diff --git a/sauSynKlick/SynKlick.cc b/sauSynKlick/SynKlick.cc index 8f9996d..0156ff9 100644 --- a/sauSynKlick/SynKlick.cc +++ b/sauSynKlick/SynKlick.cc @@ -20,6 +20,7 @@ GNU PUBLIC LICENCE (GPL) Version 2 and above. #include using std::string; +using std::to_string; using std::vector; using std::cout; using std::cerr; @@ -32,7 +33,7 @@ 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 = 4096.0f * EPSILON;// signal below this level (-33dB) is too low to detect jumps -const float TRIGGER_FACTOR = 5.0f; // discontinuity detected by local change compared to average change +const float TRIGGER_FACTOR = 6.0f; // discontinuity detected by local change compared to average change 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 @@ -76,16 +77,19 @@ reduceBufferPos (size_t & pos, size_t elementsToRemove) */ class EventScore { - uint contributions_ = 0; - uint positives_ = 0; - float prevDeg_ = 0.0f; + float weights_ = 0.0f; + float score_ = 0.0f; + + uint last_ = 0; + float fac_ = 0.0f; public: float confirmationDegree() { - return contributions_? float(positives_)/contributions_ - : 0.0f; + if (0==weights_) return 0.0; + float avgScore = score_/weights_; + return 0.5 * (avgScore + 1.0); } operator bool() @@ -94,23 +98,31 @@ class EventScore } void - recordConfirmation(bool confirmed) + decide(bool unclear, bool confirmed, float factor) { - prevDeg_ = confirmationDegree(); // record for diagnostics + fac_ = factor; + last_ = unclear? 0 : confirmed? 2 : 1; // record for diagnostics + if (unclear) return; - ++contributions_; - if (confirmed) - ++positives_; + float weight = confirmed? (factor/TRIGGER_FACTOR) + : (0.0 prevDeg_? "conf " - : "rej " - ) + std::to_string(deg); + return 0==last_? "neutral" + : (2==last_? "conf\t" + : "rej \t" + ) + to_string(fac_) +'\t'+ to_string(confirmationDegree()); } }; @@ -145,7 +157,7 @@ class Channel error ("could not open "+name+" -- " + sf_strerror (NULL)); if (1 != info_in_.channels) error ("only Mono streams supported -- but '"+name_ - +"' was found to have "+std::to_string(info_in_.channels)+" channels."); + +"' was found to have "+to_string(info_in_.channels)+" channels."); info_out_.format = info_in_.format; info_out_.channels = info_in_.channels; @@ -223,8 +235,9 @@ class Channel workPos_ = i; float averageDelta = updateMovingAverage(); float changeFactor = delta() / (averageDelta + EPSILON); - if (SILENCE_GATE < sampleLevel()) - event.recordConfirmation (changeFactor > TRIGGER_FACTOR); + bool unclear = (sampleLevel() < SILENCE_GATE ); + bool trigger = (changeFactor > TRIGGER_FACTOR); + event.decide (unclear, trigger, changeFactor); } } @@ -251,7 +264,10 @@ class Channel float updateMovingAverage() { - return ema_ = (delta() + ema_*(AVERAGE_SAMPLES - 1)) / AVERAGE_SAMPLES; + float old_ema = ema_; // avoid poisoning EMA used for detection + + ema_ = (delta() + ema_*(AVERAGE_SAMPLES - 1)) / AVERAGE_SAMPLES; + return old_ema; } float* @@ -355,8 +371,12 @@ 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 && trail != absPos) trail = 0; + if (!trail && event.possible()) + { + trail = absPos; + cerr << "...\n"; + } if (trail) cerr <