summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-08-13 15:32:29 +0000
committerDavid Robillard <d@drobilla.net>2007-08-13 15:32:29 +0000
commit67a0d6b2d95b78ccac98dc051ff4314a509a9003 (patch)
tree834367eb6f39ad51e46672c11f495e8f96ac2ddb /libs
parent5156998e6e2536c9c713974d3ae719a5d2ef5c7f (diff)
Fix (edited) MIDI saving restoring (restore note offs/durations correctly).
git-svn-id: svn://localhost/ardour2/trunk@2292 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/midi_model.cc43
-rw-r--r--libs/ardour/smf_source.cc10
2 files changed, 32 insertions, 21 deletions
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 34c345254b..45a49e73ba 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -118,17 +118,12 @@ MidiModel::read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframe
{
size_t read_events = 0;
- cerr << "MM READ @ " << start << " + " << nframes << endl;
-
- /* FIXME: cache last lookup value to avoid the search */
+ /* FIXME: cache last lookup value to avoid O(n) search every time */
if (_note_mode == Sustained) {
- /* FIXME: cache last lookup value to avoid the search */
for (Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n) {
- cerr << "MM NOTE " << n->time() << endl;
-
while ( ! _active_notes.empty() ) {
const Note* const earliest_off = _active_notes.top();
const MidiEvent& off_ev = earliest_off->off_event();
@@ -153,6 +148,19 @@ MidiModel::read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframe
}
}
+
+ // Write any trailing note offs
+ while ( ! _active_notes.empty() ) {
+ const Note* const earliest_off = _active_notes.top();
+ const MidiEvent& off_ev = earliest_off->off_event();
+ if (off_ev.time() < start + nframes) {
+ dst.write(off_ev.time() + stamp_offset, off_ev.size(), off_ev.buffer());
+ _active_notes.pop();
+ ++read_events;
+ } else {
+ break;
+ }
+ }
// Percussive
} else {
@@ -170,9 +178,6 @@ MidiModel::read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframe
}
}
- //if (read_events > 0)
- // cerr << "MM READ " << read_events << " EVENTS" << endl;
-
return read_events;
}
@@ -205,7 +210,7 @@ MidiModel::end_write(bool delete_stuck)
{
assert(_writing);
- //cerr << "MM END WRITE\n";
+ //cerr << "MM END WRITE: " << _notes.size() << " STUCK NOTES\n";
if (_note_mode == Sustained && delete_stuck) {
for (Notes::iterator n = _notes.begin(); n != _notes.end() ; ) {
@@ -278,10 +283,10 @@ MidiModel::append_note_on(double time, uint8_t note_num, uint8_t velocity)
assert(_writing);
_notes.push_back(Note(time, 0, note_num, velocity));
if (_note_mode == Sustained) {
- //cerr << "MM Appending note on " << (unsigned)(uint8_t)note_num << endl;
+ //cerr << "MM Sustained: Appending active note on " << (unsigned)(uint8_t)note_num << endl;
_write_notes.push_back(_notes.size() - 1);
} else {
- //cerr << "MM NOT appending note on" << endl;
+ //cerr << "MM Percussive: NOT appending active note on" << endl;
}
}
@@ -309,7 +314,7 @@ MidiModel::append_note_off(double time, uint8_t note_num)
assert(time > note.time());
note.set_duration(time - note.time());
_write_notes.erase(n);
- //cerr << "MidiModel resolved note, duration: " << note.duration() << endl;
+ //cerr << "MM resolved note, duration: " << note.duration() << endl;
break;
}
}
@@ -319,7 +324,7 @@ MidiModel::append_note_off(double time, uint8_t note_num)
void
MidiModel::add_note_unlocked(const Note& note)
{
- cerr << "MidiModel " << this << " add note " << (int)note.note() << " @ " << note.time() << endl;
+ //cerr << "MidiModel " << this << " add note " << (int)note.note() << " @ " << note.time() << endl;
Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note, note_time_comparator);
_notes.insert(i, note);
}
@@ -328,7 +333,7 @@ MidiModel::add_note_unlocked(const Note& note)
void
MidiModel::remove_note_unlocked(const Note& note)
{
- cerr << "MidiModel " << this << " remove note " << (int)note.note() << " @ " << note.time() << endl;
+ //cerr << "MidiModel " << this << " remove note " << (int)note.note() << " @ " << note.time() << endl;
Notes::iterator n = find(_notes.begin(), _notes.end(), note);
if (n != _notes.end())
_notes.erase(n);
@@ -445,7 +450,7 @@ MidiModel::DeltaCommand::undo()
bool
MidiModel::write_to(boost::shared_ptr<MidiSource> source)
{
- cerr << "Writing model to " << source->name() << endl;
+ //cerr << "Writing model to " << source->name() << endl;
/* This could be done using a temporary MidiRingBuffer and using
* MidiModel::read and MidiSource::write, but this is more efficient
@@ -490,6 +495,12 @@ MidiModel::write_to(boost::shared_ptr<MidiSource> source)
if (n->duration() > 0)
active_notes.push(&(*n));
}
+
+ // Write any trailing note offs
+ while ( ! active_notes.empty() ) {
+ source->append_event_unlocked(active_notes.top()->off_event());
+ active_notes.pop();
+ }
_edited = false;
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 1f7221c316..537f2ccfb2 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -70,7 +70,7 @@ SMFSource::SMFSource (Session& s, std::string path, Flag flags)
throw failed_constructor ();
}
- cerr << "SMF Source path: " << path << endl;
+ //cerr << "SMF Source path: " << path << endl;
assert(_name.find("/") == string::npos);
}
@@ -99,7 +99,7 @@ SMFSource::SMFSource (Session& s, const XMLNode& node)
throw failed_constructor ();
}
- cerr << "SMF Source name: " << _name << endl;
+ //cerr << "SMF Source name: " << _name << endl;
assert(_name.find("/") == string::npos);
}
@@ -402,11 +402,11 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
void
SMFSource::append_event_unlocked(const MidiEvent& ev)
{
- printf("SMF - writing event, time = %lf, size = %u, data = ", ev.time(), ev.size());
+ /*printf("SMF - writing event, time = %lf, size = %u, data = ", ev.time(), ev.size());
for (size_t i=0; i < ev.size(); ++i) {
printf("%X ", ev.buffer()[i]);
}
- printf("\n");
+ printf("\n");*/
assert(ev.time() >= _last_ev_time);
@@ -730,7 +730,7 @@ SMFSource::is_empty () const
{
bool ret = (_track_size > 4);
- cerr << name() << " IS EMPTY: " << ret << endl;
+ //cerr << name() << " IS EMPTY: " << ret << endl;
return ret;
}