@@ -966,7 +966,7 @@ public: | |||
CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | |||
uint8_t data1, data2, data3; | |||
data1 = static_cast<uint8_t>((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
data1 = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
data2 = note.note; | |||
data3 = note.velo; | |||
@@ -990,7 +990,7 @@ public: | |||
bool allNotesOffSent = false; | |||
for (uint32_t i=0, numEvents = pData->event.portIn->getEventCount(); i < numEvents; ++i) | |||
for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) | |||
{ | |||
const EngineEvent& event(pData->event.portIn->getEvent(i)); | |||
@@ -1124,11 +1124,9 @@ public: | |||
if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE) | |||
continue; | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
uint8_t channel = event.channel; | |||
const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data); | |||
if (MIDI_IS_STATUS_NOTE_ON(status) && midiEvent.data[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData)); | |||
if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | |||
continue; | |||
@@ -1139,20 +1137,26 @@ public: | |||
if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | |||
continue; | |||
// Fix bad note-off | |||
if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
fShmRtControl.writeOpcode(kPluginBridgeRtMidiEvent); | |||
fShmRtControl.writeUInt(event.time); | |||
fShmRtControl.writeByte(midiEvent.port); | |||
fShmRtControl.writeByte(midiEvent.size); | |||
for (uint8_t j=0; j < midiEvent.size; ++j) | |||
fShmRtControl.writeByte(midiEvent.data[j]); | |||
fShmRtControl.writeByte(uint8_t(midiData[0] | (event.channel & MIDI_CHANNEL_BIT))); | |||
for (uint8_t j=1; j < midiEvent.size; ++j) | |||
fShmRtControl.writeByte(midiData[j]); | |||
fShmRtControl.commitWrite(); | |||
if (status == MIDI_STATUS_NOTE_ON) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiData[1], midiData[2]); | |||
else if (status == MIDI_STATUS_NOTE_OFF) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0f); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiData[1], 0.0f); | |||
} break; | |||
} | |||
} | |||
@@ -1092,6 +1092,7 @@ public: | |||
} | |||
ulong midiEventCount = 0; | |||
carla_zeroStruct<snd_seq_event_t>(fMidiEvents, kPluginMaxMidiEvents); | |||
// -------------------------------------------------------------------------------------------------------- | |||
// Check if needs reset | |||
@@ -1101,7 +1102,6 @@ public: | |||
if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) | |||
{ | |||
midiEventCount = MAX_MIDI_CHANNELS*2; | |||
carla_zeroStruct<snd_seq_event_t>(fMidiEvents, midiEventCount); | |||
for (uchar i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i) | |||
{ | |||
@@ -1117,7 +1117,6 @@ public: | |||
else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) | |||
{ | |||
midiEventCount = MAX_MIDI_NOTE; | |||
carla_zeroStruct<snd_seq_event_t>(fMidiEvents, midiEventCount); | |||
for (uchar i=0; i < MAX_MIDI_NOTE; ++i) | |||
{ | |||
@@ -1156,13 +1155,12 @@ public: | |||
CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | |||
snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]); | |||
carla_zeroStruct<snd_seq_event_t>(midiEvent); | |||
snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); | |||
midiEvent.type = (note.velo > 0) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF; | |||
midiEvent.data.note.channel = static_cast<uchar>(note.channel); | |||
midiEvent.data.note.note = note.note; | |||
midiEvent.data.note.velocity = note.velo; | |||
seqEvent.type = (note.velo > 0) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF; | |||
seqEvent.data.note.channel = static_cast<uchar>(note.channel); | |||
seqEvent.data.note.note = note.note; | |||
seqEvent.data.note.velocity = note.velo; | |||
} | |||
pData->extNotes.mutex.unlock(); | |||
@@ -1177,7 +1175,6 @@ public: | |||
#endif | |||
const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | |||
uint32_t numEvents = pData->event.portIn->getEventCount(); | |||
uint32_t startTime = 0; | |||
uint32_t timeOffset = 0; | |||
uint32_t nextBankId; | |||
@@ -1187,7 +1184,7 @@ public: | |||
else | |||
nextBankId = 0; | |||
for (uint32_t i=0; i < numEvents; ++i) | |||
for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) | |||
{ | |||
const EngineEvent& event(pData->event.portIn->getEvent(i)); | |||
@@ -1319,15 +1316,14 @@ public: | |||
if (midiEventCount >= kPluginMaxMidiEvents) | |||
continue; | |||
snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]); | |||
carla_zeroStruct<snd_seq_event_t>(midiEvent); | |||
snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); | |||
midiEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
seqEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
midiEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
midiEvent.data.control.channel = event.channel; | |||
midiEvent.data.control.param = ctrlEvent.param; | |||
midiEvent.data.control.value = int8_t(ctrlEvent.value*127.0f); | |||
seqEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
seqEvent.data.control.channel = event.channel; | |||
seqEvent.data.control.param = ctrlEvent.param; | |||
seqEvent.data.control.value = int8_t(ctrlEvent.value*127.0f); | |||
} | |||
break; | |||
} // case kEngineControlEventTypeParameter | |||
@@ -1361,14 +1357,13 @@ public: | |||
if (midiEventCount >= kPluginMaxMidiEvents) | |||
continue; | |||
snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]); | |||
carla_zeroStruct<snd_seq_event_t>(midiEvent); | |||
snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); | |||
midiEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
seqEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
midiEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
midiEvent.data.control.channel = event.channel; | |||
midiEvent.data.control.param = MIDI_CONTROL_ALL_SOUND_OFF; | |||
seqEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
seqEvent.data.control.channel = event.channel; | |||
seqEvent.data.control.param = MIDI_CONTROL_ALL_SOUND_OFF; | |||
} | |||
break; | |||
@@ -1386,16 +1381,13 @@ public: | |||
if (midiEventCount >= kPluginMaxMidiEvents) | |||
continue; | |||
snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]); | |||
carla_zeroStruct<snd_seq_event_t>(midiEvent); | |||
snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); | |||
midiEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
seqEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
midiEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
midiEvent.data.control.channel = event.channel; | |||
midiEvent.data.control.param = MIDI_CONTROL_ALL_NOTES_OFF; | |||
midiEventCount += 1; | |||
seqEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
seqEvent.data.control.channel = event.channel; | |||
seqEvent.data.control.param = MIDI_CONTROL_ALL_NOTES_OFF; | |||
} | |||
break; | |||
} // switch (ctrlEvent.type) | |||
@@ -1406,103 +1398,101 @@ public: | |||
if (midiEventCount >= kPluginMaxMidiEvents) | |||
continue; | |||
const EngineMidiEvent& engineEvent(event.midi); | |||
const EngineMidiEvent& midiEvent(event.midi); | |||
if (midiEvent.size > EngineMidiEvent::kDataSize) | |||
continue; | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(engineEvent.data)); | |||
uint8_t channel = event.channel; | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
// Fix bad note-off (per DSSI spec) | |||
if (MIDI_IS_STATUS_NOTE_ON(status) && engineEvent.data[2] == 0) | |||
if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount]); | |||
carla_zeroStruct<snd_seq_event_t>(midiEvent); | |||
snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]); | |||
midiEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
seqEvent.time.tick = isSampleAccurate ? startTime : event.time; | |||
switch (status) | |||
{ | |||
case MIDI_STATUS_NOTE_OFF: { | |||
const uint8_t note = engineEvent.data[1]; | |||
const uint8_t note = midiEvent.data[1]; | |||
midiEvent.type = SND_SEQ_EVENT_NOTEOFF; | |||
midiEvent.data.note.channel = channel; | |||
midiEvent.data.note.note = note; | |||
seqEvent.type = SND_SEQ_EVENT_NOTEOFF; | |||
seqEvent.data.note.channel = event.channel; | |||
seqEvent.data.note.note = note; | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, note, 0.0f); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, note, 0.0f); | |||
break; | |||
} | |||
case MIDI_STATUS_NOTE_ON: { | |||
const uint8_t note = engineEvent.data[1]; | |||
const uint8_t velo = engineEvent.data[2]; | |||
const uint8_t note = midiEvent.data[1]; | |||
const uint8_t velo = midiEvent.data[2]; | |||
midiEvent.type = SND_SEQ_EVENT_NOTEON; | |||
midiEvent.data.note.channel = channel; | |||
midiEvent.data.note.note = note; | |||
midiEvent.data.note.velocity = velo; | |||
seqEvent.type = SND_SEQ_EVENT_NOTEON; | |||
seqEvent.data.note.channel = event.channel; | |||
seqEvent.data.note.note = note; | |||
seqEvent.data.note.velocity = velo; | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, note, velo); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, note, velo); | |||
break; | |||
} | |||
case MIDI_STATUS_POLYPHONIC_AFTERTOUCH: | |||
if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) | |||
{ | |||
const uint8_t note = engineEvent.data[1]; | |||
const uint8_t pressure = engineEvent.data[2]; | |||
const uint8_t note = midiEvent.data[1]; | |||
const uint8_t pressure = midiEvent.data[2]; | |||
midiEvent.type = SND_SEQ_EVENT_KEYPRESS; | |||
midiEvent.data.note.channel = channel; | |||
midiEvent.data.note.note = note; | |||
midiEvent.data.note.velocity = pressure; | |||
seqEvent.type = SND_SEQ_EVENT_KEYPRESS; | |||
seqEvent.data.note.channel = event.channel; | |||
seqEvent.data.note.note = note; | |||
seqEvent.data.note.velocity = pressure; | |||
} | |||
break; | |||
case MIDI_STATUS_CONTROL_CHANGE: | |||
if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) | |||
{ | |||
const uint8_t control = engineEvent.data[1]; | |||
const uint8_t value = engineEvent.data[2]; | |||
const uint8_t control = midiEvent.data[1]; | |||
const uint8_t value = midiEvent.data[2]; | |||
midiEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
midiEvent.data.control.channel = channel; | |||
midiEvent.data.control.param = control; | |||
midiEvent.data.control.value = value; | |||
seqEvent.type = SND_SEQ_EVENT_CONTROLLER; | |||
seqEvent.data.control.channel = event.channel; | |||
seqEvent.data.control.param = control; | |||
seqEvent.data.control.value = value; | |||
} | |||
break; | |||
case MIDI_STATUS_CHANNEL_PRESSURE: | |||
if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) | |||
{ | |||
const uint8_t pressure = engineEvent.data[1]; | |||
const uint8_t pressure = midiEvent.data[1]; | |||
midiEvent.type = SND_SEQ_EVENT_CHANPRESS; | |||
midiEvent.data.control.channel = channel; | |||
midiEvent.data.control.value = pressure; | |||
seqEvent.type = SND_SEQ_EVENT_CHANPRESS; | |||
seqEvent.data.control.channel = event.channel; | |||
seqEvent.data.control.value = pressure; | |||
} | |||
break; | |||
case MIDI_STATUS_PITCH_WHEEL_CONTROL: | |||
if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) | |||
{ | |||
const uint8_t lsb = engineEvent.data[1]; | |||
const uint8_t msb = engineEvent.data[2]; | |||
const uint8_t lsb = midiEvent.data[1]; | |||
const uint8_t msb = midiEvent.data[2]; | |||
midiEvent.type = SND_SEQ_EVENT_PITCHBEND; | |||
midiEvent.data.control.channel = channel; | |||
midiEvent.data.control.value = ((msb << 7) | lsb) - 8192; | |||
seqEvent.type = SND_SEQ_EVENT_PITCHBEND; | |||
seqEvent.data.control.channel = event.channel; | |||
seqEvent.data.control.value = ((msb << 7) | lsb) - 8192; | |||
} | |||
break; | |||
default: | |||
continue; | |||
--midiEventCount; | |||
break; | |||
} // switch (status) | |||
midiEventCount += 1; | |||
break; | |||
} // case kEngineEventTypeMidi | |||
} break; | |||
} // switch (event.type) | |||
} | |||
@@ -1946,7 +1936,7 @@ public: | |||
#if 0 | |||
uint8_t midiData[4]; | |||
midiData[0] = 0; | |||
midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_ON + channel); | |||
midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||
midiData[2] = note; | |||
midiData[3] = velo; | |||
@@ -1965,7 +1955,7 @@ public: | |||
#if 0 | |||
uint8_t midiData[4]; | |||
midiData[0] = 0; | |||
midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_OFF + channel); | |||
midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||
midiData[2] = note; | |||
midiData[3] = 0; | |||
@@ -1074,7 +1074,6 @@ public: | |||
#ifndef BUILD_BRIDGE | |||
bool allNotesOffSent = false; | |||
#endif | |||
uint32_t time, nEvents = pData->event.portIn->getEventCount(); | |||
uint32_t timeOffset = 0; | |||
uint32_t nextBankIds[MAX_MIDI_CHANNELS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0 }; | |||
@@ -1082,20 +1081,20 @@ public: | |||
if (pData->midiprog.current >= 0 && pData->midiprog.count > 0 && pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) | |||
nextBankIds[pData->ctrlChannel] = pData->midiprog.data[pData->midiprog.current].bank; | |||
for (uint32_t i=0; i < nEvents; ++i) | |||
for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) | |||
{ | |||
const EngineEvent& event(pData->event.portIn->getEvent(i)); | |||
time = event.time; | |||
if (event.time >= frames) | |||
continue; | |||
CARLA_SAFE_ASSERT_CONTINUE(time < frames); | |||
CARLA_SAFE_ASSERT_BREAK(time >= timeOffset); | |||
CARLA_ASSERT_INT2(event.time >= timeOffset, event.time, timeOffset); | |||
if (time > timeOffset) | |||
if (event.time > timeOffset) | |||
{ | |||
if (processSingle(audioOut, time - timeOffset, timeOffset)) | |||
if (processSingle(audioOut, event.time - timeOffset, timeOffset)) | |||
{ | |||
timeOffset = time; | |||
timeOffset = event.time; | |||
if (pData->midiprog.current >= 0 && pData->midiprog.count > 0 && pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) | |||
nextBankIds[pData->ctrlChannel] = pData->midiprog.data[pData->midiprog.current].bank; | |||
@@ -1215,6 +1214,7 @@ public: | |||
const uint32_t bankId(nextBankIds[event.channel]); | |||
const uint32_t progId(ctrlEvent.param); | |||
// TODO int32_t midiprog.find(bank, prog) | |||
for (uint32_t k=0; k < pData->midiprog.count; ++k) | |||
{ | |||
if (pData->midiprog.data[k].bank == bankId && pData->midiprog.data[k].program == progId) | |||
@@ -1265,66 +1265,85 @@ public: | |||
break; | |||
} | |||
case kEngineEventTypeMidi: | |||
{ | |||
case kEngineEventTypeMidi: { | |||
const EngineMidiEvent& midiEvent(event.midi); | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
uint8_t channel = event.channel; | |||
if (midiEvent.size > EngineMidiEvent::kDataSize) | |||
continue; | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
// Fix bad note-off | |||
if (MIDI_IS_STATUS_NOTE_ON(status) && midiEvent.data[2] == 0) | |||
if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
if (MIDI_IS_STATUS_NOTE_OFF(status)) | |||
switch (status) | |||
{ | |||
case MIDI_STATUS_NOTE_OFF: { | |||
const uint8_t note = midiEvent.data[1]; | |||
fluid_synth_noteoff(fSynth, channel, note); | |||
fluid_synth_noteoff(fSynth, event.channel, note); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, note, 0.0f); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, note, 0.0f); | |||
break; | |||
} | |||
else if (MIDI_IS_STATUS_NOTE_ON(status)) | |||
{ | |||
case MIDI_STATUS_NOTE_ON: { | |||
const uint8_t note = midiEvent.data[1]; | |||
const uint8_t velo = midiEvent.data[2]; | |||
fluid_synth_noteon(fSynth, channel, note, velo); | |||
fluid_synth_noteon(fSynth, event.channel, note, velo); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, note, velo); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, note, velo); | |||
break; | |||
} | |||
else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) != 0) | |||
{ | |||
//const uint8_t note = midiEvent.data[1]; | |||
//const uint8_t pressure = midiEvent.data[2]; | |||
// TODO, not in fluidsynth API | |||
} | |||
else if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0) | |||
{ | |||
const uint8_t control = midiEvent.data[1]; | |||
const uint8_t value = midiEvent.data[2]; | |||
case MIDI_STATUS_POLYPHONIC_AFTERTOUCH: | |||
if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) | |||
{ | |||
//const uint8_t note = midiEvent.data[1]; | |||
//const uint8_t pressure = midiEvent.data[2]; | |||
fluid_synth_cc(fSynth, channel, control, value); | |||
} | |||
else if (MIDI_IS_STATUS_CHANNEL_PRESSURE(status) && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) != 0) | |||
{ | |||
const uint8_t pressure = midiEvent.data[1]; | |||
// not in fluidsynth API | |||
} | |||
break; | |||
fluid_synth_channel_pressure(fSynth, channel, pressure);; | |||
} | |||
else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) != 0) | |||
{ | |||
const uint8_t lsb = midiEvent.data[1]; | |||
const uint8_t msb = midiEvent.data[2]; | |||
const int value = ((msb << 7) | lsb); | |||
case MIDI_STATUS_CONTROL_CHANGE: | |||
if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) | |||
{ | |||
const uint8_t control = midiEvent.data[1]; | |||
const uint8_t value = midiEvent.data[2]; | |||
fluid_synth_pitch_bend(fSynth, channel, value); | |||
} | |||
fluid_synth_cc(fSynth, event.channel, control, value); | |||
} | |||
break; | |||
break; | |||
} | |||
} | |||
case MIDI_STATUS_CHANNEL_PRESSURE: | |||
if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) | |||
{ | |||
const uint8_t pressure = midiEvent.data[1]; | |||
fluid_synth_channel_pressure(fSynth, event.channel, pressure);; | |||
} | |||
break; | |||
case MIDI_STATUS_PITCH_WHEEL_CONTROL: | |||
if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) | |||
{ | |||
const uint8_t lsb = midiEvent.data[1]; | |||
const uint8_t msb = midiEvent.data[2]; | |||
const int value = ((msb << 7) | lsb); | |||
fluid_synth_pitch_bend(fSynth, event.channel, value); | |||
} | |||
break; | |||
default: | |||
continue; | |||
break; | |||
} // switch (status) | |||
} break; | |||
} // switch (event.type) | |||
} | |||
pData->postRtEvents.trySplice(); | |||
@@ -609,7 +609,7 @@ public: | |||
CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | |||
uint8_t midiEvent[3]; | |||
midiEvent[0] = static_cast<uint8_t>((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
midiEvent[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
midiEvent[1] = note.note; | |||
midiEvent[2] = note.velo; | |||
@@ -627,7 +627,6 @@ public: | |||
#ifndef BUILD_BRIDGE | |||
bool allNotesOffSent = false; | |||
#endif | |||
uint32_t numEvents = pData->event.portIn->getEventCount(); | |||
uint32_t nextBankId; | |||
if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | |||
@@ -635,7 +634,7 @@ public: | |||
else | |||
nextBankId = 0; | |||
for (uint32_t i=0; i < numEvents; ++i) | |||
for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) | |||
{ | |||
const EngineEvent& event(pData->event.portIn->getEvent(i)); | |||
@@ -746,8 +745,8 @@ public: | |||
if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F) | |||
{ | |||
uint8_t midiData[3]; | |||
midiData[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + i); | |||
midiData[1] = static_cast<uint8_t>(ctrlEvent.param); | |||
midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
midiData[1] = uint8_t(ctrlEvent.param); | |||
midiData[2] = uint8_t(ctrlEvent.value*127.0f); | |||
fMidiBuffer.addEvent(midiData, 3, static_cast<int>(event.time)); | |||
@@ -782,7 +781,7 @@ public: | |||
if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) | |||
{ | |||
uint8_t midiData[3]; | |||
midiData[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + i); | |||
midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
midiData[2] = 0; | |||
@@ -802,7 +801,7 @@ public: | |||
#endif | |||
uint8_t midiData[3]; | |||
midiData[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + i); | |||
midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
midiData[2] = 0; | |||
@@ -813,16 +812,12 @@ public: | |||
break; | |||
} // case kEngineEventTypeControl | |||
case kEngineEventTypeMidi: | |||
{ | |||
case kEngineEventTypeMidi: { | |||
const EngineMidiEvent& midiEvent(event.midi); | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
uint8_t channel = event.channel; | |||
const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data); | |||
// Fix bad note-off | |||
if (MIDI_IS_STATUS_NOTE_ON(status) && midiEvent.data[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData)); | |||
if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | |||
continue; | |||
@@ -833,15 +828,22 @@ public: | |||
if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | |||
continue; | |||
fMidiBuffer.addEvent(midiEvent.data, midiEvent.size, static_cast<int>(event.time)); | |||
// Fix bad note-off | |||
if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
// put back channel in data | |||
uint8_t midiData2[midiEvent.size]; | |||
midiData2[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT)); | |||
std::memcpy(midiData2+1, midiData+1, static_cast<std::size_t>(midiEvent.size-1)); | |||
fMidiBuffer.addEvent(midiData2, midiEvent.size, static_cast<int>(event.time)); | |||
if (status == MIDI_STATUS_NOTE_ON) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiData[1], midiData[2]); | |||
else if (status == MIDI_STATUS_NOTE_OFF) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0f); | |||
break; | |||
} // case kEngineEventTypeMidi | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiData[1], 0.0f); | |||
} break; | |||
} // switch (event.type) | |||
} | |||
@@ -799,11 +799,10 @@ public: | |||
#endif | |||
bool sampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | |||
uint32_t nEvents = pData->event.portIn->getEventCount(); | |||
uint32_t startTime = 0; | |||
uint32_t timeOffset = 0; | |||
for (uint32_t i=0; i < nEvents; ++i) | |||
for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) | |||
{ | |||
const EngineEvent& event(pData->event.portIn->getEvent(i)); | |||
@@ -982,42 +981,38 @@ public: | |||
break; | |||
} | |||
case kEngineEventTypeMidi: | |||
{ | |||
case kEngineEventTypeMidi: { | |||
const EngineMidiEvent& midiEvent(event.midi); | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
uint8_t channel = event.channel; | |||
const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data); | |||
// Fix bad note-off | |||
if (MIDI_IS_STATUS_NOTE_ON(status) && midiEvent.data[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData)); | |||
if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) | |||
if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | |||
continue; | |||
if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) | |||
if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) | |||
continue; | |||
if (MIDI_IS_STATUS_CHANNEL_PRESSURE(status) && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | |||
if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) | |||
continue; | |||
if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | |||
if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | |||
continue; | |||
// put back channel in data | |||
uint8_t data[EngineMidiEvent::kDataSize]; | |||
std::memcpy(data, event.midi.data, EngineMidiEvent::kDataSize); | |||
// Fix bad note-off | |||
if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
if (status < 0xF0 && channel < MAX_MIDI_CHANNELS) | |||
data[0] = uint8_t(data[0] + channel); | |||
// put back channel in data | |||
uint8_t midiData2[midiEvent.size]; | |||
midiData2[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT)); | |||
std::memcpy(midiData2+1, midiData+1, static_cast<std::size_t>(midiEvent.size-1)); | |||
fMidiInputPort->DispatchRaw(data, static_cast<int32_t>(sampleAccurate ? startTime : event.time)); | |||
fMidiInputPort->DispatchRaw(midiData2, static_cast<int32_t>(sampleAccurate ? startTime : event.time)); | |||
if (status == MIDI_STATUS_NOTE_ON) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, data[1], data[2]); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiData[1], midiData[2]); | |||
else if (status == MIDI_STATUS_NOTE_OFF) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel,data[1], 0.0f); | |||
break; | |||
} | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiData[1], 0.0f); | |||
} break; | |||
} | |||
} | |||
@@ -2517,7 +2517,7 @@ public: | |||
if (pData->needsReset) | |||
{ | |||
uint8_t midiData[3] = { 0 }; | |||
uint8_t midiData[3] = { 0, 0, 0 }; | |||
if (fEventsIn.ctrl != nullptr && (fEventsIn.ctrl->type & CARLA_EVENT_TYPE_MIDI) != 0) | |||
{ | |||
@@ -2527,7 +2527,7 @@ public: | |||
{ | |||
for (uint8_t i=0; i < MAX_MIDI_CHANNELS; ++i) | |||
{ | |||
midiData[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + i); | |||
midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT)); | |||
midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) | |||
@@ -2539,7 +2539,7 @@ public: | |||
else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) | |||
lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiData); | |||
midiData[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + i); | |||
midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT)); | |||
midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) | |||
@@ -2556,7 +2556,7 @@ public: | |||
{ | |||
for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k) | |||
{ | |||
midiData[0] = static_cast<uint8_t>(MIDI_STATUS_NOTE_OFF + pData->ctrlChannel); | |||
midiData[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT)); | |||
midiData[1] = k; | |||
if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) | |||
@@ -2796,7 +2796,7 @@ public: | |||
CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | |||
uint8_t midiEvent[3]; | |||
midiEvent[0] = static_cast<uint8_t>((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
midiEvent[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
midiEvent[1] = note.note; | |||
midiEvent[2] = note.velo; | |||
@@ -2825,7 +2825,6 @@ public: | |||
#endif | |||
bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | |||
uint32_t numEvents = (fEventsIn.ctrl->port != nullptr) ? fEventsIn.ctrl->port->getEventCount() : 0; | |||
uint32_t startTime = 0; | |||
uint32_t timeOffset = 0; | |||
uint32_t nextBankId; | |||
@@ -2835,6 +2834,8 @@ public: | |||
else | |||
nextBankId = 0; | |||
const uint32_t numEvents = (fEventsIn.ctrl->port != nullptr) ? fEventsIn.ctrl->port->getEventCount() : 0; | |||
for (uint32_t i=0; i < numEvents; ++i) | |||
{ | |||
const EngineEvent& event(fEventsIn.ctrl->port->getEvent(i)); | |||
@@ -2984,8 +2985,8 @@ public: | |||
if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F) | |||
{ | |||
uint8_t midiData[3]; | |||
midiData[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + i); | |||
midiData[1] = static_cast<uint8_t>(ctrlEvent.param); | |||
midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
midiData[1] = uint8_t(ctrlEvent.param); | |||
midiData[2] = uint8_t(ctrlEvent.value*127.0f); | |||
const uint32_t mtime(isSampleAccurate ? startTime : event.time); | |||
@@ -3031,7 +3032,7 @@ public: | |||
const uint32_t mtime(isSampleAccurate ? startTime : event.time); | |||
uint8_t midiData[3]; | |||
midiData[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + i); | |||
midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
midiData[2] = 0; | |||
@@ -3060,7 +3061,7 @@ public: | |||
const uint32_t mtime(isSampleAccurate ? startTime : event.time); | |||
uint8_t midiData[3]; | |||
midiData[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + i); | |||
midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
midiData[2] = 0; | |||
@@ -3078,17 +3079,12 @@ public: | |||
break; | |||
} // case kEngineEventTypeControl | |||
case kEngineEventTypeMidi: | |||
{ | |||
case kEngineEventTypeMidi: { | |||
const EngineMidiEvent& midiEvent(event.midi); | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
uint8_t channel = event.channel; | |||
uint32_t mtime = isSampleAccurate ? startTime : event.time; | |||
const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data); | |||
// Fix bad note-off (per LV2 spec) | |||
if (MIDI_IS_STATUS_NOTE_ON(status) && midiEvent.data[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData)); | |||
if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | |||
continue; | |||
@@ -3099,24 +3095,32 @@ public: | |||
if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | |||
continue; | |||
const uint32_t j = fEventsIn.ctrlIndex; | |||
// Fix bad note-off (per LV2 spec) | |||
if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
const uint32_t j = fEventsIn.ctrlIndex; | |||
const uint32_t mtime = isSampleAccurate ? startTime : event.time; | |||
// put back channel in data | |||
uint8_t midiData2[midiEvent.size]; | |||
midiData2[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT)); | |||
std::memcpy(midiData2+1, midiData+1, static_cast<std::size_t>(midiEvent.size-1)); | |||
if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) | |||
lv2_atom_buffer_write(&evInAtomIters[j], mtime, 0, CARLA_URI_MAP_ID_MIDI_EVENT, midiEvent.size, midiEvent.data); | |||
lv2_atom_buffer_write(&evInAtomIters[j], mtime, 0, CARLA_URI_MAP_ID_MIDI_EVENT, midiEvent.size, midiData2); | |||
else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT) | |||
lv2_event_write(&evInEventIters[j], mtime, 0, CARLA_URI_MAP_ID_MIDI_EVENT, midiEvent.size, midiEvent.data); | |||
lv2_event_write(&evInEventIters[j], mtime, 0, CARLA_URI_MAP_ID_MIDI_EVENT, midiEvent.size, midiData2); | |||
else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) | |||
lv2midi_put_event(&evInMidiStates[j], mtime, midiEvent.size, midiEvent.data); | |||
lv2midi_put_event(&evInMidiStates[j], mtime, midiEvent.size, midiData2); | |||
if (status == MIDI_STATUS_NOTE_ON) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiData[1], midiData[2]); | |||
else if (status == MIDI_STATUS_NOTE_OFF) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0f); | |||
break; | |||
} // case kEngineEventTypeMidi | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiData[1], 0.0f); | |||
} break; | |||
} // switch (event.type) | |||
} | |||
@@ -3773,7 +3777,7 @@ public: | |||
if (pData->osc.data.target != nullptr) | |||
{ | |||
uint8_t midiData[4] = { 0, 0, 0, 0 }; | |||
midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_ON + channel); | |||
midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||
midiData[2] = note; | |||
midiData[3] = velo; | |||
osc_send_midi(pData->osc.data, midiData); | |||
@@ -3787,7 +3791,7 @@ public: | |||
midiEv.event.time.frames = 0; | |||
midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT; | |||
midiEv.event.body.size = 3; | |||
midiEv.data[0] = static_cast<uint8_t>(MIDI_STATUS_NOTE_ON + channel); | |||
midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||
midiEv.data[1] = note; | |||
midiEv.data[2] = velo; | |||
@@ -3807,7 +3811,7 @@ public: | |||
if (pData->osc.data.target != nullptr) | |||
{ | |||
uint8_t midiData[4] = { 0, 0, 0, 0 }; | |||
midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_OFF + channel); | |||
midiData[1] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT)); | |||
midiData[2] = note; | |||
osc_send_midi(pData->osc.data, midiData); | |||
} | |||
@@ -3820,7 +3824,7 @@ public: | |||
midiEv.event.time.frames = 0; | |||
midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT; | |||
midiEv.event.body.size = 3; | |||
midiEv.data[0] = static_cast<uint8_t>(MIDI_STATUS_NOTE_OFF + channel); | |||
midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT)); | |||
midiEv.data[1] = note; | |||
midiEv.data[2] = 0; | |||
@@ -1302,32 +1302,32 @@ public: | |||
{ | |||
if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) | |||
{ | |||
fMidiEventCount = MAX_MIDI_CHANNELS*2; | |||
for (uint8_t k=0, i=MAX_MIDI_CHANNELS; k < MAX_MIDI_CHANNELS; ++k) | |||
{ | |||
fMidiEvents[k].data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + k); | |||
fMidiEvents[k].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT)); | |||
fMidiEvents[k].data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
fMidiEvents[k].data[2] = 0; | |||
fMidiEvents[k].size = 3; | |||
fMidiEvents[k+i].data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + k); | |||
fMidiEvents[k+i].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT)); | |||
fMidiEvents[k+i].data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
fMidiEvents[k+i].data[2] = 0; | |||
fMidiEvents[k+i].size = 3; | |||
} | |||
fMidiEventCount = MAX_MIDI_CHANNELS*2; | |||
} | |||
else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) | |||
{ | |||
fMidiEventCount = MAX_MIDI_NOTE; | |||
for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k) | |||
{ | |||
fMidiEvents[k].data[0] = static_cast<uint8_t>(MIDI_STATUS_NOTE_OFF + pData->ctrlChannel); | |||
fMidiEvents[k].data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT)); | |||
fMidiEvents[k].data[1] = k; | |||
fMidiEvents[k].data[2] = 0; | |||
fMidiEvents[k].size = 3; | |||
} | |||
fMidiEventCount = MAX_MIDI_NOTE; | |||
} | |||
pData->needsReset = false; | |||
@@ -1372,19 +1372,18 @@ public: | |||
{ | |||
ExternalMidiNote note = { 0, 0, 0 }; | |||
//for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin(); it.valid(); it.next()) | |||
while (fMidiEventCount < kPluginMaxMidiEvents*2 && ! pData->extNotes.data.isEmpty()) | |||
for (; fMidiEventCount < kPluginMaxMidiEvents*2 && ! pData->extNotes.data.isEmpty();) | |||
{ | |||
note = pData->extNotes.data.getFirst(note, true); | |||
CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | |||
fMidiEvents[fMidiEventCount].data[0] = static_cast<uint8_t>((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
fMidiEvents[fMidiEventCount].data[1] = note.note; | |||
fMidiEvents[fMidiEventCount].data[2] = note.velo; | |||
fMidiEvents[fMidiEventCount].size = 3; | |||
NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]); | |||
fMidiEventCount += 1; | |||
nativeEvent.data[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = note.note; | |||
nativeEvent.data[2] = note.velo; | |||
nativeEvent.size = 3; | |||
} | |||
pData->extNotes.mutex.unlock(); | |||
@@ -1399,31 +1398,30 @@ public: | |||
#endif | |||
bool sampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | |||
uint32_t time, nEvents = pData->event.portIn->getEventCount(); | |||
uint32_t startTime = 0; | |||
uint32_t timeOffset = 0; | |||
uint32_t nextBankId = 0; | |||
uint32_t nextBankId; | |||
if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | |||
nextBankId = pData->midiprog.data[pData->midiprog.current].bank; | |||
else | |||
nextBankId = 0; | |||
for (uint32_t i=0; i < nEvents; ++i) | |||
for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i) | |||
{ | |||
const EngineEvent& event(pData->event.portIn->getEvent(i)); | |||
time = event.time; | |||
if (time >= frames) | |||
if (event.time >= frames) | |||
continue; | |||
CARLA_ASSERT_INT2(time >= timeOffset, time, timeOffset); | |||
CARLA_ASSERT_INT2(event.time >= timeOffset, event.time, timeOffset); | |||
if (time > timeOffset && sampleAccurate) | |||
if (event.time > timeOffset && sampleAccurate) | |||
{ | |||
if (processSingle(audioIn, audioOut, cvIn, cvOut, time - timeOffset, timeOffset)) | |||
if (processSingle(audioIn, audioOut, cvIn, cvOut, event.time - timeOffset, timeOffset)) | |||
{ | |||
startTime = 0; | |||
timeOffset = time; | |||
timeOffset = event.time; | |||
if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | |||
nextBankId = pData->midiprog.data[pData->midiprog.current].bank; | |||
@@ -1538,14 +1536,14 @@ public: | |||
if (fMidiEventCount >= kPluginMaxMidiEvents*2) | |||
continue; | |||
fMidiEvents[fMidiEventCount].port = 0; | |||
fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time; | |||
fMidiEvents[fMidiEventCount].data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + event.channel); | |||
fMidiEvents[fMidiEventCount].data[1] = static_cast<uint8_t>(ctrlEvent.param); | |||
fMidiEvents[fMidiEventCount].data[2] = uint8_t(ctrlEvent.value*127.0f); | |||
fMidiEvents[fMidiEventCount].size = 3; | |||
NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]); | |||
carla_zeroStruct(nativeEvent); | |||
fMidiEventCount += 1; | |||
nativeEvent.time = sampleAccurate ? startTime : event.time; | |||
nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = uint8_t(ctrlEvent.param); | |||
nativeEvent.data[2] = uint8_t(ctrlEvent.value*127.0f); | |||
nativeEvent.size = 3; | |||
} | |||
break; | |||
} | |||
@@ -1586,14 +1584,15 @@ public: | |||
if (fMidiEventCount >= kPluginMaxMidiEvents*2) | |||
continue; | |||
fMidiEvents[fMidiEventCount].port = 0; | |||
fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time; | |||
fMidiEvents[fMidiEventCount].data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + event.channel); | |||
fMidiEvents[fMidiEventCount].data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
fMidiEvents[fMidiEventCount].data[2] = 0; | |||
fMidiEvents[fMidiEventCount].size = 3; | |||
NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]); | |||
carla_zeroStruct(nativeEvent); | |||
fMidiEventCount += 1; | |||
nativeEvent.port = 0; | |||
nativeEvent.time = sampleAccurate ? startTime : event.time; | |||
nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
nativeEvent.data[2] = 0; | |||
nativeEvent.size = 3; | |||
} | |||
break; | |||
@@ -1611,14 +1610,14 @@ public: | |||
if (fMidiEventCount >= kPluginMaxMidiEvents*2) | |||
continue; | |||
fMidiEvents[fMidiEventCount].port = 0; | |||
fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time; | |||
fMidiEvents[fMidiEventCount].data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + event.channel); | |||
fMidiEvents[fMidiEventCount].data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
fMidiEvents[fMidiEventCount].data[2] = 0; | |||
fMidiEvents[fMidiEventCount].size = 3; | |||
NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]); | |||
carla_zeroStruct(nativeEvent); | |||
fMidiEventCount += 1; | |||
nativeEvent.time = sampleAccurate ? startTime : event.time; | |||
nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
nativeEvent.data[2] = 0; | |||
nativeEvent.size = 3; | |||
} | |||
break; | |||
} | |||
@@ -1631,41 +1630,43 @@ public: | |||
const EngineMidiEvent& midiEvent(event.midi); | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
uint8_t channel = event.channel; | |||
if (midiEvent.size > 4) | |||
continue; | |||
static_assert(4 <= EngineMidiEvent::kDataSize, "Incorrect data"); | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
if (MIDI_IS_STATUS_CHANNEL_PRESSURE(status) && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | |||
if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | |||
continue; | |||
if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) | |||
if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0) | |||
continue; | |||
if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) | |||
if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0) | |||
continue; | |||
if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | |||
if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | |||
continue; | |||
// Fix bad note-off | |||
if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
fMidiEvents[fMidiEventCount].port = 0; | |||
fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time; | |||
fMidiEvents[fMidiEventCount].size = midiEvent.size; | |||
NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]); | |||
carla_zeroStruct(nativeEvent); | |||
fMidiEvents[fMidiEventCount].data[0] = static_cast<uint8_t>(status + channel); | |||
fMidiEvents[fMidiEventCount].data[1] = midiEvent.data[1]; | |||
fMidiEvents[fMidiEventCount].data[2] = midiEvent.data[2]; | |||
fMidiEvents[fMidiEventCount].data[3] = midiEvent.data[3]; | |||
nativeEvent.port = midiEvent.port; | |||
nativeEvent.time = sampleAccurate ? startTime : event.time; | |||
nativeEvent.size = midiEvent.size; | |||
fMidiEventCount += 1; | |||
nativeEvent.data[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = midiEvent.size >= 2 ? midiEvent.data[1] : 0; | |||
nativeEvent.data[2] = midiEvent.size >= 3 ? midiEvent.data[2] : 0; | |||
nativeEvent.data[3] = midiEvent.size == 4 ? midiEvent.data[3] : 0; | |||
if (status == MIDI_STATUS_NOTE_ON) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiEvent.data[1], midiEvent.data[2]); | |||
else if (status == MIDI_STATUS_NOTE_OFF) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0f); | |||
break; | |||
} | |||
} | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiEvent.data[1], 0.0f); | |||
} break; | |||
} // switch (event.type) | |||
} | |||
pData->postRtEvents.trySplice(); | |||
@@ -47,6 +47,8 @@ const uint PLUGIN_HAS_COCKOS_EXTENSIONS = 0x2000; | |||
const uint PLUGIN_USES_OLD_VSTSDK = 0x4000; | |||
const uint PLUGIN_WANTS_MIDI_INPUT = 0x8000; | |||
static const int32_t kVstMidiEventSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||
// ----------------------------------------------------- | |||
class VstPlugin : public CarlaPlugin, | |||
@@ -1083,13 +1085,13 @@ public: | |||
for (uint8_t i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i) | |||
{ | |||
fMidiEvents[k].type = kVstMidiType; | |||
fMidiEvents[k].byteSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||
fMidiEvents[k].midiData[0] = static_cast<char>(MIDI_STATUS_CONTROL_CHANGE + k); | |||
fMidiEvents[k].byteSize = kVstMidiEventSize; | |||
fMidiEvents[k].midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT)); | |||
fMidiEvents[k].midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
fMidiEvents[k+i].type = kVstMidiType; | |||
fMidiEvents[k+i].byteSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||
fMidiEvents[k+i].midiData[0] = static_cast<char>(MIDI_STATUS_CONTROL_CHANGE + k); | |||
fMidiEvents[k+i].byteSize = kVstMidiEventSize; | |||
fMidiEvents[k+i].midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT)); | |||
fMidiEvents[k+i].midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
} | |||
} | |||
@@ -1100,9 +1102,9 @@ public: | |||
for (uint8_t i=0; i < MAX_MIDI_NOTE; ++i) | |||
{ | |||
fMidiEvents[i].type = kVstMidiType; | |||
fMidiEvents[i].byteSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||
fMidiEvents[i].midiData[0] = static_cast<char>(MIDI_STATUS_NOTE_OFF + pData->ctrlChannel); | |||
fMidiEvents[i].midiData[1] = static_cast<char>(i); | |||
fMidiEvents[i].byteSize = kVstMidiEventSize; | |||
fMidiEvents[i].midiData[0] = char(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT)); | |||
fMidiEvents[i].midiData[1] = char(i); | |||
} | |||
} | |||
@@ -1193,13 +1195,13 @@ public: | |||
CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | |||
fMidiEvents[fMidiEventCount].type = kVstMidiType; | |||
fMidiEvents[fMidiEventCount].byteSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||
fMidiEvents[fMidiEventCount].midiData[0] = static_cast<char>((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
fMidiEvents[fMidiEventCount].midiData[1] = static_cast<char>(note.note); | |||
fMidiEvents[fMidiEventCount].midiData[2] = static_cast<char>(note.velo); | |||
VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); | |||
++fMidiEventCount; | |||
vstMidiEvent.type = kVstMidiType; | |||
vstMidiEvent.byteSize = kVstMidiEventSize; | |||
vstMidiEvent.midiData[0] = char((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT)); | |||
vstMidiEvent.midiData[1] = char(note.note); | |||
vstMidiEvent.midiData[2] = char(note.velo); | |||
} | |||
pData->extNotes.mutex.unlock(); | |||
@@ -1214,11 +1216,10 @@ public: | |||
#endif | |||
bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | |||
uint32_t numEvents = pData->event.portIn->getEventCount(); | |||
uint32_t startTime = 0; | |||
uint32_t timeOffset = 0; | |||
for (uint32_t i=0; i < numEvents; ++i) | |||
for (uint32_t i=0, numEvents = pData->event.portIn->getEventCount(); i < numEvents; ++i) | |||
{ | |||
const EngineEvent& event(pData->event.portIn->getEvent(i)); | |||
@@ -1350,16 +1351,15 @@ public: | |||
if (fMidiEventCount >= kPluginMaxMidiEvents*2) | |||
continue; | |||
carla_zeroStruct<VstMidiEvent>(fMidiEvents[fMidiEventCount]); | |||
fMidiEvents[fMidiEventCount].type = kVstMidiType; | |||
fMidiEvents[fMidiEventCount].byteSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||
fMidiEvents[fMidiEventCount].midiData[0] = static_cast<char>(MIDI_STATUS_CONTROL_CHANGE + event.channel); | |||
fMidiEvents[fMidiEventCount].midiData[1] = static_cast<char>(ctrlEvent.param); | |||
fMidiEvents[fMidiEventCount].midiData[2] = char(ctrlEvent.value*127.0f); | |||
fMidiEvents[fMidiEventCount].deltaFrames = static_cast<int32_t>(isSampleAccurate ? startTime : event.time); | |||
VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); | |||
carla_zeroStruct(vstMidiEvent); | |||
++fMidiEventCount; | |||
vstMidiEvent.type = kVstMidiType; | |||
vstMidiEvent.byteSize = kVstMidiEventSize; | |||
vstMidiEvent.deltaFrames = static_cast<int32_t>(isSampleAccurate ? startTime : event.time); | |||
vstMidiEvent.midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
vstMidiEvent.midiData[1] = char(ctrlEvent.param); | |||
vstMidiEvent.midiData[2] = char(ctrlEvent.value*127.0f); | |||
} | |||
break; | |||
@@ -1386,15 +1386,14 @@ public: | |||
if (fMidiEventCount >= kPluginMaxMidiEvents*2) | |||
continue; | |||
carla_zeroStruct<VstMidiEvent>(fMidiEvents[fMidiEventCount]); | |||
fMidiEvents[fMidiEventCount].type = kVstMidiType; | |||
fMidiEvents[fMidiEventCount].byteSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||
fMidiEvents[fMidiEventCount].midiData[0] = static_cast<char>(MIDI_STATUS_CONTROL_CHANGE + event.channel); | |||
fMidiEvents[fMidiEventCount].midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
fMidiEvents[fMidiEventCount].deltaFrames = static_cast<int32_t>(isSampleAccurate ? startTime : event.time); | |||
VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); | |||
carla_zeroStruct(vstMidiEvent); | |||
++fMidiEventCount; | |||
vstMidiEvent.type = kVstMidiType; | |||
vstMidiEvent.byteSize = kVstMidiEventSize; | |||
vstMidiEvent.deltaFrames = static_cast<int32_t>(isSampleAccurate ? startTime : event.time); | |||
vstMidiEvent.midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
vstMidiEvent.midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
} | |||
break; | |||
@@ -1412,15 +1411,14 @@ public: | |||
if (fMidiEventCount >= kPluginMaxMidiEvents*2) | |||
continue; | |||
carla_zeroStruct<VstMidiEvent>(fMidiEvents[fMidiEventCount]); | |||
VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); | |||
carla_zeroStruct(vstMidiEvent); | |||
fMidiEvents[fMidiEventCount].type = kVstMidiType; | |||
fMidiEvents[fMidiEventCount].byteSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||
fMidiEvents[fMidiEventCount].midiData[0] = static_cast<char>(MIDI_STATUS_CONTROL_CHANGE + event.channel); | |||
fMidiEvents[fMidiEventCount].midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
fMidiEvents[fMidiEventCount].deltaFrames = static_cast<int32_t>(isSampleAccurate ? startTime : event.time); | |||
++fMidiEventCount; | |||
vstMidiEvent.type = kVstMidiType; | |||
vstMidiEvent.byteSize = kVstMidiEventSize; | |||
vstMidiEvent.deltaFrames = static_cast<int32_t>(isSampleAccurate ? startTime : event.time); | |||
vstMidiEvent.midiData[0] = char(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
vstMidiEvent.midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
} | |||
break; | |||
} // switch (ctrlEvent.type) | |||
@@ -1433,12 +1431,11 @@ public: | |||
const EngineMidiEvent& midiEvent(event.midi); | |||
uint8_t status = static_cast<uint8_t>(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
uint8_t channel = event.channel; | |||
if (midiEvent.size > 3) | |||
continue; | |||
static_assert(3 <= EngineMidiEvent::kDataSize, "Incorrect data"); | |||
// Fix bad note-off (per VST spec) | |||
if (MIDI_IS_STATUS_NOTE_ON(status) && midiEvent.data[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data)); | |||
if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | |||
continue; | |||
@@ -1449,24 +1446,25 @@ public: | |||
if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | |||
continue; | |||
carla_zeroStruct<VstMidiEvent>(fMidiEvents[fMidiEventCount]); | |||
// Fix bad note-off | |||
if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) | |||
status = MIDI_STATUS_NOTE_OFF; | |||
fMidiEvents[fMidiEventCount].type = kVstMidiType; | |||
fMidiEvents[fMidiEventCount].byteSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||
fMidiEvents[fMidiEventCount].midiData[0] = static_cast<char>(status + channel); | |||
fMidiEvents[fMidiEventCount].midiData[1] = static_cast<char>(midiEvent.data[1]); | |||
fMidiEvents[fMidiEventCount].midiData[2] = static_cast<char>(midiEvent.data[2]); | |||
fMidiEvents[fMidiEventCount].deltaFrames = static_cast<int32_t>(isSampleAccurate ? startTime : event.time); | |||
VstMidiEvent& vstMidiEvent(fMidiEvents[fMidiEventCount++]); | |||
carla_zeroStruct(vstMidiEvent); | |||
++fMidiEventCount; | |||
vstMidiEvent.type = kVstMidiType; | |||
vstMidiEvent.byteSize = kVstMidiEventSize; | |||
vstMidiEvent.deltaFrames = static_cast<int32_t>(isSampleAccurate ? startTime : event.time); | |||
vstMidiEvent.midiData[0] = char(status | (event.channel & MIDI_CHANNEL_BIT)); | |||
vstMidiEvent.midiData[1] = char(midiEvent.size >= 2 ? midiEvent.data[1] : 0); | |||
vstMidiEvent.midiData[2] = char(midiEvent.size >= 3 ? midiEvent.data[2] : 0); | |||
if (status == MIDI_STATUS_NOTE_ON) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]); | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiEvent.data[1], midiEvent.data[2]); | |||
else if (status == MIDI_STATUS_NOTE_OFF) | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0f); | |||
break; | |||
} // case kEngineEventTypeMidi | |||
pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiEvent.data[1], 0.0f); | |||
} break; | |||
} // switch (event.type) | |||
} | |||
@@ -1497,18 +1495,17 @@ public: | |||
if (fMidiEvents[k].type == 0) | |||
break; | |||
CARLA_SAFE_ASSERT_CONTINUE(fMidiEvents[k].deltaFrames >= 0); | |||
CARLA_SAFE_ASSERT_CONTINUE(fMidiEvents[k].midiData[0] != 0); | |||
const VstMidiEvent& vstMidiEvent(fMidiEvents[k]); | |||
const uint8_t status(static_cast<uint8_t>(fMidiEvents[k].midiData[0])); | |||
const uint8_t channel(static_cast<uint8_t>(status < MIDI_STATUS_BIT ? status & MIDI_CHANNEL_BIT : 0)); | |||
CARLA_SAFE_ASSERT_CONTINUE(vstMidiEvent.deltaFrames >= 0); | |||
CARLA_SAFE_ASSERT_CONTINUE(vstMidiEvent.midiData[0] != 0); | |||
uint8_t midiData[3]; | |||
midiData[0] = static_cast<uint8_t>(fMidiEvents[k].midiData[0]); | |||
midiData[1] = static_cast<uint8_t>(fMidiEvents[k].midiData[1]); | |||
midiData[2] = static_cast<uint8_t>(fMidiEvents[k].midiData[2]); | |||
midiData[0] = static_cast<uint8_t>(vstMidiEvent.midiData[0]); | |||
midiData[1] = static_cast<uint8_t>(vstMidiEvent.midiData[1]); | |||
midiData[2] = static_cast<uint8_t>(vstMidiEvent.midiData[2]); | |||
pData->event.portOut->writeMidiEvent(static_cast<uint32_t>(fMidiEvents[k].deltaFrames), channel, 0, 3, midiData); | |||
pData->event.portOut->writeMidiEvent(static_cast<uint32_t>(vstMidiEvent.deltaFrames), MIDI_GET_CHANNEL_FROM_DATA(midiData), 0, 3, midiData); | |||
} | |||
} // End of MIDI Output | |||
@@ -1740,7 +1737,7 @@ public: | |||
uint8_t midiData[4]; | |||
midiData[0] = 0; | |||
midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_ON + channel); | |||
midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||
midiData[2] = note; | |||
midiData[3] = velo; | |||
@@ -1759,7 +1756,7 @@ public: | |||
uint8_t midiData[4]; | |||
midiData[0] = 0; | |||
midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_OFF + channel); | |||
midiData[1] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT)); | |||
midiData[2] = note; | |||
midiData[3] = 0; | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla common MIDI code | |||
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
@@ -35,17 +35,23 @@ | |||
#define MIDI_STATUS_CHANNEL_PRESSURE 0xD0 // pressure (0-127), none | |||
#define MIDI_STATUS_PITCH_WHEEL_CONTROL 0xE0 // LSB (0-127), MSB (0-127) | |||
#define MIDI_IS_STATUS_NOTE_OFF(status) (((status) < MIDI_STATUS_BIT) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_NOTE_OFF) | |||
#define MIDI_IS_STATUS_NOTE_ON(status) (((status) < MIDI_STATUS_BIT) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_NOTE_ON) | |||
#define MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) (((status) < MIDI_STATUS_BIT) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_POLYPHONIC_AFTERTOUCH) | |||
#define MIDI_IS_STATUS_CONTROL_CHANGE(status) (((status) < MIDI_STATUS_BIT) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_CONTROL_CHANGE) | |||
#define MIDI_IS_STATUS_PROGRAM_CHANGE(status) (((status) < MIDI_STATUS_BIT) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_PROGRAM_CHANGE) | |||
#define MIDI_IS_STATUS_CHANNEL_PRESSURE(status) (((status) < MIDI_STATUS_BIT) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_CHANNEL_PRESSURE) | |||
#define MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) (((status) < MIDI_STATUS_BIT) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_PITCH_WHEEL_CONTROL) | |||
// MIDI Message type | |||
#define MIDI_IS_CHANNEL_MESSAGE(status) ((status) >= MIDI_STATUS_NOTE_OFF && (status) < MIDI_STATUS_BIT) | |||
#define MIDI_IS_SYSTEM_MESSAGE(status) ((status) >= MIDI_STATUS_BIT && (status) <= 0xFF) | |||
#define MIDI_IS_OSC_MESSAGE(status) ((status) == '/' || (status) == '#') | |||
// MIDI Channel message type | |||
#define MIDI_IS_STATUS_NOTE_OFF(status) (MIDI_IS_CHANNEL_MESSAGE(status) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_NOTE_OFF) | |||
#define MIDI_IS_STATUS_NOTE_ON(status) (MIDI_IS_CHANNEL_MESSAGE(status) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_NOTE_ON) | |||
#define MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) (MIDI_IS_CHANNEL_MESSAGE(status) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_POLYPHONIC_AFTERTOUCH) | |||
#define MIDI_IS_STATUS_CONTROL_CHANGE(status) (MIDI_IS_CHANNEL_MESSAGE(status) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_CONTROL_CHANGE) | |||
#define MIDI_IS_STATUS_PROGRAM_CHANGE(status) (MIDI_IS_CHANNEL_MESSAGE(status) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_PROGRAM_CHANGE) | |||
#define MIDI_IS_STATUS_CHANNEL_PRESSURE(status) (MIDI_IS_CHANNEL_MESSAGE(status) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_CHANNEL_PRESSURE) | |||
#define MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) (MIDI_IS_CHANNEL_MESSAGE(status) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_PITCH_WHEEL_CONTROL) | |||
// MIDI Utils | |||
#define MIDI_GET_STATUS_FROM_DATA(data) ((data[0] < MIDI_STATUS_BIT) ? data[0] & MIDI_STATUS_BIT : data[0]) | |||
#define MIDI_GET_CHANNEL_FROM_DATA(data) ((data[0] < MIDI_STATUS_BIT) ? data[0] & MIDI_CHANNEL_BIT : 0) | |||
#define MIDI_GET_STATUS_FROM_DATA(data) (MIDI_IS_CHANNEL_MESSAGE(data[0]) ? data[0] & MIDI_STATUS_BIT : data[0]) | |||
#define MIDI_GET_CHANNEL_FROM_DATA(data) (MIDI_IS_CHANNEL_MESSAGE(data[0]) ? data[0] & MIDI_CHANNEL_BIT : 0) | |||
// Control Change Messages List | |||
#define MIDI_CONTROL_BANK_SELECT 0x00 // 0-127, MSB | |||