1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-04 09:39:42 +02:00

Workaround for GarageBand as synth not respecting notes-off message

This commit is contained in:
Paul Licameli 2017-07-25 14:56:02 -04:00
parent c2229b131f
commit 07ea0ae03f
2 changed files with 35 additions and 1 deletions

View File

@ -3869,7 +3869,21 @@ void AudioIO::OutputEvent()
data2 = (data2 < 1 ? 1 : (data2 > 127 ? 127 : data2));
// since we are going to play this note, we need to get a note_off
mIterator->request_note_off();
} else data2 = 0; // 0 velocity means "note off"
#ifdef AUDIO_IO_GB_MIDI_WORKAROUND
mPendingNotesOff.push_back(std::make_pair(channel, data1));
#endif
}
else {
data2 = 0; // 0 velocity means "note off"
#ifdef AUDIO_IO_GB_MIDI_WORKAROUND
auto end = mPendingNotesOff.end();
auto iter = std::find(
mPendingNotesOff.begin(), end, std::make_pair(channel, data1) );
if (iter != end)
mPendingNotesOff.erase(iter);
#endif
}
command = 0x90; // MIDI NOTE ON (or OFF when velocity == 0)
// Update event
} else if (mNextEvent->is_update()) {
@ -4007,6 +4021,17 @@ PmTimestamp AudioIO::MidiTime()
void AudioIO::AllNotesOff()
{
#ifdef AUDIO_IO_GB_MIDI_WORKAROUND
// Send individual note-off messages for each note-on not yet paired.
for (const auto &pair : mPendingNotesOff) {
Pm_WriteShort(mMidiStream, 0, Pm_Message(
0x90 + pair.first, pair.second, 0));
}
mPendingNotesOff.clear();
// Proceed to do the usual messages too.
#endif
for (int chan = 0; chan < 16; chan++) {
Pm_WriteShort(mMidiStream, 0, Pm_Message(0xB0 + chan, 0x7B, 0));
}

View File

@ -125,6 +125,10 @@ struct AudioIOStartStreamOptions
#endif
};
// This workaround makes pause and stop work when output is to GarageBand,
// which seems not to implement the notes-off message correctly.
#define AUDIO_IO_GB_MIDI_WORKAROUND
class AUDACITY_DLL_API AudioIO final {
public:
@ -543,6 +547,11 @@ private:
std::unique_ptr<Alg_iterator> mIterator;
/// The next event to play (or null)
Alg_event_ptr mNextEvent;
#ifdef AUDIO_IO_GB_MIDI_WORKAROUND
std::vector< std::pair< int, int > > mPendingNotesOff;
#endif
/// Time at which the next event should be output, measured in seconds.
/// Note that this could be a note's time+duration for note offs.
double mNextEventTime;