| @@ -966,7 +966,7 @@ public: | |||||
| CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | ||||
| uint8_t data1, data2, data3; | 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; | data2 = note.note; | ||||
| data3 = note.velo; | data3 = note.velo; | ||||
| @@ -990,7 +990,7 @@ public: | |||||
| bool allNotesOffSent = false; | 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)); | const EngineEvent& event(pData->event.portIn->getEvent(i)); | ||||
| @@ -1124,11 +1124,9 @@ public: | |||||
| if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE) | if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE) | ||||
| continue; | 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) | if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | ||||
| continue; | continue; | ||||
| @@ -1139,20 +1137,26 @@ public: | |||||
| if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | ||||
| continue; | continue; | ||||
| // Fix bad note-off | |||||
| if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0) | |||||
| status = MIDI_STATUS_NOTE_OFF; | |||||
| fShmRtControl.writeOpcode(kPluginBridgeRtMidiEvent); | fShmRtControl.writeOpcode(kPluginBridgeRtMidiEvent); | ||||
| fShmRtControl.writeUInt(event.time); | fShmRtControl.writeUInt(event.time); | ||||
| fShmRtControl.writeByte(midiEvent.port); | fShmRtControl.writeByte(midiEvent.port); | ||||
| fShmRtControl.writeByte(midiEvent.size); | 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(); | fShmRtControl.commitWrite(); | ||||
| if (status == MIDI_STATUS_NOTE_ON) | 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) | 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; | } break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -1092,6 +1092,7 @@ public: | |||||
| } | } | ||||
| ulong midiEventCount = 0; | ulong midiEventCount = 0; | ||||
| carla_zeroStruct<snd_seq_event_t>(fMidiEvents, kPluginMaxMidiEvents); | |||||
| // -------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------- | ||||
| // Check if needs reset | // Check if needs reset | ||||
| @@ -1101,7 +1102,6 @@ public: | |||||
| if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) | if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) | ||||
| { | { | ||||
| midiEventCount = MAX_MIDI_CHANNELS*2; | 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) | 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) | else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) | ||||
| { | { | ||||
| midiEventCount = MAX_MIDI_NOTE; | midiEventCount = MAX_MIDI_NOTE; | ||||
| carla_zeroStruct<snd_seq_event_t>(fMidiEvents, midiEventCount); | |||||
| for (uchar i=0; i < MAX_MIDI_NOTE; ++i) | 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); | 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(); | pData->extNotes.mutex.unlock(); | ||||
| @@ -1177,7 +1175,6 @@ public: | |||||
| #endif | #endif | ||||
| const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | ||||
| uint32_t numEvents = pData->event.portIn->getEventCount(); | |||||
| uint32_t startTime = 0; | uint32_t startTime = 0; | ||||
| uint32_t timeOffset = 0; | uint32_t timeOffset = 0; | ||||
| uint32_t nextBankId; | uint32_t nextBankId; | ||||
| @@ -1187,7 +1184,7 @@ public: | |||||
| else | else | ||||
| nextBankId = 0; | 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)); | const EngineEvent& event(pData->event.portIn->getEvent(i)); | ||||
| @@ -1319,15 +1316,14 @@ public: | |||||
| if (midiEventCount >= kPluginMaxMidiEvents) | if (midiEventCount >= kPluginMaxMidiEvents) | ||||
| continue; | 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; | break; | ||||
| } // case kEngineControlEventTypeParameter | } // case kEngineControlEventTypeParameter | ||||
| @@ -1361,14 +1357,13 @@ public: | |||||
| if (midiEventCount >= kPluginMaxMidiEvents) | if (midiEventCount >= kPluginMaxMidiEvents) | ||||
| continue; | 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; | break; | ||||
| @@ -1386,16 +1381,13 @@ public: | |||||
| if (midiEventCount >= kPluginMaxMidiEvents) | if (midiEventCount >= kPluginMaxMidiEvents) | ||||
| continue; | 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; | break; | ||||
| } // switch (ctrlEvent.type) | } // switch (ctrlEvent.type) | ||||
| @@ -1406,103 +1398,101 @@ public: | |||||
| if (midiEventCount >= kPluginMaxMidiEvents) | if (midiEventCount >= kPluginMaxMidiEvents) | ||||
| continue; | 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) | // 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; | 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) | switch (status) | ||||
| { | { | ||||
| case MIDI_STATUS_NOTE_OFF: { | 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; | break; | ||||
| } | } | ||||
| case MIDI_STATUS_NOTE_ON: { | 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; | break; | ||||
| } | } | ||||
| case MIDI_STATUS_POLYPHONIC_AFTERTOUCH: | case MIDI_STATUS_POLYPHONIC_AFTERTOUCH: | ||||
| if (pData->options & PLUGIN_OPTION_SEND_NOTE_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; | break; | ||||
| case MIDI_STATUS_CONTROL_CHANGE: | case MIDI_STATUS_CONTROL_CHANGE: | ||||
| if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) | 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; | break; | ||||
| case MIDI_STATUS_CHANNEL_PRESSURE: | case MIDI_STATUS_CHANNEL_PRESSURE: | ||||
| if (pData->options & PLUGIN_OPTION_SEND_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; | break; | ||||
| case MIDI_STATUS_PITCH_WHEEL_CONTROL: | case MIDI_STATUS_PITCH_WHEEL_CONTROL: | ||||
| if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) | 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; | break; | ||||
| default: | default: | ||||
| continue; | |||||
| --midiEventCount; | |||||
| break; | break; | ||||
| } // switch (status) | } // switch (status) | ||||
| midiEventCount += 1; | |||||
| break; | |||||
| } // case kEngineEventTypeMidi | |||||
| } break; | |||||
| } // switch (event.type) | } // switch (event.type) | ||||
| } | } | ||||
| @@ -1946,7 +1936,7 @@ public: | |||||
| #if 0 | #if 0 | ||||
| uint8_t midiData[4]; | uint8_t midiData[4]; | ||||
| midiData[0] = 0; | 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[2] = note; | ||||
| midiData[3] = velo; | midiData[3] = velo; | ||||
| @@ -1965,7 +1955,7 @@ public: | |||||
| #if 0 | #if 0 | ||||
| uint8_t midiData[4]; | uint8_t midiData[4]; | ||||
| midiData[0] = 0; | 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[2] = note; | ||||
| midiData[3] = 0; | midiData[3] = 0; | ||||
| @@ -1074,7 +1074,6 @@ public: | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| bool allNotesOffSent = false; | bool allNotesOffSent = false; | ||||
| #endif | #endif | ||||
| uint32_t time, nEvents = pData->event.portIn->getEventCount(); | |||||
| uint32_t timeOffset = 0; | 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 }; | 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) | 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; | 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)); | 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) | 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; | 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 bankId(nextBankIds[event.channel]); | ||||
| const uint32_t progId(ctrlEvent.param); | const uint32_t progId(ctrlEvent.param); | ||||
| // TODO int32_t midiprog.find(bank, prog) | |||||
| for (uint32_t k=0; k < pData->midiprog.count; ++k) | for (uint32_t k=0; k < pData->midiprog.count; ++k) | ||||
| { | { | ||||
| if (pData->midiprog.data[k].bank == bankId && pData->midiprog.data[k].program == progId) | if (pData->midiprog.data[k].bank == bankId && pData->midiprog.data[k].program == progId) | ||||
| @@ -1265,66 +1265,85 @@ public: | |||||
| break; | break; | ||||
| } | } | ||||
| case kEngineEventTypeMidi: | |||||
| { | |||||
| case kEngineEventTypeMidi: { | |||||
| const EngineMidiEvent& midiEvent(event.midi); | 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 | // 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; | 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]; | 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 note = midiEvent.data[1]; | ||||
| const uint8_t velo = midiEvent.data[2]; | 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(); | pData->postRtEvents.trySplice(); | ||||
| @@ -609,7 +609,7 @@ public: | |||||
| CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | ||||
| uint8_t midiEvent[3]; | 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[1] = note.note; | ||||
| midiEvent[2] = note.velo; | midiEvent[2] = note.velo; | ||||
| @@ -627,7 +627,6 @@ public: | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| bool allNotesOffSent = false; | bool allNotesOffSent = false; | ||||
| #endif | #endif | ||||
| uint32_t numEvents = pData->event.portIn->getEventCount(); | |||||
| uint32_t nextBankId; | uint32_t nextBankId; | ||||
| if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | ||||
| @@ -635,7 +634,7 @@ public: | |||||
| else | else | ||||
| nextBankId = 0; | 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)); | 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) | if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F) | ||||
| { | { | ||||
| uint8_t midiData[3]; | 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); | midiData[2] = uint8_t(ctrlEvent.value*127.0f); | ||||
| fMidiBuffer.addEvent(midiData, 3, static_cast<int>(event.time)); | fMidiBuffer.addEvent(midiData, 3, static_cast<int>(event.time)); | ||||
| @@ -782,7 +781,7 @@ public: | |||||
| if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) | if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) | ||||
| { | { | ||||
| uint8_t midiData[3]; | 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[1] = MIDI_CONTROL_ALL_SOUND_OFF; | ||||
| midiData[2] = 0; | midiData[2] = 0; | ||||
| @@ -802,7 +801,7 @@ public: | |||||
| #endif | #endif | ||||
| uint8_t midiData[3]; | 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[1] = MIDI_CONTROL_ALL_NOTES_OFF; | ||||
| midiData[2] = 0; | midiData[2] = 0; | ||||
| @@ -813,16 +812,12 @@ public: | |||||
| break; | break; | ||||
| } // case kEngineEventTypeControl | } // case kEngineEventTypeControl | ||||
| case kEngineEventTypeMidi: | |||||
| { | |||||
| case kEngineEventTypeMidi: { | |||||
| const EngineMidiEvent& midiEvent(event.midi); | 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) | if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | ||||
| continue; | continue; | ||||
| @@ -833,15 +828,22 @@ public: | |||||
| if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | ||||
| continue; | 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) | 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) | 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) | } // switch (event.type) | ||||
| } | } | ||||
| @@ -799,11 +799,10 @@ public: | |||||
| #endif | #endif | ||||
| bool sampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | bool sampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | ||||
| uint32_t nEvents = pData->event.portIn->getEventCount(); | |||||
| uint32_t startTime = 0; | uint32_t startTime = 0; | ||||
| uint32_t timeOffset = 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)); | const EngineEvent& event(pData->event.portIn->getEvent(i)); | ||||
| @@ -982,42 +981,38 @@ public: | |||||
| break; | break; | ||||
| } | } | ||||
| case kEngineEventTypeMidi: | |||||
| { | |||||
| case kEngineEventTypeMidi: { | |||||
| const EngineMidiEvent& midiEvent(event.midi); | 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; | 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; | 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; | 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; | 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) | 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) | 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) | 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) | 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) | 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; | midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; | ||||
| if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) | if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) | ||||
| @@ -2539,7 +2539,7 @@ public: | |||||
| else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) | else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL) | ||||
| lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiData); | 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; | midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; | ||||
| if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) | if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) | ||||
| @@ -2556,7 +2556,7 @@ public: | |||||
| { | { | ||||
| for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k) | 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; | midiData[1] = k; | ||||
| if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) | 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); | CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | ||||
| uint8_t midiEvent[3]; | 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[1] = note.note; | ||||
| midiEvent[2] = note.velo; | midiEvent[2] = note.velo; | ||||
| @@ -2825,7 +2825,6 @@ public: | |||||
| #endif | #endif | ||||
| bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | 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 startTime = 0; | ||||
| uint32_t timeOffset = 0; | uint32_t timeOffset = 0; | ||||
| uint32_t nextBankId; | uint32_t nextBankId; | ||||
| @@ -2835,6 +2834,8 @@ public: | |||||
| else | else | ||||
| nextBankId = 0; | nextBankId = 0; | ||||
| const uint32_t numEvents = (fEventsIn.ctrl->port != nullptr) ? fEventsIn.ctrl->port->getEventCount() : 0; | |||||
| for (uint32_t i=0; i < numEvents; ++i) | for (uint32_t i=0; i < numEvents; ++i) | ||||
| { | { | ||||
| const EngineEvent& event(fEventsIn.ctrl->port->getEvent(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) | if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F) | ||||
| { | { | ||||
| uint8_t midiData[3]; | 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); | midiData[2] = uint8_t(ctrlEvent.value*127.0f); | ||||
| const uint32_t mtime(isSampleAccurate ? startTime : event.time); | const uint32_t mtime(isSampleAccurate ? startTime : event.time); | ||||
| @@ -3031,7 +3032,7 @@ public: | |||||
| const uint32_t mtime(isSampleAccurate ? startTime : event.time); | const uint32_t mtime(isSampleAccurate ? startTime : event.time); | ||||
| uint8_t midiData[3]; | 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[1] = MIDI_CONTROL_ALL_SOUND_OFF; | ||||
| midiData[2] = 0; | midiData[2] = 0; | ||||
| @@ -3060,7 +3061,7 @@ public: | |||||
| const uint32_t mtime(isSampleAccurate ? startTime : event.time); | const uint32_t mtime(isSampleAccurate ? startTime : event.time); | ||||
| uint8_t midiData[3]; | 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[1] = MIDI_CONTROL_ALL_NOTES_OFF; | ||||
| midiData[2] = 0; | midiData[2] = 0; | ||||
| @@ -3078,17 +3079,12 @@ public: | |||||
| break; | break; | ||||
| } // case kEngineEventTypeControl | } // case kEngineEventTypeControl | ||||
| case kEngineEventTypeMidi: | |||||
| { | |||||
| case kEngineEventTypeMidi: { | |||||
| const EngineMidiEvent& midiEvent(event.midi); | 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) | if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | ||||
| continue; | continue; | ||||
| @@ -3099,24 +3095,32 @@ public: | |||||
| if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | ||||
| continue; | 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) | 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) | 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) | 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) | 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) | 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) | } // switch (event.type) | ||||
| } | } | ||||
| @@ -3773,7 +3777,7 @@ public: | |||||
| if (pData->osc.data.target != nullptr) | if (pData->osc.data.target != nullptr) | ||||
| { | { | ||||
| uint8_t midiData[4] = { 0, 0, 0, 0 }; | 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[2] = note; | ||||
| midiData[3] = velo; | midiData[3] = velo; | ||||
| osc_send_midi(pData->osc.data, midiData); | osc_send_midi(pData->osc.data, midiData); | ||||
| @@ -3787,7 +3791,7 @@ public: | |||||
| midiEv.event.time.frames = 0; | midiEv.event.time.frames = 0; | ||||
| midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT; | midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT; | ||||
| midiEv.event.body.size = 3; | 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[1] = note; | ||||
| midiEv.data[2] = velo; | midiEv.data[2] = velo; | ||||
| @@ -3807,7 +3811,7 @@ public: | |||||
| if (pData->osc.data.target != nullptr) | if (pData->osc.data.target != nullptr) | ||||
| { | { | ||||
| uint8_t midiData[4] = { 0, 0, 0, 0 }; | 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; | midiData[2] = note; | ||||
| osc_send_midi(pData->osc.data, midiData); | osc_send_midi(pData->osc.data, midiData); | ||||
| } | } | ||||
| @@ -3820,7 +3824,7 @@ public: | |||||
| midiEv.event.time.frames = 0; | midiEv.event.time.frames = 0; | ||||
| midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT; | midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT; | ||||
| midiEv.event.body.size = 3; | 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[1] = note; | ||||
| midiEv.data[2] = 0; | midiEv.data[2] = 0; | ||||
| @@ -1302,32 +1302,32 @@ public: | |||||
| { | { | ||||
| if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) | 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) | 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[1] = MIDI_CONTROL_ALL_NOTES_OFF; | ||||
| fMidiEvents[k].data[2] = 0; | fMidiEvents[k].data[2] = 0; | ||||
| fMidiEvents[k].size = 3; | 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[1] = MIDI_CONTROL_ALL_SOUND_OFF; | ||||
| fMidiEvents[k+i].data[2] = 0; | fMidiEvents[k+i].data[2] = 0; | ||||
| fMidiEvents[k+i].size = 3; | fMidiEvents[k+i].size = 3; | ||||
| } | } | ||||
| fMidiEventCount = MAX_MIDI_CHANNELS*2; | |||||
| } | } | ||||
| else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) | else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) | ||||
| { | { | ||||
| fMidiEventCount = MAX_MIDI_NOTE; | |||||
| for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k) | 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[1] = k; | ||||
| fMidiEvents[k].data[2] = 0; | fMidiEvents[k].data[2] = 0; | ||||
| fMidiEvents[k].size = 3; | fMidiEvents[k].size = 3; | ||||
| } | } | ||||
| fMidiEventCount = MAX_MIDI_NOTE; | |||||
| } | } | ||||
| pData->needsReset = false; | pData->needsReset = false; | ||||
| @@ -1372,19 +1372,18 @@ public: | |||||
| { | { | ||||
| ExternalMidiNote note = { 0, 0, 0 }; | 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); | note = pData->extNotes.data.getFirst(note, true); | ||||
| CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); | 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(); | pData->extNotes.mutex.unlock(); | ||||
| @@ -1399,31 +1398,30 @@ public: | |||||
| #endif | #endif | ||||
| bool sampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | bool sampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | ||||
| uint32_t time, nEvents = pData->event.portIn->getEventCount(); | |||||
| uint32_t startTime = 0; | uint32_t startTime = 0; | ||||
| uint32_t timeOffset = 0; | uint32_t timeOffset = 0; | ||||
| uint32_t nextBankId = 0; | |||||
| uint32_t nextBankId; | |||||
| if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | ||||
| nextBankId = pData->midiprog.data[pData->midiprog.current].bank; | 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)); | const EngineEvent& event(pData->event.portIn->getEvent(i)); | ||||
| time = event.time; | |||||
| if (time >= frames) | |||||
| if (event.time >= frames) | |||||
| continue; | 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; | startTime = 0; | ||||
| timeOffset = time; | |||||
| timeOffset = event.time; | |||||
| if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | if (pData->midiprog.current >= 0 && pData->midiprog.count > 0) | ||||
| nextBankId = pData->midiprog.data[pData->midiprog.current].bank; | nextBankId = pData->midiprog.data[pData->midiprog.current].bank; | ||||
| @@ -1538,14 +1536,14 @@ public: | |||||
| if (fMidiEventCount >= kPluginMaxMidiEvents*2) | if (fMidiEventCount >= kPluginMaxMidiEvents*2) | ||||
| continue; | 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; | break; | ||||
| } | } | ||||
| @@ -1586,14 +1584,15 @@ public: | |||||
| if (fMidiEventCount >= kPluginMaxMidiEvents*2) | if (fMidiEventCount >= kPluginMaxMidiEvents*2) | ||||
| continue; | 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; | break; | ||||
| @@ -1611,14 +1610,14 @@ public: | |||||
| if (fMidiEventCount >= kPluginMaxMidiEvents*2) | if (fMidiEventCount >= kPluginMaxMidiEvents*2) | ||||
| continue; | 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; | break; | ||||
| } | } | ||||
| @@ -1631,41 +1630,43 @@ public: | |||||
| const EngineMidiEvent& midiEvent(event.midi); | 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; | 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; | 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; | 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; | continue; | ||||
| // Fix bad note-off | // Fix bad note-off | ||||
| if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) | if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0) | ||||
| status = MIDI_STATUS_NOTE_OFF; | 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) | 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) | 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(); | pData->postRtEvents.trySplice(); | ||||
| @@ -47,6 +47,8 @@ const uint PLUGIN_HAS_COCKOS_EXTENSIONS = 0x2000; | |||||
| const uint PLUGIN_USES_OLD_VSTSDK = 0x4000; | const uint PLUGIN_USES_OLD_VSTSDK = 0x4000; | ||||
| const uint PLUGIN_WANTS_MIDI_INPUT = 0x8000; | const uint PLUGIN_WANTS_MIDI_INPUT = 0x8000; | ||||
| static const int32_t kVstMidiEventSize = static_cast<int32_t>(sizeof(VstMidiEvent)); | |||||
| // ----------------------------------------------------- | // ----------------------------------------------------- | ||||
| class VstPlugin : public CarlaPlugin, | class VstPlugin : public CarlaPlugin, | ||||
| @@ -1083,13 +1085,13 @@ public: | |||||
| for (uint8_t i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i) | for (uint8_t i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i) | ||||
| { | { | ||||
| fMidiEvents[k].type = kVstMidiType; | 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].midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF; | ||||
| fMidiEvents[k+i].type = kVstMidiType; | 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; | 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) | for (uint8_t i=0; i < MAX_MIDI_NOTE; ++i) | ||||
| { | { | ||||
| fMidiEvents[i].type = kVstMidiType; | 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); | 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(); | pData->extNotes.mutex.unlock(); | ||||
| @@ -1214,11 +1216,10 @@ public: | |||||
| #endif | #endif | ||||
| bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | ||||
| uint32_t numEvents = pData->event.portIn->getEventCount(); | |||||
| uint32_t startTime = 0; | uint32_t startTime = 0; | ||||
| uint32_t timeOffset = 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)); | const EngineEvent& event(pData->event.portIn->getEvent(i)); | ||||
| @@ -1350,16 +1351,15 @@ public: | |||||
| if (fMidiEventCount >= kPluginMaxMidiEvents*2) | if (fMidiEventCount >= kPluginMaxMidiEvents*2) | ||||
| continue; | 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; | break; | ||||
| @@ -1386,15 +1386,14 @@ public: | |||||
| if (fMidiEventCount >= kPluginMaxMidiEvents*2) | if (fMidiEventCount >= kPluginMaxMidiEvents*2) | ||||
| continue; | 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; | break; | ||||
| @@ -1412,15 +1411,14 @@ public: | |||||
| if (fMidiEventCount >= kPluginMaxMidiEvents*2) | if (fMidiEventCount >= kPluginMaxMidiEvents*2) | ||||
| continue; | 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; | break; | ||||
| } // switch (ctrlEvent.type) | } // switch (ctrlEvent.type) | ||||
| @@ -1433,12 +1431,11 @@ public: | |||||
| const EngineMidiEvent& midiEvent(event.midi); | 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) | if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0) | ||||
| continue; | continue; | ||||
| @@ -1449,24 +1446,25 @@ public: | |||||
| if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | ||||
| continue; | 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) | 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) | 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) | } // switch (event.type) | ||||
| } | } | ||||
| @@ -1497,18 +1495,17 @@ public: | |||||
| if (fMidiEvents[k].type == 0) | if (fMidiEvents[k].type == 0) | ||||
| break; | 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]; | 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 | } // End of MIDI Output | ||||
| @@ -1740,7 +1737,7 @@ public: | |||||
| uint8_t midiData[4]; | uint8_t midiData[4]; | ||||
| midiData[0] = 0; | 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[2] = note; | ||||
| midiData[3] = velo; | midiData[3] = velo; | ||||
| @@ -1759,7 +1756,7 @@ public: | |||||
| uint8_t midiData[4]; | uint8_t midiData[4]; | ||||
| midiData[0] = 0; | 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[2] = note; | ||||
| midiData[3] = 0; | midiData[3] = 0; | ||||
| @@ -1,6 +1,6 @@ | |||||
| /* | /* | ||||
| * Carla common MIDI code | * 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 | * This program is free software; you can redistribute it and/or | ||||
| * modify it under the terms of the GNU General Public License as | * 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_CHANNEL_PRESSURE 0xD0 // pressure (0-127), none | ||||
| #define MIDI_STATUS_PITCH_WHEEL_CONTROL 0xE0 // LSB (0-127), MSB (0-127) | #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 | // 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 | // Control Change Messages List | ||||
| #define MIDI_CONTROL_BANK_SELECT 0x00 // 0-127, MSB | #define MIDI_CONTROL_BANK_SELECT 0x00 // 0-127, MSB | ||||