| @@ -1755,6 +1755,9 @@ private: | |||
| Array<const AudioProcessorParameterGroup*> parameterGroups; | |||
| //============================================================================== | |||
| // According to the docs, this is the maximum size of a MIDIPacketList. | |||
| static constexpr UInt32 packetListBytes = 65536; | |||
| AudioUnitEvent auEvent; | |||
| mutable Array<AUPreset> presetsArray; | |||
| CriticalSection incomingMidiLock; | |||
| @@ -1762,6 +1765,7 @@ private: | |||
| AudioTimeStamp lastTimeStamp; | |||
| int totalInChannels, totalOutChannels; | |||
| HeapBlock<bool> pulledSucceeded; | |||
| HeapBlock<MIDIPacketList> packetList { packetListBytes, 1 }; | |||
| ThreadLocalValue<bool> 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<MIDIPacketList> packetList; | |||
| packetList.malloc (packetListMembersSize + packetMembersSize * numPackets + dataSize, 1); | |||
| packetList->numPackets = numPackets; | |||
| const auto add = [&] (const MidiMessageMetadata& metadata) | |||
| { | |||
| end = MIDIPacketListAdd (packetList, | |||
| packetListBytes, | |||
| end, | |||
| static_cast<MIDITimeStamp> (metadata.samplePosition), | |||
| static_cast<ByteCount> (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) | |||