diff options
Diffstat (limited to 'libs/ardour/midi_model.cc')
-rw-r--r-- | libs/ardour/midi_model.cc | 100 |
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; + } + } } |