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 "pitchspelling.h"
26 : #include "../types/types.h"
27 :
28 : #include <array>
29 :
30 : namespace mu::engraving {
31 : class XmlWriter;
32 : class XmlReader;
33 : class Articulation;
34 :
35 : struct DrumInstrumentVariant {
36 : int pitch = INVALID_PITCH;
37 : TremoloType tremolo = TremoloType::INVALID_TREMOLO;
38 : String articulationName;
39 :
40 0 : bool operator==(const DrumInstrumentVariant& other) const
41 : {
42 0 : return pitch == other.pitch
43 0 : && tremolo == other.tremolo
44 0 : && articulationName == other.articulationName;
45 : }
46 : };
47 :
48 : //---------------------------------------------------------
49 : // DrumInstrument
50 : //---------------------------------------------------------
51 :
52 : struct DrumInstrument {
53 : String name;
54 :
55 : // if notehead = HEAD_CUSTOM, custom, use noteheads
56 : NoteHeadGroup notehead = NoteHeadGroup::HEAD_INVALID; ///< notehead symbol set
57 : std::array<SymId, int(NoteHeadType::HEAD_TYPES)> noteheads
58 : = { SymId::noteheadWhole, SymId::noteheadHalf, SymId::noteheadBlack, SymId::noteheadDoubleWhole };
59 :
60 : int line = 0; ///< place notehead onto this line
61 : DirectionV stemDirection = DirectionV::AUTO;
62 :
63 : int panelRow = -1;
64 : int panelColumn = -1;
65 :
66 : int voice = 0;
67 : String shortcut;
68 : std::vector<DrumInstrumentVariant> variants;
69 :
70 3713 : DrumInstrument() {}
71 1399 : DrumInstrument(const String& n, NoteHeadGroup nh, int l, DirectionV d,
72 : int pr = -1, int pc = -1, int v = 0, String sc = String())
73 1399 : : name(n), notehead(nh), line(l), stemDirection(d), panelRow(pr), panelColumn(pc), voice(v), shortcut(sc) {}
74 :
75 0 : void addVariant(DrumInstrumentVariant v) { variants.push_back(v); }
76 :
77 0 : bool operator==(const DrumInstrument& other) const
78 : {
79 0 : return name == other.name
80 0 : && notehead == other.notehead
81 0 : && noteheads == other.noteheads
82 0 : && line == other.line
83 0 : && stemDirection == other.stemDirection
84 0 : && voice == other.voice
85 0 : && shortcut == other.shortcut
86 0 : && variants == other.variants
87 0 : && panelRow == other.panelRow
88 0 : && panelColumn == other.panelColumn;
89 : }
90 : };
91 :
92 : static const int DRUM_INSTRUMENTS = 128;
93 :
94 : //---------------------------------------------------------
95 : // Drumset
96 : // defines noteheads and line position for all
97 : // possible midi notes in a drumset
98 : //---------------------------------------------------------
99 :
100 : class Drumset
101 : {
102 : public:
103 : bool isValid(int pitch) const;
104 3336 : NoteHeadGroup noteHead(int pitch) const { return m_drums[pitch].notehead; }
105 92 : SymId noteHeads(int pitch, NoteHeadType t) const { return m_drums[pitch].noteheads[int(t)]; }
106 3870 : int line(int pitch) const { return m_drums[pitch].line; }
107 1217 : int voice(int pitch) const { return m_drums[pitch].voice; }
108 1208 : DirectionV stemDirection(int pitch) const { return m_drums[pitch].stemDirection; }
109 192765 : const String& name(int pitch) const { return m_drums[pitch].name; }
110 : String translatedName(int pitch) const;
111 1170 : String shortcut(int pitch) const { return m_drums[pitch].shortcut; }
112 1113 : const std::vector<DrumInstrumentVariant>& variants(int pitch) const { return m_drums[pitch].variants; }
113 1467 : int panelRow(int pitch) const { return m_drums[pitch].panelRow; }
114 921 : int panelColumn(int pitch) const { return m_drums[pitch].panelColumn; }
115 :
116 0 : size_t percussionPanelColumns() const { return m_percussionPanelColumns; }
117 0 : void setPercussionPanelColumns(size_t columns) { m_percussionPanelColumns = columns; }
118 :
119 : int pitchForShortcut(const String& shortcut) const;
120 :
121 : // defaultPitchForLine tries to find the pitch of a normal notehead at "line". If a normal notehead can't be found it will
122 : // instead return the "first valid pitch" (i.e. the lowest used midi note)
123 : int defaultPitchForLine(int line) const;
124 :
125 : void save(XmlWriter&) const;
126 : void loadDrum(XmlReader&);
127 : bool readDrumProperties(XmlReader&, int);
128 : void clear();
129 : int nextPitch(int) const;
130 : int prevPitch(int) const;
131 19298 : DrumInstrument& drum(int i) { return m_drums[i]; }
132 5632 : const DrumInstrument& drum(int i) const { return m_drums[i]; }
133 0 : void setDrum(int pitch, const DrumInstrument& di) { m_drums[pitch] = di; }
134 : DrumInstrumentVariant findVariant(int pitch, const std::vector<Articulation*>& articulations, TremoloType tremType) const;
135 :
136 : static void initDrumset();
137 :
138 0 : bool operator==(const Drumset& other) const
139 : {
140 0 : for (int pitch = 0; pitch < DRUM_INSTRUMENTS; ++pitch) {
141 0 : if (m_drums[pitch] == other.m_drums[pitch]) {
142 0 : continue;
143 : }
144 0 : return false;
145 : }
146 0 : return m_percussionPanelColumns == other.m_percussionPanelColumns;
147 : }
148 :
149 0 : bool operator!=(const Drumset& other) const
150 : {
151 0 : return !(*this == other);
152 : }
153 :
154 : private:
155 : DrumInstrument m_drums[DRUM_INSTRUMENTS];
156 : size_t m_percussionPanelColumns = 8;
157 : };
158 :
159 : extern Drumset* smDrumset;
160 : } // namespace mu::engraving
|