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 : #include "utils.h"
23 :
24 : #include "realfn.h"
25 : #include "engraving/dom/chord.h"
26 : #include "engraving/dom/factory.h"
27 : #include "engraving/dom/note.h"
28 : #include "engraving/dom/parenthesis.h"
29 : #include "engraving/dom/playcounttext.h"
30 : #include "engraving/dom/score.h"
31 : #include "engraving/dom/measure.h"
32 : #include "engraving/dom/segment.h"
33 : #include "engraving/style/styledef.h"
34 :
35 : using namespace mu::engraving;
36 :
37 : namespace mu::iex::guitarpro::utils {
38 74 : int harmonicOvertone(Note* note, float harmonicValue, int harmonicType)
39 : {
40 74 : int result{ 0 };
41 :
42 74 : if (muse::RealIsEqual(harmonicValue, 12.0f)) {
43 56 : result = 12;
44 18 : } else if (muse::RealIsEqual(harmonicValue, 7.0f) || muse::RealIsEqual(harmonicValue, 19.0f)) {
45 2 : result = 19;
46 16 : } else if (muse::RealIsEqual(harmonicValue, 5.0f) || muse::RealIsEqual(harmonicValue, 24.0f)) {
47 3 : result = 24;
48 13 : } else if (muse::RealIsEqual(harmonicValue, 3.9f)
49 13 : || muse::RealIsEqual(harmonicValue, 4.0f)
50 10 : || muse::RealIsEqual(harmonicValue, 9.0f)
51 26 : || muse::RealIsEqual(harmonicValue, 16.0f)) {
52 3 : result = 28;
53 10 : } else if (muse::RealIsEqual(harmonicValue, 3.2f)) {
54 2 : result = 31;
55 8 : } else if (muse::RealIsEqual(harmonicValue, 2.7f)
56 6 : || muse::RealIsEqual(harmonicValue, 5.8f)
57 6 : || muse::RealIsEqual(harmonicValue, 9.6f)
58 6 : || muse::RealIsEqual(harmonicValue, 14.7f)
59 14 : || muse::RealIsEqual(harmonicValue, 21.7f)) {
60 4 : result = 34;
61 4 : } else if (muse::RealIsEqual(harmonicValue, 2.3f)
62 4 : || muse::RealIsEqual(harmonicValue, 2.4f)
63 0 : || muse::RealIsEqual(harmonicValue, 8.2f)
64 8 : || muse::RealIsEqual(harmonicValue, 17.0f)) {
65 4 : result = 36;
66 0 : } else if (muse::RealIsEqual(harmonicValue, 2.0f)) {
67 0 : result = 38;
68 0 : } else if (muse::RealIsEqual(harmonicValue, 1.8f)) {
69 0 : result = 40;
70 : }
71 :
72 74 : return harmonicType == 1 ? result : (result + note->fret());
73 : }
74 :
75 560 : std::vector<int> standardTuningFor(int midiProgram, int stringsCount)
76 : {
77 : static const std::map<std::pair<int, /* program */ int /* strings count */>, std::vector<int> > tunings {
78 : // Guitars 6 strings
79 0 : { { 25, 6 }, { 40, 45, 50, 55, 59, 64 } },
80 0 : { { 26, 6 }, { 40, 45, 50, 55, 59, 64 } },
81 0 : { { 27, 6 }, { 40, 45, 50, 55, 59, 64 } },
82 0 : { { 28, 6 }, { 40, 45, 50, 55, 59, 64 } },
83 0 : { { 29, 6 }, { 40, 45, 50, 55, 59, 64 } },
84 0 : { { 30, 6 }, { 40, 45, 50, 55, 59, 64 } },
85 0 : { { 31, 6 }, { 40, 45, 50, 55, 59, 64 } },
86 0 : { { 32, 6 }, { 40, 45, 50, 55, 59, 64 } },
87 : // Guitars 7 strings
88 0 : { { 25, 7 }, { 35, 40, 45, 50, 55, 59, 64 } },
89 0 : { { 26, 7 }, { 35, 40, 45, 50, 55, 59, 64 } },
90 0 : { { 27, 7 }, { 35, 40, 45, 50, 55, 59, 64 } },
91 0 : { { 28, 7 }, { 35, 40, 45, 50, 55, 59, 64 } },
92 0 : { { 29, 7 }, { 35, 40, 45, 50, 55, 59, 64 } },
93 0 : { { 30, 7 }, { 35, 40, 45, 50, 55, 59, 64 } },
94 0 : { { 31, 7 }, { 35, 40, 45, 50, 55, 59, 64 } },
95 0 : { { 32, 7 }, { 35, 40, 45, 50, 55, 59, 64 } },
96 : // Basses 4 strings
97 0 : { { 33, 4 }, { 28, 33, 38, 43 } },
98 0 : { { 34, 4 }, { 28, 33, 38, 43 } },
99 0 : { { 35, 4 }, { 28, 33, 38, 43 } },
100 0 : { { 36, 4 }, { 28, 33, 38, 43 } },
101 0 : { { 37, 4 }, { 28, 33, 38, 43 } },
102 0 : { { 38, 4 }, { 28, 33, 38, 43 } },
103 : // Basses 5 strings
104 0 : { { 33, 5 }, { 23, 28, 33, 38, 43 } },
105 0 : { { 34, 5 }, { 23, 28, 33, 38, 43 } },
106 0 : { { 35, 5 }, { 23, 28, 33, 38, 43 } },
107 0 : { { 36, 5 }, { 23, 28, 33, 38, 43 } },
108 0 : { { 37, 5 }, { 23, 28, 33, 38, 43 } },
109 0 : { { 38, 5 }, { 23, 28, 33, 38, 43 } },
110 620 : };
111 560 : std::pair<int, int> key{ midiProgram, stringsCount };
112 :
113 560 : if (tunings.find(key) == tunings.end()) {
114 97 : return tunings.at({ 25, 6 });
115 : }
116 463 : return tunings.at(key);
117 29 : }
118 :
119 316 : bool isStandardTuning(int midiProgram, const std::vector<int>& tuning)
120 : {
121 316 : const auto& standardTuning = standardTuningFor(midiProgram, (int)tuning.size());
122 :
123 2094 : for (size_t i = 0; i < standardTuning.size(); ++i) {
124 1797 : if (tuning[i] != standardTuning[i]) {
125 19 : return false;
126 : }
127 : }
128 :
129 297 : return true;
130 316 : }
131 :
132 337 : Chord* getLocatedChord(mu::engraving::Score* score, Fraction tickFr, track_idx_t track)
133 : {
134 337 : const Measure* measure = score->tick2measure(tickFr);
135 337 : if (!measure) {
136 0 : LOGE() << "bend import error: no valid measure for track " << track << ", tick " << tickFr.ticks();
137 0 : return nullptr;
138 : }
139 :
140 337 : Chord* chord = measure->findChord(tickFr, track);
141 337 : if (!chord) {
142 0 : LOGE() << "bend import error: no valid chord for track " << track << ", tick " << tickFr.ticks();
143 0 : return nullptr;
144 : }
145 :
146 337 : return chord;
147 : }
148 :
149 2 : static void addParenthesesToNotes(Chord* ch, const std::vector<Note*>& notes)
150 : {
151 4 : auto createParen = [ch](DirectionH dir) {
152 4 : Parenthesis* p = Factory::createParenthesis(ch);
153 4 : p->setTrack(ch->track());
154 4 : p->setDirection(dir);
155 4 : return p;
156 2 : };
157 :
158 2 : NoteParenthesisInfo* parenInfo = new NoteParenthesisInfo(createParen(DirectionH::LEFT), createParen(DirectionH::RIGHT), notes);
159 2 : ch->addNoteParenthesisInfo(parenInfo);
160 :
161 4 : for (Note* n : notes) {
162 2 : n->setProperty(Pid::HAS_PARENTHESES, PropertyValue::fromValue(ParenthesesMode::BOTH));
163 2 : n->setHideGeneratedParens(true);
164 : }
165 2 : }
166 :
167 2086 : void createGhostNoteParenGroups(Chord* ch)
168 : {
169 2086 : if (!ch->noteParentheses().empty()) {
170 0 : return;
171 : }
172 :
173 2086 : const std::vector<Note*>& notes = ch->notes();
174 2086 : const size_t count = notes.size();
175 2086 : std::vector<Note*> currentGroup;
176 :
177 6912 : for (size_t i = 0; i <= count; ++i) {
178 4826 : if (i < count && notes[i]->ghost()) {
179 2 : currentGroup.push_back(notes[i]);
180 4824 : } else if (!currentGroup.empty()) {
181 2 : addParenthesesToNotes(ch, currentGroup);
182 2 : currentGroup.clear();
183 : }
184 : }
185 2086 : }
186 :
187 287 : void addPlayCountTexts(Score* score)
188 : {
189 287 : const bool showText = score->style().styleB(Sid::repeatPlayCountShow);
190 287 : const bool singleRepeats = score->style().styleB(Sid::repeatPlayCountShowSingleRepeats);
191 1191 : for (Measure* m = score->firstMeasure(); m; m = m->nextMeasure()) {
192 904 : if (!m->repeatEnd()) {
193 895 : continue;
194 : }
195 9 : const int playCount = m->repeatCount();
196 9 : if (!showText || (playCount == 2 && !singleRepeats)) {
197 5 : continue;
198 : }
199 4 : Segment* endBarSeg = m->last(SegmentType::BarLineTypes);
200 4 : if (!endBarSeg || endBarSeg->findAnnotation(ElementType::PLAY_COUNT_TEXT, 0, 0)) {
201 0 : continue;
202 : }
203 4 : PlayCountText* pct = Factory::createPlayCountText(endBarSeg);
204 4 : pct->setTrack(0);
205 4 : score->addElement(pct);
206 : }
207 287 : }
208 : } // namespace mu::iex::guitarpro
|