00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "JackError.h"
00021 #include "JackPortType.h"
00022 #include "JackMidiPort.h"
00023 #include <assert.h>
00024 #include <string.h>
00025
00026 namespace Jack
00027 {
00028
00029 void JackMidiBuffer::Reset(jack_nframes_t nframes)
00030 {
00031
00032 this->nframes = nframes;
00033 write_pos = 0;
00034 event_count = 0;
00035 lost_events = 0;
00036 mix_index = 0;
00037 }
00038
00039 jack_shmsize_t JackMidiBuffer::MaxEventSize() const
00040 {
00041 assert (((jack_shmsize_t) - 1) < 0);
00042 jack_shmsize_t left = buffer_size - (sizeof(JackMidiBuffer) + sizeof(JackMidiEvent) * (event_count + 1) + write_pos);
00043 if (left < 0)
00044 return 0;
00045 if (left <= JackMidiEvent::INLINE_SIZE_MAX)
00046 return JackMidiEvent::INLINE_SIZE_MAX;
00047 return left;
00048 }
00049
00050 jack_midi_data_t* JackMidiBuffer::ReserveEvent(jack_nframes_t time, jack_shmsize_t size)
00051 {
00052 jack_shmsize_t space = MaxEventSize();
00053 if (space == 0 || size > space) {
00054 lost_events++;
00055 return 0;
00056 }
00057
00058 JackMidiEvent* event = &events[event_count++];
00059 event->time = time;
00060 event->size = size;
00061 if (size <= JackMidiEvent::INLINE_SIZE_MAX)
00062 return event->data;
00063
00064 write_pos += size;
00065 event->offset = buffer_size - write_pos;
00066 return (jack_midi_data_t*)this + event->offset;
00067 }
00068
00069 static void MidiBufferInit(void* buffer, size_t buffer_size, jack_nframes_t nframes)
00070 {
00071 JackMidiBuffer* midi = (JackMidiBuffer*)buffer;
00072 midi->magic = JackMidiBuffer::MAGIC;
00073 midi->buffer_size = buffer_size;
00074 midi->Reset(nframes);
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 static void MidiBufferMixdown(void* mixbuffer, void** src_buffers, int src_count, jack_nframes_t nframes)
00088 {
00089 JackMidiBuffer* mix = static_cast<JackMidiBuffer*>(mixbuffer);
00090 if (!mix->IsValid()) {
00091 jack_error("MIDI: invalid mix buffer");
00092 return;
00093 }
00094 mix->Reset(nframes);
00095
00096 int event_count = 0;
00097 for (int i = 0; i < src_count; ++i) {
00098 JackMidiBuffer* buf = static_cast<JackMidiBuffer*>(src_buffers[i]);
00099 if (!buf->IsValid())
00100 return;
00101 buf->mix_index = 0;
00102 event_count += buf->event_count;
00103 mix->lost_events += buf->lost_events;
00104 }
00105
00106 int events_done;
00107 for (events_done = 0; events_done < event_count; ++events_done) {
00108 JackMidiBuffer* next_buf = 0;
00109 JackMidiEvent* next_event = 0;
00110
00111
00112 for (int i = 0; i < src_count; ++i) {
00113 JackMidiBuffer* buf = static_cast<JackMidiBuffer*>(src_buffers[i]);
00114 if (buf->mix_index >= buf->event_count)
00115 continue;
00116 JackMidiEvent* e = &buf->events[buf->mix_index];
00117 if (!next_event || e->time < next_event->time) {
00118 next_event = e;
00119 next_buf = buf;
00120 }
00121 }
00122 assert(next_event != 0);
00123
00124
00125 jack_midi_data_t* dest = mix->ReserveEvent(next_event->time, next_event->size);
00126 if (!dest)
00127 break;
00128 memcpy(dest, next_event->GetData(next_buf), next_event->size);
00129 next_buf->mix_index++;
00130 }
00131 mix->lost_events += event_count - events_done;
00132 }
00133
00134 const JackPortType gMidiPortType = {
00135 JACK_DEFAULT_MIDI_TYPE,
00136 MidiBufferInit,
00137 MidiBufferMixdown
00138 };
00139
00140 }