take all tracks inside a midi-file into account when loading model

* fixes [region] length calculation,
* prepare for auditioning midi files (one track plays it all)
This commit is contained in:
Robin Gareus 2014-01-20 13:44:31 +01:00
parent 9e799c6146
commit 1e3ad60eb6

View File

@ -476,6 +476,12 @@ SMFSource::safe_midi_file_extension (const string& file)
return true;
}
static bool compare_eventlist (
const std::pair< Evoral::Event<double>*, gint >& a,
const std::pair< Evoral::Event<double>*, gint >& b) {
return ( a.first->time() < b.first->time() );
}
void
SMFSource::load_model (bool lock, bool force_reload)
{
@ -514,60 +520,74 @@ SMFSource::load_model (bool lock, bool force_reload)
uint8_t* buf = NULL;
int ret;
gint event_id;
bool have_event_id = false;
bool have_event_id;
while ((ret = read_event (&delta_t, &size, &buf, &event_id)) >= 0) {
// TODO simplify event allocation
std::list< std::pair< Evoral::Event<double>*, gint > > eventlist;
time += delta_t;
for (unsigned i = 1; i <= num_tracks(); ++i) {
if (seek_to_track(i)) continue;
if (ret == 0) {
time = 0;
have_event_id = false;
/* meta-event : did we get an event ID ?
*/
while ((ret = read_event (&delta_t, &size, &buf, &event_id)) >= 0) {
if (event_id >= 0) {
have_event_id = true;
time += delta_t;
if (ret == 0) {
/* meta-event : did we get an event ID ? */
if (event_id >= 0) {
have_event_id = true;
}
continue;
}
continue;
}
if (ret > 0) {
/* not a meta-event */
if (ret > 0) {
/* not a meta-event */
ev.set (buf, size, time / (double)ppqn());
ev.set_event_type(EventTypeMap::instance().midi_event_type(buf[0]));
if (!have_event_id) {
event_id = Evoral::next_event_id();
}
if (!have_event_id) {
event_id = Evoral::next_event_id();
}
uint32_t event_type = EventTypeMap::instance().midi_event_type(buf[0]);
double event_time = time / (double) ppqn();
#ifndef NDEBUG
std::string ss;
std::string ss;
for (uint32_t xx = 0; xx < size; ++xx) {
char b[8];
snprintf (b, sizeof (b), "0x%x ", buf[xx]);
ss += b;
}
for (uint32_t xx = 0; xx < size; ++xx) {
char b[8];
snprintf (b, sizeof (b), "0x%x ", buf[xx]);
ss += b;
}
DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF %6 load model delta %1, time %2, size %3 buf %4, type %5\n",
delta_t, time, size, ss , ev.event_type(), name()));
DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF %6 load model delta %1, time %2, size %3 buf %4, type %5\n",
delta_t, time, size, ss , event_type, name()));
#endif
_model->append (ev, event_id);
eventlist.push_back(make_pair (
new Evoral::Event<double> (
event_type, event_time,
size, buf, true)
, event_id));
// Set size to max capacity to minimize allocs in read_event
scratch_size = std::max(size, scratch_size);
size = scratch_size;
// Set size to max capacity to minimize allocs in read_event
scratch_size = std::max(size, scratch_size);
size = scratch_size;
_length_beats = max(_length_beats, ev.time());
_length_beats = max(_length_beats, event_time);
}
/* event ID's must immediately precede the event they are for */
have_event_id = false;
}
}
/* event ID's must immediately precede the event they are for
*/
eventlist.sort(compare_eventlist);
have_event_id = false;
std::list< std::pair< Evoral::Event<double>*, gint > >::iterator it;
for (it=eventlist.begin(); it!=eventlist.end(); ++it) {
_model->append (*it->first, it->second);
delete it->first;
}
_model->end_write (Evoral::Sequence<Evoral::MusicalTime>::ResolveStuckNotes, _length_beats);