From c7c29dfbbd6b237aada410ed36d5dcaaed8efbc8 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 18 Sep 2007 00:59:38 +0000 Subject: Fix MIDI buffer reading error, fixes reading of multiple MIDI events per cycle (including stuck notes, fixes ticket 86). git-svn-id: http://svn.drobilla.net/lad/ingen@717 a436a847-0d15-0410-975c-d299462d15a1 --- src/libs/engine/MidiBuffer.cpp | 16 ++++++++++++---- src/libs/engine/MidiNoteNode.cpp | 24 +++++++++++++++++++----- src/libs/engine/Patch.cpp | 9 +-------- src/libs/engine/ProcessSlave.cpp | 8 -------- 4 files changed, 32 insertions(+), 25 deletions(-) (limited to 'src/libs') diff --git a/src/libs/engine/MidiBuffer.cpp b/src/libs/engine/MidiBuffer.cpp index 4ec63524..5a8dbc4e 100644 --- a/src/libs/engine/MidiBuffer.cpp +++ b/src/libs/engine/MidiBuffer.cpp @@ -135,6 +135,7 @@ MidiBuffer::copy(const Buffer* src_buf, size_t start_sample, size_t end_sample) unsigned char* data; while (src->increment() < frame_count) { src->get_event(&time, &size, &data); + assert(data[0] >= 0x80); append(time, size, data); } } @@ -152,12 +153,15 @@ MidiBuffer::increment() const return _this_nframes; // hit end } - _position += sizeof(double) + sizeof(uint32_t) + *(uint32_t*)(_buf->data + _position); + _position += sizeof(double) + sizeof(uint32_t) + + *(uint32_t*)(_buf->data + _position + sizeof(double)); - if (_position >= _buf->size) + if (_position >= _buf->size) { + _position = _buf->size; return _this_nframes; - else + } else { return *(double*)(_buf->data + _position); + } } @@ -175,6 +179,9 @@ MidiBuffer::append(double timestamp, { if (_buf->capacity - _buf->size < sizeof(double) + sizeof(uint32_t) + size) return false; + + assert(size > 0); + assert(data[0] >= 0x80); *(double*)(_buf->data + _buf->size) = timestamp; _buf->size += sizeof(double); @@ -204,12 +211,13 @@ MidiBuffer::get_event(double* timestamp, *timestamp = _this_nframes; *size = 0; *data = NULL; - return *timestamp; + return _this_nframes; } *timestamp = *(double*)(_buf->data + _position); *size = *(uint32_t*)(_buf->data + _position + sizeof(double)); *data = _buf->data + _position + sizeof(double) + sizeof(uint32_t); + return *timestamp; } diff --git a/src/libs/engine/MidiNoteNode.cpp b/src/libs/engine/MidiNoteNode.cpp index e4ad4f87..6ad80675 100644 --- a/src/libs/engine/MidiNoteNode.cpp +++ b/src/libs/engine/MidiNoteNode.cpp @@ -86,6 +86,7 @@ MidiNoteNode::process(SampleCount nframes, FrameTime start, FrameTime end) MidiBuffer* const midi_in = (MidiBuffer*)_midi_in_port->buffer(0); assert(midi_in->this_nframes() == nframes); + if (midi_in->event_count() > 0) while (midi_in->get_event(×tamp, &size, &buffer) < nframes) { const FrameTime time = start + (FrameTime)timestamp; @@ -114,15 +115,23 @@ MidiNoteNode::process(SampleCount nframes, FrameTime start, FrameTime end) sustain_off(time, nframes, start, end); break; case MIDI_CMD_BENDER: - + // ? + break; + default: + //cerr << "Ignored controller " << buffer[1] << endl; break; } + break; default: + //fprintf(stderr, "Unknown (size %d) MIDI event %X\n", size, buffer[0]); break; } + } else { + //fprintf(stderr, "Unknown (size %d) MIDI event %X\n", size, buffer[0]); } - midi_in->increment(); + if (midi_in->increment() == midi_in->this_nframes()) + break; } NodeBase::post_process(nframes, start, end); @@ -165,7 +174,7 @@ MidiNoteNode::note_on(uchar note_num, uchar velocity, FrameTime time, SampleCoun assert(voice != NULL); assert(voice == &_voices[voice_num]); - //cerr << "[MidiNoteNode] Note on. Key " << (int)note_num << ", Voice " << voice_num << endl; + //cerr << "[MidiNoteNode] Note on @ " << time << ". Key " << (int)note_num << ", Voice " << voice_num << endl; // Update stolen key, if applicable if (voice->state == Voice::Voice::ACTIVE) { @@ -218,16 +227,21 @@ MidiNoteNode::note_off(uchar note_num, FrameTime time, SampleCount nframes, Fram assert(time - start < _buffer_size); Key* key = &_keys[note_num]; + + //cerr << "[MidiNoteNode] Note off @ " << time << ". Key " << (int)note_num << endl; if (key->state == Key::ON_ASSIGNED) { // Assigned key, turn off voice and key if (_voices[key->voice].state == Voice::ACTIVE) { assert(_voices[key->voice].note == note_num); - if ( ! _sustain) + if ( ! _sustain) { + //cerr << "... free voice " << key->voice << endl; free_voice(key->voice, time, nframes, start, end); - else + } else { + //cerr << "... hold voice " << key->voice << endl; _voices[key->voice].state = Voice::HOLDING; + } } else { #ifndef NDEBUG diff --git a/src/libs/engine/Patch.cpp b/src/libs/engine/Patch.cpp index 8e0b8862..78184a82 100644 --- a/src/libs/engine/Patch.cpp +++ b/src/libs/engine/Patch.cpp @@ -120,7 +120,7 @@ Patch::process(SampleCount nframes, FrameTime start, FrameTime end) /* Prepare input ports */ - // This breaks MIDI input, somehow (?) + // FIXME: This breaks MIDI input, somehow? OK disabled? //for (Raul::List::iterator i = _input_ports.begin(); i != _input_ports.end(); ++i) // (*i)->pre_process(nframes, start, end); for (Raul::List::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) @@ -171,7 +171,6 @@ Patch::process_parallel(SampleCount nframes, FrameTime start, FrameTime end) */ size_t index = 0; - //size_t run_count = 0; size_t num_finished = 0; // Number of consecutive finished nodes hit while (num_finished < cp->size()) { @@ -180,16 +179,12 @@ Patch::process_parallel(SampleCount nframes, FrameTime start, FrameTime end) if (n.node()->process_lock()) { if (n.node()->n_inputs_ready() == n.n_providers()) { - //cout << "************ Main running " << n.node()->path() << " at index " << index << endl; n.node()->process(nframes, start, end); - //cerr << n.node()->path() << " @ " << &n << " dependants: " << n.dependants().size() << endl; - /* Signal dependants their input is ready */ for (size_t i=0; i < n.dependants().size(); ++i) n.dependants()[i]->signal_input_ready(); - //++run_count; ++num_finished; } else { n.node()->process_unlock(); @@ -205,8 +200,6 @@ Patch::process_parallel(SampleCount nframes, FrameTime start, FrameTime end) index = (index + 1) % cp->size(); } - //cout << "Main Thread ran \t" << run_count << " nodes this cycle." << endl; - /* Tell slaves we're done in case we beat them, and pray they're * really done by the start of next cycle. * FIXME: This probably breaks (race) at extremely small nframes. diff --git a/src/libs/engine/ProcessSlave.cpp b/src/libs/engine/ProcessSlave.cpp index fba09da4..749f6a5c 100644 --- a/src/libs/engine/ProcessSlave.cpp +++ b/src/libs/engine/ProcessSlave.cpp @@ -39,7 +39,6 @@ ProcessSlave::_whipped() * and thus are finished this cycle. */ - //size_t run_count = 0; size_t num_finished = 0; // Number of consecutive finished nodes hit while (_state == STATE_RUNNING) { @@ -50,17 +49,12 @@ ProcessSlave::_whipped() n.node()->wait_for_input(n.n_providers()); - //cout << "************ Thread " << _id << " running " - // << n.node()->path() << " at index " << _index << endl; n.node()->process(_nframes, _start, _end); - //cerr << n.node()->path() << " @ " << &n << " dependants: " << n.dependants().size() << endl; - /* Signal dependants their input is ready */ for (size_t i=0; i < n.dependants().size(); ++i) n.dependants()[i]->signal_input_ready(); - //++run_count; num_finished = 1; } else { ++num_finished; @@ -75,8 +69,6 @@ ProcessSlave::_whipped() _index = 0; _compiled_patch = NULL; _state = STATE_FINISHED; - - //cout << "Thread " << _id << " ran \t" << run_count << " nodes this cycle." << endl; } -- cgit v1.2.1