fix #270408, #270878: merge the restriking patches

This brings master to the same state as v2.3.2 wrt. the MIDI issues;
*this* commit can later easily be reverted once we switch away from
restriking again as @lasconic indicated in:
https://musescore.org/en/node/270562#comment-826020
This commit is contained in:
mirabilos 2018-03-30 21:43:00 +02:00 committed by mirabilos
parent d741d5055f
commit 0a0ce26b33
No known key found for this signature in database
GPG key ID: 8950C1895EB8D3B3
6 changed files with 48 additions and 31 deletions

View file

@ -222,7 +222,7 @@ static void playNote(EventMap* events, const Note* note, int channel, int pitch,
NPlayEvent ev(ME_NOTEON, channel, pitch, velo);
ev.setOriginatingStaff(staffIdx);
ev.setTuning(note->tuning());
ev.notes.push_back(note);
ev.setNote(note);
if (offTime < onTime)
offTime = onTime;
events->insert(std::pair<int, NPlayEvent>(onTime, ev));

View file

@ -288,9 +288,19 @@ bool ExportMidi::write(const QString& name, bool midiExpandRepeats, bool exportR
for (auto i = events.begin(); i != events.end(); ++i) {
const NPlayEvent& event = i->second;
if (event.discard() == staffIdx + 1 && event.velo() > 0)
// turn note off so we can restrike it in another track
track.insert(pauseMap.addPauseTicks(i->first), MidiEvent(ME_NOTEON, channel,
event.pitch(), 0));
if (event.getOriginatingStaff() != staffIdx)
continue;
if (event.discard() && event.velo() == 0)
// ignore noteoff but restrike noteon
continue;
char eventPort = cs->masterScore()->midiPort(event.channel());
char eventChannel = cs->masterScore()->midiChannel(event.channel());
if (port != eventPort || channel != eventChannel)

View file

@ -512,16 +512,23 @@ void Seq::playEvent(const NPlayEvent& event, unsigned framePos)
if (type == ME_NOTEON) {
bool mute = false;
if (!event.notes.empty()) {
const Note* note = event.notes[0];
const Note* note = event.note();
if (note) {
Staff* staff = note->staff();
Instrument* instr = staff->part()->instrument(note->chord()->tick());
const Channel* a = instr->channel(note->subchannel());
mute = a->mute() || a->soloMute() || !staff->playbackVoice(note->voice());
}
if (!mute)
if (!mute) {
if (event.discard()) { // ignore noteoff but restrike noteon
if (event.velo() > 0)
putEvent(NPlayEvent(ME_NOTEON, event.channel(), event.pitch(), 0) ,framePos);
else
return;
}
putEvent(event, framePos);
}
}
else if (type == ME_CONTROLLER || type == ME_PITCHBEND)
putEvent(event, framePos);
}
@ -1486,18 +1493,20 @@ void Seq::heartBeatTimeout()
break;
const NPlayEvent& n = guiPos->second;
if (n.type() == ME_NOTEON) {
for (auto it = n.notes.cbegin(); it != n.notes.cend(); ++it) {
const Note* note1 = *it;
while (note1) {
const Note* note1 = n.note();
if (n.velo()) {
while (note1) {
note1->setMark(true);
markedNotes.append(note1);
r |= note1->canvasBoundingRect();
note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
}
}
else {
while (note1) {
note1->setMark(false);
markedNotes.removeOne(note1);
}
r |= note1->canvasBoundingRect();
markedNotes.removeOne(note1);
note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
}
}

View file

@ -385,6 +385,8 @@ void TestMidi::events()
QTextStream out(&filehandler);
for (auto iter = events.begin(); iter!= events.end(); ++iter){
if (iter->second.discard())
continue;
out << qSetFieldWidth(5) << "Tick = ";
out << qSetFieldWidth(5) << iter->first;
out << qSetFieldWidth(5) << " Type = ";

View file

@ -391,36 +391,27 @@ void EventMap::fixupMIDI()
auto it = begin();
while (it != end()) {
bool discard = false;
/* ME_NOTEOFF is never emitted, no need to check for it */
if (it->second.type() == ME_NOTEON) {
unsigned short np = info[it->second.channel()].nowPlaying[it->second.pitch()];
if (it->second.velo() == 0) {
/* already off (should not happen) or still playing? */
if (np == 0 || --np > 0)
discard = true;
it->second.setDiscard(1);
else {
/* hoist NOTEOFF to same track as NOTEON */
it->second.setOriginatingStaff(info[it->second.channel()].event[it->second.pitch()]->getOriginatingStaff());
/* copy linked Notes */
it->second.notes = info[it->second.channel()].event[it->second.pitch()]->notes;
}
}
else if (++np > 1) {
/* already playing */
discard = true;
/* carry over the corresponding score notes */
info[it->second.channel()].event[it->second.pitch()]->notes.insert(info[it->second.channel()].event[it->second.pitch()]->notes.end(), it->second.notes.begin(), it->second.notes.end());
}
else
else {
if (++np > 1)
/* restrike, possibly on different track */
it->second.setDiscard(info[it->second.channel()].event[it->second.pitch()]->getOriginatingStaff() + 1);
info[it->second.channel()].event[it->second.pitch()] = &(it->second);
}
info[it->second.channel()].nowPlaying[it->second.pitch()] = np;
}
if (discard)
it = erase(it);
else
++it;
}

View file

@ -234,7 +234,9 @@ class PlayEvent : public MidiCoreEvent {
//---------------------------------------------------------
class NPlayEvent : public PlayEvent {
const Note* _note = 0;
int _origin = -1;
int _discard = 0;
public:
NPlayEvent() : PlayEvent() {}
@ -243,10 +245,13 @@ class NPlayEvent : public PlayEvent {
NPlayEvent(const MidiCoreEvent& e) : PlayEvent(e) {}
NPlayEvent(BeatType beatType);
std::vector<const Note*> notes;
const Note* note() const { return _note; }
void setNote(const Note* v) { _note = v; }
int getOriginatingStaff() const { return _origin; }
void setOriginatingStaff(int i) { _origin = i; }
void setDiscard(int d) { _discard = d; }
int discard() const { return _discard; }
};
//---------------------------------------------------------