From bc46a7e2e9bf8688dd6461369978555f835cc623 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sat, 5 Aug 2017 15:35:31 +0200 Subject: PortAudio backend RT-safe MIDI buffer allocation --- libs/backends/portaudio/portaudio_backend.cc | 52 +++++++++++----------- libs/backends/portaudio/portaudio_backend.h | 8 ++-- libs/backends/portaudio/winmmemidi_io.h | 2 +- .../backends/portaudio/winmmemidi_output_device.cc | 5 +-- libs/backends/portaudio/winmmemidi_output_device.h | 2 + 5 files changed, 34 insertions(+), 35 deletions(-) (limited to 'libs') diff --git a/libs/backends/portaudio/portaudio_backend.cc b/libs/backends/portaudio/portaudio_backend.cc index 3ce0f094ac..ad7d976a2d 100644 --- a/libs/backends/portaudio/portaudio_backend.cc +++ b/libs/backends/portaudio/portaudio_backend.cc @@ -93,6 +93,8 @@ PortAudioBackend::PortAudioBackend (AudioEngine& e, AudioBackendInfo& info) pthread_mutex_init (&_freewheel_mutex, 0); pthread_cond_init (&_freewheel_signal, 0); + _port_connection_queue.reserve (128); + _pcmio = new PortAudioIO (); _midiio = new WinMMEMidiIO (); } @@ -1618,11 +1620,11 @@ PortAudioBackend::midi_event_get ( if (event_index >= source.size ()) { return -1; } - PortMidiEvent * const event = source[event_index].get (); + PortMidiEvent const& event = source[event_index].get (); - timestamp = event->timestamp (); - size = event->size (); - *buf = event->data (); + timestamp = event.timestamp (); + size = event.size (); + *buf = event.data (); return 0; } @@ -1634,13 +1636,15 @@ PortAudioBackend::midi_event_put ( { if (!buffer || !port_buffer) return -1; PortMidiBuffer& dst = * static_cast(port_buffer); - if (dst.size () && (pframes_t)dst.back ()->timestamp () > timestamp) { +#ifndef NDEBUG + if (dst.size () && (pframes_t)dst.back ().timestamp () > timestamp) { // nevermind, ::get_buffer() sorts events DEBUG_MIDI (string_compose ("PortMidiBuffer: unordered event: %1 > %2\n", - (pframes_t)dst.back ()->timestamp (), + (pframes_t)dst.back ().timestamp (), timestamp)); } - dst.push_back (boost::shared_ptr(new PortMidiEvent (timestamp, buffer, size))); +#endif + dst.push_back (PortMidiEvent (timestamp, buffer, size)); return 0; } @@ -2038,7 +2042,7 @@ PortAudioBackend::process_incoming_midi () mbuf->clear(); uint64_t timestamp; pframes_t sample_offset; - uint8_t data[256]; + uint8_t data[MaxWinMidiEventSize]; size_t size = sizeof(data); while (_midiio->dequeue_input_event(i, _cycle_timer.get_start(), @@ -2079,14 +2083,14 @@ PortAudioBackend::process_outgoing_midi () for (PortMidiBuffer::const_iterator mit = src->begin(); mit != src->end(); ++mit) { uint64_t timestamp = - _cycle_timer.timestamp_from_sample_offset((*mit)->timestamp()); + _cycle_timer.timestamp_from_sample_offset(mit->timestamp()); DEBUG_MIDI(string_compose("Queuing outgoing MIDI data for device: " "%1 sample_offset: %2 timestamp: %3, size: %4\n", _midiio->get_outputs()[i]->name(), - (*mit)->timestamp(), + mit->timestamp(), timestamp, - (*mit)->size())); - _midiio->enqueue_output_event(i, timestamp, (*mit)->data(), (*mit)->size()); + mit->size())); + _midiio->enqueue_output_event(i, timestamp, mit->data(), mit->size()); } } } @@ -2354,13 +2358,16 @@ PortMidiPort::PortMidiPort (PortAudioBackend &b, const std::string& name, PortFl { _buffer[0].clear (); _buffer[1].clear (); + + _buffer[0].reserve (256); + _buffer[1].reserve (256); } PortMidiPort::~PortMidiPort () { } struct MidiEventSorter { - bool operator() (const boost::shared_ptr& a, const boost::shared_ptr& b) { - return *a < *b; + bool operator() (PortMidiEvent const& a, PortMidiEvent const& b) { + return a < b; } }; @@ -2373,7 +2380,7 @@ void* PortMidiPort::get_buffer (pframes_t /* nframes */) ++i) { const PortMidiBuffer * src = static_cast(*i)->const_buffer (); for (PortMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) { - (_buffer[_bufperiod]).push_back (boost::shared_ptr(new PortMidiEvent (**it))); + (_buffer[_bufperiod]).push_back (*it); } } std::stable_sort ((_buffer[_bufperiod]).begin (), (_buffer[_bufperiod]).end (), MidiEventSorter()); @@ -2384,10 +2391,8 @@ void* PortMidiPort::get_buffer (pframes_t /* nframes */) PortMidiEvent::PortMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size) : _size (size) , _timestamp (timestamp) - , _data (0) { - if (size > 0) { - _data = (uint8_t*) malloc (size); + if (size > 0 && size < MaxWinMidiEventSize) { memcpy (_data, data, size); } } @@ -2395,14 +2400,9 @@ PortMidiEvent::PortMidiEvent (const pframes_t timestamp, const uint8_t* data, si PortMidiEvent::PortMidiEvent (const PortMidiEvent& other) : _size (other.size ()) , _timestamp (other.timestamp ()) - , _data (0) { - if (other.size () && other.const_data ()) { - _data = (uint8_t*) malloc (other.size ()); - memcpy (_data, other.const_data (), other.size ()); + if (other._size > 0) { + assert (other._size < MaxWinMidiEventSize); + memcpy (_data, other._data, other._size); } }; - -PortMidiEvent::~PortMidiEvent () { - free (_data); -}; diff --git a/libs/backends/portaudio/portaudio_backend.h b/libs/backends/portaudio/portaudio_backend.h index 34bdabe787..d5ce42aad0 100644 --- a/libs/backends/portaudio/portaudio_backend.h +++ b/libs/backends/portaudio/portaudio_backend.h @@ -45,19 +45,17 @@ class PortMidiEvent { public: PortMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size); PortMidiEvent (const PortMidiEvent& other); - ~PortMidiEvent (); size_t size () const { return _size; }; pframes_t timestamp () const { return _timestamp; }; - const unsigned char* const_data () const { return _data; }; - unsigned char* data () { return _data; }; + const uint8_t* const_data () const { return _data; }; bool operator< (const PortMidiEvent &other) const { return timestamp () < other.timestamp (); }; private: size_t _size; pframes_t _timestamp; - uint8_t *_data; + uint8_t _data[MaxWinMidiEventSize]; }; -typedef std::vector > PortMidiBuffer; +typedef std::vector PortMidiBuffer; class PamPort { // PortAudio / PortMidi Backend Port protected: diff --git a/libs/backends/portaudio/winmmemidi_io.h b/libs/backends/portaudio/winmmemidi_io.h index 672a68cc73..4d146981fb 100644 --- a/libs/backends/portaudio/winmmemidi_io.h +++ b/libs/backends/portaudio/winmmemidi_io.h @@ -50,7 +50,7 @@ struct WinMMEMIDIPacket { // MIDITimeStamp timeStamp; uint16_t length; - uint8_t data[256]; + uint8_t data[MaxWinMidiEventSize]; }; typedef std::vector > WinMMEMIDIQueue; diff --git a/libs/backends/portaudio/winmmemidi_output_device.cc b/libs/backends/portaudio/winmmemidi_output_device.cc index 5730e4b1be..2f6ad01895 100644 --- a/libs/backends/portaudio/winmmemidi_output_device.cc +++ b/libs/backends/portaudio/winmmemidi_output_device.cc @@ -32,7 +32,6 @@ // remove dup with input_device static const uint32_t MIDI_BUFFER_SIZE = 32768; -static const uint32_t MAX_MIDI_MSG_SIZE = 256; // fix this for sysex static const uint32_t MAX_QUEUE_SIZE = 4096; namespace ARDOUR { @@ -361,7 +360,7 @@ WinMMEMidiOutputDevice::midi_output_thread () DEBUG_MIDI ("WinMMEMidiOut: output thread woken by semaphore\n"); MidiEventHeader h (0, 0); - uint8_t data[MAX_MIDI_MSG_SIZE]; + uint8_t data[MaxWinMidiEventSize]; const uint32_t read_space = m_midi_buffer->read_space (); @@ -375,7 +374,7 @@ WinMMEMidiOutputDevice::midi_output_thread () } assert (read_space >= h.size); - if (h.size > MAX_MIDI_MSG_SIZE) { + if (h.size > MaxWinMidiEventSize) { m_midi_buffer->increment_read_idx (h.size); DEBUG_MIDI ("WinMMEMidiOut: MIDI event too large!\n"); continue; diff --git a/libs/backends/portaudio/winmmemidi_output_device.h b/libs/backends/portaudio/winmmemidi_output_device.h index 8c4d4d0c90..bc3a6251ae 100644 --- a/libs/backends/portaudio/winmmemidi_output_device.h +++ b/libs/backends/portaudio/winmmemidi_output_device.h @@ -31,6 +31,8 @@ #include +#define MaxWinMidiEventSize 256 + namespace ARDOUR { class WinMMEMidiOutputDevice { -- cgit v1.2.3