summaryrefslogtreecommitdiff
path: root/libs/ardour/midi_model.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/midi_model.cc')
-rw-r--r--libs/ardour/midi_model.cc100
1 files changed, 79 insertions, 21 deletions
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index bfc1e4b300..98d29a2729 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -1,6 +1,6 @@
/*
- Copyright (C) 2006 Paul Davis
- Written by Dave Robillard, 2006
+ Copyright (C) 2007 Paul Davis
+ Written by Dave Robillard, 2007
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
#include <iostream>
#include <ardour/midi_model.h>
+#include <ardour/midi_events.h>
#include <ardour/types.h>
using namespace std;
@@ -27,14 +28,45 @@ using namespace ARDOUR;
MidiModel::MidiModel(size_t size)
-: _events(size)
+ : _notes(size)
{
}
-MidiModel::~MidiModel()
+
+/** Begin a write of events to the model.
+ *
+ * As note on and off events are written, complete notes with duration are
+ * constructed
+ */
+void
+MidiModel::start_write()
{
- for (size_t i=0; i < _events.size(); ++i)
- delete _events[i].buffer;
+ _write_notes.clear();
+}
+
+
+
+/** Finish a write of events to the model.
+ *
+ * If \a delete_stuck is true, note on events that were never resolved with
+ * a corresonding note off will be deleted. Otherwise they will remain as
+ * notes with duration 0.
+ */
+void
+MidiModel::end_write(bool delete_stuck)
+{
+ if (delete_stuck) {
+ _write_notes.clear();
+ } else {
+ cerr << "FIXME: Stuck notes lost" << endl;
+ _write_notes.clear();
+ /* Merge _write_events into _events */
+ /*size_t ev_index = 0
+ size_t write_index = 0;
+ while ( ! _write_events.empty()) {
+ // do stuff
+ }*/
+ }
}
@@ -50,16 +82,14 @@ void
MidiModel::append(const MidiBuffer& buf)
{
for (size_t i=0; i < buf.size(); ++i) {
- const MidiEvent& buf_event = buf[i];
- assert(_events.empty() || buf_event.time >= _events.back().time);
-
- _events.push_back(buf_event);
- MidiEvent& my_event = _events.back();
- assert(my_event.time == buf_event.time);
- assert(my_event.size == buf_event.size);
+ const MidiEvent& ev = buf[i];
- my_event.buffer = new Byte[my_event.size];
- memcpy(my_event.buffer, buf_event.buffer, my_event.size);
+ assert(_write_notes.empty() || ev.time >= _write_notes.back().start);
+
+ if (ev.type() == MIDI_CMD_NOTE_ON)
+ append_note_on(ev.time, ev.note(), ev.velocity());
+ else if (ev.type() == MIDI_CMD_NOTE_OFF)
+ append_note_off(ev.time, ev.note());
}
}
@@ -71,14 +101,42 @@ MidiModel::append(const MidiBuffer& buf)
* and MUST be >= the latest event currently in the model.
*/
void
-MidiModel::append(double time, size_t size, Byte* in_buffer)
+MidiModel::append(double time, size_t size, Byte* buf)
+{
+ assert(_write_notes.empty() || time >= _write_notes.back().start);
+
+ if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_ON)
+ append_note_on(time, buf[1], buf[2]);
+ else if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_OFF)
+ append_note_off(time, buf[1]);
+}
+
+
+void
+MidiModel::append_note_on(double time, uint8_t note, uint8_t velocity)
{
- assert(_events.empty() || time >= _events.back().time);
+ _write_notes.push_back(Note(time, 0, note, velocity));
+}
- //cerr << "Model event: time = " << time << endl;
- Byte* my_buffer = new Byte[size];
- memcpy(my_buffer, in_buffer, size);
- _events.push_back(MidiEvent(time, size, my_buffer));
+void
+MidiModel::append_note_off(double time, uint8_t note_num)
+{
+ /* _write_notes (active notes) is presumably small enough for linear
+ * search to be a good idea. maybe not with instruments (percussion)
+ * that don't send note off at all though.... FIXME? */
+
+ /* FIXME: note off velocity for that one guy out there who actually has
+ * keys that send it */
+
+ for (size_t i=0; i < _write_notes.size(); ++i) {
+ Note& note = _write_notes[i];
+ if (note.note == note_num) {
+ assert(time > note.start);
+ note.duration = time - note.start;
+ cerr << "MidiModel resolved note, duration: " << note.duration << endl;
+ break;
+ }
+ }
}