Skip to content

Commit

Permalink
Fix #207346: Restrict first track to timing events
Browse files Browse the repository at this point in the history
Currently, exported MIDI files will have data events in the first MIDI
track. While this is not forbidden by the standard, the industry
convention is to only put timing related events in the first track, in
which case it is called a tempo track. MuseScore should follow that
convention because a lot of the available software assumes this
convention. This has been discussed and agreed upon in:

https://musescore.org/en/node/207346
  • Loading branch information
OmarEmaraDev committed Feb 15, 2021
1 parent 84f6aa7 commit 5149e9d
Show file tree
Hide file tree
Showing 17 changed files with 13 additions and 11 deletions.
22 changes: 12 additions & 10 deletions audio/exports/exportmidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@ namespace Ms {
// writeHeader
//---------------------------------------------------------

void ExportMidi::writeHeader()
void ExportMidi::writeHeader(MidiTrack& tempoTrack)
{
if (mf.tracks().isEmpty())
return;
MidiTrack &track = mf.tracks().front();
#if 0 // TODO
MeasureBase* measure = cs->first();

Expand Down Expand Up @@ -86,7 +85,7 @@ void ExportMidi::writeHeader()
//--------------------------------------------

int staffIdx = 0;
for (auto& track1: mf.tracks()) {
for (auto& track: mf.tracks()) {
Staff* staff = cs->staff(staffIdx);

QByteArray partName = staff->partName().toUtf8();
Expand All @@ -101,7 +100,7 @@ void ExportMidi::writeHeader()
ev.setEData(data);
ev.setLen(len);

track1.insert(0, ev);
track.insert(0, ev);


++staffIdx;
Expand Down Expand Up @@ -149,7 +148,7 @@ void ExportMidi::writeHeader()
ev.setMetaType(META_TIME_SIGNATURE);
ev.setEData(data);
ev.setLen(4);
track.insert(pauseMap.addPauseTicks(is->first + tickOffset), ev);
tempoTrack.insert(pauseMap.addPauseTicks(is->first + tickOffset), ev);
}
}

Expand All @@ -159,7 +158,7 @@ void ExportMidi::writeHeader()
//---------------------------------------------------

staffIdx = 0;
for (auto& track1: mf.tracks()) {
for (auto& track: mf.tracks()) {
Staff* staff = cs->staff(staffIdx);
KeyList* keys = staff->keyList();

Expand All @@ -183,7 +182,7 @@ void ExportMidi::writeHeader()
data[1] = 0; // major
ev.setEData(data);
int tick = ik->first + tickOffset;
track1.insert(pauseMap.addPauseTicks(tick), ev);
track.insert(pauseMap.addPauseTicks(tick), ev);
if (tick == 0)
initialKeySigFound = true;
}
Expand All @@ -200,7 +199,7 @@ void ExportMidi::writeHeader()
data[0] = key;
data[1] = 0; // major
ev.setEData(data);
track1.insert(0, ev);
track.insert(0, ev);
}

++staffIdx;
Expand Down Expand Up @@ -228,7 +227,7 @@ void ExportMidi::writeHeader()
data[1] = tempo >> 8;
data[2] = tempo;
ev.setEData(data);
track.insert(it->first, ev);
tempoTrack.insert(it->first, ev);
}
}

Expand All @@ -249,6 +248,8 @@ bool ExportMidi::write(QIODevice* device, bool midiExpandRepeats, bool exportRPN
mf.setDivision(MScore::division);
mf.setFormat(1);
QList<MidiTrack>& tracks = mf.tracks();
MidiTrack tempoTrack;
tempoTrack.setOutChannel(0);

for (int i = 0; i < cs->nstaves(); ++i)
tracks.append(MidiTrack());
Expand All @@ -257,7 +258,7 @@ bool ExportMidi::write(QIODevice* device, bool midiExpandRepeats, bool exportRPN
cs->renderMidi(&events, false, midiExpandRepeats, synthState);

pauseMap.calculate(cs);
writeHeader();
writeHeader(tempoTrack);

int staffIdx = 0;
for (auto &track: tracks) {
Expand Down Expand Up @@ -370,6 +371,7 @@ bool ExportMidi::write(QIODevice* device, bool midiExpandRepeats, bool exportRPN
}
++staffIdx;
}
tracks.prepend(tempoTrack);
return !mf.write(device);
}

Expand Down
2 changes: 1 addition & 1 deletion audio/exports/exportmidi.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ExportMidi {

PauseMap pauseMap;

void writeHeader();
void writeHeader(MidiTrack& tempoTrack);

public:
MidiFile mf;
Expand Down
Binary file modified mtest/libmscore/midi/testArpeggio-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testBends1-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testBends2-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testInitialKeySigThenRepeatToMeas2-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testMidiPort-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testMutedUnison-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testRepeatsWithKeySigs-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testRepeatsWithKeySigsExceptFirstMeas-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testSingleNoteDynamics-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testTimeStretchFermata-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testTimeStretchFermataTempoEdit-120-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testTimeStretchFermataTempoEdit-200-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testVoltaDynamic-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testVoltaStaffText-ref.mid
Binary file not shown.
Binary file modified mtest/libmscore/midi/testVoltaTemp-ref.mid
Binary file not shown.

0 comments on commit 5149e9d

Please sign in to comment.