mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-04 17:49:45 +02:00
Workaround for GarageBand as synth not respecting notes-off message
This commit is contained in:
parent
c2229b131f
commit
07ea0ae03f
@ -3869,7 +3869,21 @@ void AudioIO::OutputEvent()
|
|||||||
data2 = (data2 < 1 ? 1 : (data2 > 127 ? 127 : data2));
|
data2 = (data2 < 1 ? 1 : (data2 > 127 ? 127 : data2));
|
||||||
// since we are going to play this note, we need to get a note_off
|
// since we are going to play this note, we need to get a note_off
|
||||||
mIterator->request_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)
|
command = 0x90; // MIDI NOTE ON (or OFF when velocity == 0)
|
||||||
// Update event
|
// Update event
|
||||||
} else if (mNextEvent->is_update()) {
|
} else if (mNextEvent->is_update()) {
|
||||||
@ -4007,6 +4021,17 @@ PmTimestamp AudioIO::MidiTime()
|
|||||||
|
|
||||||
void AudioIO::AllNotesOff()
|
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++) {
|
for (int chan = 0; chan < 16; chan++) {
|
||||||
Pm_WriteShort(mMidiStream, 0, Pm_Message(0xB0 + chan, 0x7B, 0));
|
Pm_WriteShort(mMidiStream, 0, Pm_Message(0xB0 + chan, 0x7B, 0));
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,10 @@ struct AudioIOStartStreamOptions
|
|||||||
#endif
|
#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 {
|
class AUDACITY_DLL_API AudioIO final {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -543,6 +547,11 @@ private:
|
|||||||
std::unique_ptr<Alg_iterator> mIterator;
|
std::unique_ptr<Alg_iterator> mIterator;
|
||||||
/// The next event to play (or null)
|
/// The next event to play (or null)
|
||||||
Alg_event_ptr mNextEvent;
|
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.
|
/// 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.
|
/// Note that this could be a note's time+duration for note offs.
|
||||||
double mNextEventTime;
|
double mNextEventTime;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user