summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-09-18 00:59:38 +0000
committerDavid Robillard <d@drobilla.net>2007-09-18 00:59:38 +0000
commitc7c29dfbbd6b237aada410ed36d5dcaaed8efbc8 (patch)
tree56af8996e3f98954433929c9465a885f905e3b72
parent89f56f276b9dc16fec03725f73f7df12260cd246 (diff)
downloadingen-c7c29dfbbd6b237aada410ed36d5dcaaed8efbc8.tar.gz
ingen-c7c29dfbbd6b237aada410ed36d5dcaaed8efbc8.tar.bz2
ingen-c7c29dfbbd6b237aada410ed36d5dcaaed8efbc8.zip
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
-rw-r--r--src/libs/engine/MidiBuffer.cpp16
-rw-r--r--src/libs/engine/MidiNoteNode.cpp24
-rw-r--r--src/libs/engine/Patch.cpp9
-rw-r--r--src/libs/engine/ProcessSlave.cpp8
4 files changed, 32 insertions, 25 deletions
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(&timestamp, &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<Port*>::iterator i = _input_ports.begin(); i != _input_ports.end(); ++i)
// (*i)->pre_process(nframes, start, end);
for (Raul::List<Port*>::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;
}