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 : #include "synthesizerstate.h"
24 :
25 : #include "rw/xmlwriter.h"
26 : #include "rw/xmlreader.h"
27 :
28 : #include "log.h"
29 :
30 : using namespace mu;
31 :
32 : namespace mu::engraving {
33 : //---------------------------------------------------------
34 : // write
35 : //---------------------------------------------------------
36 :
37 0 : void SynthesizerState::write(XmlWriter& xml, bool force /* = false */) const
38 : {
39 0 : if (isDefault() && !force) {
40 0 : return;
41 : }
42 :
43 0 : xml.startElement("Synthesizer");
44 0 : for (const SynthesizerGroup& g : *this) {
45 0 : if (!g.name().isEmpty()) {
46 0 : muse::ByteArray ba = g.name().toAscii();
47 0 : xml.startElement(ba.constChar());
48 0 : for (const IdValue& v : g) {
49 0 : xml.tag("val", { { "id", v.id } }, v.data);
50 : }
51 0 : xml.endElement();
52 0 : }
53 : }
54 0 : xml.endElement();
55 0 : }
56 :
57 : //---------------------------------------------------------
58 : // read
59 : //---------------------------------------------------------
60 :
61 33 : void SynthesizerState::read(XmlReader& e)
62 : {
63 33 : std::list<SynthesizerGroup> tempGroups;
64 33 : while (e.readNextStartElement()) {
65 0 : SynthesizerGroup group;
66 0 : group.setName(String::fromAscii(e.name().ascii()));
67 :
68 0 : while (e.readNextStartElement()) {
69 0 : if (e.name() == "val") {
70 0 : int id = e.intAttribute("id");
71 0 : group.push_back(IdValue(id, e.readText()));
72 : } else {
73 0 : e.unknown();
74 : }
75 : }
76 0 : tempGroups.push_back(group);
77 0 : }
78 :
79 33 : if (!tempGroups.empty()) {
80 : // Replace any previously set state if we have read a new state
81 0 : swap(tempGroups);
82 0 : setIsDefault(false);
83 : }
84 33 : }
85 :
86 : //---------------------------------------------------------
87 : // group
88 : /// Get SynthesizerGroup by name
89 : //---------------------------------------------------------
90 :
91 36 : SynthesizerGroup SynthesizerState::group(const String& name) const
92 : {
93 36 : for (const SynthesizerGroup& g : *this) {
94 0 : if (g.name() == name) {
95 0 : return g;
96 : }
97 : }
98 36 : SynthesizerGroup sg;
99 36 : return sg;
100 36 : }
101 :
102 : //---------------------------------------------------------
103 : // isDefaultSynthSoundfont
104 : /// check if synthesizer state uses default synth and
105 : /// default font only
106 : //---------------------------------------------------------
107 :
108 0 : bool SynthesizerState::isDefaultSynthSoundfont()
109 : {
110 0 : SynthesizerGroup fluid = group(u"Fluid");
111 0 : if (fluid.size() == 1) {
112 0 : if (fluid.front().data == u"MS Basic.sf3") {
113 0 : return true;
114 : }
115 : }
116 0 : return false;
117 0 : }
118 :
119 : //---------------------------------------------------------
120 : // ccToUse
121 : //---------------------------------------------------------
122 :
123 24 : int SynthesizerState::ccToUse() const
124 : {
125 24 : SynthesizerGroup g = group(u"master");
126 :
127 24 : int method = 1;
128 24 : int cc = -1;
129 :
130 24 : for (const IdValue& idVal : g) {
131 0 : if (idVal.id == 4) {
132 0 : method = idVal.data.toInt();
133 0 : } else if (idVal.id == 5) {
134 0 : switch (idVal.data.toInt()) {
135 0 : case 0:
136 0 : cc = 1;
137 0 : break;
138 0 : case 1:
139 0 : cc = 2;
140 0 : break;
141 0 : case 2:
142 0 : cc = 4;
143 0 : break;
144 0 : case 3:
145 0 : cc = 11;
146 0 : break;
147 0 : default:
148 0 : LOGW("Unrecognised CCToUse index from synthesizer: %d", idVal.data.toInt());
149 : }
150 : }
151 : }
152 :
153 24 : if (method == 0) { // velocity only
154 0 : return -1;
155 : }
156 :
157 24 : return cc;
158 24 : }
159 :
160 : //---------------------------------------------------------
161 : // method
162 : //---------------------------------------------------------
163 :
164 12 : int SynthesizerState::method() const
165 : {
166 12 : SynthesizerGroup g = group(u"master");
167 :
168 12 : int method = -1;
169 :
170 12 : for (const IdValue& idVal : g) {
171 0 : if (idVal.id == 4) {
172 0 : method = idVal.data.toInt();
173 0 : break;
174 : }
175 : }
176 :
177 12 : return method;
178 12 : }
179 : }
|