Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #pragma once
24 :
25 : #include <vector>
26 :
27 : #include "global/containers.h"
28 :
29 : #include "clef.h"
30 : #include "interval.h"
31 : #include "notifier.h"
32 : #include "stafflabel.h"
33 : #include "stringdata.h"
34 :
35 : #include "../compat/midi/midicoreevent.h"
36 :
37 : namespace mu::engraving {
38 : class ChannelListener;
39 : class Drumset;
40 : class InstrumentTemplate;
41 : class MasterScore;
42 : class Part;
43 : class StringData;
44 : class Synthesizer;
45 :
46 : //---------------------------------------------------------
47 : // NamedEventList
48 : //---------------------------------------------------------
49 :
50 : struct NamedEventList {
51 : String name;
52 : String descr;
53 : std::vector<MidiCoreEvent> events;
54 :
55 0 : bool operator==(const NamedEventList& i) const { return i.name == name && i.events == events; }
56 : };
57 :
58 : //---------------------------------------------------------
59 : // MidiArticulation
60 : //---------------------------------------------------------
61 :
62 : struct MidiArticulation {
63 : String name;
64 : String descr;
65 : int velocity = 0; // velocity change: -100% - +100%
66 : int gateTime = 0; // gate time change: -100% - +100%
67 :
68 7708 : MidiArticulation() {}
69 104 : MidiArticulation(const String& n, const String& d, int v, int g)
70 104 : : name(n), descr(d), velocity(v), gateTime(g) {}
71 :
72 : bool operator==(const MidiArticulation& i) const;
73 : };
74 :
75 : //---------------------------------------------------------
76 : // Channel
77 : //---------------------------------------------------------
78 :
79 : class InstrChannel
80 : {
81 : public:
82 : static const char* DEFAULT_NAME;
83 : static const char* HARMONY_NAME;
84 : static const char* PALM_MUTE_NAME;
85 : static const int DEFAULT_COLOR = 0x3399ff;
86 : static constexpr char defaultVolume = 100;
87 :
88 : enum class A : char {
89 : HBANK, LBANK, PROGRAM, VOLUME, PAN, CHORUS, REVERB,
90 : INIT_COUNT
91 : };
92 :
93 : enum class Prop : char {
94 : VOLUME, PAN, CHORUS, REVERB, NAME, PROGRAM, BANK, COLOR,
95 : SYNTI, CHANNEL, USER_BANK_CONTROL
96 : };
97 :
98 : std::vector<MidiCoreEvent>& initList() const;
99 :
100 26376 : String name() const { return m_name; }
101 : void setName(const String& value);
102 1 : String synti() const { return m_synti; }
103 : void setSynti(const String& value);
104 1966 : int color() const { return m_color; }
105 : void setColor(int value);
106 :
107 2826 : char volume() const { return m_volume; }
108 : void setVolume(char value);
109 2826 : char pan() const { return m_pan; }
110 : void setPan(char value);
111 1951 : char chorus() const { return m_chorus; }
112 : void setChorus(char value);
113 1951 : char reverb() const { return m_reverb; }
114 : void setReverb(char value);
115 :
116 0 : void addToInit(const MidiCoreEvent& e) { m_init.push_back(e); }
117 14372 : void setMustUpdateInit(bool arg) { m_mustUpdateInit = arg; }
118 :
119 588891 : int program() const { return m_program; }
120 : void setProgram(int value);
121 567145 : int bank() const { return m_bank; }
122 : void setBank(int value);
123 83985 : int channel() const { return m_channel; }
124 : void setChannel(int value);
125 :
126 : // If the bank controller is set by the user or not
127 3861 : bool userBankController() const { return m_userBankController; }
128 : void setUserBankController(bool val);
129 :
130 0 : bool isHarmonyChannel() const { return m_name == String::fromUtf8(InstrChannel::HARMONY_NAME); }
131 :
132 : std::vector<NamedEventList> midiActions;
133 : std::vector<MidiArticulation> articulation;
134 :
135 : InstrChannel();
136 :
137 : void updateInitList() const;
138 0 : bool operator==(const InstrChannel& c) const { return (m_name == c.m_name) && (m_channel == c.m_channel); }
139 0 : bool operator!=(const InstrChannel& c) const { return !(*this == c); }
140 :
141 : void addListener(ChannelListener* l);
142 : void removeListener(ChannelListener* l);
143 :
144 : void switchExpressive(Synthesizer* synth, bool expressive, bool force = false);
145 :
146 28744 : void setNotifyAboutChangedEnabled(bool arg) { m_notifyAboutChangedEnabled = arg; }
147 :
148 : private:
149 49822 : void firePropertyChanged(InstrChannel::Prop prop)
150 : {
151 49822 : if (m_notifyAboutChangedEnabled) {
152 15842 : m_notifier.notify(prop);
153 : }
154 49822 : }
155 :
156 : Notifier<InstrChannel::Prop> m_notifier;
157 : bool m_notifyAboutChangedEnabled = true;
158 :
159 : // this are the indexes of controllers which are always present in
160 : // Channel init EventList (maybe zero)
161 : String m_name;
162 :
163 : int m_color = 0; //rgb
164 :
165 : String m_synti;
166 :
167 : char m_volume = 0;
168 : char m_pan = 0;
169 :
170 : char m_chorus = 0;
171 : char m_reverb = 0;
172 :
173 : int m_program = 0; // current values as shown in mixer
174 : int m_bank = 0; // initialized from "init"
175 : int m_channel = 0; // mscore channel number, mapped to midi port/channel
176 :
177 : // MuseScore General-specific SND flags:
178 : //! TODO Needs porting to MU4
179 : bool m_userBankController = false; // if the user has changed the bank controller as opposed to switchExpressive
180 : //bool _switchedToExpressive = false; // if the patch has been automatically switched to an expr variant
181 :
182 : mutable std::vector<MidiCoreEvent> m_init;
183 : mutable bool m_mustUpdateInit = true;
184 : };
185 :
186 : //---------------------------------------------------------
187 : // ChannelListener
188 : //---------------------------------------------------------
189 :
190 : class ChannelListener : public Listener<InstrChannel::Prop>
191 : {
192 0 : OBJECT_ALLOCATOR(engraving, ChannelListener)
193 : public:
194 : virtual void propertyChanged(InstrChannel::Prop property) = 0;
195 : void setNotifier(InstrChannel* ch)
196 : {
197 : Listener::setNotifier(nullptr);
198 : if (ch) {
199 : ch->addListener(this);
200 : }
201 : }
202 :
203 : private:
204 3792 : void receive(InstrChannel::Prop prop) override { propertyChanged(prop); }
205 : };
206 :
207 : //---------------------------------------------------------
208 : // PartChannelSettingsLink
209 : //---------------------------------------------------------
210 :
211 : class PartChannelSettingsLink final : private ChannelListener
212 : {
213 : public:
214 : PartChannelSettingsLink() = default;
215 : PartChannelSettingsLink(InstrChannel* main, InstrChannel* bound, bool excerpt);
216 : PartChannelSettingsLink(const PartChannelSettingsLink&) = delete;
217 : PartChannelSettingsLink(PartChannelSettingsLink&&);
218 : PartChannelSettingsLink& operator=(const PartChannelSettingsLink&) = delete;
219 : PartChannelSettingsLink& operator=(PartChannelSettingsLink&&);
220 19160 : ~PartChannelSettingsLink() {}
221 :
222 : friend void swap(PartChannelSettingsLink&, PartChannelSettingsLink&);
223 :
224 : private:
225 :
226 : static void applyProperty(InstrChannel::Prop p, const InstrChannel* from, InstrChannel* to);
227 : void propertyChanged(InstrChannel::Prop p) override;
228 :
229 : InstrChannel* m_main = nullptr;
230 : InstrChannel* m_bound = nullptr;
231 : bool m_excerpt = false;
232 : };
233 :
234 : //---------------------------------------------------------
235 : // Trait
236 : //---------------------------------------------------------
237 :
238 : enum class TraitType : unsigned char
239 : {
240 : Unknown,
241 : Tuning,
242 : Transposition,
243 : Course
244 : };
245 :
246 : struct Trait
247 : {
248 : String name;
249 :
250 : TraitType type = TraitType::Unknown;
251 :
252 : bool isDefault = false;
253 : bool isHiddenOnScore = false;
254 :
255 : bool isValid() const { return !name.isEmpty(); }
256 : };
257 :
258 : //---------------------------------------------------------
259 : // Instrument
260 : //---------------------------------------------------------
261 :
262 : class Instrument
263 : {
264 : public:
265 : Instrument(String id = String());
266 : Instrument(const Instrument&);
267 : ~Instrument();
268 :
269 : NamedEventList* midiAction(const String& s, int channel) const;
270 : int channelIdx(const String& s) const;
271 : double getVelocityMultiplier(const String& name) const;
272 : void updateGateTime(int* gateTime, const String& name) const;
273 :
274 : String recognizeMusicXmlId() const;
275 : String recognizeId() const;
276 : int recognizeMidiProgram() const;
277 :
278 : void operator=(const Instrument&);
279 : bool operator==(const Instrument&) const;
280 : bool operator!=(const Instrument&) const;
281 :
282 : bool isDifferentInstrument(const Instrument& i) const;
283 :
284 64521 : const String& id() const { return m_id; }
285 1808 : const String& soundId() const { return m_soundId; }
286 799 : void setSoundId(const String& id) { m_soundId = id; }
287 : String family() const;
288 : String group() const;
289 1566 : void setId(const String& id) { m_id = id; }
290 1357 : void setMinPitchP(int v) { m_minPitchP = v; }
291 1357 : void setMaxPitchP(int v) { m_maxPitchP = v; }
292 1357 : void setMinPitchA(int v) { m_minPitchA = v; }
293 1357 : void setMaxPitchA(int v) { m_maxPitchA = v; }
294 259518 : Interval transpose() const { return m_transpose; }
295 2441 : void setTranspose(const Interval& v) { m_transpose = v; }
296 2509 : void setMusicXmlId(const String& musicXmlId) { m_musicXmlId = musicXmlId; }
297 :
298 : void setDrumset(const Drumset* ds);
299 3175 : const Drumset* drumset() const { return m_drumset; }
300 18093 : Drumset* drumset() { return m_drumset; }
301 343860 : bool useDrumset() const { return m_useDrumset; }
302 : void setUseDrumset(bool val);
303 799 : void setAmateurPitchRange(int a, int b) { m_minPitchA = a; m_maxPitchA = b; }
304 799 : void setProfessionalPitchRange(int a, int b) { m_minPitchP = a; m_maxPitchP = b; }
305 6385 : InstrChannel* channel(int idx) { return muse::value(m_channel, idx); }
306 7484 : const InstrChannel* channel(int idx) const { return muse::value(m_channel, idx); }
307 : InstrChannel* playbackChannel(int idx, MasterScore*);
308 : const InstrChannel* playbackChannel(int idx, const MasterScore*) const;
309 : size_t cleffTypeCount() const;
310 : ClefTypeList clefType(size_t staffIdx) const;
311 : void setClefType(size_t staffIdx, const ClefTypeList& c);
312 :
313 1762 : const std::vector<NamedEventList>& midiActions() const { return m_midiActions; }
314 0 : void addMidiAction(const NamedEventList& l) { m_midiActions.push_back(l); }
315 :
316 3372 : const std::vector<MidiArticulation>& articulation() const { return m_articulation; }
317 7244 : void addMidiArticulation(const MidiArticulation& a) { m_articulation.push_back(a); }
318 :
319 43544 : const std::vector<InstrChannel*>& channel() const { return m_channel; }
320 2019 : void appendChannel(InstrChannel* c) { m_channel.push_back(c); }
321 3 : void removeChannel(InstrChannel* c) { muse::remove(m_channel, c); }
322 1627 : void clearChannels() { m_channel.clear(); }
323 :
324 799 : void setMidiActions(const std::vector<NamedEventList>& l) { m_midiActions = l; }
325 831 : void setArticulation(const std::vector<MidiArticulation>& l) { m_articulation = l; }
326 8412 : const StringData* stringData() const { return &m_stringData; }
327 1378 : void setStringData(const StringData& d) { m_stringData.set(d); }
328 121369 : bool hasStrings() const { return m_stringData.strings() > 0; }
329 :
330 3205 : void setLongName(const String& f) { m_instrumentLabel.setLongName(f); }
331 2912 : void setShortName(const String& f) { m_instrumentLabel.setShortName(f); }
332 799 : void setInstrumentName(const InstrumentLabel& n) { m_instrumentLabel = n; }
333 599828 : const String& longName() const { return m_instrumentLabel.longName(); }
334 596314 : const String& shortName() const { return m_instrumentLabel.shortName(); }
335 38494 : const InstrumentLabel& instrumentLabel() const { return m_instrumentLabel; }
336 31056 : InstrumentLabel& instrumentLabel() { return m_instrumentLabel; }
337 :
338 9725 : int number() const { return m_instrumentLabel.number(); }
339 0 : void setNumber(int v) { return m_instrumentLabel.setNumber(v); }
340 :
341 9174 : const String& transposition() const { return m_instrumentLabel.transposition(); }
342 0 : void setTransposition(const String& s) { m_instrumentLabel.setTransposition(s); }
343 :
344 : int minPitchP() const;
345 : int maxPitchP() const;
346 : int minPitchA() const;
347 : int maxPitchA() const;
348 : String musicXmlId() const;
349 :
350 : String trackName() const;
351 : void setTrackName(const String& s);
352 : String nameAsXmlText() const;
353 : String nameAsPlainText() const;
354 : String abbreviatureAsXmlText() const;
355 : String abbreviatureAsPlainText() const;
356 : static Instrument fromTemplate(const InstrumentTemplate* t);
357 :
358 : Trait trait() const;
359 : void setTrait(const Trait& trait);
360 :
361 : bool isPrimary() const;
362 : void setIsPrimary(bool isPrimary);
363 :
364 : void updateInstrumentId();
365 :
366 2940 : bool singleNoteDynamics() const { return m_singleNoteDynamics; }
367 2743 : void setSingleNoteDynamics(bool val) { m_singleNoteDynamics = val; }
368 : void setSingleNoteDynamicsFromTemplate();
369 : bool getSingleNoteDynamicsFromTemplate() const;
370 : void switchExpressive(MasterScore* score, Synthesizer* synth, bool expressive, bool force = false);
371 :
372 : bool isVocalInstrument() const;
373 : bool isNormallyMultiStaveInstrument() const;
374 :
375 : GlissandoStyle glissandoStyle() const;
376 : void setGlissandoStyle(GlissandoStyle style);
377 :
378 : private:
379 :
380 : InstrumentLabel m_instrumentLabel;
381 :
382 : String m_trackName;
383 : String m_id;
384 : String m_soundId;
385 :
386 : int m_minPitchA = 0;
387 : int m_maxPitchA = 0;
388 : int m_minPitchP = 0;
389 : int m_maxPitchP = 0;
390 : Interval m_transpose;
391 : String m_musicXmlId;
392 :
393 : bool m_useDrumset = false;
394 : Drumset* m_drumset = nullptr;
395 : StringData m_stringData;
396 :
397 : std::vector<NamedEventList> m_midiActions;
398 : std::vector<MidiArticulation> m_articulation;
399 : std::vector<InstrChannel*> m_channel; // at least one entry
400 : std::vector<ClefTypeList> m_clefType;
401 :
402 : bool m_singleNoteDynamics = false;
403 :
404 : Trait m_trait;
405 : bool m_isPrimary = false;
406 :
407 : mutable String m_familyCache;
408 : mutable String m_groupCache;
409 :
410 : GlissandoStyle m_glissandoStyle = GlissandoStyle::CHROMATIC;
411 : };
412 :
413 : //---------------------------------------------------------
414 : // InstrumentList
415 : //---------------------------------------------------------
416 :
417 : class InstrumentList : public std::map<const int, Instrument*>
418 : {
419 : OBJECT_ALLOCATOR(engraving, InstrumentList)
420 :
421 : public:
422 3587 : InstrumentList() {}
423 : const Instrument* instrument(int tick) const;
424 : Instrument* instrument(int tick);
425 : void setInstrument(Instrument*, int tick);
426 : bool contains(const String& instrumentId) const;
427 :
428 : private:
429 :
430 : static Instrument defaultInstrument;
431 : };
432 : }
|