29 #define STATUS if (mVerbosity >= 4) qDebug() << "SoundGenerator:" 30 #define MESSAGE if (mVerbosity >= 3) qDebug() << "SoundGenerator:" 31 #define WARNING if (mVerbosity >= 2) qWarning()<<"SoundGenerator: WARNING:" 32 #define ERROR if (mVerbosity >= 1) qCritical() << "SoundGenerator: ERROR:" 43 , mIncrements(128,0x1000)
47 , pApplication(nullptr)
48 , mSustainPedeal(false)
49 , mSostenutoPedal(false)
114 QList<Tone> copy =
mTones;
117 for (
Tone &tone : copy)
121 request.
key = tone.mKey;
172 int key = request.
key;
173 double volume1 = 0.6, volume2 = 0;
174 if (pVoice->isVolumeDynamic())
176 if (pVoice->getNumberOfScales()==1) volume1 = pow(request.
intensity,0.75);
184 if (volume1 > 0 and pVoice->getNumberOfScales() > 0)
186 Wave &sample = pVoice->getScale(0).getWave(key);
189 Tone::Type type = (key > pVoice->getHighestDampedKey() ?
190 Tone::Type::SUSTAIN_NONENDING : Tone::Type::SUSTAIN_ENDING);
191 Tone T(key,0,sample,volume1,type);
197 if (volume2 > 0 and pVoice->getNumberOfScales() > 1)
199 Wave &sample = pVoice->getScale(1).getWave(key);
202 Tone::Type type = (key > pVoice->getHighestDampedKey() ?
203 Tone::Type::SUSTAIN_NONENDING : Tone::Type::SUSTAIN_ENDING);
204 Tone T(key,1,sample,volume2,type);
214 int key = request.
key;
218 and tone.mState == State::PLAYING
219 and tone.mType == Tone::Type::SUSTAIN_ENDING)
220 tone.mState = State::RELEASE_REQUESTED;
227 if (tone.mState == State::PLAYING)
228 tone.mState = State::RELEASE_REQUESTED;
238 LOGWARNING <<
"Sound::run: Request undefined";
249 double const releaseVolume = 0.005;
250 double const terminationVolume = 0.0001;
261 case State::OFF_PLAYING:
262 if (tone.mVolume < releaseVolume)
264 LOGSTATUS <<
"Released key" << tone.mKey <<
"below cutoff volume";
265 tone.mState = State::RELEASED;
268 case State::RELEASE_REQUESTED:
278 LOGSTATUS <<
"Retriggering off key" << key;
279 tone.mState = State::RELEASED;
280 int scale = tone.mScaleIndex;
284 quint32 arrayindex = (tone.mTime>>11) & 0x1FFFFEU;
285 double env = tone.getSample().
getEnvelope(arrayindex);
290 switch(tone.mScaleIndex)
294 vol = pow(env/500.0*tone.mVolume,0.5);
295 if (key<30) vol *= pow(key/30.0,3);
300 vol = pow(env/80.0*tone.mVolume,0.35);
308 Tone T(key,scale,sample,vol,Tone::Type::RELEASETONE);
309 T.
mState = State::OFF_PLAYING;
314 case State::RELEASED:
316 if (tone.mVolume < terminationVolume)
318 LOGSTATUS <<
"Terminated key" << tone.mKey <<
"below infinitesimal volume";
319 tone.mState = State::TERMINATED;
327 if (not
mQueue.empty())
return;
332 for (
auto it = mTones.begin(); it != mTones.end(); )
334 if (it->mState == State::TERMINATED)
336 LOGSTATUS <<
"Remove key" << it->mKey <<
"from mTones";
337 it = mTones.erase(it);
338 if (not
mQueue.empty())
return;
350 return not
mQueue.empty();
385 auto f = [factor] (
double cent) {
return static_cast<int>( 0.5 + factor*(1. + 0.00057762265*cent + 1.6682396E-7*cent*cent)); };
387 for (
auto it = corrections.begin(); it!=corrections.end(); it++)
389 if (it.key()<0 or it.key()>127)
continue;
390 setIncrement(it.key(),
f(it.value() - pVoice->getRecordedPitch(it.key())));
396 LOGSTATUS <<
"Sustain pedal =" << pressed;
402 LOGSTATUS <<
"Sostenuto pedal =" << pressed;
408 LOGSTATUS <<
"Sostenuto pedal =" << pressed;
void setTimerInterval(const int msec, const int firstMsec=0)
Set timer interval for the periodically called worker.
bool isActive() const
Return true if thread is running and not suspended.
Wave & getWave(int &key)
Get the wave corresponding to a given key.
Class holding the sampled sound for one key.
virtual void suspend()
Mark the thread as suspended.
Structure containing the data for a play-note request.
Voice - a set of scales, keeping the acoustic data of an instrument.
Adiabatically drive the overall pitch down.
void receiveTuningCorrections(QMap< int, double > corrections)
void registerRequest(Request &request)
Register a single request to play a note in the queue.
void handleRequest(Request &request)
double getEnvelope(int index)
QString f(Eigen::MatrixXd mat)
Class describing a tone that is currently being played.
bool init() override
Virtual initialization function (no functionality here)
int key
Key index according to MIDI norm (0..127)
void init(SoundGenerator *soundgenerator)
Initialization of the sampler.
QVector< quint32 > mIncrements
State mState
Phase in which the tone is playing.
void setIncrement(int key, quint32 increment)
void registerAllNotesOff()
void timeout() override final
Private thread worker function.
Application * pApplication
void setSustainPedal(bool pressed)
virtual bool exit()
Virtual exit function (no functionality here)
void manageToneDynamics()
void setSoftPedal(bool pressed)
void suspend() override final
Mark the thread as suspended.
bool isInterruptionRequested() const
Return true if the thread was requested to interrupt or terminate.
void forceImmediateProcessing()
Play a note with parameters listed below.
quint32 getIncrement(int key)
Adiabatically drive the overall pitch up.
void setSostenutoPedal(bool pressed)