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:
parent
d741d5055f
commit
0a0ce26b33
6 changed files with 48 additions and 31 deletions
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -512,15 +512,22 @@ 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,21 +1493,23 @@ 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;
|
||||
const Note* note1 = n.note();
|
||||
if (n.velo()) {
|
||||
while (note1) {
|
||||
if (n.velo()) {
|
||||
note1->setMark(true);
|
||||
markedNotes.append(note1);
|
||||
}
|
||||
else {
|
||||
note1->setMark(false);
|
||||
markedNotes.removeOne(note1);
|
||||
}
|
||||
note1->setMark(true);
|
||||
markedNotes.append(note1);
|
||||
r |= note1->canvasBoundingRect();
|
||||
note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (note1) {
|
||||
note1->setMark(false);
|
||||
r |= note1->canvasBoundingRect();
|
||||
markedNotes.removeOne(note1);
|
||||
note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int utick = ppos->first;
|
||||
|
|
|
@ -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 = ";
|
||||
|
|
|
@ -391,37 +391,28 @@ 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;
|
||||
++it;
|
||||
}
|
||||
|
||||
free((void *)info);
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue