/* Merge all tracks into one big track. This will not copy any event * and only return a list of pointers to the events in the right order. * Note though that this will modify the relative_* times! * * The tracks will not be modified but may not be used later for * playback since the times are messed up (but you could reconstruct * them using the absolute_* times) * * The parameter muted is a set of muted track/channel combinations in * the format ttttcccc, that is the last 4 bits are the channel and the * remaining bits are the track: * (track_nr << 4) | channel_nr * */ EventList MidiFile::mergedTracks(std::set<int> muted) { EventList result; typedef std::vector<_track> trackv; trackv tracks; int tindex = 0; for (TrackList::iterator t = m_tracks.begin(); t != m_tracks.end(); ++t) { _track tentry; tentry.t = *t; tentry.pos = 0; tentry.size = (*t)->size(); tentry.index = tindex; tracks.push_back(tentry); ++tindex; } bool exhausted; MidiEvent* min_event; _track* min_track; int combination; std::map<int, int> chanmap; int nextchan = 0; for (;;) { exhausted = true; min_event = 0; min_track = 0; for (trackv::iterator t = tracks.begin(); t != tracks.end(); ++t) { if (t->pos < t->size) { exhausted = false; if (min_event == 0 || t->t->at(t->pos)->absolute_musec < min_event->absolute_musec) { min_event = t->t->at(t->pos); min_track = &(*t); } } } if (exhausted) break; ++min_track->pos; if (min_event->type() == Event_Note_On) { NoteOnEvent *e = dynamic_cast<NoteOnEvent*>(min_event); combination = min_track->index << 4 | e->getChannel(); e->muted = (muted.find(combination) != muted.end()); if (chanmap.find(combination) == chanmap.end()) { chanmap[combination] = nextchan; ++nextchan; } e->setChannel(chanmap[combination]); } else if (min_event->type() == Event_Note_Off) { NoteOffEvent *e = dynamic_cast<NoteOffEvent*>(min_event); combination = min_track->index << 4 | e->getChannel(); e->muted = (muted.find(combination) != muted.end()); if (chanmap.find(combination) == chanmap.end()) { chanmap[combination] = nextchan; ++nextchan; } e->setChannel(chanmap[combination]); } result.push_back(min_event); } int dticks; double dmusec; for (size_t i = 0; i < result.size(); ++i) { if (i == 0) { dticks = result[i]->absolute_ticks; dmusec = result[i]->absolute_musec; } else { dticks = result[i]->absolute_ticks - result[i-1]->absolute_ticks; dmusec = result[i]->absolute_musec - result[i-1]->absolute_musec; } result[i]->relative_ticks = dticks; result[i]->relative_musec = dmusec; } return result; }