Skip to content

Commit

Permalink
Merge pull request #653 from trig-ger/midi_fixes
Browse files Browse the repository at this point in the history
Fixes for MIDI import
  • Loading branch information
wschweer committed Jan 20, 2014
2 parents 9079166 + 758b0cb commit 6dffde5
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 32 deletions.
2 changes: 1 addition & 1 deletion midi/midifile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ int MidiFile::readLong()
int val = 0;
for (int i = 0; i < 4; ++i) {
fp->getChar(&c);
val <<= 8;
val <<= 8;
val += (c & 0xff);
}
return val;
Expand Down
5 changes: 2 additions & 3 deletions mscore/importmidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void MTrack::processMeta(int tick, const MidiEvent& mm)
break; // lyric and text are added in importmidi_lyrics.cpp
case META_TRACK_NAME:
{
std::string text = MidiCharset::fromUchar(data);
const std::string text = MidiCharset::fromUchar(data);
if (name.isEmpty())
name = MidiCharset::convertToCharset(text);
}
Expand Down Expand Up @@ -543,8 +543,7 @@ std::multimap<int, MTrack> createMTrackList(ReducedFraction &lastTick,
else if (e.type() == ME_NOTE) {
++events;
const int pitch = e.pitch();
const auto len = ReducedFraction::fromTicks(
(e.len() * MScore::division + mf->division() / 2) / mf->division());
const auto len = toMuseScoreTicks(e.len(), track.division);
if (tick + len > lastTick)
lastTick = tick + len;

Expand Down
68 changes: 41 additions & 27 deletions mscore/importmidi_chord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ bool areOnTimeValuesDifferent(const std::multimap<ReducedFraction, MidiChord> &c
return true;
}

bool areSingleNoteChords(const std::multimap<ReducedFraction, MidiChord> &chords)
{
for (const auto &chordEvent: chords) {
if (chordEvent.second.notes.size() > 1)
return false;
}
return true;
}

#endif


Expand Down Expand Up @@ -139,43 +148,48 @@ void collectChords(std::multimap<int, MTrack> &tracks)
ReducedFraction fudgeTime = threshTime / 4;
ReducedFraction threshExtTime = threshTime / 2;

ReducedFraction startTime(-1, 1); // invalid
ReducedFraction currentChordStart(-1, 1); // invalid
ReducedFraction curThreshTime(-1, 1);
// if intersection of note durations is less than min(minNoteDuration, threshTime)
// then this is not a chord
ReducedFraction tol(-1, 1); // invalid
ReducedFraction beg(-1, 1);
ReducedFraction end(-1, 1);
// chords here consist of a single note
// because notes are not united into chords yet
// if note onTime goes after max chord offTime
// then this is not a chord but arpeggio
ReducedFraction maxOffTime(-1, 1);

// chords here should consist of a single note
// because notes are not united into chords yet
Q_ASSERT_X(areSingleNoteChords(chords),
"MChord: collectChords", "Some chords have more than one note");

for (auto it = chords.begin(); it != chords.end(); ) {
const auto &note = it->second.notes[0];
// this should not be executed when it == chords.begin()
if (it->first <= startTime + curThreshTime) {
if (it->first > beg)
beg = it->first;
if (it->first + note.len < end)
end = it->first + note.len;
if (note.len < tol)
tol = note.len;
if (end - beg >= tol) {
// add current note to the previous chord

// short events with len < minAllowedDuration must be cleaned up
Q_ASSERT_X(note.len >= minAllowedDuration(),
"MChord: collectChords", "Note length is less than min allowed duration");

if (it->first <= currentChordStart + curThreshTime) {

// this branch should not be executed when it == chords.begin()
Q_ASSERT_X(it != chords.begin(),
"MChord: collectChords", "it == chords.begin()");

if (it->first < maxOffTime) {
// add current note to the previous chord
auto prev = std::prev(it);
prev->second.notes.push_back(note);
if (it->first >= startTime + curThreshTime - fudgeTime)
if (it->first >= currentChordStart + curThreshTime - fudgeTime
&& curThreshTime == threshTime) {
curThreshTime += threshExtTime;
}
if (it->first + note.len > maxOffTime)
maxOffTime = it->first + note.len;
it = chords.erase(it);
continue;
}
}
else {
startTime = it->first;
beg = startTime;
end = startTime + note.len;
tol = threshTime;
if (curThreshTime != threshTime)
curThreshTime = threshTime;
}
currentChordStart = it->first;
maxOffTime = currentChordStart + note.len;
if (curThreshTime != threshTime)
curThreshTime = threshTime;
++it;
}

Expand Down
2 changes: 1 addition & 1 deletion mscore/importmidi_tuplet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1415,7 +1415,7 @@ std::vector<TupletData> convertToData(const std::vector<TupletInfo> &tuplets)
return tupletsData;
}

// check is the chord is already in tuplet in prev bar or division
// check is the chord already in tuplet in prev bar or division
// it's possible because we use (startDivTick - tol) as a start tick

template <typename Iter>
Expand Down

0 comments on commit 6dffde5

Please sign in to comment.