From 75fae3bf213fa7bc56e69491ad06c2a4ce6d4c8b Mon Sep 17 00:00:00 2001 From: reuk Date: Mon, 1 Mar 2021 17:05:47 +0000 Subject: [PATCH] AU: Fix midi output to use correct packet alignment on ARM --- .../AU/juce_AU_Wrapper.mm | 64 +++++++++++++------ 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm index 1a6879078e..aad5da8f28 100644 --- a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm +++ b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm @@ -1755,6 +1755,9 @@ private: Array parameterGroups; //============================================================================== + // According to the docs, this is the maximum size of a MIDIPacketList. + static constexpr UInt32 packetListBytes = 65536; + AudioUnitEvent auEvent; mutable Array presetsArray; CriticalSection incomingMidiLock; @@ -1762,6 +1765,7 @@ private: AudioTimeStamp lastTimeStamp; int totalInChannels, totalOutChannels; HeapBlock pulledSucceeded; + HeapBlock packetList { packetListBytes, 1 }; ThreadLocalValue inParameterChangedCallback; @@ -1858,37 +1862,55 @@ private: void pushMidiOutput (UInt32 nFrames) noexcept { - UInt32 numPackets = 0; - size_t dataSize = 0; + MIDIPacket* end = nullptr; - for (const auto metadata : midiEvents) + const auto init = [&] { - jassert (isPositiveAndBelow (metadata.samplePosition, nFrames)); - ignoreUnused (nFrames); + end = MIDIPacketListInit (packetList); + }; - dataSize += (size_t) metadata.numBytes; - ++numPackets; - } - - MIDIPacket* p; - const size_t packetMembersSize = sizeof (MIDIPacket) - sizeof (p->data); // NB: GCC chokes on "sizeof (MidiMessage::data)" - const size_t packetListMembersSize = sizeof (MIDIPacketList) - sizeof (p->data); + const auto send = [&] + { + midiCallback.midiOutputCallback (midiCallback.userData, &lastTimeStamp, 0, packetList); + }; - HeapBlock packetList; - packetList.malloc (packetListMembersSize + packetMembersSize * numPackets + dataSize, 1); - packetList->numPackets = numPackets; + const auto add = [&] (const MidiMessageMetadata& metadata) + { + end = MIDIPacketListAdd (packetList, + packetListBytes, + end, + static_cast (metadata.samplePosition), + static_cast (metadata.numBytes), + metadata.data); + }; - p = packetList->packet; + init(); for (const auto metadata : midiEvents) { - p->timeStamp = (MIDITimeStamp) metadata.samplePosition; - p->length = (UInt16) metadata.numBytes; - memcpy (p->data, metadata.data, (size_t) metadata.numBytes); - p = MIDIPacketNext (p); + jassert (isPositiveAndBelow (metadata.samplePosition, nFrames)); + ignoreUnused (nFrames); + + add (metadata); + + if (end == nullptr) + { + send(); + init(); + add (metadata); + + if (end == nullptr) + { + // If this is hit, the size of this midi packet exceeds the maximum size of + // a MIDIPacketList. Large SysEx messages should be broken up into smaller + // chunks. + jassertfalse; + init(); + } + } } - midiCallback.midiOutputCallback (midiCallback.userData, &lastTimeStamp, 0, packetList); + send(); } void GetAudioBufferList (bool isInput, int busIdx, AudioBufferList*& bufferList, bool& interleaved, int& numChannels)