Entscheidungslogik beobachtet und optimiert

verwende nun ein gewichtets Mittel, in das die Stärke des Sprunges
mit einfließt. Dies führt zu wesentlich stabileren Entscheidungen.

Verbesserte Diagnostik (Konstante VERBOSE im Code setzen!),
erlaubt nun, den Entscheidungsprozeß im Detail nachzuvollziehen.
This commit is contained in:
Fischlurch 2014-09-01 01:11:16 +02:00
parent 3260b1d7d8
commit 139225fc5c
2 changed files with 43 additions and 23 deletions

View file

@ -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

View file

@ -20,6 +20,7 @@ GNU PUBLIC LICENCE (GPL) Version 2 and above.
#include <cmath>
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<factor? TRIGGER_FACTOR/factor : -10);
weights_ += weight;
score_ += weight * (confirmed? 1.0 : -1.0);
}
bool
possible()
{
return 0.0 < weights_ && 0.1 < confirmationDegree();
}
string
showLastUpdate()
{
float deg = confirmationDegree();
return deg == prevDeg_? "neutral"
: (deg > 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 <<absPos<<"\t jump? "