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

Duplicate of musescore#7523
  • Loading branch information
OmarEmaraDev authored and Jojo-Schmitz committed Sep 4, 2021
1 parent 47918f3 commit b22895c
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 b22895c

Please sign in to comment.