rework/optimize CoreMidi
authorRobin Gareus <robin@gareus.org>
Mon, 9 Mar 2015 22:28:18 +0000 (23:28 +0100)
committerRobin Gareus <robin@gareus.org>
Mon, 9 Mar 2015 22:28:57 +0000 (23:28 +0100)
libs/backends/coreaudio/coreaudio_backend.cc
libs/backends/coreaudio/coremidi_io.cc
libs/backends/coreaudio/coremidi_io.h

index b3459511fbb83cd6830a3edf8e8bc7c28a5d62f1..0e978bff7162c4aefdf75e0ea05ebee777e76887 100644 (file)
@@ -1577,7 +1577,7 @@ CoreAudioBackend::process_callback (const uint32_t n_samples, const uint64_t hos
        pre_process();
 
        // cycle-length in usec
-       const int64_t nominal_time = 1e6 * n_samples / _samplerate;
+       const double nominal_time = 1e6 * n_samples / _samplerate;
 
        clock1 = g_get_monotonic_time();
 
@@ -1627,10 +1627,15 @@ CoreAudioBackend::process_callback (const uint32_t n_samples, const uint64_t hos
        /* queue outgoing midi */
        i = 0;
        for (std::vector<CoreBackendPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
+#if 0 // something's still b0rked with CoreMidiIo::send_events()
+               const CoreMidiBuffer *src = static_cast<const CoreMidiPort*>(*it)->const_buffer();
+               _midiio->send_events (i, nominal_time, (void*)src);
+#else // works..
                const CoreMidiBuffer *src = static_cast<const CoreMidiPort*>(*it)->const_buffer();
                for (CoreMidiBuffer::const_iterator mit = src->begin (); mit != src->end (); ++mit) {
                        _midiio->send_event (i, (*mit)->timestamp() / nominal_time, (*mit)->data(), (*mit)->size());
                }
+#endif
        }
 
        /* write back audio */
@@ -1644,7 +1649,7 @@ CoreAudioBackend::process_callback (const uint32_t n_samples, const uint64_t hos
        /* calc DSP load. */
        clock2 = g_get_monotonic_time();
        const int64_t elapsed_time = clock2 - clock1;
-       _dsp_load = elapsed_time / (float) nominal_time;
+       _dsp_load = elapsed_time / nominal_time;
 
        pthread_mutex_unlock (&_process_callback_mutex);
        return 0;
index 365bde945760ac2d22c6ea745afe8d93e276a31c..8b6bad82e8108daaba889ecc7802f70d554c357c 100644 (file)
@@ -20,6 +20,7 @@
 #include <CoreAudio/HostTime.h>
 
 #include "coremidi_io.h"
+#include "coreaudio_backend.h"
 
 using namespace ARDOUR;
 
@@ -36,13 +37,16 @@ static void midiInputCallback(const MIDIPacketList *list, void *procRef, void *s
        }
        RingBuffer<uint8_t> * rb  = static_cast<RingBuffer < uint8_t > *> (srcRef);
        if (!rb) return;
-       for (UInt32 i = 0; i < list->numPackets; i++) {
-               const MIDIPacket *packet = &list->packet[i];
-               if (rb->write_space() < sizeof(MIDIPacket)) {
+       MIDIPacket const *p = &list->packet[0];
+       for (UInt32 i = 0; i < list->numPackets; ++i) {
+               uint32_t len = ((p->length + 3)&~3) + sizeof(MIDITimeStamp) + sizeof(UInt16);
+               if (rb->write_space() < sizeof(uint32_t) + len) {
                        fprintf(stderr, "CoreMIDI: dropped MIDI event\n");
                        continue;
                }
-               rb->write((uint8_t*)packet, sizeof(MIDIPacket));
+               rb->write ((uint8_t*)&len, sizeof(uint32_t));
+               rb->write ((uint8_t*)p, len);
+               p = MIDIPacketNext (p);
        }
 }
 
@@ -176,10 +180,16 @@ CoreMidiIo::recv_event (uint32_t port, double cycle_time_us, uint64_t &time, uin
        }
        assert(port < _n_midi_in);
 
-       while (_rb[port]->read_space() >= sizeof(MIDIPacket)) {
+       const size_t minsize = 1 + sizeof(uint32_t) + sizeof(MIDITimeStamp) + sizeof(UInt16);
+
+       while (_rb[port]->read_space() > minsize) {
                MIDIPacket packet;
-               size_t rv = _rb[port]->read((uint8_t*)&packet, sizeof(MIDIPacket));
-               assert(rv == sizeof(MIDIPacket));
+               size_t rv;
+               uint32_t s = 0;
+               rv = _rb[port]->read((uint8_t*)&s, sizeof(uint32_t));
+               assert(rv == sizeof(uint32_t));
+               rv = _rb[port]->read((uint8_t*)&packet, s);
+               assert(rv == s);
                _input_queue[port].push_back(boost::shared_ptr<CoreMIDIPacket>(new _CoreMIDIPacket (&packet)));
        }
 
@@ -212,6 +222,40 @@ CoreMidiIo::recv_event (uint32_t port, double cycle_time_us, uint64_t &time, uin
        return 0;
 }
 
+int
+CoreMidiIo::send_events (uint32_t port, double timescale, const void *b)
+{
+       if (!_active || _time_at_cycle_start == 0) {
+               return 0;
+       }
+
+       assert(port < _n_midi_out);
+       const UInt64 ts = AudioConvertHostTimeToNanos(_time_at_cycle_start);
+
+       const CoreMidiBuffer *src = static_cast<CoreMidiBuffer const *>(b);
+
+       int32_t bytes[8192]; // int for alignment
+       MIDIPacketList *mpl = (MIDIPacketList*)bytes;
+       MIDIPacket *cur = MIDIPacketListInit(mpl);
+
+       for (CoreMidiBuffer::const_iterator mit = src->begin (); mit != src->end (); ++mit) {
+               assert((*mit)->size() < 256);
+               cur = MIDIPacketListAdd(mpl, sizeof(bytes), cur,
+                               AudioConvertNanosToHostTime(ts + (*mit)->timestamp() / timescale),
+                               (*mit)->size(), (*mit)->data());
+               if (!cur) {
+#ifndef DEBUG
+                       printf("CoreMidi: Packet list overflow, dropped events\n");
+#endif
+                       break;
+               }
+       }
+       if (mpl->numPackets > 0) {
+               MIDISend(_output_ports[port], _output_endpoints[port], mpl);
+       }
+       return 0;
+}
+
 int
 CoreMidiIo::send_event (uint32_t port, double reltime_us, const uint8_t *d, const size_t s)
 {
index b5eda1c2fdfeb666e4b4f62638ed4ca49d5e3774..21806ab4fd60641a3220476b298655ee8729f328 100644 (file)
@@ -75,6 +75,7 @@ public:
        void start_cycle ();
 
        int send_event (uint32_t, double, const uint8_t *, const size_t);
+       int send_events (uint32_t, double, const void *);
        size_t recv_event (uint32_t, double, uint64_t &, uint8_t *, size_t &);
 
        uint32_t n_midi_inputs (void) const { return _n_midi_in; }