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