From: <sv...@op...> - 2024-11-30 22:52:39
|
Author: sagamusix Date: Sat Nov 30 23:52:26 2024 New Revision: 22368 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=22368 Log: [Ref] Do not distinguish between SysEx and non-SysEx MIDI messages in the IMixPlugin interface. Modified: trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/Vstplug.h trunk/OpenMPT/mptrack/mod2midi.cpp trunk/OpenMPT/mptrack/plugins/MidiInOut.cpp trunk/OpenMPT/mptrack/plugins/MidiInOut.h trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/plugins/LFOPlugin.cpp trunk/OpenMPT/soundlib/plugins/LFOPlugin.h trunk/OpenMPT/soundlib/plugins/PlugInterface.cpp trunk/OpenMPT/soundlib/plugins/PlugInterface.h Modified: trunk/OpenMPT/mptrack/Vstplug.cpp ============================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/mptrack/Vstplug.cpp Sat Nov 30 23:52:26 2024 (r22368) @@ -1485,7 +1485,7 @@ } else if(ev->type == kVstSysExType) { auto event = static_cast<const VstMidiSysexEvent *>(ev); - plugin->MidiSysexSend(mpt::as_span(mpt::byte_cast<const std::byte *>(event->sysexDump), event->dumpBytes)); + plugin->MidiSend(mpt::as_span(mpt::byte_cast<const std::byte *>(event->sysexDump), event->dumpBytes)); } } } @@ -1596,40 +1596,39 @@ } -bool CVstPlugin::MidiSend(uint32 dwMidiCode) +bool CVstPlugin::MidiSend(mpt::const_byte_span midiData) { if(IsBypassed()) return true; - // Note-Offs go at the start of the queue (since OpenMPT 1.17). Needed for situations like this: - // ... ..|C-5 01 - // C-5 01|=== .. - // TODO: Should not be used with real-time notes! Letting the key go too quickly - // (e.g. while output device is being initialized) will cause the note to be stuck! - bool insertAtFront = (MIDIEvents::GetTypeFromEvent(dwMidiCode) == MIDIEvents::evNoteOff); - - VstMidiEvent event{}; - event.type = kVstMidiType; - event.byteSize = sizeof(event); - event.midiData = dwMidiCode; ResetSilence(); - return vstEvents.Enqueue(&event, insertAtFront); -} - - -bool CVstPlugin::MidiSysexSend(mpt::const_byte_span sysex) -{ - if(IsBypassed()) - return true; + const uint8 type = mpt::byte_cast<uint8>(midiData[0]); + if(type == 0xF0) + { + VstMidiSysexEvent event{}; + event.type = kVstSysExType; + event.byteSize = sizeof(event); + event.dumpBytes = mpt::saturate_cast<int32>(midiData.size()); + event.sysexDump = midiData.data(); // We will make our own copy in VstEventQueue::Enqueue - VstMidiSysexEvent event{}; - event.type = kVstSysExType; - event.byteSize = sizeof(event); - event.dumpBytes = mpt::saturate_cast<int32>(sysex.size()); - event.sysexDump = sysex.data(); // We will make our own copy in VstEventQueue::Enqueue + return vstEvents.Enqueue(&event); + } else + { + // Note-Offs go at the start of the queue (since OpenMPT 1.17). Needed for situations like this: + // ... ..|C-5 01 + // C-5 01|=== .. + // TODO: Should not be used with real-time notes! Letting the key go too quickly + // (e.g. while output device is being initialized) will cause the note to be stuck! + bool insertAtFront = (MIDIEvents::GetTypeFromEvent(type) == MIDIEvents::evNoteOff); + + VstMidiEvent event{}; + event.type = kVstMidiType; + event.byteSize = sizeof(event); + MPT_ASSERT(midiData.size() <= sizeof(event.midiData) && midiData.size() == MIDIEvents::GetEventLength(type)); + memcpy(&event.midiData, midiData.data(), std::min(sizeof(event.midiData), midiData.size())); - ResetSilence(); - return vstEvents.Enqueue(&event); + return vstEvents.Enqueue(&event, insertAtFront); + } } Modified: trunk/OpenMPT/mptrack/Vstplug.h ============================================================================== --- trunk/OpenMPT/mptrack/Vstplug.h Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/mptrack/Vstplug.h Sat Nov 30 23:52:26 2024 (r22368) @@ -158,8 +158,8 @@ void SaveAllParameters() override; void RestoreAllParameters(int32 program) override; void Process(float *pOutL, float *pOutR, uint32 numFrames) override; - bool MidiSend(uint32 dwMidiCode) override; - bool MidiSysexSend(mpt::const_byte_span sysex) override; + using IMixPlugin::MidiSend; + bool MidiSend(mpt::const_byte_span midiData) override; void HardAllNotesOff() override; void NotifySongPlaying(bool playing) override; Modified: trunk/OpenMPT/mptrack/mod2midi.cpp ============================================================================== --- trunk/OpenMPT/mptrack/mod2midi.cpp Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/mptrack/mod2midi.cpp Sat Nov 30 23:52:26 2024 (r22368) @@ -71,7 +71,7 @@ std::shared_ptr<MidiChannelState> m_channelState; std::array<decltype(m_instr.midiPWD), 16> m_pitchWheelDepth = { 0 }; - std::vector<std::array<char, 4>> m_queuedEvents; + std::vector<std::array<uint8, 4>> m_queuedEvents; std::ostringstream f; double m_tempo = 0.0; @@ -229,11 +229,11 @@ { if(m_channelState->lastModChannel[midiCh] == CHANNELINDEX_INVALID) continue; - char newPanning = static_cast<char>(std::clamp(m_sndFile.m_PlayState.Chn[m_channelState->lastModChannel[midiCh]].nRealPan / 2, 0, 127)); + uint8 newPanning = static_cast<uint8>(std::clamp(m_sndFile.m_PlayState.Chn[m_channelState->lastModChannel[midiCh]].nRealPan / 2, 0, 127)); if(m_channelState->panning[midiCh] == newPanning) continue; m_channelState->panning[midiCh] = newPanning; - std::array<char, 4> midiData = {static_cast<char>(0xB0 | midiCh), 0x0A, newPanning, 0}; + std::array<uint8, 4> midiData = {static_cast<uint8>(0xB0 | midiCh), 0x0A, newPanning, 0}; m_queuedEvents.push_back(midiData); } @@ -298,32 +298,34 @@ float RenderSilence(uint32) override { return 0.0f; } - bool MidiSend(uint32 midiCode) override + using IMixPlugin::MidiSend; + bool MidiSend(mpt::const_byte_span midiData) override { - std::array<char, 4> midiData; - memcpy(midiData.data(), &midiCode, 4); - - // Note-On events go last to prevent early note-off in a situation like this: - // ... ..|C-5 01 - // C-5 01|=== .. - if(MIDIEvents::GetTypeFromEvent(midiCode) == MIDIEvents::evNoteOn) - { - m_queuedEvents.push_back(midiData); - return true; - } - WriteTicks(); - mpt::IO::WriteRaw(f, midiData.data(), MIDIEvents::GetEventLength(midiData[0])); - return true; - } - - bool MidiSysexSend(mpt::const_byte_span sysex) override - { - if(sysex.size() > 1) + if(midiData.empty()) + return false; + const uint8 type = mpt::byte_cast<uint8>(midiData[0]); + if(type == 0xF0) { + // SysEx WriteTicks(); mpt::IO::WriteIntBE<uint8>(f, 0xF0); - mpt::IO::WriteVarInt(f, mpt::saturate_cast<uint32>(sysex.size() - 1)); - mpt::IO::WriteRaw(f, sysex.data() + 1, sysex.size() - 1); + mpt::IO::WriteVarInt(f, mpt::saturate_cast<uint32>(midiData.size() - 1)); + mpt::IO::WriteRaw(f, midiData.data() + 1, midiData.size() - 1); + } else + { + // Note-On events go last to prevent early note-off in a situation like this: + // ... ..|C-5 01 + // C-5 01|=== .. + if(MIDIEvents::GetTypeFromEvent(type) == MIDIEvents::evNoteOn) + { + std::array<uint8, 4> midiDataArray; + MPT_ASSERT(midiData.size() <= sizeof(midiDataArray) && midiData.size() == MIDIEvents::GetEventLength(type)); + memcpy(midiDataArray.data(), midiData.data(), std::min(sizeof(midiDataArray), midiData.size())); + m_queuedEvents.push_back(midiDataArray); + return true; + } + WriteTicks(); + mpt::IO::WriteRaw(f, midiData.data(), midiData.size()); } return true; } Modified: trunk/OpenMPT/mptrack/plugins/MidiInOut.cpp ============================================================================== --- trunk/OpenMPT/mptrack/plugins/MidiInOut.cpp Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/mptrack/plugins/MidiInOut.cpp Sat Nov 30 23:52:26 2024 (r22368) @@ -339,22 +339,20 @@ { // End of message found! if(!isBypassed) - ReceiveSysex(mpt::byte_cast<mpt::const_byte_span>(mpt::as_span(m_bufferedInput))); + ReceiveMidi(mpt::byte_cast<mpt::const_byte_span>(mpt::as_span(m_bufferedInput))); m_bufferedInput.clear(); } } else if(message.front() == 0xF0) { // Start of SysEx message... if(message.back() != 0xF7) - m_bufferedInput.insert(m_bufferedInput.end(), message.begin(), message.end()); // ...but not the end! + m_bufferedInput.insert(m_bufferedInput.end(), message.begin(), message.end()); // ...but not the end! else if(!isBypassed) - ReceiveSysex(mpt::byte_cast<mpt::const_byte_span>(mpt::as_span(message))); + ReceiveMidi(mpt::byte_cast<mpt::const_byte_span>(mpt::as_span(message))); } else if(!isBypassed) { // Regular message - uint32 msg = 0; - memcpy(&msg, message.data(), std::min(message.size(), sizeof(msg))); - ReceiveMidi(msg); + ReceiveMidi(mpt::byte_cast<mpt::const_byte_span>(mpt::as_span(message))); } } @@ -438,7 +436,7 @@ } -bool MidiInOut::MidiSend(uint32 midiCode) +bool MidiInOut::MidiSend(mpt::const_byte_span midiData) { if(!m_midiOut.isPortOpen() || IsBypassed()) { @@ -447,21 +445,7 @@ } mpt::lock_guard<mpt::mutex> lock(m_mutex); - m_outQueue.push_back(Message(GetOutputTimestamp(), &midiCode, MIDIEvents::GetEventLength(static_cast<uint8>(midiCode)))); - return true; -} - - -bool MidiInOut::MidiSysexSend(mpt::const_byte_span sysex) -{ - if(!m_midiOut.isPortOpen() || IsBypassed()) - { - // We need an output device to send MIDI messages to. - return true; - } - - mpt::lock_guard<mpt::mutex> lock(m_mutex); - m_outQueue.push_back(Message(GetOutputTimestamp(), sysex.data(), sysex.size())); + m_outQueue.push_back(Message(GetOutputTimestamp(), midiData.data(), midiData.size())); return true; } Modified: trunk/OpenMPT/mptrack/plugins/MidiInOut.h ============================================================================== --- trunk/OpenMPT/mptrack/plugins/MidiInOut.h Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/mptrack/plugins/MidiInOut.h Sat Nov 30 23:52:26 2024 (r22368) @@ -178,8 +178,8 @@ void Process(float *pOutL, float *pOutR, uint32 numFrames) final; // Render silence and return the highest resulting output level float RenderSilence(uint32) final{ return 0; } - bool MidiSend(uint32 midiCode) final; - bool MidiSysexSend(mpt::const_byte_span sysex) final; + using IMixPlugin::MidiSend; + bool MidiSend(mpt::const_byte_span midiData) final; void HardAllNotesOff() final; // Modify parameter by given amount. Only needs to be re-implemented if plugin architecture allows this to be performed atomically. void Resume() final; Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp Sat Nov 30 23:52:26 2024 (r22368) @@ -5817,16 +5817,7 @@ { if(IMixPlugin *pPlugin = m_MixPlugins[plug - 1].pMixPlugin; pPlugin != nullptr) { - if(macro[0] == 0xF0) - { - pPlugin->MidiSysexSend(mpt::byte_cast<mpt::const_byte_span>(macro)); - } else - { - size_t len = std::min(static_cast<size_t>(MIDIEvents::GetEventLength(macro[0])), macro.size()); - uint32 curData = 0; - memcpy(&curData, macro.data(), len); - pPlugin->MidiSend(curData); - } + pPlugin->MidiSend(mpt::byte_cast<mpt::const_byte_span>(macro)); } } } Modified: trunk/OpenMPT/soundlib/plugins/LFOPlugin.cpp ============================================================================== --- trunk/OpenMPT/soundlib/plugins/LFOPlugin.cpp Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/soundlib/plugins/LFOPlugin.cpp Sat Nov 30 23:52:26 2024 (r22368) @@ -196,19 +196,10 @@ } -bool LFOPlugin::MidiSend(uint32 midiCode) +bool LFOPlugin::MidiSend(mpt::const_byte_span midiData) { if(IMixPlugin *plugin = GetOutputPlugin()) - return plugin->MidiSend(midiCode); - else - return true; -} - - -bool LFOPlugin::MidiSysexSend(mpt::const_byte_span sysex) -{ - if(IMixPlugin *plugin = GetOutputPlugin()) - return plugin->MidiSysexSend(sysex); + return plugin->MidiSend(midiData); else return true; } Modified: trunk/OpenMPT/soundlib/plugins/LFOPlugin.h ============================================================================== --- trunk/OpenMPT/soundlib/plugins/LFOPlugin.h Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/soundlib/plugins/LFOPlugin.h Sat Nov 30 23:52:26 2024 (r22368) @@ -85,8 +85,7 @@ float RenderSilence(uint32) override { return 0.0f; } // MIDI event handling (mostly passing it through to the follow-up plugin) - bool MidiSend(uint32 midiCode) override; - bool MidiSysexSend(mpt::const_byte_span sysex) override; + bool MidiSend(mpt::const_byte_span midiData) override; void MidiCC(MIDIEvents::MidiCC nController, uint8 nParam, CHANNELINDEX trackChannel) override; void MidiPitchBend(int32 increment, int8 pwd, CHANNELINDEX trackChannel) override; void MidiTonePortamento(int32 increment, uint8 newNote, int8 pwd, CHANNELINDEX trackChannel) override; Modified: trunk/OpenMPT/soundlib/plugins/PlugInterface.cpp ============================================================================== --- trunk/OpenMPT/soundlib/plugins/PlugInterface.cpp Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/soundlib/plugins/PlugInterface.cpp Sat Nov 30 23:52:26 2024 (r22368) @@ -378,6 +378,14 @@ } +bool IMixPlugin::MidiSend(uint32 midiCode) +{ + std::array<std::byte, 4> midiData; + memcpy(midiData.data(), &midiCode, 4); + return MidiSend(mpt::as_span(midiData.data(), std::min(midiData.size(), MIDIEvents::GetEventLength(mpt::byte_cast<uint8>(midiData[0]))))); +} + + // Get list of plugins to which output is sent. A nullptr indicates master output. size_t IMixPlugin::GetOutputPlugList(std::vector<IMixPlugin *> &list) { @@ -995,8 +1003,11 @@ } -void IMidiPlugin::ReceiveMidi(uint32 midiCode) +void IMidiPlugin::ReceiveMidi(mpt::const_byte_span midiData) { + if(midiData.empty()) + return; + ResetSilence(); // I think we should only route events to plugins that are explicitely specified as output plugins of the current plugin. @@ -1006,32 +1017,18 @@ { IMixPlugin *plugin = m_SndFile.m_MixPlugins[receiver].pMixPlugin; // Add all events to the plugin's queue. - plugin->MidiSend(midiCode); + plugin->MidiSend(midiData); } #ifdef MODPLUG_TRACKER - if(m_recordMIDIOut) + if(m_recordMIDIOut && midiData[0] != std::byte{0xF0}) { // Spam MIDI data to all views + uint32 midiCode = 0; + memcpy(&midiCode, midiData.data(), std::min(sizeof(midiCode), midiData.size())); ::PostMessage(CMainFrame::GetMainFrame()->GetMidiRecordWnd(), WM_MOD_MIDIMSG, midiCode, reinterpret_cast<LPARAM>(this)); } -#endif // MODPLUG_TRACKER -} - - -void IMidiPlugin::ReceiveSysex(mpt::const_byte_span sysex) -{ - ResetSilence(); - - // I think we should only route events to plugins that are explicitely specified as output plugins of the current plugin. - // This should probably use GetOutputPlugList here if we ever get to support multiple output plugins. - PLUGINDEX receiver; - if(m_pMixStruct != nullptr && (receiver = m_pMixStruct->GetOutputPlugin()) != PLUGINDEX_INVALID) - { - IMixPlugin *plugin = m_SndFile.m_MixPlugins[receiver].pMixPlugin; - // Add all events to the plugin's queue. - plugin->MidiSysexSend(sysex); - } +#endif // MODPLUG_TRACKER } Modified: trunk/OpenMPT/soundlib/plugins/PlugInterface.h ============================================================================== --- trunk/OpenMPT/soundlib/plugins/PlugInterface.h Sat Nov 30 21:41:34 2024 (r22367) +++ trunk/OpenMPT/soundlib/plugins/PlugInterface.h Sat Nov 30 23:52:26 2024 (r22368) @@ -148,8 +148,8 @@ virtual float RenderSilence(uint32 numSamples); // MIDI event handling - virtual bool MidiSend(uint32 /*midiCode*/) { return true; } - virtual bool MidiSysexSend(mpt::const_byte_span /*sysex*/) { return true; } + bool MidiSend(uint32 midiCode); + virtual bool MidiSend(mpt::const_byte_span /*midiData*/) { return true; } virtual void MidiCC(MIDIEvents::MidiCC /*nController*/, uint8 /*nParam*/, CHANNELINDEX /*trackChannel*/) { } virtual void MidiPitchBendRaw(int32 /*pitchbend*/, CHANNELINDEX /*trackChannel*/) {} virtual void MidiPitchBend(int32 /*increment*/, int8 /*pwd*/, CHANNELINDEX /*trackChannel*/) { } @@ -292,8 +292,7 @@ uint8 GetMidiChannel(CHANNELINDEX trackChannel) const; // Plugin wants to send MIDI to OpenMPT - virtual void ReceiveMidi(uint32 midiCode); - virtual void ReceiveSysex(mpt::const_byte_span sysex); + virtual void ReceiveMidi(mpt::const_byte_span midiData); // Converts a 14-bit MIDI pitch bend position to our internal pitch bend position representation static constexpr int32 EncodePitchBendParam(int32 position) { return (position << kPitchBendShift); } |