summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-02-18 23:30:27 +0000
committerDavid Robillard <d@drobilla.net>2008-02-18 23:30:27 +0000
commit466500fdaf25b57ba7c99ffe7a78364212be8e40 (patch)
tree4d2b9a9f644b6a350e986bdb7287dfb0e3a03b3d /libs
parentfbfb26b45c075da880861cf2303b851fe1acc0e8 (diff)
Channel-aware note recording in MidiModel (i.e. multi-channel note input doesn't cause stuck notes).
Fix MIDI regions randomly displaying 100% stuck notes (uninitialized MidiPlaylist::_note_mode). git-svn-id: svn://localhost/ardour2/branches/3.0@3084 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/midi_model.h8
-rw-r--r--libs/ardour/import.cc6
-rw-r--r--libs/ardour/midi_diskstream.cc1
-rw-r--r--libs/ardour/midi_model.cc68
-rw-r--r--libs/ardour/midi_playlist.cc1
-rw-r--r--libs/ardour/midi_track.cc2
-rw-r--r--libs/ardour/session.cc1
-rw-r--r--libs/ardour/smf_source.cc6
8 files changed, 59 insertions, 34 deletions
diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h
index 8e7d786722..61b39c9142 100644
--- a/libs/ardour/ardour/midi_model.h
+++ b/libs/ardour/ardour/midi_model.h
@@ -191,9 +191,9 @@ private:
bool is_sorted() const;
#endif
- void append_note_on_unlocked(double time, uint8_t note, uint8_t velocity);
- void append_note_off_unlocked(double time, uint8_t note);
- void append_cc_unlocked(double time, uint8_t number, uint8_t value);
+ void append_note_on_unlocked(uint8_t chan, double time, uint8_t note, uint8_t velocity);
+ void append_note_off_unlocked(uint8_t chan, double time, uint8_t note);
+ void append_cc_unlocked(uint8_t chan, double time, uint8_t number, uint8_t value);
mutable Glib::RWLock _lock;
@@ -201,7 +201,7 @@ private:
NoteMode _note_mode;
typedef std::vector<size_t> WriteNotes;
- WriteNotes _write_notes;
+ WriteNotes _write_notes[16];
bool _writing;
bool _edited;
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index d4a1bc72e7..b028e1c1a7 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -289,12 +289,6 @@ write_midi_data_to_new_files (SMFReader* source, Session::import_status& status,
if (source->read_event(4, ev.buffer(), &size, &delta_t) < 0)
break;
- // FIXME: kluuudge
- if (ev.channel() != 0) {
- cout << "Skipping event with channel " << ev.channel() << endl;
- continue;
- }
-
t += delta_t;
ev.time() = t * (double)source->ppqn();
ev.size() = size;
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 921824c615..7c3bc73fb8 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -304,6 +304,7 @@ MidiDiskstream::set_destructive (bool yn)
void
MidiDiskstream::set_note_mode (NoteMode m)
{
+ cout << "MDS: SET NOTE MODE: " << m << endl;
_note_mode = m;
midi_playlist()->set_note_mode(m);
if (_write_source && _write_source->model())
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 51793a4189..b2c7369edd 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -331,7 +331,8 @@ MidiModel::start_write()
//cerr << "MM " << this << " START WRITE, MODE = " << enum_2_string(_note_mode) << endl;
write_lock();
_writing = true;
- _write_notes.clear();
+ for (int i = 0; i < 16; ++i)
+ _write_notes[i].clear();
write_unlock();
}
@@ -362,7 +363,14 @@ MidiModel::end_write(bool delete_stuck)
}
}
- _write_notes.clear();
+ for (int i = 0; i < 16; ++i) {
+ if (!_write_notes[i].empty()) {
+ cerr << "WARNING: MidiModel::end_write: Channel " << i << " has "
+ << _write_notes[i].size() << " stuck notes" << endl;
+ }
+ _write_notes[i].clear();
+ }
+
_writing = false;
write_unlock();
}
@@ -383,11 +391,11 @@ MidiModel::append(const MidiEvent& ev)
assert(_writing);
if (ev.is_note_on())
- append_note_on_unlocked(ev.time(), ev.note(), ev.velocity());
+ append_note_on_unlocked(ev.channel(), ev.time(), ev.note(), ev.velocity());
else if (ev.is_note_off())
- append_note_off_unlocked(ev.time(), ev.note());
+ append_note_off_unlocked(ev.channel(), ev.time(), ev.note());
else if (ev.is_cc())
- append_cc_unlocked(ev.time(), ev.cc_number(), ev.cc_value());
+ append_cc_unlocked(ev.channel(), ev.time(), ev.cc_number(), ev.cc_value());
else
printf("MM Unknown event type %X\n", ev.type());
@@ -396,32 +404,36 @@ MidiModel::append(const MidiEvent& ev)
void
-MidiModel::append_note_on_unlocked(double time, uint8_t note_num, uint8_t velocity)
+MidiModel::append_note_on_unlocked(uint8_t chan, double time, uint8_t note_num, uint8_t velocity)
{
- //cerr << "MidiModel " << this << " note " << (int)note_num << " on @ " << time << endl;
+ /*cerr << "MidiModel " << this << " chan " << (int)chan <<
+ " note " << (int)note_num << " on @ " << time << endl;*/
+ assert(chan < 16);
assert(_writing);
+
_notes.push_back(boost::shared_ptr<Note>(new Note(time, 0, note_num, velocity)));
if (_note_mode == Sustained) {
//cerr << "MM Sustained: Appending active note on " << (unsigned)(uint8_t)note_num << endl;
- _write_notes.push_back(_notes.size() - 1);
- } else {
- //cerr << "MM Percussive: NOT appending active note on" << endl;
- }
+ _write_notes[chan].push_back(_notes.size() - 1);
+ }/* else {
+ cerr << "MM Percussive: NOT appending active note on" << endl;
+ }*/
}
void
-MidiModel::append_note_off_unlocked(double time, uint8_t note_num)
+MidiModel::append_note_off_unlocked(uint8_t chan, double time, uint8_t note_num)
{
- //cerr << "MidiModel " << this << " note " << (int)note_num << " off @ " << time << endl;
+ /*cerr << "MidiModel " << this << " chan " << (int)chan <<
+ " note " << (int)note_num << " off @ " << time << endl;*/
+ assert(chan < 16);
assert(_writing);
+
if (_note_mode == Percussive) {
- //cerr << "MM Ignoring note off (percussive mode)" << endl;
+ cerr << "MidiModel Ignoring note off (percussive mode)" << endl;
return;
- } else {
- //cerr << "MM Attempting to resolve note off " << (unsigned)(uint8_t)note_num << endl;
}
/* FIXME: make _write_notes fixed size (127 noted) for speed */
@@ -429,28 +441,42 @@ MidiModel::append_note_off_unlocked(double time, uint8_t note_num)
/* FIXME: note off velocity for that one guy out there who actually has
* keys that send it */
- for (WriteNotes::iterator n = _write_notes.begin(); n != _write_notes.end(); ++n) {
+ bool resolved = false;
+
+ for (WriteNotes::iterator n = _write_notes[chan].begin(); n != _write_notes[chan].end(); ++n) {
Note& note = *_notes[*n].get();
//cerr << (unsigned)(uint8_t)note.note() << " ? " << (unsigned)note_num << endl;
if (note.note() == note_num) {
assert(time >= note.time());
note.set_duration(time - note.time());
- _write_notes.erase(n);
+ _write_notes[chan].erase(n);
//cerr << "MM resolved note, duration: " << note.duration() << endl;
+ resolved = true;
break;
}
}
+
+ if (!resolved)
+ cerr << "MidiModel " << this << " spurious note off chan " << (int)chan
+ << ", note " << (int)note_num << " @ " << time << endl;
}
void
-MidiModel::append_cc_unlocked(double time, uint8_t number, uint8_t value)
+MidiModel::append_cc_unlocked(uint8_t chan, double time, uint8_t number, uint8_t value)
{
+ /*cerr << "MidiModel " << this << " chan " << (int)chan <<
+ " CC " << (int)number << " = " << (int)value << " @ " << time << endl;*/
+
+ assert(chan < 16);
+ assert(_writing);
+
+ if (chan != 0) // FIXME
+ cerr << "WARNING: CC on non-0 channel, channel information lost!" << endl;
+
Parameter param(MidiCCAutomation, number);
boost::shared_ptr<AutomationControl> control = Automatable::control(param, true);
- //cerr << "MidiModel " << this << "(" << control.get() << ") add CC " << (int)number << " = " << (int)value
- // << " @ " << time << endl;
control->list()->fast_simple_add(time, (double)value);
}
diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc
index 9720384130..d8e59efd4a 100644
--- a/libs/ardour/midi_playlist.cc
+++ b/libs/ardour/midi_playlist.cc
@@ -42,6 +42,7 @@ using namespace std;
MidiPlaylist::MidiPlaylist (Session& session, const XMLNode& node, bool hidden)
: Playlist (session, node, DataType::MIDI, hidden)
+ , _note_mode(Sustained)
{
const XMLProperty* prop = node.property("type");
assert(prop && DataType(prop->value()) == DataType::MIDI);
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 8e41df84ef..e1fa109342 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -80,6 +80,7 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo
MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
: Track (sess, node)
, _immediate_events(1024) // FIXME: size?
+ , _note_mode(Sustained)
{
_set_state(node, false);
@@ -690,6 +691,7 @@ MidiTrack::unfreeze ()
void
MidiTrack::set_note_mode (NoteMode m)
{
+ cout << _name << " SET NOTE MODE " << m << endl;
_note_mode = m;
midi_diskstream()->set_note_mode(m);
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index a7c693fb2d..52cfc093cc 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -130,6 +130,7 @@ Session::Session (AudioEngine &eng,
_session_dir (new SessionDirectory(fullpath)),
pending_events (2048),
//midi_requests (128), // the size of this should match the midi request pool size
+ post_transport_work((PostTransportWork)0),
_send_smpte_update (false),
diskstreams (new DiskstreamList),
routes (new RouteList),
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 59ad7269db..4903cf384f 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -444,14 +444,14 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
void
SMFSource::append_event_unlocked(const MidiEvent& ev)
{
- /*printf("SMF %s - writing event, time = %lf, size = %u, data = ", _path.c_str(), ev.time(), ev.size());
+ printf("%s - append chan = %u, time = %lf, size = %u, data = ", _path.c_str(),
+ (unsigned)ev.channel(), 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() >= 0);
-
assert(ev.time() >= _last_ev_time);
// FIXME: assumes tempo never changes after start