How Musescore works?

• May 6, 2012 - 13:16

I'm a Computer Science student from the Hong Kong University of Science and Technology. And now I'm doing a music related project in which I use Musescore to convert midi files into MusicXML. To ensure the validy of the project, I wish to know how Musescore does the conversion and what algorithms it is using. Is there any documentation I can refer to?


Comments

In reply to by kevin.hy.lee

No. The algorithms are not documented.

You can check the sources and in particular importmidi.cpp and exportxml.cpp. As you may have guess, MuseScore imports MIDI in its own internal model and then convert this internal model to MusicXML. MusicXML is pretty solid and has a nice test suite. MIDI import is more difficult, and less solid... In particular, tuplets are not handled at all and ties are always favored instead of dotted notes without considering the beats. Any help is welcome :)

I notice that in midi file.cpp, there's a function that finds chords.

Is it an algorithm published in a research paper?


//---------------------------------------------------------
// findChords
//---------------------------------------------------------

void MidiTrack::findChords()
{
EventList dl;
int n = _events.size();

Drumset* drumset;
if (_drumTrack)
drumset = smDrumset;
else
drumset = 0;
int jitter = 3; // tick tolerance for note on/off

for (int i = 0; i < n; ++i) {
Event* e = _events[i];
if (e == 0)
continue;
if (e->type() != ME_NOTE) {
dl.append(e);
continue;
}

int ontime = e->ontime();
int offtime = e->offtime();
Event* chord = new Event(ME_CHORD);
chord->setOntime(ontime);
chord->setDuration(e->duration());
chord->notes().append(e);
int voice = 0;
chord->setVoice(voice);
dl.append(chord);
_events[i] = 0;

bool useDrumset = false;
if (drumset) {
int pitch = e->pitch();
if (drumset->isValid(pitch)) {
useDrumset = true;
voice = drumset->voice(pitch);
chord->setVoice(voice);
}
}
for (int k = i + 1; k < n; ++k) {
if (_events[k] == 0 || _events[k]->type() != ME_NOTE)
continue;
Event* nn = _events[k];
if (nn->ontime() - jitter > ontime)
break;
if (qAbs(nn->ontime() - ontime) > jitter || qAbs(nn->offtime() - offtime) > jitter)
continue;
int pitch = nn->pitch();
if (useDrumset) {
if (drumset->isValid(pitch) && drumset->voice(pitch) == voice) {
chord->notes().append(nn);
_events[k] = 0;
}
}
else {
chord->notes().append(nn);
_events[k] = 0;
}
}
}
_events = dl;
}

In reply to by kevin.hy.lee

I can't be 100% positive. Werner will have a more definitive answer since he wrote the code. But I guess the algorithm here is not from a research paper. After all it's quite "simple". It goes through the events and replace noteon/noteoff by "chord" events if the noteon/noteoff overlap including a little jitter.

Btw, the code you pasted here is from MuseScore 1.2 and can differ from the current development version.

Do you still have an unanswered question? Please log in first to post your question.