34a6d600d93c8773d87d1e76a64b4e9bd7b2e963
[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 @@ -166,7 +166,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/exportaudio.cpp
24 +++ b/mscore/exportaudio.cpp
25 @@ -23,8 +23,6 @@
26  #include "libmscore/score.h"
27  #include "libmscore/note.h"
28  #include "libmscore/part.h"
29 -#include "libmscore/staff.h"
30 -#include "libmscore/chord.h"
31  #include "libmscore/mscore.h"
32  #include "synthesizer/msynthesizer.h"
33  #include "musescore.h"
34 @@ -133,35 +131,13 @@ bool MuseScore::saveAudio(Score* score,
35  
36                        playTime  += n;
37                        frames    -= n;
38 -                      const NPlayEvent& event = playPos->second;
39 -                      if (event.isChannelEvent()) {
40 -                              int channelIdx = event.channel();
41 -                              Channel* c = score->midiMapping(channelIdx)->articulation;
42 -                              int type = event.type();
43 -                              int syntiIndex = synti->index(c->synti);
44 -                              if (type == ME_NOTEON) {
45 -                                    bool mute;
46 -                                    const Note* note = event.note();
47 -                                    if (note) {
48 -                                          Instrument* instr = note->staff()->part()->instrument(note->chord()->tick());
49 -                                          const Channel* a = instr->channel(note->subchannel());
50 -                                          mute = a->mute || a->soloMute;
51 -                                          }
52 -                                    else
53 -                                          mute = false;
54 -
55 -                                    if (!mute) {
56 -                                          if (event.discard()) { // ignore noteoff but restrike noteon
57 -                                                if (event.velo() > 0)
58 -                                                      synti->play(NPlayEvent(ME_NOTEON, event.channel(), event.pitch(), 0), syntiIndex);
59 -                                                else
60 -                                                      continue;
61 -                                                }
62 -                                          synti->play(event, syntiIndex);
63 -                                          }
64 -                                    }
65 -                              else if (type == ME_CONTROLLER || type == ME_PITCHBEND)
66 -                                    synti->play(event, syntiIndex);
67 +                      const NPlayEvent& e = playPos->second;
68 +                      if (e.isChannelEvent()) {
69 +                            int channelIdx = e.channel();
70 +                            Channel* c = score->midiMapping(channelIdx)->articulation;
71 +                            if (!c->mute) {
72 +                                  synti->play(e, synti->index(c->synti));
73 +                                  }
74                              }
75                        }
76                  if (frames) {
77 --- a/mscore/exportmidi.cpp
78 +++ b/mscore/exportmidi.cpp
79 @@ -289,18 +289,9 @@ bool ExportMidi::write(const QString& na
80                          for (auto i = events.begin(); i != events.end(); ++i) {
81                                const NPlayEvent& event = i->second;
82  
83 -                              if (event.discard() == staffIdx + 1 && event.velo() > 0)
84 -                                    // turn note off so we can restrike it in another track
85 -                                    track.insert(pauseMap.addPauseTicks(i->first), MidiEvent(ME_NOTEON, channel,
86 -                                                                     event.pitch(), 0));
87 -
88                                if (event.getOriginatingStaff() != staffIdx)
89                                      continue;
90  
91 -                              if (event.discard() && event.velo() == 0)
92 -                                    // ignore noteoff but restrike noteon
93 -                                    continue;
94 -
95                                char eventPort    = cs->midiPort(event.channel());
96                                char eventChannel = cs->midiChannel(event.channel());
97                                if (port != eventPort || channel != eventChannel)
98 --- a/mscore/musescore.cpp
99 +++ b/mscore/musescore.cpp
100 @@ -5662,36 +5662,14 @@ bool MuseScore::saveMp3(Score* score, co
101                                playTime  += n;
102                                frames    -= n;
103                                }
104 -                        const NPlayEvent& event = playPos->second;
105 -                        if (event.isChannelEvent()) {
106 -                              int channelIdx = event.channel();
107 +                        const NPlayEvent& e = playPos->second;
108 +                        if (e.isChannelEvent()) {
109 +                              int channelIdx = e.channel();
110                                Channel* c = score->midiMapping(channelIdx)->articulation;
111 -                              int type = event.type();
112 -                              int syntiIndex = synti->index(c->synti);
113 -                              if (type == ME_NOTEON) {
114 -                                    bool mute;
115 -                                    const Note* note = event.note();
116 -                                    if (note) {
117 -                                          Instrument* instr = note->staff()->part()->instrument(note->chord()->tick());
118 -                                          const Channel* a = instr->channel(note->subchannel());
119 -                                          mute = a->mute || a->soloMute;
120 -                                          }
121 -                                    else
122 -                                          mute = false;
123 -
124 -                                    if (!mute) {
125 -                                          if (event.discard()) { // ignore noteoff but restrike noteon
126 -                                                if (event.velo() > 0)
127 -                                                      synti->play(NPlayEvent(ME_NOTEON, event.channel(), event.pitch(), 0), syntiIndex);
128 -                                                else
129 -                                                      continue;
130 -                                                }
131 -                                          synti->play(event, syntiIndex);
132 -                                          }
133 +                              if (!c->mute) {
134 +                                    synti->play(e, synti->index(c->synti));
135                                      }
136 -                              else if (type == ME_CONTROLLER || type == ME_PITCHBEND)
137 -                                    synti->play(event, syntiIndex);
138 -                            }
139 +                              }
140                          }
141                    if (frames) {
142                          float bu[frames * 2];
143 --- a/mscore/seq.cpp
144 +++ b/mscore/seq.cpp
145 @@ -512,8 +512,9 @@ void Seq::playEvent(const NPlayEvent& ev
146        int type = event.type();
147        if (type == ME_NOTEON) {
148              bool mute;
149 -            const Note* note = event.note();
150 -            if (note) {
151 +
152 +            if (!event.notes.empty()) {
153 +                  const Note* note = event.notes[0];
154                    Instrument* instr = note->staff()->part()->instrument(note->chord()->tick());
155                    const Channel* a = instr->channel(note->subchannel());
156                    mute = a->mute || a->soloMute;
157 @@ -521,15 +522,8 @@ void Seq::playEvent(const NPlayEvent& ev
158              else
159                    mute = false;
160  
161 -            if (!mute) {
162 -                  if (event.discard()) { // ignore noteoff but restrike noteon
163 -                        if (event.velo() > 0)
164 -                              putEvent(NPlayEvent(ME_NOTEON, event.channel(), event.pitch(), 0) ,framePos);
165 -                        else
166 -                              return;
167 -                        }
168 +            if (!mute)
169                    putEvent(event, framePos);
170 -                  }
171              }
172        else if (type == ME_CONTROLLER || type == ME_PITCHBEND)
173              putEvent(event, framePos);
174 @@ -1494,20 +1488,18 @@ void Seq::heartBeatTimeout()
175                          break;
176              const NPlayEvent& n = guiPos->second;
177              if (n.type() == ME_NOTEON) {
178 -                  const Note* note1 = n.note();
179 -                  if (n.velo()) {
180 +                  for (auto it = n.notes.cbegin(); it != n.notes.cend(); ++it) {
181 +                        const Note* note1 = *it;
182                          while (note1) {
183 -                              note1->setMark(true);
184 -                              markedNotes.append(note1);
185 -                              r |= note1->canvasBoundingRect();
186 -                              note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
187 -                              }
188 -                        }
189 -                  else {
190 -                        while (note1) {
191 -                              note1->setMark(false);
192 +                              if (n.velo()) {
193 +                                    note1->setMark(true);
194 +                                    markedNotes.append(note1);
195 +                                    }
196 +                              else {
197 +                                    note1->setMark(false);
198 +                                    markedNotes.removeOne(note1);
199 +                                    }
200                                r |= note1->canvasBoundingRect();
201 -                              markedNotes.removeOne(note1);
202                                note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
203                                }
204                          }
205 --- a/mtest/libmscore/midi/tst_midi.cpp
206 +++ b/mtest/libmscore/midi/tst_midi.cpp
207 @@ -378,7 +378,6 @@ void TestMidi::events()
208        QTextStream out(&filehandler);
209        multimap<int, NPlayEvent> ::iterator iter;
210        for (auto iter = events.begin(); iter!= events.end(); ++iter){
211 -            if (iter->second.discard()) continue;
212              out << qSetFieldWidth(5) << "Tick  =  ";
213              out << qSetFieldWidth(5) << iter->first;
214              out << qSetFieldWidth(5) << "   Type  = ";
215 --- a/synthesizer/event.cpp
216 +++ b/synthesizer/event.cpp
217 @@ -390,28 +390,37 @@ void EventMap::fixupMIDI()
218  
219        auto it = begin();
220        while (it != end()) {
221 +            bool discard = false;
222 +
223              /* ME_NOTEOFF is never emitted, no need to check for it */
224              if (it->second.type() == ME_NOTEON) {
225                    unsigned short np = info[it->second.channel()].nowPlaying[it->second.pitch()];
226                    if (it->second.velo() == 0) {
227                          /* already off (should not happen) or still playing? */
228                          if (np == 0 || --np > 0)
229 -                              it->second.setDiscard(1);
230 +                              discard = true;
231                          else {
232                                /* hoist NOTEOFF to same track as NOTEON */
233                                it->second.setOriginatingStaff(info[it->second.channel()].event[it->second.pitch()]->getOriginatingStaff());
234 +                              /* copy linked Notes */
235 +                              it->second.notes = info[it->second.channel()].event[it->second.pitch()]->notes;
236                                }
237                          }
238 -                  else {
239 -                        if (++np > 1)
240 -                              /* restrike, possibly on different track */
241 -                              it->second.setDiscard(info[it->second.channel()].event[it->second.pitch()]->getOriginatingStaff() + 1);
242 -                        info[it->second.channel()].event[it->second.pitch()] = &(it->second);
243 +                  else if (++np > 1) {
244 +                        /* already playing */
245 +                        discard = true;
246 +                        /* carry over the corresponding score notes */
247 +                        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());
248                          }
249 +                  else
250 +                        info[it->second.channel()].event[it->second.pitch()] = &(it->second);
251                    info[it->second.channel()].nowPlaying[it->second.pitch()] = np;
252                    }
253  
254 -            ++it;
255 +            if (discard)
256 +                  it = erase(it);
257 +            else
258 +                  ++it;
259              }
260  
261              free((void *)info);
262 --- a/synthesizer/event.h
263 +++ b/synthesizer/event.h
264 @@ -234,9 +234,7 @@ class PlayEvent : public MidiCoreEvent {
265  //---------------------------------------------------------
266  
267  class NPlayEvent : public PlayEvent {
268 -      const Note* _note = 0;
269        int _origin = -1;
270 -      int _discard = 0;
271  
272     public:
273        NPlayEvent() : PlayEvent() {}
274 @@ -245,13 +243,10 @@ class NPlayEvent : public PlayEvent {
275        NPlayEvent(const MidiCoreEvent& e) : PlayEvent(e) {}
276        NPlayEvent(BeatType beatType);
277  
278 -      const Note* note() const       { return _note; }
279 -      void setNote(const Note* v)    { _note = v; }
280 +      std::vector<const Note*> notes;
281  
282        int getOriginatingStaff() const { return _origin; }
283        void setOriginatingStaff(int i) { _origin = i; }
284 -      void setDiscard(int d) { _discard = d; }
285 -      int discard() const { return _discard; }
286        };
287  
288  //---------------------------------------------------------