37 , mGlobalTargetPitchInCents(0)
39 , mStaticReferenceKey(0)
40 , mWolfsIntervalShift(0)
41 , mTuningEnabled(true)
43 , mIntervalSizes(12,0)
44 , mIntervalWeights(12,1)
46 , pElapsedTimer(nullptr)
47 , mStaticTuningModeEnabled(false)
48 , mPitchAutoCorrectionParameter(0.5)
73 for (
int n=0; n<128; n++)
113 double cents = 1200 * log(f/440.0) / log(2.0);
115 if (cents > 200 or cents < -200)
117 LOGWARNING <<
"Unreasonable global pitch =" << cents;
120 LOGMESSAGE <<
"Setting global ptich to" << cents;
146 LOGMESSAGE <<
"Tuning mode: ET: Equal temperament";
149 LOGMESSAGE <<
"Tuning mode: JI: Dynamically tuned optimized just intonation";
152 LOGMESSAGE <<
"Tuning mode: UT: Custom unequal temperament given by table";
155 LOGERROR <<
"Undefined value for tuning mode";
177 LOGMESSAGE << (enable ?
"enable" :
"disable") <<
" tunging algorithm";
203 if (lambda<0 or lambda>1)
205 LOGWARNING <<
"Unreasonable correction parameter =" << lambda;
206 LOGWARNING <<
"Value should be between 0 and 1.";
209 LOGMESSAGE <<
"Setting pitch progression parameter lambda =" << lambda;
228 if (delay<0 or delay>10)
230 LOGWARNING <<
"Unreasonable delay parameter =" << delay;
231 LOGWARNING <<
"Value should be between 0 and 10.";
234 LOGMESSAGE <<
"Setting delay parameter: delay=" << delay;
249 if (seconds<0 or seconds>10)
251 LOGWARNING <<
"Unreasonable memory duration parameter =" << seconds;
252 LOGWARNING <<
"Value should be between 0 and 10.";
255 LOGMESSAGE <<
"Setting memory duration parameter: delay=" << seconds;
276 int key =
event.byte1() & 0x7F;
277 double intensity =
static_cast<double>(
event.byte2())/127.0;
279 switch (event.byte0() & 0xF0)
303 switch(event.byte1())
341 if (semitones<1 or semitones>12)
342 {
LOGERROR <<
"Set cents: Number of halftones" << semitones <<
"must be between 1 and 12"; }
343 else if (cents < -50 or cents > 50)
344 {
LOGERROR <<
"Set cents: Value" << cents <<
"out of allowed range (-50..50)"; }
371 if (semitones < 1 or semitones > 12)
372 {
LOGERROR <<
"Set weights: Number of halftones" << semitones <<
"must be between 1 and 12"; }
373 else if (weight < 0 or weight > 1)
374 {
LOGERROR <<
"Set weights: Value" << weight <<
"out of allowed range (0..1)"; }
391 const double centQuantization = 0.05;
392 QMap<int,double> changes;
400 if (not keydata.emitted or
401 fabs(pitch-keydata.previousPitch) > centQuantization)
402 changes[keydata.key] = keydata.previousPitch = pitch;
403 keydata.emitted =
true;
405 if (changes.size()>0)
410 QString message =
"| ";
411 int firstkey=0;
double lastpitch=0;
412 for (
KeyData &key : mKeyDataVector)
if (key.pressed)
414 firstkey=key.key; lastpitch=key.pitch;
break;
416 for (
KeyData &key : mKeyDataVector)
if (key.pressed and key.key > firstkey)
418 message += QString::number(((
int)(10*(key.pitch-lastpitch)))/10.0) +
" | ";
419 lastpitch = key.pitch;
459 LOGMESSAGE <<
"Setting static tuning =" << enable
460 <<
"with reference key" << reference;
491 double secondsTreble,
492 double secondsRelease)
494 LOGMESSAGE <<
"Envelope: Bass =" << secondsBass <<
" Treble =" 495 << secondsTreble <<
" Release =" << secondsRelease;
496 auto factor = [
this] (
double seconds) {
498 for (
int key=0; key<128; key++)
500 double sedondsSustain = secondsBass +
501 (108.0-key)/88.0*(secondsTreble-secondsBass);
502 mKeyDataVector[key].sustainDampingFactor = factor(sedondsSustain);
503 mKeyDataVector[key].releaseDampingFactor = factor(secondsRelease);
553 key.intensity *= key.sustainDampingFactor;
563 key.intensity *= key.releaseDampingFactor;
588 { QTimer::singleShot(1,
this,&
Tuner::tune);
return; }
628 double avsum = 0, norm = 0;
630 { avsum += key.pitch * key.intensity; norm += key.intensity; }
633 double averagePitch = avsum/norm;
634 if (not mStaticTuningModeEnabled)
637 for (
KeyData &key : mKeyDataVector) key.pitch += dP;
640 if (std::abs(averagePitch) < 1E-6) averagePitch=0;
658 LOGMESSAGE <<
"Resetting global pitch correction";
663 av += e.intensity * e.pitch;
665 for (
KeyData &e : mKeyDataVector)
667 if (e.intensity > 0 and sum > 0) e.pitch -= av/sum;
void setTimerInterval(const int msec, const int firstMsec=0)
Set timer interval for the periodically called worker.
void signalIntervalString(QVariant str)
Signal emitting the tuned interval sizes in a human-readable form.
bool isActive() const
Return true if thread is running and not suspended.
bool start() override final
Public slot: Start the tuner, starting the tuner thread.
Universal base class for threaded modules.
void setIntervalSize(int semitones, double cents)
Public Slot: Set interval size This function allows the user to specify the temperament. To this end one specifies the interval sizes relative to the equal temperament in cents. The complete definition of the temperament requires to set all interval sizes, meaning that this slot has to be called 11 times.
void setModuleName(const QString &name)
Specify the name of the class-specific module.
const double cutoffMemory
double mPitchAutoCorrectionParameter
Pitch correction parameters.
void tuneStatically(KeyDataVector &keys, const QVector< double > pitches, const int referenceKey, const int wolfsIntervalShift)
Tune statically in a given unequal temperament (UT)
const uint tuningIntervalMsec
Update interval tuning.
QVector< double > mIntervalWeights
List of 12 interval weights.
int getVerbosity()
Get verbosity level.
TunerAlgorithm mTunerAlgorithm
The tuning algorithm.
void enableTuning(bool enable)
Public Slot: Enable or disable adaptive tuning.
double mMemoryOffFactor
Update factor for memory decay.
Structure holding the tuner's data of a single key.
void setStaticTuningMode(bool enable, int reference=0)
Slot: Enable or disable static tuning mode.
void signalAveragePitchDrift(double progression)
Signal that periodically transmits the average pitch progression. In the GUI this progression is indi...
bool init() override final
Initialize the Tuner.
void setMemoryLength(double seconds)
Public slot: Set memory parameter.
void resetPitchProgression()
Reset average pitch progression to a given value.
QString mLastMessage
remember last message sent
const uint noteTimeoutSeconds
void setTuningMode(int mode, int wolfsShift)
Public slot: Set tuning mode.
Tuner()
Constructor of the Tuner.
virtual void periodicallyCalledWorker() override final
Periodically called worker function: Update key data.
bool mTuningEnabled
Flag for temporary on/off.
double mDelayParameter
Delay time.
QString f(Eigen::MatrixXd mat)
virtual bool init()
Virtual initialization function (no functionality here)
qint8 mWaitingTimeMsec
Waiting time before tuning event.
void setDelayParameter(double delay)
Public Slot: Set delay parameter.
void signalTension(QVariant mu)
Signal emitting the network tension in the tuned chord, indicating the deviation from just intonation...
int mStaticReferenceKey
Index of static UT reference key.
void handlePitchDrift()
Handle pitch drift.
void setIntervalWeight(int semitones, double weight)
Public Slot: Set interval weight The human perception of various intervals depends on their size...
QVector< double > mIntervalSizes
List of 12 interval sizes.
double mGlobalTargetPitchInCents
Global pitch against 440Hz.
qint64 getNow()
Private function: Get current elapsed tuner runtime in milliseconds.
void signalTuningCorrections(QMap< int, double > corrections)
Signal sending the tuning results to the microtonal sound device in the form of a map keyindex -> cen...
const uint updateIntervalMsec
Update interval envelope.
void receiveMidiEvent(QMidiMessage event)
Public slot: Receive Midi event (Main input of the tuner)
void setFrequencyOfA4(double f=440)
Public slot: Set the desired target frequency of A4 (concert pitch)
QVector< KeyData > mKeyDataVector
Vector containing all key data.
const double memoryOnFactor
virtual bool start()
Start the thread.
int mWolfsIntervalShift
Placement of the wolfs interval.
bool isInterruptionRequested() const
Return true if the thread was requested to interrupt or terminate.
void setPitchProgressionCompensationParameter(double lambda)
Public slot: Set the parameter for pitch progression compensation.
void setThreadName(const QString name)
Set thread name (Linux only)
void emitPitchCorrections()
Emit the pitch corrections This functions checks to what extent the calculated pitches differ from th...
void signalReadyForReceivingParameters()
Signal telling the GUI that the tuner is ready and that the GUI may send the user-defined parameters ...
QElapsedTimer * pElapsedTimer
Time elapsed since construction.
bool mStaticTuningModeEnabled
Flag: Tune statically.
virtual void finallyCalledWorker() override final
Cleanup of the terminating thread.
double tuneDynamically(KeyDataVector &keyData, const QVector< double > intervals, const QVector< double > weights, bool optimizedJI)
Main Tuninig Procedure: Tune dynamically.
const double cutoffIntensity
int mTuningMode
Actual tuning mode.
void setEnvelopeParameters(double secondsSustainBass, double secondsSustainTreble, double secondsRelease)
Set the essential parameters of the envelope.
virtual void initiallyCalledWorker() override final
Initialization of the starting thread.
void tune()
Tune the pitches of the pressed keys (call TunerAlgorithm)