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 SERVER_EXPORT 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 SERVER_EXPORT 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 SERVER_EXPORT 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
00075 midi->buffer_size = BUFFER_SIZE_MAX * sizeof(float);
00076 midi->Reset(nframes);
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 static void MidiBufferMixdown(void* mixbuffer, void** src_buffers, int src_count, jack_nframes_t nframes)
00090 {
00091 JackMidiBuffer* mix = static_cast<JackMidiBuffer*>(mixbuffer);
00092 if (!mix->IsValid()) {
00093 jack_error("MIDI: invalid mix buffer");
00094 return;
00095 }
00096 mix->Reset(nframes);
00097
00098 int event_count = 0;
00099 for (int i = 0; i < src_count; ++i) {
00100 JackMidiBuffer* buf = static_cast<JackMidiBuffer*>(src_buffers[i]);
00101 if (!buf->IsValid())
00102 return;
00103 buf->mix_index = 0;
00104 event_count += buf->event_count;
00105 mix->lost_events += buf->lost_events;
00106 }
00107
00108 int events_done;
00109 for (events_done = 0; events_done < event_count; ++events_done) {
00110 JackMidiBuffer* next_buf = 0;
00111 JackMidiEvent* next_event = 0;
00112
00113
00114 for (int i = 0; i < src_count; ++i) {
00115 JackMidiBuffer* buf = static_cast<JackMidiBuffer*>(src_buffers[i]);
00116 if (buf->mix_index >= buf->event_count)
00117 continue;
00118 JackMidiEvent* e = &buf->events[buf->mix_index];
00119 if (!next_event || e->time < next_event->time) {
00120 next_event = e;
00121 next_buf = buf;
00122 }
00123 }
00124 assert(next_event != 0);
00125
00126
00127 jack_midi_data_t* dest = mix->ReserveEvent(next_event->time, next_event->size);
00128 if (!dest)
00129 break;
00130 memcpy(dest, next_event->GetData(next_buf), next_event->size);
00131 next_buf->mix_index++;
00132 }
00133 mix->lost_events += event_count - events_done;
00134 }
00135
00136 const JackPortType gMidiPortType =
00137 {
00138 JACK_DEFAULT_MIDI_TYPE,
00139 MidiBufferInit,
00140 MidiBufferMixdown
00141 };
00142
00143 }