e268ef89287a140868bd84871817baad03280190
[alioth/musescore.git] / debian / patches / experiments / revert-restriking-patch.diff
1 Description: Revert the unison restriking patch
2  The restriking patch went into 2.2 (and up), 3.x, and master,
3  while it is not unquestioned. It was never meant to last; MIDI
4  channel assignment to individual voices must be made user-friendly,
5  but then, a reversal was intended by upstream. This diff implements
6  said reversal, in preparation of those other (UI, mostly) changes.
7 Author: mirabilos <m@mirbsd.org>
8 Bug: https://musescore.org/en/node/12971
9 Forwarded: https://github.com/musescore/MuseScore/pull/3797
10  except reversal of commit d5a81add16497f9b4b7fac5717ea005c31dcc1cf
11
12 --- a/libmscore/rendermidi.cpp
13 +++ b/libmscore/rendermidi.cpp
14 @@ -230,7 +230,7 @@ static void playNote(EventMap* events, c
15        NPlayEvent ev(ME_NOTEON, channel, pitch, velo);
16        ev.setOriginatingStaff(staffIdx);
17        ev.setTuning(note->tuning());
18 -      ev.setNote(note);
19 +      ev.notes.push_back(note);
20        if (offTime < onTime)
21              offTime = onTime;
22        events->insert(std::pair<int, NPlayEvent>(onTime, ev));
23 --- a/mscore/exportmidi.cpp
24 +++ b/mscore/exportmidi.cpp
25 @@ -295,18 +295,9 @@ bool ExportMidi::write(QIODevice* device
26  
27                                if (event.isMuted())
28                                      continue;
29 -                              if (event.discard() == staffIdx + 1 && event.velo() > 0)
30 -                                    // turn note off so we can restrike it in another track
31 -                                    track.insert(pauseMap.addPauseTicks(i->first), MidiEvent(ME_NOTEON, channel,
32 -                                                                     event.pitch(), 0));
33 -
34                                if (event.getOriginatingStaff() != staffIdx)
35                                      continue;
36  
37 -                              if (event.discard() && event.velo() == 0)
38 -                                    // ignore noteoff but restrike noteon
39 -                                    continue;
40 -
41                                char eventPort    = cs->masterScore()->midiPort(event.channel());
42                                char eventChannel = cs->masterScore()->midiChannel(event.channel());
43                                if (port != eventPort || channel != eventChannel)
44 --- a/mscore/seq.cpp
45 +++ b/mscore/seq.cpp
46 @@ -552,12 +552,6 @@ void Seq::playEvent(const NPlayEvent& ev
47        int type = event.type();
48        if (type == ME_NOTEON) {
49              if (!event.isMuted()) {
50 -                  if (event.discard()) { // ignore noteoff but restrike noteon
51 -                        if (event.velo() > 0)
52 -                              putEvent(NPlayEvent(ME_NOTEON, event.channel(), event.pitch(), 0) ,framePos);
53 -                        else
54 -                              return;
55 -                        }
56                    putEvent(event, framePos);
57                    }
58              }
59 @@ -1611,29 +1605,22 @@ void Seq::heartBeatTimeout()
60                          break;
61              const NPlayEvent& n = guiPos->second;
62              if (n.type() == ME_NOTEON) {
63 -                  const Note* note1 = n.note();
64 -                  if (n.velo()) {
65 -                        while (note1) {
66 -                              for (ScoreElement* se : note1->linkList()) {
67 -                                    if (!se->isNote())
68 -                                          continue;
69 -                                    Note* currentNote = toNote(se);
70 -                                    currentNote->setMark(true);
71 -                                    markedNotes.append(currentNote);
72 -                                    r |= currentNote->canvasBoundingRect();
73 -                                    }
74 -                              note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
75 -                              }
76 -                        }
77 -                  else {
78 +                  for (auto it = n.notes.cbegin(); it != n.notes.cend(); ++it) {
79 +                        const Note* note1 = *it;
80                          while (note1) {
81                                for (ScoreElement* se : note1->linkList()) {
82                                      if (!se->isNote())
83                                            continue;
84                                      Note* currentNote = toNote(se);
85 -                                    currentNote->setMark(false);
86 +                                    if (n.velo()) {
87 +                                          currentNote->setMark(true);
88 +                                          markedNotes.append(currentNote);
89 +                                          }
90 +                                    else {
91 +                                          currentNote->setMark(false);
92 +                                          markedNotes.removeOne(currentNote);
93 +                                          }
94                                      r |= currentNote->canvasBoundingRect();
95 -                                    markedNotes.removeOne(currentNote);
96                                      }
97                                note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
98                                }
99 --- a/mtest/libmscore/midi/tst_midi.cpp
100 +++ b/mtest/libmscore/midi/tst_midi.cpp
101 @@ -548,8 +548,6 @@ void TestMidi::events()
102        QTextStream out(&filehandler);
103  
104        for (auto iter = events.begin(); iter!= events.end(); ++iter){
105 -            if (iter->second.discard())
106 -                  continue;
107              out << qSetFieldWidth(5) << "Tick  =  ";
108              out << qSetFieldWidth(5) << iter->first;
109              out << qSetFieldWidth(5) << "   Type  = ";
110 --- a/synthesizer/event.cpp
111 +++ b/synthesizer/event.cpp
112 @@ -172,8 +172,8 @@ NPlayEvent::NPlayEvent(BeatType beatType
113  
114  bool NPlayEvent::isMuted() const
115        {
116 -      const Note* n = note();
117 -      if (n) {
118 +      if (!notes.empty()) {
119 +            const Note* n = notes[0];
120              MasterScore* cs = n->masterScore();
121              Staff* staff = n->staff();
122              Instrument* instr = staff->part()->instrument(n->tick());
123 @@ -411,6 +411,8 @@ void EventMap::fixupMIDI()
124  
125        auto it = begin();
126        while (it != end()) {
127 +            bool discard = false;
128 +
129              NPlayEvent& event = it->second;
130              /* ME_NOTEOFF is never emitted, no need to check for it */
131              if (event.type() == ME_NOTEON && !event.isMuted()) {
132 @@ -418,22 +420,30 @@ void EventMap::fixupMIDI()
133                    if (event.velo() == 0) {
134                          /* already off (should not happen) or still playing? */
135                          if (np == 0 || --np > 0)
136 -                              event.setDiscard(1);
137 +                              discard = true;
138                          else {
139                                /* hoist NOTEOFF to same track as NOTEON */
140                                event.setOriginatingStaff(info[event.channel()].event[event.pitch()]->getOriginatingStaff());
141 +                              /* copy linked Notes */
142 +                              event.notes = info[event.channel()].event[event.pitch()]->notes;
143                                }
144                          }
145 +                  else if (++np > 1) {
146 +                        /* already playing */
147 +                        discard = true;
148 +                        /* carry over the corresponding score notes */
149 +                        info[event.channel()].event[event.pitch()]->notes.insert(info[event.channel()].event[event.pitch()]->notes.end(), event.notes.begin(), event.notes.end());
150 +                        }
151                    else {
152 -                        if (++np > 1)
153 -                              /* restrike, possibly on different track */
154 -                              event.setDiscard(info[event.channel()].event[event.pitch()]->getOriginatingStaff() + 1);
155                          info[event.channel()].event[event.pitch()] = &event;
156                          }
157                    info[event.channel()].nowPlaying[event.pitch()] = np;
158                    }
159  
160 -            ++it;
161 +            if (discard)
162 +                  it = erase(it);
163 +            else
164 +                  ++it;
165              }
166  
167              free((void *)info);
168 --- a/synthesizer/event.h
169 +++ b/synthesizer/event.h
170 @@ -236,9 +236,7 @@ class PlayEvent : public MidiCoreEvent {
171  //---------------------------------------------------------
172  
173  class NPlayEvent : public PlayEvent {
174 -      const Note* _note = 0;
175        int _origin = -1;
176 -      int _discard = 0;
177  
178     public:
179        NPlayEvent() : PlayEvent() {}
180 @@ -247,13 +245,10 @@ class NPlayEvent : public PlayEvent {
181        NPlayEvent(const MidiCoreEvent& e) : PlayEvent(e) {}
182        NPlayEvent(BeatType beatType);
183  
184 -      const Note* note() const       { return _note; }
185 -      void setNote(const Note* v)    { _note = v; }
186 +      std::vector<const Note*> notes;
187  
188        int getOriginatingStaff() const { return _origin; }
189        void setOriginatingStaff(int i) { _origin = i; }
190 -      void setDiscard(int d) { _discard = d; }
191 -      int discard() const { return _discard; }
192        bool isMuted() const;
193        };
194