Using the RtMidi library, I'm setting up a loop to play multiple notes and voices. However the examples in RTMidi use a "busy wait" SLEEP to keep the sound sustained until the note ends which makes it impossible to play, say, quarter notes and whole notes together, as the quarter notes have to wait until the whole note has "SLEPT" until they can play.
I've tried using QTimer::singleShot and I've tried offloading the SLEEP with QtConcurrent::run to a different thread, and tried combining them. My working theory is that using either a timer or a thread or a combination can give the notes time to play without causing the other notes to have to wait.
Each QT call has worked as they are supposed to but don't achieve the desired effect of playing one note after another in the case of the quarter notes. They all sound at once. So far I haven't even gotten to the point of multi-voices but that is essential, too.
What is wrong with this code that I can't get the desired effect?
...
foreach (Note* tn, noteList) {
// Note On: 144, 64, 90
message[0] = 144;
message[1] = tn->midiNumber;
message[2] = tn->velocity;
midiout->sendMessage( &message );
// setup params in globals for now
mNum = tn->midiNumber;
int ticks = (tn->ticks * 125);
QTimer::singleShot(ticks ,
this,
SLOT(noteOff
()));
// can't do parameters
/*
SLEEP (tn->ticks * 125); ////////////////////// original example code with SLEEP
// Note Off: 128, 64, 40
message[0] = 128;
message[1] = mNum; // tn->midiNumber;
message[2] = 100; //tn->velocity;
midiout->sendMessage( &message );
*/
}
...
...
foreach (Note* tn, noteList) {
// Note On: 144, 64, 90
message[0] = 144;
message[1] = tn->midiNumber;
message[2] = tn->velocity;
midiout->sendMessage( &message );
// setup params in globals for now
mNum = tn->midiNumber;
int ticks = (tn->ticks * 125);
QTimer::singleShot(ticks , this, SLOT(noteOff())); // can't do parameters
/*
SLEEP (tn->ticks * 125); ////////////////////// original example code with SLEEP
// Note Off: 128, 64, 40
message[0] = 128;
message[1] = mNum; // tn->midiNumber;
message[2] = 100; //tn->velocity;
midiout->sendMessage( &message );
*/
}
...
To copy to clipboard, switch view to plain text mode
void AMidi_Rt::noteOff()
{
// should fire accurately after each QTimer::singleShot timer times out
// this routine stops a specific note after a specific amount of time
message[0] = 128;
message[1] = mNum; // tn->midiNumber;
message[2] = 100; //tn->velocity;
midiout->sendMessage( &message );
}
void AMidi_Rt::noteOff()
{
// should fire accurately after each QTimer::singleShot timer times out
// this routine stops a specific note after a specific amount of time
message[0] = 128;
message[1] = mNum; // tn->midiNumber;
message[2] = 100; //tn->velocity;
midiout->sendMessage( &message );
}
To copy to clipboard, switch view to plain text mode
Bookmarks