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 "braille.h"
24 :
25 : #include <QRegularExpression>
26 :
27 : #include "containers.h"
28 :
29 : #include "engraving/dom/accidental.h"
30 : #include "engraving/dom/arpeggio.h"
31 : #include "engraving/dom/articulation.h"
32 : #include "engraving/dom/barline.h"
33 : #include "engraving/dom/breath.h"
34 : #include "engraving/dom/chord.h"
35 : #include "engraving/dom/clef.h"
36 : #include "engraving/dom/durationtype.h"
37 : #include "engraving/dom/dynamic.h"
38 : #include "engraving/dom/engravingitem.h"
39 : #include "engraving/dom/fermata.h"
40 : #include "engraving/dom/fingering.h"
41 : #include "engraving/dom/hairpin.h"
42 : #include "engraving/dom/jump.h"
43 : #include "engraving/dom/keysig.h"
44 : #include "engraving/dom/lyrics.h"
45 : #include "engraving/dom/marker.h"
46 : #include "engraving/dom/measure.h"
47 : #include "engraving/dom/mmrest.h"
48 : #include "engraving/dom/mscore.h"
49 : #include "engraving/dom/note.h"
50 : #include "engraving/dom/page.h"
51 : #include "engraving/dom/part.h"
52 : #include "engraving/dom/pitchspelling.h"
53 : #include "engraving/dom/rest.h"
54 : #include "engraving/dom/score.h"
55 : #include "engraving/dom/segment.h"
56 : #include "engraving/dom/slur.h"
57 : #include "engraving/dom/spanner.h"
58 : #include "engraving/dom/staff.h"
59 : #include "engraving/dom/system.h"
60 : #include "engraving/dom/tempotext.h"
61 : #include "engraving/dom/text.h"
62 : #include "engraving/dom/tie.h"
63 : #include "engraving/dom/timesig.h"
64 : #include "engraving/dom/tuplet.h"
65 : #include "engraving/dom/utils.h"
66 : #include "engraving/dom/volta.h"
67 :
68 : #include "louis.h"
69 : #include "braillecode.h"
70 :
71 : #define BRAILLE_TRACE_ENABLED 0
72 : #if BRAILLE_TRACE_ENABLED
73 : #define BRAILLE_TRACE LOGD
74 : #else
75 : #define BRAILLE_TRACE LOGN
76 : #endif
77 :
78 : namespace mu::engraving {
79 : // Max lyrics num
80 : #define MAX_LYRICS_NUM 16
81 : // Table 1. Page 2. Music Braille Code 2015.
82 : #define BRAILLE_EQUALS_METRONOME QString("7")
83 : #define BRAILLE_MUSICAL_HYPEN QString("\"")
84 : #define BRAILLE_BARLINE QString(" ")
85 : #define BRAILLE_BARLINE_BROKEN QString("K")
86 : #define BRAILLE_BARLINE_DOUBLE QString("<K'")
87 : #define BRAILLE_BARLINE_END QString("<K")
88 : #define BRAILLE_BARLINE_DOTTED QString("l")
89 :
90 : #define BRAILLE_ACC_NATURAL QString("*")
91 : #define BRAILLE_ACC_SHARP QString("%")
92 : #define BRAILLE_ACC_FLAT QString("<")
93 : #define BRAILLE_ACC_QUARTER_STEP QString("@")
94 : #define BRAILLE_ACC_3QUARTER_STEP QString("_")
95 : #define BRAILLE_ACC_5QUARTER_STEP QString(".") //extrapolated from octave marks. not sure.
96 :
97 : // Table 2. Page 4. Music Braille Code 2015
98 : //8th and 128th notes have the same representation in Braille
99 : #define BRAILLE_C_8TH_128TH 'D'
100 : #define BRAILLE_D_8TH_128TH 'E'
101 : #define BRAILLE_E_8TH_128TH 'F'
102 : #define BRAILLE_F_8TH_128TH 'G'
103 : #define BRAILLE_G_8TH_128TH 'H'
104 : #define BRAILLE_A_8TH_128TH 'I'
105 : #define BRAILLE_B_8TH_128TH 'J'
106 : //64th and quarter notes have the same representation in Braille
107 : #define BRAILLE_C_64TH_QUARTER '?'
108 : #define BRAILLE_D_64TH_QUARTER ':'
109 : #define BRAILLE_E_64TH_QUARTER '$'
110 : #define BRAILLE_F_64TH_QUARTER ']'
111 : #define BRAILLE_G_64TH_QUARTER '\\'
112 : #define BRAILLE_A_64TH_QUARTER '['
113 : #define BRAILLE_B_64TH_QUARTER 'W'
114 : //32nd and half notes have the same representation in Braille
115 : #define BRAILLE_C_32ND_HALF 'N'
116 : #define BRAILLE_D_32ND_HALF 'o'
117 : #define BRAILLE_E_32ND_HALF 'p'
118 : #define BRAILLE_F_32ND_HALF 'q'
119 : #define BRAILLE_G_32ND_HALF 'r'
120 : #define BRAILLE_A_32ND_HALF 's'
121 : #define BRAILLE_B_32ND_HALF 't'
122 : //16th and whole notes have the same representation in Braille.
123 : // Breve has the same representation, but with an extra suffix;
124 : // 256th has the same representation, but with an extra prefix;
125 : #define BRAILLE_C_16TH_WHOLE 'Y'
126 : #define BRAILLE_D_16TH_WHOLE 'Z'
127 : #define BRAILLE_E_16TH_WHOLE '&'
128 : #define BRAILLE_F_16TH_WHOLE '='
129 : #define BRAILLE_G_16TH_WHOLE '('
130 : #define BRAILLE_A_16TH_WHOLE '!'
131 : #define BRAILLE_B_16TH_WHOLE ')'
132 :
133 : #define BRAILLE_BREVE_SUFFIX QString("k")
134 : #define BRAILLE_256TH_PREFIX QString(";<1")
135 : #define BRAILLE_DURATION_DOT QString("'")
136 :
137 : // Table 3. Page 4. Music Braille Code 2015.
138 : #define BRAILLE_BELOW_FIRST_OCTAVE QString("@@")
139 : #define BRAILLE_1ST_OCTAVE QString("@")
140 : #define BRAILLE_2ND_OCTAVE QString("^")
141 : #define BRAILLE_3RD_OCTAVE QString("_")
142 : #define BRAILLE_4TH_OCTAVE QString("\"")
143 : #define BRAILLE_5TH_OCTAVE QString(".")
144 : #define BRAILLE_6TH_OCTAVE QString(";")
145 : #define BRAILLE_7TH_OCTAVE QString(",")
146 : #define BRAILLE_ABOVE_7TH_OCTAVE QString(",,")
147 :
148 : // Table 4. Page 4. Music Braille Code 2015.
149 : #define BRAILLE_TREBLE_CLEF QString(">/l")
150 : #define BRAILLE_TREBLE_CLEF_15MB QString(">/l#15")
151 : #define BRAILLE_TREBLE_CLEF_8VB QString(">/l#8")
152 : #define BRAILLE_TREBLE_CLEF_8VA QString(">/l#h")
153 : #define BRAILLE_TREBLE_CLEF_15MA QString(">/l#ae")
154 : #define BRAILLE_D_TREBLE_CLEF_8VB_O QString(">/l/l#8")
155 : #define BRAILLE_TREBLE_CLEF_8VB_P QString(">/l#787")
156 : #define BRAILLE_FRENCH_VIOLINE_CLEF QString(">/@l")
157 : #define BRAILLE_SOPRANO_CLEF QString(">+@l")
158 : #define BRAILLE_MEZZO_SOPRANO_CLEF QString(">+^l")
159 : #define BRAILLE_ALTO_CLEF QString(">+l")
160 : #define BRAILLE_TENOR_CLEF QString(">+\"l")
161 : #define BRAILLE_BARITONE_C_CLEF QString(">+.l")
162 : #define BRAILLE_BASS_CLEF QString(">#l")
163 : #define BRAILLE_BASS_CLEF_15MB QString(">#l#15")
164 : #define BRAILLE_BASS_CLEF_8VB QString(">#l#8")
165 : #define BRAILLE_BASS_CLEF_8VA QString(">#l#h")
166 : #define BRAILLE_BASS_CLEF_15MA QString(">#l#ae")
167 : #define BRAILLE_BARITONE_F_CLEF QString(">#_l")
168 : #define BRAILLE_SUBBASS_CLEF QString(">#.l")
169 :
170 : // Table 5. Page 5. Music Braille Code 2015.
171 : #define BRAILLE_REST_LONG QString("m^c^cm")
172 : #define BRAILLE_REST_BREVE QString("mk")
173 : #define BRAILLE_REST_WHOLE QString("m")
174 : #define BRAILLE_REST_HALF QString("u")
175 : #define BRAILLE_REST_QUARTER QString("v")
176 : #define BRAILLE_REST_EIGHTH QString("x")
177 : #define BRAILLE_REST_16TH QString("m")
178 : #define BRAILLE_REST_32ND QString("u")
179 : #define BRAILLE_REST_64TH QString("v")
180 : #define BRAILLE_REST_128TH QString("x")
181 : #define BRAILLE_REST_256TH QString(";<1m")
182 : #define BRAILLE_REST_MEASURE QString("m")
183 :
184 : // Table 9. Page 7. Music Braille Code 2015.
185 : #define BRAILLE_OCTAVE QString("-")
186 : #define BRAILLE_SECOND QString("/")
187 : #define BRAILLE_THIRD QString("+")
188 : #define BRAILLE_FOURTH QString("#")
189 : #define BRAILLE_FIFTH QString("9")
190 : #define BRAILLE_SIXTH QString("0")
191 : #define BRAILLE_SEVENTH QString("3")
192 :
193 : // Table 10. Page 7. Music Braille Code 2015
194 : #define BRAILLE_TIE QString("@c")
195 : #define BRAILLE_TIE_CHORD QString(".c")
196 :
197 : // Table 11. Page 8. Music Braille Code 2015
198 : #define BRAILLE_FULL_MEASURE_IN_ACORD QString("<>")
199 : #define BRAILLE_PART_MEASURE_IN_ACORD QString("\"1")
200 : #define BRAILLE_MEASURE_DIVISION QString(".k")
201 :
202 : // Table 13. Page 9. Music Braille Code 2015.
203 : #define BRAILLE_SLUR_SHORT QString("c")
204 : #define BRAILLE_SLUR_SHORT_CONVERGENCE QString(",c")
205 : #define BRAILLE_SLUR_BRACKET_START QString(";b")
206 : #define BRAILLE_SLUR_BRACKET_END QString("^2")
207 :
208 : // Table 14. Page 10. Music Braille Code 2015
209 : #define BRAILLE_TREMOLO_8THS QString("^b")
210 : #define BRAILLE_TREMOLO_16THS QString("^l")
211 : #define BRAILLE_TREMOLO_32NDS QString("^1")
212 : #define BRAILLE_TREMOLO_64THS QString("^k")
213 : #define BRAILLE_TREMOLO_128THS QString("^'")
214 : #define BRAILLE_TREMOLO_8THS_ALT QString(".b")
215 : #define BRAILLE_TREMOLO_16THS_ALT QString(".l")
216 : #define BRAILLE_TREMOLO_32NDS_ALT QString(".1")
217 : #define BRAILLE_TREMOLO_64THS_ALT QString(".k")
218 : #define BRAILLE_TREMOLO_128THS_ALT QString(".'")
219 :
220 : // Table 15. Page 11. Music Braille Code 2015.
221 : #define BRAILLE_FINGERING_OPEN QString("K")
222 : #define BRAILLE_FINGERING_1ST QString("a")
223 : #define BRAILLE_FINGERING_2ND QString("b")
224 : #define BRAILLE_FINGERING_3RD QString("l")
225 : #define BRAILLE_FINGERING_4TH QString("1")
226 : #define BRAILLE_FINGERING_5TH QString("k")
227 : #define BRAILLE_FINGERING_CHANGE QString("c")
228 :
229 : // Table 16.A. Page 12. Music Braille Code 2015.
230 : #define BRAILLE_GRACE_LONG QString("\"5")
231 : #define BRAILLE_GRACE_SHORT QString("5")
232 :
233 : // Table 16.B. Page 12. Music Braille Code 2015.
234 : #define BRAILLE_TRILL QString("6")
235 : #define BRAILLE_TRILL_FLAT QString("<6")
236 : #define BRAILLE_TRILL_SHARP QString("%6")
237 : #define BRAILLE_TURN_BTWN_NOTES QString("4")
238 : #define BRAILLE_TURN_NOTE QString(",4")
239 : #define BRAILLE_INVERTED_TURN_BTWN_NOTES QString("4l")
240 : #define BRAILLE_INVERTED_TURN_NOTE QString(",4l")
241 :
242 : // Table 16.C. Page 13. Music Braille Code 2015
243 : #define BRAILLE_SHORT_TRILL QString("\"6")
244 : #define BRAILLE_TREBLEMENT QString(";6")
245 : #define BRAILLE_MORDENT QString("\"6l")
246 : #define BRAILLE_PRALL_MORDENT QString(";6l")
247 :
248 : // Table 16.D. Page 13. Music Braille Code 2015
249 : #define BRAILLE_GLISSANDO QString("@a")
250 :
251 : // Table 16.F. Page 14. Music Braille Code 2015
252 : #define BRAILLE_MORDENT_WITH_UPPER_FIX QString("4;6")
253 : #define BRAILLE_UP_PRALL QString("4l;6")
254 : #define BRAILLE_UP_MORDENT QString("4l;6l") //extrapolated. not sure
255 : #define BRAILLE_DOWN_MORDENT QString("4;6") //extrapolated. not sure
256 : #define BRAILLE_PRALL_DOWN QString(";64l") //extrapolated. not sure
257 : #define BRAILLE_PRALL_UP QString(";64") //extrapolated. not sure
258 : #define BRAILLE_LINE_PRALL QString(";6l4") //extrapolated. not sure
259 :
260 : // Table 17. Page 15.x Music Braille Code 2015
261 : #define BRAILLE_BARLINE_START_REPEAT QString("<7")
262 : #define BRAILLE_BARLINE_END_REPEAT QString("<2")
263 :
264 : // Table 18. Page 15. Music Braille Code 2015
265 : #define BRAILLE_MEASURE_REPEAT QString("7")
266 :
267 : // Table 20. Page 16. Music Braille Code 2015
268 : #define BRAILLE_SEGNO QString("+ ")
269 : #define BRAILLE_CODA QString("+l ")
270 : #define BRAILLE_FINE QString(">fine> ")
271 : #define BRAILLE_TOCODA QString(">to coda> ")
272 : #define BRAILLE_DA_CAPO QString(">d'c'> ")
273 : #define BRAILLE_DA_CAPO_AL_FINE QString(">d'c' al fine> ")
274 : #define BRAILLE_DA_CAPO_AL_CODA QString(">d'c' al coda> ")
275 : #define BRAILLE_DAL_SEGNO_AL_CODA QString(">d's' al coda> ")
276 : #define BRAILLE_DAL_SEGNO_AL_FINE QString(">d's' al fine> ")
277 : #define BRAILLE_DAL_SEGNO QString(">d's'> ")
278 :
279 : // Table 21. Page 16. Music Braille Code 2015
280 : #define BRAILLE_MUSIC_PARENTHESES QString(",'")
281 :
282 : // Table 22. Page 17. Music Braille Code 2015.
283 : #define BRAILLE_ARPEGGIO_UPWARD QString(">k")
284 : #define BRAILLE_ARPEGGIO_DOWNWARD QString(">kk")
285 : #define BRAILLE_ARPEGGIO_MULTISTAVES QString("\"")
286 :
287 : // Table 22.A. Page 17. Music Braille Code 2015.
288 : #define BRAILLE_ARTIC_STACCATO QString("8")
289 : #define BRAILLE_ARTIC_STACCATISSIMO QString(",8")
290 : #define BRAILLE_ARTIC_TENUTO_STACCATO QString("\"8")
291 : #define BRAILLE_ARTIC_TENUTO QString("_8")
292 : #define BRAILLE_ARTIC_ACCENT QString(".8")
293 : #define BRAILLE_ARTIC_MARCATO QString(";8")
294 : #define BRAILLE_ARTIC_REVERSED_ACCENT QString("@8")
295 : #define BRAILLE_ARTIC_EXPRESSIVE_ACCENT QString("^8")
296 : #define BRAILLE_ARTIC_SWELL QString("*'")
297 :
298 : // Table 22.2.B. Page 18. Music Braille Code 2015.
299 : #define BRAILLE_FERMATA QString("<l")
300 : #define BRAILLE_SHORT_FERMATA QString("^<l")
301 : #define BRAILLE_LONG_FERMATA QString(";<l")
302 : #define BRAILLE_BREATH QString(">1")
303 : #define BRAILLE_CAESURA QString(",/")
304 :
305 : // Table 22.C
306 : #define BRAILLE_HAIRPIN_DIV_START QString(">c")
307 : #define BRAILLE_HAIRPIN_DIV_END QString(">3")
308 : #define BRAILLE_HAIRPIN_CONV_START QString(">d")
309 : #define BRAILLE_HAIRPIN_CONV_END QString(">4")
310 : #define BRAILLE_CRESC QString(">cr'")
311 : #define BRAILLE_DESCRESC QString(">decr'")
312 : #define BRAILLE_DIM QString(">dim'")
313 : #define BRAILLE_LV QString(">lvb'")
314 : #define BRAILLE_LINE_CONT_START_1 QString("''")
315 : #define BRAILLE_LINE_CONT_END_1 QString(">'")
316 : #define BRAILLE_LINE_CONT_START_2 QString("--")
317 : #define BRAILLE_LINE_CONT_END_2 QString(">-")
318 :
319 : // TABLE 24.B. Page 22. Music Braille Code 2015
320 : #define BRAILLE_DOWN_BOW QString("<b")
321 : #define BRAILLE_UP_BOW QString("<'")
322 : #define BRAILLE_LEFT_HAND_PIZZICATO QString("_>")
323 :
324 0 : BrailleEngravingItem::BrailleEngravingItem(BEIType type,
325 : EngravingItem* el,
326 0 : QString braille)
327 : {
328 0 : m_type = type;
329 0 : m_el = el;
330 0 : m_braille = braille;
331 0 : if (type == BEIType::EndOfLine) {
332 0 : m_start = -1;
333 0 : m_end = -1;
334 : } else {
335 0 : m_start = 0;
336 0 : m_end = braille.length();
337 : }
338 0 : }
339 :
340 0 : BrailleEngravingItem::BrailleEngravingItem(BEIType type,
341 : EngravingItem* e, QString b,
342 0 : QString extra_info, int extra_val)
343 0 : : BrailleEngravingItem(type, e, b)
344 : {
345 0 : m_extra_info = extra_info;
346 0 : m_extra_val = extra_val;
347 0 : }
348 :
349 0 : BrailleEngravingItem::~BrailleEngravingItem()
350 : {
351 0 : m_braille = QString();
352 0 : m_extra_info = QString();
353 0 : }
354 :
355 0 : BEIType BrailleEngravingItem::type()
356 : {
357 0 : return m_type;
358 : }
359 :
360 0 : EngravingItem* BrailleEngravingItem::el()
361 : {
362 0 : return m_el;
363 : }
364 :
365 0 : QString BrailleEngravingItem::braille()
366 : {
367 0 : return m_braille;
368 : }
369 :
370 0 : int BrailleEngravingItem::start()
371 : {
372 0 : return m_start;
373 : }
374 :
375 0 : int BrailleEngravingItem::end()
376 : {
377 0 : return m_end;
378 : }
379 :
380 0 : QString BrailleEngravingItem::extra_info()
381 : {
382 0 : return m_extra_info;
383 : }
384 :
385 0 : int BrailleEngravingItem::extra_val()
386 : {
387 0 : return m_extra_val;
388 : }
389 :
390 0 : void BrailleEngravingItem::setBraille(QString b)
391 : {
392 0 : m_braille = b;
393 0 : }
394 :
395 0 : void BrailleEngravingItem::setPos(int start, int end)
396 : {
397 0 : m_start = start;
398 0 : m_end = end;
399 0 : }
400 :
401 0 : void BrailleEngravingItem::setExtra(QString info, int val)
402 : {
403 0 : m_extra_info = info;
404 0 : m_extra_val = val;
405 0 : }
406 :
407 0 : BrailleEngravingItemList::BrailleEngravingItemList()
408 : {
409 0 : m_braille_str = QString();
410 0 : }
411 :
412 0 : BrailleEngravingItemList::~BrailleEngravingItemList()
413 : {
414 0 : clear();
415 0 : }
416 :
417 0 : void BrailleEngravingItemList::clear()
418 : {
419 0 : m_braille_str = QString();
420 0 : m_items.clear();
421 0 : }
422 :
423 0 : void BrailleEngravingItemList::join(BrailleEngravingItemList* another, bool newline, bool del)
424 : {
425 0 : int len = m_braille_str.length();
426 :
427 0 : if (newline && !m_braille_str.isEmpty()) {
428 0 : BrailleEngravingItem item = BrailleEngravingItem(BEIType::EndOfLine, NULL, "\n");
429 0 : m_items.push_back(item);
430 0 : m_braille_str.append("\n");
431 0 : len++;
432 0 : }
433 :
434 0 : m_braille_str.append(another->brailleStr());
435 :
436 0 : for (auto item: *another->items()) {
437 0 : int start = item.start() + len;
438 0 : int end = item.end() + len;
439 0 : item.setPos(start, end);
440 0 : m_items.push_back(item);
441 0 : }
442 :
443 0 : if (del) {
444 0 : delete another;
445 : }
446 0 : }
447 :
448 0 : void BrailleEngravingItemList::join(std::vector<BrailleEngravingItemList*> lst, bool newline, bool del)
449 : {
450 0 : for (auto item: lst) {
451 0 : join(item, newline, del);
452 : }
453 0 : }
454 :
455 0 : QString BrailleEngravingItemList::brailleStr()
456 : {
457 0 : return m_braille_str;
458 : }
459 :
460 0 : std::vector<BrailleEngravingItem>* BrailleEngravingItemList::items()
461 : {
462 0 : return &m_items;
463 : }
464 :
465 0 : void BrailleEngravingItemList::setBrailleStr(QString str)
466 : {
467 0 : m_braille_str = str;
468 0 : m_items.clear();
469 0 : }
470 :
471 0 : void BrailleEngravingItemList::insert(int pos, BrailleEngravingItem bei)
472 : {
473 0 : if (bei.braille().isEmpty()) {
474 0 : return;
475 : }
476 :
477 0 : if (pos == 0) { // insert front
478 0 : QString buff = bei.braille();
479 0 : int len = bei.braille().length();
480 :
481 0 : for (size_t i=0; i < m_items.size(); i++) {
482 0 : int start = m_items[i].start() + len;
483 0 : int end = m_items[i].end() + len;
484 0 : m_items[i].setPos(start, end);
485 : }
486 :
487 0 : bei.setPos(0, len);
488 0 : m_items.insert(m_items.begin(), bei);
489 0 : m_braille_str = buff.append(m_braille_str);
490 0 : } else if (pos >= m_braille_str.length()) { // insert back
491 0 : int len = bei.braille().length();
492 :
493 0 : int start = m_braille_str.length();
494 0 : int end = start + len - 1;
495 0 : bei.setPos(start, end);
496 0 : m_items.push_back(bei);
497 :
498 0 : m_braille_str.append(bei.braille());
499 : } else { // insert middle
500 0 : std::vector<BrailleEngravingItem> lst;
501 0 : QString buff = "";
502 :
503 0 : std::vector<BrailleEngravingItem>::iterator ptr;
504 0 : int inc = 0;
505 0 : for (ptr = m_items.begin(); ptr < m_items.end(); ptr++) {
506 0 : if (ptr->start() >= pos) {
507 0 : if (inc == 0) {
508 0 : if (bei.type() != BEIType::EndOfLine) {
509 0 : inc = bei.braille().length();
510 0 : int start = buff.length();
511 0 : int end = start + inc - 1;
512 0 : bei.setPos(start, end);
513 : }
514 0 : lst.push_back(bei);
515 : }
516 0 : if (ptr->type() != BEIType::EndOfLine) {
517 0 : int start = ptr->start() + inc;
518 0 : int end = ptr->end() + inc;
519 0 : ptr->setPos(start, end);
520 : }
521 0 : lst.push_back(*ptr);
522 : } else {
523 0 : lst.push_back(*ptr);
524 : }
525 0 : buff.append(bei.braille());
526 : }
527 :
528 0 : m_braille_str = buff;
529 0 : m_items = lst;
530 0 : }
531 : }
532 :
533 0 : bool BrailleEngravingItemList::isEmpty()
534 : {
535 0 : return m_braille_str.isEmpty();
536 : }
537 :
538 0 : void BrailleEngravingItemList::addEngravingItem(EngravingItem* el, const QString& braille)
539 : {
540 : //braille = braille.replace(QRegularExpression ("/\\/"), "\\\\");
541 : //Manual doubling slashes '\' because Regex doesn't work. Don't know why.
542 0 : QString txt = QString();
543 0 : for (int i=0; i < braille.length(); i++) {
544 0 : if (braille.at(i) == '\\') {
545 0 : txt.append(braille.at(i));
546 : }
547 0 : txt.append(braille.at(i));
548 : }
549 0 : QString unitxt = QString::fromStdString(braille_long_translate(table_ascii_to_unicode.c_str(), txt.toStdString()));
550 :
551 0 : BrailleEngravingItem bei = BrailleEngravingItem(BEIType::EngravingItem, el, unitxt);
552 0 : bei.setExtra(el->typeName(), -1);
553 0 : insert(MAX_LIVE_BRAILLE_LENGTH, bei);
554 0 : }
555 :
556 0 : void BrailleEngravingItemList::addLyricsItem(Lyrics* l)
557 : {
558 0 : std::string txt = l->plainText().toStdString();
559 0 : QString unitxt = QString::fromStdString(braille_long_translate(table_for_literature.c_str(), txt));
560 :
561 0 : switch (l->syllabic()) {
562 0 : case LyricsSyllabic::SINGLE:
563 : case LyricsSyllabic::BEGIN:
564 : {
565 0 : if (!m_braille_str.isEmpty()) {
566 0 : m_braille_str.append(" ");
567 : }
568 : }
569 : // fallthrough
570 : case LyricsSyllabic::END:
571 : case LyricsSyllabic::MIDDLE:
572 : {
573 0 : BrailleEngravingItem bei = BrailleEngravingItem(BEIType::LyricItem, l, unitxt, QString::fromStdString(txt), -1);
574 0 : insert(MAX_LIVE_BRAILLE_LENGTH, bei);
575 0 : break;
576 0 : }
577 : }
578 0 : }
579 :
580 0 : BrailleEngravingItem* BrailleEngravingItemList::getItem(int pos)
581 : {
582 0 : for (size_t i=0; i < m_items.size(); i++) {
583 0 : if (m_items[i].start() <= pos && m_items[i].end() >= pos) {
584 0 : return &m_items[i];
585 : }
586 : }
587 0 : return nullptr;
588 : }
589 :
590 0 : BrailleEngravingItem* BrailleEngravingItemList::getItem(engraving::EngravingItem* e)
591 : {
592 0 : for (size_t i=0; i < m_items.size(); i++) {
593 0 : if (!m_items[i].el()) {
594 0 : continue;
595 : }
596 0 : if (m_items[i].el() == e) {
597 0 : return &m_items[i];
598 : }
599 0 : if (m_items[i].el()->elementBase() == e->elementBase()) {
600 0 : return &m_items[i];
601 : }
602 : }
603 0 : return nullptr;
604 : }
605 :
606 0 : void BrailleEngravingItemList::log()
607 : {
608 0 : LOGD() << brailleStr();
609 0 : for (size_t i=0; i < m_items.size(); i++) {
610 0 : if (!m_items[i].el()) {
611 0 : LOGD() << " - null {" << m_items[i].start() << "," << m_items[i].end() << "}";
612 : } else {
613 0 : LOGD() << " -" << m_items[i].el()->accessibleInfo() << " {" << m_items[i].start() << "," << m_items[i].end() << "}";
614 : }
615 : }
616 0 : }
617 :
618 320 : TextToUEBBraille::TextToUEBBraille()
619 : {
620 320 : textToBrailleASCII["a"] = 'a';
621 320 : textToBrailleASCII["b"] = 'b';
622 320 : textToBrailleASCII["c"] = 'c';
623 320 : textToBrailleASCII["d"] = 'd';
624 320 : textToBrailleASCII["e"] = 'e';
625 320 : textToBrailleASCII["f"] = 'f';
626 320 : textToBrailleASCII["g"] = 'g';
627 320 : textToBrailleASCII["h"] = 'h';
628 320 : textToBrailleASCII["i"] = 'i';
629 320 : textToBrailleASCII["j"] = 'j';
630 320 : textToBrailleASCII["k"] = 'k';
631 320 : textToBrailleASCII["l"] = 'l';
632 320 : textToBrailleASCII["m"] = 'm';
633 320 : textToBrailleASCII["n"] = 'n';
634 320 : textToBrailleASCII["o"] = 'o';
635 320 : textToBrailleASCII["p"] = 'p';
636 320 : textToBrailleASCII["q"] = 'q';
637 320 : textToBrailleASCII["r"] = 'r';
638 320 : textToBrailleASCII["s"] = 's';
639 320 : textToBrailleASCII["t"] = 't';
640 320 : textToBrailleASCII["u"] = 'u';
641 320 : textToBrailleASCII["v"] = 'v';
642 320 : textToBrailleASCII["w"] = 'w';
643 320 : textToBrailleASCII["x"] = 'x';
644 320 : textToBrailleASCII["y"] = 'y';
645 320 : textToBrailleASCII["z"] = 'z';
646 :
647 320 : textToBrailleASCII["A"] = 'a';
648 320 : textToBrailleASCII["B"] = 'b';
649 320 : textToBrailleASCII["C"] = 'c';
650 320 : textToBrailleASCII["D"] = 'd';
651 320 : textToBrailleASCII["E"] = 'e';
652 320 : textToBrailleASCII["F"] = 'f';
653 320 : textToBrailleASCII["G"] = 'g';
654 320 : textToBrailleASCII["H"] = 'h';
655 320 : textToBrailleASCII["I"] = 'i';
656 320 : textToBrailleASCII["J"] = 'j';
657 320 : textToBrailleASCII["K"] = 'k';
658 320 : textToBrailleASCII["L"] = 'l';
659 320 : textToBrailleASCII["M"] = 'm';
660 320 : textToBrailleASCII["N"] = 'n';
661 320 : textToBrailleASCII["O"] = 'o';
662 320 : textToBrailleASCII["P"] = 'p';
663 320 : textToBrailleASCII["Q"] = 'q';
664 320 : textToBrailleASCII["R"] = 'r';
665 320 : textToBrailleASCII["S"] = 's';
666 320 : textToBrailleASCII["T"] = 't';
667 320 : textToBrailleASCII["U"] = 'u';
668 320 : textToBrailleASCII["V"] = 'v';
669 320 : textToBrailleASCII["W"] = 'w';
670 320 : textToBrailleASCII["X"] = 'x';
671 320 : textToBrailleASCII["Y"] = 'y';
672 320 : textToBrailleASCII["Z"] = 'z';
673 :
674 320 : textToBrailleASCII["1"] = 'a';
675 320 : textToBrailleASCII["2"] = 'b';
676 320 : textToBrailleASCII["3"] = 'c';
677 320 : textToBrailleASCII["4"] = 'd';
678 320 : textToBrailleASCII["5"] = 'e';
679 320 : textToBrailleASCII["6"] = 'f';
680 320 : textToBrailleASCII["7"] = 'g';
681 320 : textToBrailleASCII["8"] = 'h';
682 320 : textToBrailleASCII["9"] = 'i';
683 320 : textToBrailleASCII["0"] = 'j';
684 :
685 320 : textToBrailleASCII[" "] = ' ';
686 320 : textToBrailleASCII[","] = '1';
687 320 : textToBrailleASCII[";"] = '2';
688 320 : textToBrailleASCII[":"] = '3';
689 320 : textToBrailleASCII["."] = '4';
690 320 : textToBrailleASCII["!"] = '6';
691 320 : textToBrailleASCII["("] = '7';
692 320 : textToBrailleASCII[")"] = '7';
693 320 : textToBrailleASCII["?"] = '8';
694 320 : textToBrailleASCII["="] = "\"7";
695 320 : textToBrailleASCII["\n"] = '\n';
696 320 : textToBrailleASCII["©"] = "~c";
697 320 : textToBrailleASCII["-"] = "-";
698 320 : textToBrailleASCII["*"] = "99";
699 :
700 : // Appendix B: Foreign language signs. Page 31.
701 : // https://www.ukaaf.org/wp-content/uploads/B017-Braille-Music-and-Unified-English-Braille.pdf
702 320 : textToBrailleASCII["ç"] = "&";
703 320 : textToBrailleASCII["é"] = "=";
704 320 : textToBrailleASCII["à"] = "(";
705 320 : textToBrailleASCII["è"] = "!";
706 320 : textToBrailleASCII["ù"] = ")";
707 320 : textToBrailleASCII["â"] = "*";
708 320 : textToBrailleASCII["ê"] = "<";
709 320 : textToBrailleASCII["î"] = "%";
710 320 : textToBrailleASCII["ô"] = "?";
711 320 : textToBrailleASCII["û"] = ":";
712 320 : textToBrailleASCII["ë"] = "$";
713 320 : textToBrailleASCII["ï"] = "]";
714 320 : textToBrailleASCII["ü"] = "\\";
715 320 : textToBrailleASCII["œ"] = "[";
716 320 : textToBrailleASCII["ß"] = "!";
717 320 : textToBrailleASCII["ö"] = "[";
718 320 : textToBrailleASCII["ä"] = ">";
719 320 : textToBrailleASCII["ì"] = "/";
720 320 : textToBrailleASCII["ò"] = "+";
721 320 : textToBrailleASCII["á"] = "(";
722 320 : textToBrailleASCII["ú"] = ")";
723 320 : textToBrailleASCII["ñ"] = "]";
724 320 : textToBrailleASCII["í"] = "/";
725 320 : textToBrailleASCII["ó"] = "+";
726 :
727 : // dynamics symbols
728 320 : textToBrailleASCII[QChar(0xE520)] = "p";
729 320 : textToBrailleASCII[QChar(0xE521)] = "m";
730 320 : textToBrailleASCII[QChar(0xE522)] = "f";
731 320 : textToBrailleASCII[QChar(0xE523)] = "r";
732 320 : textToBrailleASCII[QChar(0xE524)] = "s";
733 320 : textToBrailleASCII[QChar(0xE525)] = "z";
734 320 : textToBrailleASCII[QChar(0xE526)] = "n";
735 320 : }
736 :
737 3688 : QString TextToUEBBraille::braille(QChar c)
738 : {
739 3688 : if (textToBrailleASCII[c] != nullptr) {
740 3686 : return QString(textToBrailleASCII[c]);
741 : }
742 2 : return QString(c);
743 : }
744 :
745 320 : QString TextToUEBBraille::braille(const QString& text)
746 : {
747 320 : QString buffer, t, p;
748 320 : QTextStream rez(&buffer), tmp(&t);
749 320 : QChar prev;
750 :
751 4008 : for (QChar c : text) {
752 3688 : if (prev.isNumber() && c.isLetter()) {
753 0 : rez << ASCII_END_OF_NUMBER;
754 : }
755 :
756 3688 : if (prev.isLetter() && prev.isUpper() && (!c.isLetter() || (c.isLetter() && c.isLower()))) {
757 341 : tmp.flush();
758 341 : rez << p << t;
759 341 : t.clear();
760 341 : p.clear();
761 : }
762 :
763 3688 : if (c.isLetter()) {
764 2651 : if (c.isUpper()) {
765 357 : if (prev.isUpper()) {
766 16 : p = ASCII_PREFIX_CAPITAL_WORD;
767 : } else {
768 341 : p = ASCII_PREFIX_CAPITAL_LETTER;
769 : }
770 357 : tmp << braille(c);
771 : } else {
772 2294 : rez << braille(c);
773 : }
774 1037 : } else if (c.isNumber()) {
775 542 : if (!prev.isNumber()) {
776 356 : rez << ASCII_PREFIX_NUMBER;
777 : }
778 542 : rez << braille(c);
779 : } else {
780 495 : rez << braille(c);
781 : }
782 3688 : prev = c;
783 : }
784 :
785 320 : tmp.flush();
786 320 : rez << p << t;
787 320 : t.clear();
788 320 : p.clear();
789 :
790 640 : return rez.readAll();
791 320 : }
792 :
793 54 : Braille::Braille(Score* s)
794 : {
795 54 : m_score = s;
796 112 : for (size_t i = 0; i < m_score->staves().size(); ++i) {
797 58 : m_context.previousNote.push_back(nullptr);
798 58 : m_context.currentClefType.push_back(ClefType::INVALID);
799 58 : m_context.currentKey.push_back(Key::INVALID);
800 : }
801 54 : }
802 :
803 54 : bool Braille::write(QIODevice& device)
804 : {
805 54 : credits(device);
806 54 : instruments(device);
807 54 : size_t nrStaves = m_score->staves().size();
808 108 : std::vector<QString> measureBraille(nrStaves);
809 108 : std::vector<QString> line(nrStaves + 1);
810 54 : std::vector<QString> lyrics(nrStaves + 1);
811 54 : int currentLineLength = 0;
812 54 : int currentMeasureMaxLength = 0;
813 54 : bool measureAboveMax = false;
814 :
815 354 : for (MeasureBase* mb = m_score->measures()->first(); mb != nullptr; mb = mb->next()) {
816 300 : if (!mb->isMeasure()) {
817 54 : continue;
818 : }
819 246 : currentMeasureMaxLength = 0;
820 246 : Measure* m = toMeasure(mb);
821 : // if we are at the beginning of the line
822 : // we write the measure number
823 246 : if (currentLineLength == 0) {
824 92 : TextToUEBBraille textToBraille;
825 92 : QString measureNumber = textToBraille.braille(QString::number(m->measureNumber() + 1)).remove(0, 1) + " ";
826 92 : int measureNumberLen = measureNumber.size();
827 92 : line[0] += measureNumber;
828 96 : for (size_t i = 1; i < nrStaves; i++) {
829 8 : line[i] += QString("").leftJustified(measureNumberLen);
830 : }
831 92 : currentLineLength += measureNumberLen;
832 92 : }
833 :
834 246 : if (m->hasMMRest() && m_score->style().styleB(Sid::createMultiMeasureRests)) {
835 2 : mb = m = m->mmRest();
836 : }
837 :
838 500 : for (size_t i = 0; i < nrStaves; ++i) {
839 : BRAILLE_TRACE() << "Measure " << m->measureNumber() + 1 << " Staff " << i;
840 :
841 254 : measureBraille[i] = brailleMeasure(m, static_cast<int>(i)).toUtf8();
842 :
843 254 : if (measureBraille[i].size() > currentMeasureMaxLength) {
844 250 : currentMeasureMaxLength = measureBraille[i].size();
845 : }
846 : }
847 :
848 : BRAILLE_TRACE() << "Current measure max len: " << currentMeasureMaxLength;
849 : // TODO handle better the case when the size of the current measure
850 : // by itself is larger than the MAX_CHARS_PER_LINE. The measure will
851 : // have to be split on multiple lines based on specific rules
852 246 : if ((currentMeasureMaxLength + currentLineLength > MAX_CHARS_PER_LINE) && !measureAboveMax) {
853 36 : QTextStream out(&device);
854 72 : for (size_t i = 0; i < nrStaves; ++i) {
855 36 : out << line[i].toUtf8() << Qt::endl;
856 36 : line[i] = QString();
857 : }
858 36 : out.flush();
859 36 : currentLineLength = 0;
860 : // We need to re-render the current measure
861 : // as it will be on a new line.
862 36 : mb = mb->prev();
863 : // 3.2.1. Page 53. Music Braille Code 2015.
864 : // The octave is always marked for the first note of a braille line
865 36 : resetOctaves();
866 36 : if (currentMeasureMaxLength >= (MAX_CHARS_PER_LINE - 4)) {
867 1 : measureAboveMax = true;
868 : }
869 36 : continue;
870 36 : }
871 :
872 210 : currentLineLength += currentMeasureMaxLength;
873 428 : for (size_t i = 0; i < nrStaves; ++i) {
874 436 : line[i] += measureBraille[i].leftJustified(currentMeasureMaxLength);
875 218 : measureBraille[i] = QString();
876 : }
877 :
878 210 : if (measureAboveMax || m->sectionBreak()) {
879 2 : QTextStream out(&device);
880 4 : for (size_t i = 0; i < nrStaves; ++i) {
881 2 : out << line[i].toUtf8() << Qt::endl;
882 2 : if (!lyrics[i].isEmpty()) {
883 0 : out << lyrics[i].toUtf8() << Qt::endl;
884 : }
885 2 : line[i] = lyrics[i] = QString();
886 : }
887 2 : currentLineLength = 0;
888 : // 3.2.1. Page 53. Music Braille Code 2015.
889 : // The octave is always marked for the first note of a braille line
890 2 : resetOctaves();
891 2 : measureAboveMax = false;
892 2 : if (m->sectionBreak()) {
893 1 : out << Qt::endl;
894 : }
895 2 : out.flush();
896 2 : }
897 : }
898 :
899 : // Write the last measures
900 54 : QTextStream out(&device);
901 112 : for (size_t i = 0; i < nrStaves; ++i) {
902 58 : out << line[i].toUtf8() << Qt::endl;
903 58 : line[i] = QString();
904 : }
905 54 : out.flush();
906 :
907 54 : return true;
908 54 : }
909 :
910 0 : bool Braille::convertMeasure(Measure* measure, BrailleEngravingItemList* beis)
911 : {
912 0 : int nrStaves = static_cast<int>(m_score->staves().size());
913 :
914 0 : if (measure->hasMMRest() && m_score->style().styleB(Sid::createMultiMeasureRests)) {
915 0 : measure = measure->mmRest();
916 : }
917 :
918 0 : for (int i = 0; i < nrStaves; ++i) {
919 0 : BrailleEngravingItemList measureBraille;
920 0 : BrailleEngravingItemList measureLyrics;
921 :
922 0 : brailleMeasureItems(&measureBraille, measure, i);
923 : //measureBraille.log();
924 0 : beis->join(&measureBraille, true, false);
925 :
926 0 : brailleMeasureLyrics(&measureLyrics, measure, i);
927 0 : if (!measureLyrics.isEmpty()) {
928 0 : beis->join(&measureLyrics, true, false);
929 : }
930 0 : }
931 :
932 0 : return true;
933 : }
934 :
935 0 : bool Braille::convertItem(EngravingItem* el, BrailleEngravingItemList* beis)
936 : {
937 0 : return brailleSingleItem(beis, el);
938 : }
939 :
940 361 : void Braille::resetOctave(size_t stave)
941 : {
942 361 : m_context.previousNote[stave] = nullptr;
943 361 : }
944 :
945 38 : void Braille::resetOctaves()
946 : {
947 76 : for (size_t i = 0; i < m_score->staves().size(); ++i) {
948 38 : resetOctave(i);
949 : }
950 38 : }
951 :
952 54 : void Braille::credits(QIODevice& device)
953 : {
954 54 : QTextStream out(&device);
955 : // find the vboxes in every page and write their elements as credit-words
956 108 : for (const auto page : m_score->pages()) {
957 168 : for (const auto system : page->systems()) {
958 378 : for (const auto mb : system->measures()) {
959 264 : if (mb->isVBox()) {
960 163 : for (const EngravingItem* element : mb->el()) {
961 109 : if (element->isText()) {
962 109 : const Text* text = toText(element);
963 109 : out << TextToUEBBraille().braille(text->plainText()).toUtf8() << Qt::endl;
964 : }
965 : }
966 : }
967 : }
968 : }
969 : }
970 :
971 54 : QStringList creators;
972 : // the creator types commonly found in MusicXML
973 54 : creators << "arranger" << "composer" << "lyricist" << "poet" << "translator";
974 324 : for (const QString& type : creators) {
975 270 : QString creator = m_score->metaTag(type);
976 270 : if (!creator.isEmpty()) {
977 156 : out << TextToUEBBraille().braille(QString("%1 %2").arg(type).arg(creator)).toUtf8() << Qt::endl;
978 : }
979 270 : }
980 54 : if (!m_score->metaTag(u"copyright").isEmpty()) {
981 0 : out << TextToUEBBraille().braille(QString("© %2").arg(m_score->metaTag(u"copyright"))).toUtf8() << Qt::endl;
982 : }
983 54 : out << Qt::endl;
984 54 : out.flush();
985 54 : }
986 :
987 54 : void Braille::instruments(QIODevice& device)
988 : {
989 : //Print staff number to instrument mapping.
990 54 : QTextStream out(&device);
991 112 : for (size_t i = 0; i < m_score->staves().size(); ++i) {
992 174 : out << TextToUEBBraille().braille(QString("%1 %2").arg(i + 1).arg(m_score->staves()[i]->part()->instrumentName())) << Qt::endl;
993 : }
994 54 : out << Qt::endl;
995 54 : out.flush();
996 54 : }
997 :
998 1247 : int Braille::computeInterval(Note* note1, Note* note2, bool ignoreOctave)
999 : {
1000 : // TODO is it possible to not have pitch?
1001 : // if yes, then this algorithm will fail in that case
1002 :
1003 1247 : QList<QString> initNotes;
1004 1247 : if (note1->epitch() < note2->epitch()) {
1005 584 : initNotes << "A" << "B" << "C" << "D" << "E" << "F" << "G";
1006 : } else {
1007 663 : initNotes << "G" << "F" << "E" << "D" << "C" << "B" << "A";
1008 : }
1009 :
1010 1247 : String note1PitchName;
1011 1247 : String note2PitchName;
1012 1247 : String accidental; //We don't need this, but tpc2name requires it
1013 1247 : tpc2name(note1->tpc(), NoteSpellingType::STANDARD, NoteCaseType::UPPER, note1PitchName, accidental);
1014 1247 : tpc2name(note2->tpc(), NoteSpellingType::STANDARD, NoteCaseType::UPPER, note2PitchName, accidental);
1015 :
1016 1247 : QList<QString> notes;
1017 1247 : int rootNodeIdx = initNotes.indexOf(note1PitchName);
1018 6080 : for (int i = rootNodeIdx; i < initNotes.size(); i++) {
1019 4833 : notes << initNotes.at(i);
1020 : }
1021 5143 : for (int i = 0; i < rootNodeIdx; i++) {
1022 3896 : notes << initNotes.at(i);
1023 : }
1024 :
1025 1247 : int interval = notes.indexOf(note2PitchName) + 1;
1026 1247 : if (!ignoreOctave && std::abs(note1->epitch() - note2->epitch()) >= 12) {
1027 33 : interval += (std::abs(note1->epitch() - note2->epitch()) / 12) * 8 - 1;
1028 : }
1029 :
1030 1247 : return interval;
1031 1247 : }
1032 :
1033 1173 : std::vector<Slur*> Braille::slurs(ChordRest* chordRest)
1034 : {
1035 1173 : std::vector<Slur*> result;
1036 1173 : SpannerMap& smap = m_score->spannerMap();
1037 1173 : auto spanners = smap.findOverlapping(chordRest->tick().ticks(), chordRest->tick().ticks());
1038 1525 : for (auto interval : spanners) {
1039 352 : Spanner* spanner = interval.value;
1040 352 : if (spanner && spanner->isSlur()
1041 299 : && spanner->track() == chordRest->track()
1042 704 : && spanner->effectiveTrack2() == chordRest->track()) {
1043 299 : result.push_back(toSlur(spanner));
1044 : }
1045 : }
1046 :
1047 1173 : return result;
1048 1173 : }
1049 :
1050 1111 : std::vector<Hairpin*> Braille::hairpins(ChordRest* chordRest)
1051 : {
1052 1111 : std::vector<Hairpin*> result;
1053 1111 : SpannerMap& smap = m_score->spannerMap();
1054 1111 : auto spanners = smap.findOverlapping(chordRest->tick().ticks(), chordRest->tick().ticks());
1055 1382 : for (auto interval : spanners) {
1056 271 : Spanner* spanner = interval.value;
1057 271 : if (spanner && spanner->isHairpin()
1058 26 : && spanner->track() == chordRest->track()
1059 542 : && spanner->effectiveTrack2() == chordRest->track()) {
1060 26 : result.push_back(toHairpin(spanner));
1061 : }
1062 : }
1063 :
1064 1111 : return result;
1065 1111 : }
1066 :
1067 868 : int Braille::notesInSlur(Slur* slur)
1068 : {
1069 868 : int result = 0;
1070 5409 : for (Segment* segment = slur->startSegment(); segment; segment = segment->next1()) {
1071 5409 : if (!segment->isChordRestType()) {
1072 439 : continue;
1073 : }
1074 :
1075 4970 : ChordRest* cr = toChordRest(segment->element(slur->track()));
1076 4970 : if (!cr) {
1077 0 : continue;
1078 : }
1079 :
1080 : // Notes in tie do not count in slur.
1081 : // See Bar 5, Example 13.5.1.b, page 98. Music Braille Code 2015
1082 4970 : if (cr->isChord() && cr != slur->endCR() && segment->next1()) {
1083 3973 : Chord* chord = toChord(cr);
1084 3973 : bool skip = false;
1085 7892 : for (Note* note : chord->notes()) {
1086 4051 : if (note->tieFor() && note->tieFor()->endNote()->chord() == segment->next1()->nextChordRest(chord->track())) {
1087 132 : skip = true;
1088 132 : break;
1089 : }
1090 : }
1091 3973 : if (skip) {
1092 132 : continue;
1093 : }
1094 : }
1095 :
1096 4838 : result++;
1097 4838 : if (segment == slur->endSegment()) {
1098 868 : break;
1099 : }
1100 : }
1101 868 : return result;
1102 : }
1103 :
1104 868 : bool Braille::isShortSlur(Slur* slur)
1105 : {
1106 868 : int notesNr = notesInSlur(slur);
1107 :
1108 : //13.2. Page 94. Braille Music Code 2015.
1109 868 : if (notesNr <= 4) {
1110 403 : return true;
1111 : }
1112 465 : return false;
1113 : }
1114 :
1115 610 : bool Braille::isLongSlur(Slur* slur)
1116 : {
1117 : //13.3. Page 94. Braille Music Code 2015.
1118 610 : return !isShortSlur(slur);
1119 : }
1120 :
1121 62 : bool Braille::isShortShortSlurConvergence(const std::vector<Slur*>& slurs)
1122 : {
1123 131 : for (Slur* slur1 : slurs) {
1124 164 : for (Slur* slur2 : slurs) {
1125 95 : if (slur1 != slur2
1126 23 : && isShortSlur(slur1)
1127 13 : && isShortSlur(slur2)
1128 118 : && (slur1->startCR() == slur2->endCR() || slur2->startCR() == slur1->endCR())) {
1129 3 : return true;
1130 : }
1131 : }
1132 : }
1133 59 : return false;
1134 : }
1135 :
1136 409 : bool Braille::isLongLongSlurConvergence(const std::vector<Slur*>& slurs)
1137 : {
1138 869 : for (Slur* slur1 : slurs) {
1139 1030 : for (Slur* slur2 : slurs) {
1140 570 : if (slur1 != slur2
1141 108 : && isLongSlur(slur1)
1142 58 : && isLongSlur(slur2)
1143 678 : && (slur1->startCR() == slur2->endCR() || slur2->startCR() == slur1->endCR())) {
1144 2 : return true;
1145 : }
1146 : }
1147 : }
1148 407 : return false;
1149 : }
1150 :
1151 65 : bool Braille::hasTies(ChordRest* chordRest)
1152 : {
1153 65 : if (chordRest->isRest()) {
1154 1 : return false;
1155 : }
1156 :
1157 64 : Chord* chord = toChord(chordRest);
1158 134 : for (Note* note : chord->notes()) {
1159 73 : if (note->tieFor()) {
1160 3 : return true;
1161 : }
1162 : }
1163 :
1164 61 : return false;
1165 : }
1166 :
1167 1057 : bool Braille::ascendingChords(ClefType clefType)
1168 : {
1169 : // 9.2. Direction of Intervals (in Chords). Page 75. Music Braille Code 2015
1170 : // In Treble, Soprano, Alto clefs: Write the highest note, then give remaining notes as intervals downward.
1171 : // In Tenor, Baritone, Bass clefs: Write the lowest note, then give remaining notes as intervals upward.
1172 : // All intervals are relative to the original (highest or lowest) note.
1173 1057 : switch (clefType) {
1174 674 : case ClefType::G: //Treble clef
1175 : case ClefType::G15_MB: //Treble clef 15ma bassa
1176 : case ClefType::G8_VB: //Treble clef 8va bassa
1177 : case ClefType::G8_VA: //Treble clef 8va alta
1178 : case ClefType::G15_MA: //Treble clef 15ma alta
1179 : case ClefType::G8_VB_O: //Double treble clef 8va bassa on 2nd line
1180 : case ClefType::G8_VB_P: //Treble clef optional 8va bassa
1181 : case ClefType::G_1: //French violin clef
1182 : case ClefType::C1: //Soprano clef
1183 : case ClefType::C1_F18C: //Soprano clef (French, 18th century)
1184 : case ClefType::C1_F20C: //Soprano clef (French, 20th century)
1185 : case ClefType::C2: //Mezzo-soprano clef
1186 : case ClefType::C3: //Alto clef
1187 : case ClefType::C3_F18C: //Alto clef (French, 18th century)
1188 : case ClefType::C3_F20C: //Alto clef (French, 20th century)
1189 : case ClefType::C_19C: //C clef, H shape (19th century)
1190 : case ClefType::TAB: //TAB
1191 : case ClefType::TAB4: //TAB
1192 : case ClefType::TAB_SERIF: //TAB
1193 : case ClefType::TAB4_SERIF: //TAB
1194 674 : return false;
1195 383 : case ClefType::C4: //Tenor clef
1196 : case ClefType::C4_8VB: //Tenor clef ottava bassa
1197 : case ClefType::C4_F18C: //Tenor clef (French, 18th century)
1198 : case ClefType::C4_F20C: //Tenor clef (French, 20th century)
1199 : case ClefType::C5: //Baritone clef (C clef)
1200 : case ClefType::F: //Bass clef
1201 : case ClefType::F_F18C: //F clef (French, 18th century)
1202 : case ClefType::F_19C: //F clef (19th century)
1203 : case ClefType::F15_MB: //Bass clef 15ma bassa
1204 : case ClefType::F8_VB: //Bass clef 8va bassa
1205 : case ClefType::F_8VA: //Bass clef 8va alta
1206 : case ClefType::F_15MA: //Bass clef 15ma alta
1207 : case ClefType::F_B: //Baritone clef (F clef)
1208 : case ClefType::F_C: //Subbass clef
1209 383 : return true;
1210 0 : case ClefType::PERC: //Percussion
1211 : case ClefType::PERC2: //Percussion
1212 0 : return false;
1213 0 : default:
1214 0 : break;
1215 : }
1216 0 : return false;
1217 : }
1218 :
1219 3 : BarLine* Braille::firstBarline(Measure* measure, track_idx_t track)
1220 : {
1221 3 : for (Segment* seg = measure->first(); seg; seg = seg->next()) {
1222 3 : EngravingItem* el = seg->element(track);
1223 3 : if (el && el->isChordRest()) {
1224 2 : return nullptr;
1225 : }
1226 1 : if (el && el->isBarLine()) {
1227 1 : return toBarLine(el);
1228 : }
1229 : }
1230 0 : return nullptr;
1231 : }
1232 :
1233 529 : BarLine* Braille::lastBarline(Measure* measure, track_idx_t track)
1234 : {
1235 547 : for (Segment* seg = measure->last(); seg; seg = seg->prev()) {
1236 547 : EngravingItem* el = seg->element(track);
1237 547 : if (el && el->isBarLine()) {
1238 529 : return toBarLine(el);
1239 : }
1240 : }
1241 0 : return nullptr;
1242 : }
1243 :
1244 0 : bool Braille::brailleSingleItem(BrailleEngravingItemList* beiz, EngravingItem* el)
1245 : {
1246 0 : resetOctaves();
1247 :
1248 0 : if (el->isMarker()) {
1249 0 : beiz->addEngravingItem(el, brailleMarker(toMarker(el)));
1250 0 : return true;
1251 0 : } else if (el->isJump()) {
1252 0 : beiz->addEngravingItem(el, brailleJump(toJump(el)));
1253 0 : return true;
1254 0 : } else if (el->isDynamic()) {
1255 0 : beiz->addEngravingItem(el, brailleDynamic(toDynamic(el)));
1256 0 : return true;
1257 0 : } else if (el->isClef()) {
1258 0 : beiz->addEngravingItem(el, brailleClef(toClef(el)));
1259 0 : return true;
1260 0 : } else if (el->isKeySig()) {
1261 0 : beiz->addEngravingItem(el, brailleKeySig(toKeySig(el)));
1262 0 : return true;
1263 0 : } else if (el->isTimeSig()) {
1264 0 : beiz->addEngravingItem(el, brailleTimeSig(toTimeSig(el)));
1265 0 : return true;
1266 0 : } else if (el->isMMRest()) {
1267 0 : beiz->addEngravingItem(el, brailleMMRest(toMMRest(el)));
1268 0 : return true;
1269 0 : } else if (el->isRest()) {
1270 0 : beiz->addEngravingItem(el, brailleRest(toRest(el)));
1271 0 : return true;
1272 0 : } else if (el->isChord()) {
1273 0 : beiz->addEngravingItem(el, brailleChord(toChord(el)));
1274 0 : return true;
1275 0 : } else if (el->isBreath()) {
1276 0 : beiz->addEngravingItem(el, brailleBreath(toBreath(el)));
1277 0 : return true;
1278 0 : } else if (el->isBarLine()) {
1279 0 : beiz->addEngravingItem(el, brailleBarline(toBarLine(el)));
1280 0 : return true;
1281 0 : } else if (el->isMeasureRepeat()) {
1282 0 : beiz->addEngravingItem(el, brailleMeasureRepeat(toMeasureRepeat(el)));
1283 0 : return true;
1284 0 : } else if (el->isBreath()) {
1285 0 : beiz->addEngravingItem(el, brailleBreath(toBreath(el)));
1286 0 : return true;
1287 0 : } else if (el->isLyrics()) {
1288 0 : beiz->addEngravingItem(el, brailleLyrics(toLyrics(el)));
1289 0 : return true;
1290 0 : } else if (el->isNote()) {
1291 0 : Note* note = toNote(el);
1292 0 : beiz->addEngravingItem(el, brailleChordRootNote(note->chord(), note));
1293 0 : return true;
1294 : }
1295 0 : return false;
1296 : }
1297 :
1298 0 : void Braille::brailleMeasureItems(BrailleEngravingItemList* beiz, Measure* measure, int staffCount)
1299 : {
1300 : //QTextStream out(&rez);
1301 : //LOGD("Braille::brailleMeasure %d", staffCount);
1302 : //Render all repeats and jumps that are on the left
1303 0 : for (EngravingItem* el : measure->el()) {
1304 0 : if (el->isMarker()) {
1305 0 : Marker* marker = toMarker(el);
1306 0 : if (marker->textStyleType() == TextStyleType::REPEAT_LEFT) {
1307 0 : beiz->addEngravingItem(el, brailleMarker(toMarker(el)));
1308 : }
1309 : }
1310 0 : if (el->isJump()) {
1311 0 : Jump* jump = toJump(el);
1312 0 : if (jump->textStyleType() == TextStyleType::REPEAT_LEFT) {
1313 0 : beiz->addEngravingItem(el, brailleJump(toJump(el)));
1314 : }
1315 : }
1316 : }
1317 :
1318 0 : auto spanners = m_score->spannerMap().findOverlapping(measure->tick().ticks(), measure->endTick().ticks());
1319 0 : for (auto interval : spanners) {
1320 0 : Spanner* s = interval.value;
1321 0 : if (s && s->isVolta()) {
1322 0 : beiz->addEngravingItem(s, brailleVolta(measure, toVolta(s), staffCount));
1323 : }
1324 : }
1325 :
1326 : //Render everything that is in Voice 1
1327 0 : for (auto seg = measure->first(); seg; seg = seg->next()) {
1328 0 : for (EngravingItem* annotation : seg->annotations()) {
1329 0 : if (annotation->isTempoText()) {
1330 0 : beiz->addEngravingItem(annotation, brailleTempoText(toTempoText(annotation), staffCount));
1331 : }
1332 0 : if (annotation->track() == staffCount * VOICES) {
1333 0 : if (annotation->isDynamic()) {
1334 0 : beiz->addEngravingItem(annotation, brailleDynamic(toDynamic(annotation)));
1335 : }
1336 : }
1337 : }
1338 :
1339 0 : EngravingItem* el = seg->element(staffCount * VOICES);
1340 0 : if (!el) {
1341 0 : continue;
1342 : }
1343 :
1344 0 : if (el->isClef()) {
1345 0 : beiz->addEngravingItem(el, brailleClef(toClef(el)));
1346 0 : } else if (el->isKeySig()) {
1347 0 : beiz->addEngravingItem(el, brailleKeySig(toKeySig(el)));
1348 0 : } else if (el->isTimeSig()) {
1349 0 : beiz->addEngravingItem(el, brailleTimeSig(toTimeSig(el)));
1350 0 : } else if (el->isMMRest()) {
1351 0 : beiz->addEngravingItem(el, brailleMMRest(toMMRest(el)));
1352 0 : } else if (el->isRest()) {
1353 0 : beiz->addEngravingItem(el, brailleRest(toRest(el)));
1354 0 : } else if (el->isChord()) {
1355 0 : beiz->addEngravingItem(el, brailleChord(toChord(el)));
1356 0 : } else if (el->isBreath()) {
1357 0 : beiz->addEngravingItem(el, brailleBreath(toBreath(el)));
1358 0 : } else if (el->isBarLine() && toBarLine(el) != lastBarline(measure, el->track())) {
1359 0 : beiz->addEngravingItem(el, brailleBarline(toBarLine(el)));
1360 0 : } else if (el->isMeasureRepeat()) {
1361 0 : beiz->addEngravingItem(el, brailleMeasureRepeat(toMeasureRepeat(el)));
1362 : }
1363 : }
1364 :
1365 : // Render the rest of the voices
1366 0 : for (size_t i = 1; i < VOICES; ++i) {
1367 0 : if (measure->hasVoice(staffCount * VOICES + i)) {
1368 : // 11.1.1. Page 87. Music Braille Code 2015.
1369 : // All voices must be complete when writing the other voices in Braille.
1370 : // We exchange the voices to voice 0 and back for MuseScore to add the missing beats as rests
1371 : // Then we undo the change, so we don't have an altered score.
1372 : // TODO: Braille dot 5 should be put before the rests that appear in Braille, but are not originally in the score
1373 : /*
1374 : m_score->deselectAll();
1375 : m_score->select(measure, SelectType::RANGE, staffCount);
1376 : m_score->update();
1377 : m_score->startCmd();
1378 : ExchangeVoices::exchangeVoicesInSelection(m_score, 0, static_cast<int>(i));
1379 : m_score->endCmd();
1380 : m_score->startCmd();
1381 : ExchangeVoices::exchangeVoicesInSelection(m_score, 0, static_cast<int>(i));
1382 : m_score->endCmd();
1383 : */
1384 0 : resetOctave(staffCount);
1385 :
1386 0 : QString in_accord = QString::fromStdString(translate2Braille(Braille_FullMeasureAccord.code));
1387 0 : BrailleEngravingItem bei = BrailleEngravingItem(BEIType::VoiceInAccord, NULL, in_accord);
1388 0 : beiz->insert(MAX_LIVE_BRAILLE_LENGTH, bei);
1389 :
1390 0 : for (auto seg = measure->first(); seg; seg = seg->next()) {
1391 0 : EngravingItem* el = seg->element(staffCount * VOICES + i);
1392 0 : if (!el) {
1393 0 : continue;
1394 : }
1395 :
1396 0 : if (el->isRest()) {
1397 0 : beiz->addEngravingItem(el, brailleRest(toRest(el)));
1398 : }
1399 0 : if (el->isChord()) {
1400 0 : beiz->addEngravingItem(el, brailleChord(toChord(el)));
1401 : }
1402 0 : if (el->isBreath()) {
1403 0 : beiz->addEngravingItem(el, brailleBreath(toBreath(el)));
1404 : }
1405 : }
1406 0 : resetOctave(staffCount);
1407 :
1408 : // Undo filling the missing beats with rests, so we don't have an altered score.
1409 : // m_score->undoRedo(true, nullptr);
1410 : // m_score->undoRedo(true, nullptr);
1411 : // m_score->deselectAll();
1412 0 : }
1413 : }
1414 :
1415 : //Render the barline
1416 0 : BarLine* bl = lastBarline(measure, staffCount * VOICES);
1417 0 : if (bl) {
1418 0 : beiz->addEngravingItem(bl, brailleBarline(bl));
1419 : }
1420 :
1421 : //Render repeats and jumps that are on the right
1422 0 : for (EngravingItem* el : measure->el()) {
1423 0 : if (el->isMarker()) {
1424 0 : Marker* marker = toMarker(el);
1425 0 : if (marker->textStyleType() == TextStyleType::REPEAT_RIGHT) {
1426 0 : beiz->addEngravingItem(el, brailleMarker(toMarker(el)));
1427 : }
1428 : }
1429 0 : if (el->isJump()) {
1430 0 : Jump* jump = toJump(el);
1431 0 : if (jump->textStyleType() == TextStyleType::REPEAT_RIGHT) {
1432 0 : beiz->addEngravingItem(el, brailleJump(toJump(el)));
1433 : }
1434 : }
1435 : }
1436 0 : }
1437 :
1438 0 : void Braille::brailleMeasureLyrics(BrailleEngravingItemList* beiz, Measure* measure, int staffCount)
1439 : {
1440 0 : BrailleEngravingItemList lyrics[MAX_LYRICS_NUM];
1441 :
1442 0 : for (auto seg = measure->first(); seg; seg = seg->next()) {
1443 0 : if (!seg->isChordRestType()) {
1444 0 : continue;
1445 : }
1446 0 : for (voice_idx_t voice = 0; voice < VOICES; ++voice) {
1447 0 : if (measure->hasVoice(staffCount * VOICES + voice)) {
1448 0 : ChordRest* cr = seg->cr(staffCount * VOICES + voice);
1449 0 : if (cr && !cr->lyrics().empty()) {
1450 0 : for (Lyrics* l : cr->lyrics()) {
1451 0 : int verse = l->verse();
1452 0 : lyrics[verse].addLyricsItem(l);
1453 : }
1454 : }
1455 : }
1456 : }
1457 : }
1458 :
1459 0 : for (int i=0; i < MAX_LYRICS_NUM; i++) {
1460 0 : if (lyrics[i].isEmpty()) {
1461 0 : lyrics[i].clear();
1462 : } else {
1463 0 : QString braille = QString::fromStdString(translate2Braille(Braille_LyricLineIndicator.code));
1464 0 : BrailleEngravingItem bei = BrailleEngravingItem(BEIType::LineIndicator, NULL, braille);
1465 0 : lyrics[i].insert(0, bei);
1466 0 : beiz->join(&lyrics[i], true, false);
1467 0 : }
1468 : }
1469 0 : }
1470 :
1471 99 : QString Braille::brailleAccidentalType(AccidentalType accidental)
1472 : {
1473 99 : switch (accidental) {
1474 0 : case AccidentalType::NONE: return QString();
1475 39 : case AccidentalType::FLAT: return BRAILLE_ACC_FLAT;
1476 11 : case AccidentalType::NATURAL: return BRAILLE_ACC_NATURAL;
1477 47 : case AccidentalType::SHARP: return BRAILLE_ACC_SHARP;
1478 0 : case AccidentalType::SHARP2: return BRAILLE_ACC_SHARP + BRAILLE_ACC_SHARP;
1479 0 : case AccidentalType::FLAT2: return BRAILLE_ACC_FLAT + BRAILLE_ACC_FLAT;
1480 0 : case AccidentalType::NATURAL_FLAT: return BRAILLE_ACC_NATURAL + BRAILLE_ACC_FLAT; //extrapolated
1481 0 : case AccidentalType::NATURAL_SHARP: return BRAILLE_ACC_NATURAL + BRAILLE_ACC_SHARP; //extrapolated
1482 0 : case AccidentalType::SHARP_SHARP: return BRAILLE_ACC_SHARP + BRAILLE_ACC_SHARP;
1483 0 : case AccidentalType::FLAT_ARROW_UP: return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_FLAT;
1484 0 : case AccidentalType::FLAT_ARROW_DOWN: return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_FLAT;
1485 0 : case AccidentalType::NATURAL_ARROW_UP: return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_SHARP;
1486 0 : case AccidentalType::NATURAL_ARROW_DOWN: return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_FLAT;
1487 0 : case AccidentalType::SHARP_ARROW_UP: return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_SHARP;
1488 0 : case AccidentalType::SHARP_ARROW_DOWN: return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_SHARP;
1489 0 : case AccidentalType::SHARP2_ARROW_UP: return BRAILLE_ACC_5QUARTER_STEP + BRAILLE_ACC_SHARP; //extrapolated. not sure
1490 0 : case AccidentalType::SHARP2_ARROW_DOWN: return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_SHARP;
1491 0 : case AccidentalType::FLAT2_ARROW_UP: return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_FLAT;
1492 0 : case AccidentalType::FLAT2_ARROW_DOWN: return BRAILLE_ACC_5QUARTER_STEP + BRAILLE_ACC_FLAT; //extrapolated. not sure
1493 0 : case AccidentalType::MIRRORED_FLAT: return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_FLAT;
1494 0 : case AccidentalType::MIRRORED_FLAT2: return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_FLAT;
1495 2 : case AccidentalType::SHARP_SLASH: return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_SHARP;
1496 2 : case AccidentalType::SHARP_SLASH4: return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_SHARP;
1497 0 : case AccidentalType::FLAT_SLASH2: return BRAILLE_ACC_FLAT;
1498 0 : case AccidentalType::FLAT_SLASH: return BRAILLE_ACC_FLAT;
1499 0 : case AccidentalType::SHARP_SLASH3: return BRAILLE_ACC_SHARP;
1500 0 : case AccidentalType::SHARP_SLASH2: return BRAILLE_ACC_SHARP;
1501 : //TODO the rest of the accidentals
1502 0 : default:
1503 0 : break;
1504 : }
1505 0 : return QString();
1506 : }
1507 :
1508 1057 : QString Braille::brailleArpeggio(Arpeggio* arpeggio)
1509 : {
1510 1057 : if (!arpeggio) {
1511 1055 : return QString();
1512 : }
1513 :
1514 : // Table 22. Page 17. Music Braille Code 2015.
1515 2 : QString result = QString();
1516 : // fix me - this is a simple heuristic. can we do better?
1517 2 : if (arpeggio->ldata()->arpeggioHeight > 200) {
1518 2 : result += BRAILLE_ARPEGGIO_MULTISTAVES;
1519 : }
1520 :
1521 2 : if (arpeggio->arpeggioType() == ArpeggioType::NORMAL
1522 0 : || arpeggio->arpeggioType() == ArpeggioType::UP
1523 0 : || arpeggio->arpeggioType() == ArpeggioType::UP_STRAIGHT
1524 2 : || arpeggio->arpeggioType() == ArpeggioType::BRACKET) {
1525 2 : result += BRAILLE_ARPEGGIO_UPWARD;
1526 : }
1527 :
1528 2 : if (arpeggio->arpeggioType() == ArpeggioType::DOWN
1529 2 : || arpeggio->arpeggioType() == ArpeggioType::DOWN_STRAIGHT) {
1530 0 : result += BRAILLE_ARPEGGIO_DOWNWARD;
1531 : }
1532 :
1533 2 : return result;
1534 2 : }
1535 :
1536 22 : QString Braille::brailleArticulation(Articulation* artic)
1537 : {
1538 22 : switch (artic->symId()) {
1539 5 : case SymId::articAccentAbove:
1540 : case SymId::articAccentBelow:
1541 5 : return BRAILLE_ARTIC_ACCENT;
1542 1 : case SymId::articStaccatoAbove:
1543 : case SymId::articStaccatoBelow:
1544 1 : return BRAILLE_ARTIC_STACCATO;
1545 2 : case SymId::articStaccatissimoAbove:
1546 : case SymId::articStaccatissimoBelow:
1547 : case SymId::articStaccatissimoStrokeAbove: //extrapolated
1548 : case SymId::articStaccatissimoStrokeBelow: //extrapolated
1549 : case SymId::articStaccatissimoWedgeAbove: //extrapolated
1550 : case SymId::articStaccatissimoWedgeBelow: //extrapolated
1551 2 : return BRAILLE_ARTIC_STACCATISSIMO;
1552 1 : case SymId::articTenutoAbove:
1553 : case SymId::articTenutoBelow:
1554 1 : return BRAILLE_ARTIC_TENUTO;
1555 2 : case SymId::articTenutoStaccatoAbove:
1556 : case SymId::articTenutoStaccatoBelow:
1557 2 : return BRAILLE_ARTIC_TENUTO_STACCATO;
1558 1 : case SymId::articMarcatoAbove:
1559 : case SymId::articMarcatoBelow:
1560 1 : return BRAILLE_ARTIC_MARCATO;
1561 1 : case SymId::articAccentStaccatoAbove:
1562 : case SymId::articAccentStaccatoBelow:
1563 2 : return BRAILLE_ARTIC_STACCATO + BRAILLE_ARTIC_ACCENT; //extrapolated
1564 0 : case SymId::articMarcatoStaccatoAbove:
1565 : case SymId::articMarcatoStaccatoBelow:
1566 0 : return BRAILLE_ARTIC_STACCATO + BRAILLE_ARTIC_MARCATO; //extrapolated
1567 0 : case SymId::articMarcatoTenutoAbove:
1568 : case SymId::articMarcatoTenutoBelow:
1569 0 : return BRAILLE_ARTIC_MARCATO + BRAILLE_ARTIC_TENUTO; //extrapolated
1570 0 : case SymId::articStressAbove:
1571 : case SymId::articStressBelow:
1572 0 : return QString(); //TODO
1573 0 : case SymId::articTenutoAccentAbove:
1574 : case SymId::articTenutoAccentBelow:
1575 0 : return BRAILLE_ARTIC_TENUTO + BRAILLE_ARTIC_ACCENT; //extrapolated
1576 0 : case SymId::articUnstressAbove:
1577 : case SymId::articUnstressBelow:
1578 0 : return QString(); //TODO
1579 0 : case SymId::articSoftAccentAbove:
1580 : case SymId::articSoftAccentBelow:
1581 0 : return QString(); //TODO
1582 0 : case SymId::articSoftAccentStaccatoAbove:
1583 : case SymId::articSoftAccentStaccatoBelow:
1584 0 : return QString(); //TODO
1585 0 : case SymId::articSoftAccentTenutoAbove:
1586 : case SymId::articSoftAccentTenutoBelow:
1587 0 : return QString(); //TODO
1588 0 : case SymId::articSoftAccentTenutoStaccatoAbove:
1589 : case SymId::articSoftAccentTenutoStaccatoBelow:
1590 0 : return QString(); //TODO
1591 0 : case SymId::guitarFadeIn:
1592 0 : return BRAILLE_ARTIC_REVERSED_ACCENT; // not sure
1593 0 : case SymId::guitarFadeOut:
1594 0 : return BRAILLE_ARTIC_EXPRESSIVE_ACCENT; //not sure
1595 0 : case SymId::guitarVolumeSwell:
1596 0 : return BRAILLE_ARTIC_SWELL;
1597 0 : case SymId::stringsDownBow:
1598 0 : return BRAILLE_DOWN_BOW;
1599 0 : case SymId::stringsUpBow:
1600 0 : return BRAILLE_UP_BOW;
1601 0 : case SymId::pluckedLeftHandPizzicato:
1602 : case SymId::pluckedBuzzPizzicato: // extrapolated. not sure
1603 : case SymId::pluckedSnapPizzicatoAbove: // extrapolated. not sure
1604 : case SymId::pluckedSnapPizzicatoBelow: // extrapolated. not sure
1605 0 : return BRAILLE_LEFT_HAND_PIZZICATO;
1606 0 : case SymId::ornamentTurn:
1607 0 : return BRAILLE_TURN_NOTE;
1608 0 : case SymId::ornamentTurnInverted:
1609 0 : return BRAILLE_INVERTED_TURN_NOTE;
1610 0 : case SymId::ornamentTrill:
1611 0 : return BRAILLE_TRILL;
1612 4 : case SymId::ornamentMordent:
1613 4 : return BRAILLE_MORDENT;
1614 3 : case SymId::ornamentShortTrill:
1615 3 : return BRAILLE_SHORT_TRILL;
1616 1 : case SymId::ornamentTremblement:
1617 1 : return BRAILLE_TREBLEMENT;
1618 1 : case SymId::ornamentPrallMordent:
1619 1 : return BRAILLE_PRALL_MORDENT;
1620 0 : case SymId::ornamentUpPrall:
1621 0 : return BRAILLE_UP_PRALL;
1622 0 : case SymId::ornamentPrecompMordentUpperPrefix:
1623 0 : return BRAILLE_MORDENT_WITH_UPPER_FIX;
1624 0 : case SymId::ornamentUpMordent:
1625 0 : return BRAILLE_UP_MORDENT;
1626 0 : case SymId::ornamentDownMordent:
1627 0 : return BRAILLE_DOWN_MORDENT;
1628 0 : case SymId::ornamentPrallDown:
1629 0 : return BRAILLE_PRALL_DOWN;
1630 0 : case SymId::ornamentPrallUp:
1631 0 : return BRAILLE_PRALL_UP;
1632 0 : case SymId::ornamentLinePrall:
1633 0 : return BRAILLE_LINE_PRALL;
1634 : //TODO. there are still more articulations
1635 0 : default:
1636 0 : break;
1637 : }
1638 0 : return QString();
1639 : }
1640 :
1641 267 : QString Braille::brailleBarline(BarLine* barline)
1642 : {
1643 267 : if (!barline) {
1644 0 : return QString();
1645 : }
1646 :
1647 267 : if (barline->measure()->system()
1648 267 : && barline->measure()->system()->firstMeasure()
1649 267 : && barline->measure()->system()->firstMeasure()->segments().first() == barline->segment()
1650 534 : && barline->barLineType() == BarLineType::NORMAL) {
1651 : // This is the barline at the beginning of the system
1652 : // We don't need to render it
1653 8 : return QString();
1654 : }
1655 :
1656 259 : bool spaceAfter = false;
1657 259 : bool spaceBefore = false;
1658 259 : QString barlineBraille = QString();
1659 :
1660 259 : switch (barline->barLineType()) {
1661 : // Table 1. Page 2. Music Braille Code 2015
1662 173 : case BarLineType::NORMAL:
1663 173 : barlineBraille = BRAILLE_BARLINE;
1664 173 : break;
1665 1 : case BarLineType::BROKEN:
1666 1 : barlineBraille = BRAILLE_BARLINE_BROKEN;
1667 1 : spaceBefore = true;
1668 1 : spaceAfter = true;
1669 1 : break;
1670 3 : case BarLineType::DOUBLE:
1671 3 : barlineBraille = BRAILLE_BARLINE_DOUBLE;
1672 3 : resetOctave(barline->staffIdx());
1673 3 : spaceAfter = true;
1674 3 : break;
1675 72 : case BarLineType::END:
1676 72 : resetOctave(barline->staffIdx());
1677 72 : barlineBraille = BRAILLE_BARLINE_END;
1678 72 : spaceAfter = true;
1679 72 : break;
1680 0 : case BarLineType::DOTTED:
1681 0 : barlineBraille = BRAILLE_BARLINE_DOTTED;
1682 0 : spaceBefore = true;
1683 0 : spaceAfter = true;
1684 0 : break;
1685 : // Start/End Repeat Table 17. Page 15. Music Braille Code 2015
1686 3 : case BarLineType::START_REPEAT:
1687 3 : resetOctave(barline->staffIdx());
1688 3 : barlineBraille = BRAILLE_BARLINE_START_REPEAT;
1689 3 : break;
1690 7 : case BarLineType::END_REPEAT:
1691 7 : resetOctave(barline->staffIdx());
1692 7 : barlineBraille = BRAILLE_BARLINE_END_REPEAT;
1693 7 : spaceAfter = true;
1694 7 : break;
1695 : //This sign was not present in the book. Extrapolated from the above two signs
1696 0 : case BarLineType::END_START_REPEAT:
1697 0 : barlineBraille = BRAILLE_BARLINE_START_REPEAT + " " + BRAILLE_BARLINE_END_REPEAT;
1698 0 : break;
1699 0 : case BarLineType::REVERSE_END:
1700 : //case BarLineType::REVERSE_FINALE: // duplicate of the above, alternative name
1701 : case BarLineType::HEAVY:
1702 : case BarLineType::DOUBLE_HEAVY:
1703 0 : break; // ToDo ?!
1704 : }
1705 :
1706 259 : QString fermataBraille = QString();
1707 259 : for (EngravingItem* el : barline->segment()->annotations()) {
1708 0 : if (el->isFermata()) {
1709 0 : fermataBraille = brailleFermata(toFermata(el));
1710 : }
1711 : }
1712 :
1713 : //This is a special case
1714 259 : if (!fermataBraille.isEmpty() && barline->barLineType() == BarLineType::NORMAL) {
1715 0 : barlineBraille = BRAILLE_BARLINE_DOTTED;
1716 0 : spaceBefore = true;
1717 0 : spaceAfter = true;
1718 : }
1719 :
1720 259 : QString musicalHypenBrailleBefore = QString();
1721 0 : QString musicalHypenBrailleAfter = QString();
1722 :
1723 : // 1.10.1. Page 43. Music Braille Code 2015.
1724 517 : if ((barline->barLineType() == BarLineType::BROKEN || barline->barLineType() == BarLineType::DOTTED)
1725 517 : && barline != lastBarline(barline->measure(), barline->track())) {
1726 1 : musicalHypenBrailleBefore = BRAILLE_MUSICAL_HYPEN;
1727 : }
1728 :
1729 : // 17.1. Page 120. Music Braille Code 2015.
1730 515 : if ((barline->barLineType() == BarLineType::START_REPEAT || barline->barLineType() == BarLineType::END_START_REPEAT)
1731 515 : && barline != firstBarline(barline->measure(), barline->track())) {
1732 2 : spaceBefore = true;
1733 2 : musicalHypenBrailleBefore = BRAILLE_MUSICAL_HYPEN;
1734 : }
1735 :
1736 : // 17.1. Page 120. Music Braille Code 2015.
1737 511 : if ((barline->barLineType() == BarLineType::END_REPEAT || barline->barLineType() == BarLineType::END_START_REPEAT)
1738 511 : && barline != lastBarline(barline->measure(), barline->track())) {
1739 1 : musicalHypenBrailleAfter = BRAILLE_MUSICAL_HYPEN;
1740 : }
1741 :
1742 : return
1743 : musicalHypenBrailleBefore
1744 518 : + (spaceBefore ? " " : "")
1745 518 : + barlineBraille
1746 518 : + fermataBraille
1747 1036 : + (spaceAfter ? " " : "")
1748 259 : + musicalHypenBrailleAfter;
1749 259 : }
1750 :
1751 2 : QString Braille::brailleBreath(Breath* breath)
1752 : {
1753 2 : if (!breath) {
1754 0 : return QString();
1755 : }
1756 :
1757 2 : if (breath->isCaesura()) {
1758 1 : return BRAILLE_CAESURA;
1759 : } else {
1760 1 : return BRAILLE_BREATH;
1761 : }
1762 : }
1763 :
1764 1057 : QString Braille::brailleChord(Chord* chord)
1765 : {
1766 : // 9.3 Interval Doubling and 9.5 Moving notes methods are not implemented as they are optional methods
1767 :
1768 1057 : if (!chord || chord->notes().empty()) {
1769 0 : return QString();
1770 : }
1771 :
1772 1057 : QString graceNoteMarking = brailleGraceNoteMarking(chord);
1773 1057 : QString graceNotesBefore = QString();
1774 1066 : for (Chord* graceChord : chord->graceNotesBefore()) {
1775 9 : graceNotesBefore += brailleChord(graceChord);
1776 : }
1777 :
1778 1057 : QString tupletBraille = brailleTuplet(chord->tuplet(), chord);
1779 :
1780 1057 : std::vector<Hairpin*> chordHairpins = hairpins(chord);
1781 1057 : QString hairpinBrailleBefore = brailleHairpinBefore(chord, chordHairpins);
1782 :
1783 : // 9.2. Direction of Intervals (in Chords). Page 75. Music Braille Code 2015
1784 : // In Treble, Soprano, Alto clefs: Write the highest note, then give remaining notes as intervals downward.
1785 : // In Tenor, Baritone, Bass clefs: Write the lowest note, then give remaining notes as intervals upward.
1786 : // All intervals are relative to the original (highest or lowest) note.
1787 1057 : std::vector<Note*> notes;
1788 1057 : if (ascendingChords(m_context.currentClefType[chord->staffIdx()])) {
1789 845 : for (auto it = chord->notes().begin(); it != chord->notes().end(); ++it) {
1790 462 : notes.push_back(*it);
1791 : }
1792 : } else {
1793 1441 : for (auto it = chord->notes().rbegin(); it != chord->notes().rend(); ++it) {
1794 767 : notes.push_back(*it);
1795 : }
1796 : }
1797 :
1798 1057 : Note* rootNote = notes.front();
1799 1057 : QString rootNoteBraille = brailleChordRootNote(chord, rootNote);
1800 :
1801 1057 : QString intervals = QString();
1802 1229 : for (auto it = notes.begin() + 1; it != notes.end(); ++it) {
1803 172 : intervals += brailleChordInterval(rootNote, notes, *it);
1804 : }
1805 :
1806 1057 : QString graceNotesAfter = QString();
1807 1057 : for (Chord* graceChord : chord->graceNotesAfter()) {
1808 0 : graceNotesAfter += brailleChord(graceChord);
1809 : }
1810 :
1811 1057 : QString chordTieBraille = brailleTie(chord);
1812 :
1813 1057 : QString fermata = QString();
1814 1068 : for (EngravingItem* el : chord->segment()->annotations()) {
1815 11 : if (el->isFermata()) {
1816 4 : fermata = brailleFermata(toFermata(el));
1817 : }
1818 : }
1819 :
1820 1057 : QString articulationsBraille = QString();
1821 1079 : for (Articulation* artic : chord->articulations()) {
1822 22 : articulationsBraille += brailleArticulation(artic);
1823 : }
1824 :
1825 1057 : std::vector<Slur*> chordSlurs = slurs(chord);
1826 1057 : QString slurBrailleBefore = brailleSlurBefore(chord, chordSlurs);
1827 1057 : QString slurBrailleAfter = brailleSlurAfter(chord, chordSlurs);
1828 :
1829 1057 : QString hairpinBrailleAfter = brailleHairpinAfter(chord, chordHairpins);
1830 :
1831 1057 : QString arpeggio = brailleArpeggio(chord->arpeggio());
1832 1057 : QString tremoloBraille = brailleTremolo(chord);
1833 1057 : QString glissandoLastNoteBraille = brailleGlissando(notes.back());
1834 :
1835 : // In Braille the order of elements is clearly defined
1836 1057 : QString result = QString();
1837 1057 : result += hairpinBrailleBefore;
1838 1057 : result += graceNotesBefore;
1839 1057 : result += graceNoteMarking;
1840 1057 : result += arpeggio;
1841 1057 : result += articulationsBraille;
1842 1057 : result += slurBrailleBefore;
1843 1057 : result += tupletBraille;
1844 1057 : result += rootNoteBraille;
1845 1057 : result += intervals;
1846 1057 : result += tremoloBraille;
1847 1057 : result += chordTieBraille;
1848 1057 : result += slurBrailleAfter;
1849 1057 : result += glissandoLastNoteBraille;
1850 : /* not really sure where grace notes that follow the chord should be put
1851 : * MBC 2015, doesn't mention them, so tentatively putting them here. */
1852 1057 : result += graceNotesAfter;
1853 1057 : result += hairpinBrailleAfter;
1854 1057 : result += fermata;
1855 :
1856 1057 : return result;
1857 1057 : }
1858 :
1859 : //-----------------------------------------------------------------------------------
1860 : // brailleChordInterval
1861 : // rootNote: The root note of the chord.
1862 : // notes: The notes in the chord in the order that they are brailled
1863 : // note: The note for which we are currently representing the braille interval
1864 : // return the braille interval representation in the chord
1865 : //-----------------------------------------------------------------------------------
1866 172 : QString Braille::brailleChordInterval(Note* rootNote, const std::vector<Note*>& notes, Note* note)
1867 : {
1868 172 : if (!rootNote || !note || notes.size() < 2) {
1869 0 : return QString();
1870 : }
1871 :
1872 172 : int interval = computeInterval(rootNote, note, true);
1873 172 : QString intervalBraille;
1874 : //Table 9. Intervals. Page 7. Music Braille Code 2015
1875 172 : switch (interval) {
1876 20 : case 1: intervalBraille = BRAILLE_OCTAVE;
1877 20 : break;
1878 1 : case 2: intervalBraille = BRAILLE_SECOND;
1879 1 : break;
1880 58 : case 3: intervalBraille = BRAILLE_THIRD;
1881 58 : break;
1882 13 : case 4: intervalBraille = BRAILLE_FOURTH;
1883 13 : break;
1884 35 : case 5: intervalBraille = BRAILLE_FIFTH;
1885 35 : break;
1886 36 : case 6: intervalBraille = BRAILLE_SIXTH;
1887 36 : break;
1888 9 : case 7: intervalBraille = BRAILLE_SEVENTH;
1889 9 : break;
1890 : }
1891 172 : QString noteOctaveBraille = QString();
1892 172 : QString noteAccidentalBraille = QString();
1893 172 : if (note->accidental() != nullptr) {
1894 7 : noteAccidentalBraille = brailleAccidentalType(note->accidental()->accidentalType());
1895 : }
1896 :
1897 : // 9.1.1. Page 74. Music Braille Code 2015.
1898 : // A note represented by an interval sign must be preceded by the appropriate octave mark when:
1899 : // (a) it forms a unison with the written note (the octave-interval sign is used with the appropriate octave mark),
1900 172 : if (interval == 1 && rootNote->octave() == note->octave()) {
1901 1 : noteOctaveBraille = brailleOctave(note->octave());
1902 : }
1903 172 : size_t noteIdx = muse::indexOf(notes, note);
1904 172 : int intervalWithPreviousNoteInChord = computeInterval(notes.at(noteIdx - 1), note, false);
1905 : // (b) it is the first or only interval and is more than an octave from the written note,
1906 172 : if (noteIdx == 1 && intervalWithPreviousNoteInChord > 8) {
1907 1 : noteOctaveBraille = brailleOctave(note->octave());
1908 : }
1909 : // (c) it is the second of two adjacent intervals that are an octave or more apart, or
1910 172 : if (noteIdx != 1 && intervalWithPreviousNoteInChord >= 8) {
1911 2 : noteOctaveBraille = brailleOctave(note->octave());
1912 : }
1913 : // (d) it forms a unison with another interval that has been given previously in the chord.
1914 172 : if (noteIdx != 1 && intervalWithPreviousNoteInChord == 1) {
1915 1 : noteOctaveBraille = brailleOctave(note->octave());
1916 : }
1917 :
1918 344 : QString noteTieBraille = brailleTie(note);
1919 :
1920 0 : QString fingeringAfterBraille = QString();
1921 172 : for (EngravingItem* el : rootNote->el()) {
1922 0 : if (el->isFingering()) {
1923 0 : fingeringAfterBraille += brailleFingeringAfter(toFingering(el));
1924 : }
1925 : }
1926 :
1927 : return
1928 : noteAccidentalBraille
1929 344 : + noteOctaveBraille
1930 344 : + intervalBraille
1931 516 : + fingeringAfterBraille
1932 172 : + noteTieBraille;
1933 172 : }
1934 :
1935 1057 : QString Braille::brailleChordRootNote(Chord* chord, Note* rootNote)
1936 : {
1937 1057 : String pitchName;
1938 1057 : String accidental; //TODO, do we need this for anything?
1939 1057 : String octaveBraille;
1940 1057 : tpc2name(rootNote->tpc(), NoteSpellingType::STANDARD, NoteCaseType::UPPER, pitchName, accidental);
1941 1057 : QString noteBraille = brailleNote(pitchName, chord->durationType().type(), chord->dots());
1942 :
1943 1057 : int octave = rootNote->octave();
1944 : // 3.2.1. Page 53. Music Braille Code 2015.
1945 : // Octave signs at the beginning of the line or when the melodic line is interrupted by specific elements
1946 1057 : if (!this->m_context.previousNote[chord->staffIdx()]) {
1947 154 : octaveBraille = brailleOctave(octave);
1948 : }
1949 : // 3.2.2. Octave signs in a melodic progression. Page 53. Music Braille Code 2015.
1950 : // a. the octave is not marked for the second of two consecutive notes if the interval is less than a fourth
1951 : // b. the octave is always marked in a skip greater than a fifth
1952 : // c. the octave is only marked in a skip of a fourth or fifth when the second note is in a different octave from the first.
1953 : else {
1954 903 : int interval = computeInterval(m_context.previousNote[chord->staffIdx()], rootNote, false);
1955 903 : if (interval > 5 || (interval > 3 && (m_context.previousNote[chord->staffIdx()]->octave() != rootNote->octave()))) {
1956 65 : octaveBraille = brailleOctave(octave);
1957 : }
1958 : }
1959 1057 : m_context.previousNote[chord->staffIdx()] = rootNote;
1960 :
1961 1057 : QString accidentalBraille = QString();
1962 1057 : if (rootNote->accidental()) {
1963 33 : accidentalBraille = brailleAccidentalType(rootNote->accidental()->accidentalType());
1964 : }
1965 :
1966 1057 : QString noteTieBraille = brailleTie(rootNote);
1967 :
1968 1057 : QString fingeringAfterBraille = QString();
1969 1073 : for (EngravingItem* el : rootNote->el()) {
1970 16 : if (el->isFingering()) {
1971 16 : fingeringAfterBraille += brailleFingeringAfter(toFingering(el));
1972 : }
1973 : }
1974 :
1975 : return
1976 : accidentalBraille
1977 2114 : + octaveBraille
1978 2114 : + noteBraille
1979 2114 : + fingeringAfterBraille
1980 2114 : + noteTieBraille;
1981 1057 : }
1982 :
1983 67 : QString Braille::brailleClef(Clef* clef)
1984 : {
1985 : //In Braille, the clef is printed only at it's first appearance.
1986 67 : if (m_context.currentClefType[clef->staffIdx()] == clef->clefType()) {
1987 7 : return QString();
1988 : }
1989 :
1990 60 : m_context.currentClefType[clef->staffIdx()] = clef->clefType();
1991 60 : resetOctave(clef->staffIdx());
1992 :
1993 60 : switch (clef->clefType()) {
1994 35 : case ClefType::G: //Treble clef
1995 35 : return BRAILLE_TREBLE_CLEF;
1996 0 : case ClefType::G15_MB: //Treble clef 15ma bassa
1997 0 : return BRAILLE_TREBLE_CLEF_15MB;
1998 0 : case ClefType::G8_VB: //Treble clef 8va bassa
1999 0 : return BRAILLE_TREBLE_CLEF_8VB;
2000 0 : case ClefType::G8_VA: //Treble clef 8va alta
2001 0 : return BRAILLE_TREBLE_CLEF_8VA;
2002 0 : case ClefType::G15_MA: //Treble clef 15ma alta
2003 0 : return BRAILLE_TREBLE_CLEF_15MA;
2004 0 : case ClefType::G8_VB_O: //Double treble clef 8va bassa on 2nd line
2005 0 : return BRAILLE_D_TREBLE_CLEF_8VB_O;
2006 0 : case ClefType::G8_VB_P: //Treble clef optional 8va bassa
2007 0 : return BRAILLE_TREBLE_CLEF_8VB_P;
2008 0 : case ClefType::G_1: //French violin clef
2009 0 : return BRAILLE_FRENCH_VIOLINE_CLEF;
2010 0 : case ClefType::C1: //Soprano clef
2011 : case ClefType::C1_F18C: //Soprano clef (French, 18th century)
2012 : case ClefType::C1_F20C: //Soprano clef (French, 20th century)
2013 0 : return BRAILLE_SOPRANO_CLEF;
2014 0 : case ClefType::C2: //Mezzo-soprano clef
2015 0 : return BRAILLE_MEZZO_SOPRANO_CLEF;
2016 0 : case ClefType::C3: //Alto clef
2017 : case ClefType::C3_F18C: //Alto clef (French, 18th century)
2018 : case ClefType::C3_F20C: //Alto clef (French, 20th century)
2019 : case ClefType::C_19C: //C clef, H shape (19th century)
2020 0 : return BRAILLE_ALTO_CLEF;
2021 1 : case ClefType::C4: //Tenor clef
2022 : case ClefType::C4_8VB: //Tenor clef ottava bassa
2023 : case ClefType::C4_F18C: //Tenor clef (French, 18th century)
2024 : case ClefType::C4_F20C: //Tenor clef (French, 20th century)
2025 1 : return BRAILLE_TENOR_CLEF;
2026 0 : case ClefType::C5: //Baritone clef (C clef)
2027 0 : return BRAILLE_BARITONE_C_CLEF;
2028 24 : case ClefType::F: //Bass clef
2029 : case ClefType::F_F18C: //F clef (French, 18th century)
2030 : case ClefType::F_19C: //F clef (19th century)
2031 24 : return BRAILLE_BASS_CLEF;
2032 0 : case ClefType::F15_MB: //Bass clef 15ma bassa
2033 0 : return BRAILLE_BASS_CLEF_15MB;
2034 0 : case ClefType::F8_VB: //Bass clef 8va bassa
2035 0 : return BRAILLE_BASS_CLEF_8VB;
2036 0 : case ClefType::F_8VA: //Bass clef 8va alta
2037 0 : return BRAILLE_BASS_CLEF_8VA;
2038 0 : case ClefType::F_15MA: //Bass clef 15ma alta
2039 0 : return BRAILLE_BASS_CLEF_15MA;
2040 0 : case ClefType::F_B: //Baritone clef (F clef)
2041 0 : return BRAILLE_BARITONE_F_CLEF;
2042 0 : case ClefType::F_C: //Subbass clef
2043 0 : return BRAILLE_SUBBASS_CLEF;
2044 0 : case ClefType::PERC: //Percussion
2045 : case ClefType::PERC2: //Percussion
2046 : case ClefType::TAB: //TAB
2047 : case ClefType::TAB4: //TAB
2048 : case ClefType::TAB_SERIF: //TAB
2049 : case ClefType::TAB4_SERIF: //TAB
2050 0 : return QString();
2051 0 : default:
2052 0 : return QString();
2053 : }
2054 : }
2055 :
2056 3 : QString Braille::brailleDynamic(Dynamic* dynamic)
2057 : {
2058 3 : if (!dynamic || dynamic->plainText().isEmpty()) {
2059 0 : return QString();
2060 : }
2061 :
2062 3 : resetOctave(dynamic->staffIdx());
2063 : // Table 22C. Page 19. Music Braille Code 2015
2064 3 : return ">" + TextToUEBBraille().braille(dynamic->plainText());
2065 : }
2066 :
2067 4 : QString Braille::brailleFermata(Fermata* fermata)
2068 : {
2069 4 : if (!fermata) {
2070 0 : return QString();
2071 : }
2072 :
2073 : // Table 22B. Page 18. Music Braille Code 2015.
2074 : // TODO Could not find dedicated Braille symbols for Henze
2075 : // or very long variants, so regular ones were used. Are there dedicated symbols?
2076 4 : switch (fermata->symId()) {
2077 4 : case SymId::fermataAbove:
2078 : case SymId::fermataBelow:
2079 4 : return BRAILLE_FERMATA;
2080 0 : case SymId::fermataVeryShortAbove:
2081 : case SymId::fermataVeryShortBelow:
2082 : case SymId::fermataShortHenzeAbove:
2083 : case SymId::fermataShortHenzeBelow:
2084 : case SymId::fermataShortAbove:
2085 : case SymId::fermataShortBelow:
2086 0 : return BRAILLE_SHORT_FERMATA;
2087 0 : case SymId::fermataVeryLongAbove:
2088 : case SymId::fermataVeryLongBelow:
2089 : case SymId::fermataLongHenzeAbove:
2090 : case SymId::fermataLongHenzeBelow:
2091 : case SymId::fermataLongAbove:
2092 : case SymId::fermataLongBelow:
2093 0 : return BRAILLE_LONG_FERMATA;
2094 0 : default:
2095 0 : break;
2096 : }
2097 0 : return QString();
2098 : }
2099 :
2100 16 : QString Braille::brailleFingeringAfter(Fingering* fingering)
2101 : {
2102 : // 15.1 - 15.2. Page 108. Music Braille Code 2015.
2103 : // TODO: 15.3 - 15.4. Page 108. Music Braille Code 2015.
2104 16 : QString result = QString();
2105 16 : if (fingering->textStyleType() == TextStyleType::FINGERING
2106 16 : || fingering->textStyleType() == TextStyleType::LH_GUITAR_FINGERING) {
2107 16 : QString plainText = fingering->plainText();
2108 38 : for (QChar c : plainText) {
2109 22 : if (c == QChar('0')) {
2110 0 : result += BRAILLE_FINGERING_OPEN;
2111 : }
2112 22 : if (c == QChar('1')) {
2113 6 : result += BRAILLE_FINGERING_1ST;
2114 : }
2115 22 : if (c == QChar('2')) {
2116 4 : result += BRAILLE_FINGERING_2ND;
2117 : }
2118 22 : if (c == QChar('3')) {
2119 1 : result += BRAILLE_FINGERING_3RD;
2120 : }
2121 22 : if (c == QChar('4')) {
2122 3 : result += BRAILLE_FINGERING_4TH;
2123 : }
2124 22 : if (c == QChar('5')) {
2125 5 : result += BRAILLE_FINGERING_5TH;
2126 : }
2127 22 : if (c == QChar('-')) {
2128 3 : result += BRAILLE_FINGERING_CHANGE;
2129 : }
2130 : }
2131 16 : }
2132 :
2133 16 : return result;
2134 0 : }
2135 :
2136 1057 : QString Braille::brailleGlissando(Note* note)
2137 : {
2138 1057 : if (!note) {
2139 0 : return QString();
2140 : }
2141 :
2142 1057 : for (Spanner* spanner : note->spannerFor()) {
2143 2 : if (spanner->isGlissando()) {
2144 2 : return BRAILLE_GLISSANDO;
2145 : }
2146 : }
2147 :
2148 1055 : return QString();
2149 : }
2150 :
2151 1057 : QString Braille::brailleGraceNoteMarking(Chord* chord)
2152 : {
2153 : // 16.2.1 - 16.2.3. Page 111 - 112. Music Braille Code 2015.
2154 : // TODO: doubling the grace note sign where there are more than 4 grace notes.
2155 : // the book is not very clear how this doubling is done and how the user
2156 : // understands where do grace notes end.
2157 1057 : if (!chord->isGrace() || !chord->ownershipParent()->isChord()) {
2158 1048 : return QString();
2159 : }
2160 :
2161 9 : QString result = QString();
2162 9 : if (chord->stemSlash()) {
2163 6 : result = BRAILLE_GRACE_SHORT;
2164 : } else {
2165 3 : result = BRAILLE_GRACE_LONG;
2166 : }
2167 9 : return result;
2168 9 : }
2169 :
2170 1 : QString Braille::brailleJump(Jump* jump)
2171 : {
2172 1 : switch (jump->jumpType()) {
2173 1 : case JumpType::DC:
2174 1 : return BRAILLE_DA_CAPO;
2175 0 : case JumpType::DC_AL_FINE:
2176 0 : return BRAILLE_DA_CAPO_AL_FINE;
2177 0 : case JumpType::DC_AL_CODA:
2178 0 : return BRAILLE_DA_CAPO_AL_CODA;
2179 0 : case JumpType::DS_AL_CODA:
2180 0 : return BRAILLE_DAL_SEGNO_AL_CODA;
2181 0 : case JumpType::DS_AL_FINE:
2182 0 : return BRAILLE_DAL_SEGNO_AL_FINE;
2183 0 : case JumpType::DS:
2184 0 : return BRAILLE_DAL_SEGNO;
2185 0 : case JumpType::USER:
2186 0 : return QString(">") + TextToUEBBraille().braille(jump->plainText().toQString().toLower()) + QString("> ");
2187 0 : case JumpType::DC_AL_DBLCODA:
2188 : case JumpType::DS_AL_DBLCODA:
2189 : case JumpType::DSS:
2190 : case JumpType::DSS_AL_CODA:
2191 : case JumpType::DSS_AL_DBLCODA:
2192 : case JumpType::DSS_AL_FINE:
2193 0 : break;
2194 : }
2195 0 : return QString();
2196 : }
2197 :
2198 69 : QString Braille::brailleKeySig(KeySig* keySig)
2199 : {
2200 : //In Braille, the key signature is printed only at it's first appearance.
2201 : //Paragraf 6.5. Page 61. Music Braille Code 2015.
2202 69 : if (!keySig || keySig->segment()->isKeySigAnnounceType()
2203 138 : || (m_context.currentKey[keySig->staffIdx()] == keySig->key() && !keySig->isCustom())) {
2204 9 : return QString();
2205 : }
2206 :
2207 60 : m_context.currentKey[keySig->staffIdx()] = keySig->key();
2208 60 : resetOctave(keySig->staffIdx());
2209 :
2210 60 : QString brailleKeySig = QString();
2211 60 : if (keySig->isCustom()) {
2212 : //Section 6.5.1. Page 62. Music Braille Code 2015.
2213 : //TODO
2214 : } else {
2215 : //Section 6.5. Page 61. Music Braille Code 2015.
2216 : //Table 6. Page 5. Music Braille Code 2015.
2217 60 : switch (keySig->key()) {
2218 0 : case Key::C_B: brailleKeySig = QString(TextToUEBBraille().braille("7") + brailleAccidentalType(AccidentalType::FLAT));
2219 0 : break;
2220 0 : case Key::G_B: brailleKeySig = QString(TextToUEBBraille().braille("6") + brailleAccidentalType(AccidentalType::FLAT));
2221 0 : break;
2222 0 : case Key::D_B: brailleKeySig = QString(TextToUEBBraille().braille("5") + brailleAccidentalType(AccidentalType::FLAT));
2223 0 : break;
2224 0 : case Key::A_B: brailleKeySig = QString(TextToUEBBraille().braille("4") + brailleAccidentalType(AccidentalType::FLAT));
2225 0 : break;
2226 16 : case Key::E_B: brailleKeySig = QString(brailleAccidentalType(AccidentalType::FLAT) + brailleAccidentalType(
2227 24 : AccidentalType::FLAT) + brailleAccidentalType(AccidentalType::FLAT));
2228 8 : break;
2229 3 : case Key::B_B: brailleKeySig = QString(brailleAccidentalType(AccidentalType::FLAT) + brailleAccidentalType(AccidentalType::FLAT));
2230 3 : break;
2231 3 : case Key::F: brailleKeySig = QString(brailleAccidentalType(AccidentalType::FLAT));
2232 3 : break;
2233 29 : case Key::C: return QString();
2234 8 : case Key::G: brailleKeySig = QString(brailleAccidentalType(AccidentalType::SHARP));
2235 8 : break;
2236 5 : case Key::D: brailleKeySig = QString(brailleAccidentalType(AccidentalType::SHARP) + brailleAccidentalType(AccidentalType::SHARP));
2237 5 : break;
2238 4 : case Key::A: brailleKeySig = QString(brailleAccidentalType(AccidentalType::SHARP) + brailleAccidentalType(
2239 6 : AccidentalType::SHARP) + brailleAccidentalType(AccidentalType::SHARP));
2240 2 : break;
2241 1 : case Key::E: brailleKeySig = QString(TextToUEBBraille().braille("4") + brailleAccidentalType(AccidentalType::SHARP));
2242 1 : break;
2243 1 : case Key::B: brailleKeySig = QString(TextToUEBBraille().braille("5") + brailleAccidentalType(AccidentalType::SHARP));
2244 1 : break;
2245 0 : case Key::F_S: brailleKeySig = QString(TextToUEBBraille().braille("6") + brailleAccidentalType(AccidentalType::SHARP));
2246 0 : break;
2247 0 : case Key::C_S: brailleKeySig = QString(TextToUEBBraille().braille("7") + brailleAccidentalType(AccidentalType::SHARP));
2248 0 : break;
2249 0 : case Key::INVALID: return QString();
2250 0 : case Key::NUM_OF: return QString(); //TODO What is this?
2251 0 : case Key::DELTA_ENHARMONIC: return QString(); //TODO What is this?
2252 : }
2253 : }
2254 :
2255 31 : if (keySig->segment()->prev() && !keySig->prevSegmentElement()->isClef()) {
2256 0 : brailleKeySig = " " + brailleKeySig;
2257 : }
2258 :
2259 31 : if (!keySig->nextSegmentElement()->isTimeSig()) {
2260 2 : brailleKeySig += " ";
2261 : }
2262 :
2263 31 : return brailleKeySig;
2264 60 : }
2265 :
2266 0 : QString Braille::brailleLyrics(Lyrics* lyrics)
2267 : {
2268 0 : std::string txt = lyrics->plainText().toStdString();
2269 0 : return QString::fromStdString(braille_long_translate(table_for_literature.c_str(), txt));
2270 0 : }
2271 :
2272 1 : QString Braille::brailleMarker(Marker* marker)
2273 : {
2274 1 : switch (marker->markerType()) {
2275 0 : case MarkerType::SEGNO:
2276 : case MarkerType::VARSEGNO:
2277 0 : return BRAILLE_SEGNO;
2278 0 : case MarkerType::CODA:
2279 : case MarkerType::VARCODA:
2280 : case MarkerType::CODETTA:
2281 0 : return BRAILLE_CODA;
2282 1 : case MarkerType::FINE:
2283 1 : return BRAILLE_FINE;
2284 0 : case MarkerType::TOCODA:
2285 : case MarkerType::TOCODASYM:
2286 : case MarkerType::DA_CODA:
2287 : case MarkerType::DA_DBLCODA:
2288 0 : return BRAILLE_TOCODA;
2289 0 : case MarkerType::USER:
2290 0 : return QString(">") + TextToUEBBraille().braille(marker->plainText().toQString().toLower()) + QString("> ");
2291 : }
2292 0 : return QString();
2293 : }
2294 :
2295 254 : QString Braille::brailleMeasure(Measure* measure, int staffCount)
2296 : {
2297 254 : QString rez;
2298 254 : QTextStream out(&rez);
2299 :
2300 : //LOGD("Braille::brailleMeasure %d", staffCount);
2301 : //Render all repeats and jumps that are on the left
2302 269 : for (EngravingItem* el : measure->el()) {
2303 15 : if (el->isMarker()) {
2304 1 : Marker* marker = toMarker(el);
2305 1 : if (marker->textStyleType() == TextStyleType::REPEAT_LEFT) {
2306 0 : out << brailleMarker(toMarker(el));
2307 : }
2308 : }
2309 15 : if (el->isJump()) {
2310 1 : Jump* jump = toJump(el);
2311 1 : if (jump->textStyleType() == TextStyleType::REPEAT_LEFT) {
2312 0 : out << brailleJump(toJump(el));
2313 : }
2314 : }
2315 : }
2316 :
2317 254 : auto spanners = m_score->spannerMap().findOverlapping(measure->tick().ticks(), measure->endTick().ticks());
2318 375 : for (auto interval : spanners) {
2319 121 : Spanner* s = interval.value;
2320 121 : if (s && s->isVolta()) {
2321 17 : out << brailleVolta(measure, toVolta(s), staffCount);
2322 : }
2323 : }
2324 :
2325 : //Render everything that is in Voice 1
2326 1806 : for (auto seg = measure->first(); seg; seg = seg->next()) {
2327 1563 : for (EngravingItem* annotation : seg->annotations()) {
2328 11 : if (annotation->isTempoText()) {
2329 4 : out << brailleTempoText(toTempoText(annotation), staffCount);
2330 : }
2331 11 : if (annotation->track() == staffCount * VOICES) {
2332 11 : if (annotation->isDynamic()) {
2333 3 : out << brailleDynamic(toDynamic(annotation));
2334 : }
2335 : }
2336 : }
2337 :
2338 1552 : EngravingItem* el = seg->element(staffCount * VOICES);
2339 1552 : if (!el) {
2340 27 : continue;
2341 : }
2342 :
2343 1525 : if (el->isClef()) {
2344 67 : out << brailleClef(toClef(el));
2345 1458 : } else if (el->isKeySig()) {
2346 69 : out << brailleKeySig(toKeySig(el));
2347 1389 : } else if (el->isTimeSig()) {
2348 74 : out << brailleTimeSig(toTimeSig(el));
2349 1315 : } else if (el->isMMRest()) {
2350 2 : out << brailleMMRest(toMMRest(el));
2351 1313 : } else if (el->isRest()) {
2352 48 : out << brailleRest(toRest(el));
2353 1265 : } else if (el->isChord()) {
2354 993 : out << brailleChord(toChord(el));
2355 272 : } else if (el->isBreath()) {
2356 2 : out << brailleBreath(toBreath(el));
2357 270 : } else if (el->isBarLine() && toBarLine(el) != lastBarline(measure, el->track())) {
2358 13 : out << brailleBarline(toBarLine(el));
2359 257 : } else if (el->isMeasureRepeat()) {
2360 0 : out << brailleMeasureRepeat(toMeasureRepeat(el));
2361 : }
2362 : }
2363 :
2364 : // Render the rest of the voices
2365 1016 : for (size_t i = 1; i < VOICES; ++i) {
2366 762 : if (measure->hasVoice(staffCount * VOICES + i)) {
2367 : // 11.1.1. Page 87. Music Braille Code 2015.
2368 : // All voices must be complete when writing the other voices in Braille.
2369 : // We exchange the voices to voice 0 and back for MuseScore to add the missing beats as rests
2370 : // Then we undo the change, so we don't have an altered score.
2371 : // TODO: Braille dot 5 should be put before the rests that appear in Braille, but are not originally in the score
2372 : /* FIXME: may break live braille but be required for export
2373 : m_score->deselectAll();
2374 : m_score->select(measure, SelectType::RANGE, staffCount);
2375 : m_score->update();
2376 : m_score->startCmd();
2377 : ExchangeVoices::exchangeVoicesInSelection(m_score, 0, static_cast<int>(i));
2378 : m_score->endCmd();
2379 : m_score->startCmd();
2380 : ExchangeVoices::exchangeVoicesInSelection(m_score, 0, static_cast<int>(i));
2381 : m_score->endCmd();
2382 : */
2383 :
2384 12 : resetOctave(staffCount);
2385 12 : out << BRAILLE_FULL_MEASURE_IN_ACORD;
2386 129 : for (auto seg = measure->first(); seg; seg = seg->next()) {
2387 117 : EngravingItem* el = seg->element(staffCount * VOICES + i);
2388 117 : if (!el) {
2389 56 : continue;
2390 : }
2391 :
2392 61 : if (el->isRest()) {
2393 6 : out << brailleRest(toRest(el));
2394 : }
2395 61 : if (el->isChord()) {
2396 55 : out << brailleChord(toChord(el));
2397 : }
2398 61 : if (el->isBreath()) {
2399 0 : out << brailleBreath(toBreath(el));
2400 : }
2401 : }
2402 12 : resetOctave(staffCount);
2403 :
2404 : // Undo filling the missing beats with rests, so we don't have an altered score.
2405 : /* see FIXME above
2406 : m_score->undoRedo(true, nullptr);
2407 : m_score->undoRedo(true, nullptr);
2408 : */
2409 12 : m_score->deselectAll();
2410 : }
2411 : }
2412 :
2413 : //Render the barline
2414 254 : BarLine* bl = lastBarline(measure, staffCount * VOICES);
2415 254 : out << brailleBarline(bl);
2416 :
2417 : //Render repeats and jumps that are on the right
2418 269 : for (EngravingItem* el : measure->el()) {
2419 15 : if (el->isMarker()) {
2420 1 : Marker* marker = toMarker(el);
2421 1 : if (marker->textStyleType() == TextStyleType::REPEAT_RIGHT) {
2422 1 : out << brailleMarker(toMarker(el));
2423 : }
2424 : }
2425 15 : if (el->isJump()) {
2426 1 : Jump* jump = toJump(el);
2427 1 : if (jump->textStyleType() == TextStyleType::REPEAT_RIGHT) {
2428 1 : out << brailleJump(toJump(el));
2429 : }
2430 : }
2431 : }
2432 254 : out.flush();
2433 254 : return rez;
2434 254 : }
2435 :
2436 0 : QString Braille::brailleMeasureRepeat(MeasureRepeat* measureRepeat)
2437 : {
2438 0 : if (!measureRepeat) {
2439 0 : return QString();
2440 : }
2441 :
2442 0 : return BRAILLE_MEASURE_REPEAT;
2443 : }
2444 :
2445 2 : QString Braille::brailleMMRest(MMRest* mmRest)
2446 : {
2447 2 : if (!mmRest) {
2448 0 : return QString();
2449 : }
2450 : // 5.3 Multiple-Measure Rests. Page 58. MBC2015.
2451 :
2452 2 : if (mmRest->measure()->mmRestCount() <= 3) {
2453 1 : return BRAILLE_REST_MEASURE.repeated(mmRest->measure()->mmRestCount());
2454 : }
2455 :
2456 1 : resetOctave(mmRest->staffIdx());
2457 2 : return TextToUEBBraille().braille(QString::number(mmRest->measure()->mmRestCount())) + BRAILLE_REST_MEASURE;
2458 : }
2459 :
2460 1061 : QString Braille::brailleNote(const QString& pitchName, DurationType durationType, int dots)
2461 : {
2462 1061 : QString noteBraille = QString();
2463 1061 : static QMap<DurationType, QMap<QString, QString> > noteToBraille;
2464 1061 : if (noteToBraille.isEmpty()) {
2465 : //8th and 128th notes have the same representation in Braille
2466 1 : noteToBraille[DurationType::V_128TH]["C"] = noteToBraille[DurationType::V_EIGHTH]["C"] = BRAILLE_C_8TH_128TH;
2467 1 : noteToBraille[DurationType::V_128TH]["D"] = noteToBraille[DurationType::V_EIGHTH]["D"] = BRAILLE_D_8TH_128TH;
2468 1 : noteToBraille[DurationType::V_128TH]["E"] = noteToBraille[DurationType::V_EIGHTH]["E"] = BRAILLE_E_8TH_128TH;
2469 1 : noteToBraille[DurationType::V_128TH]["F"] = noteToBraille[DurationType::V_EIGHTH]["F"] = BRAILLE_F_8TH_128TH;
2470 1 : noteToBraille[DurationType::V_128TH]["G"] = noteToBraille[DurationType::V_EIGHTH]["G"] = BRAILLE_G_8TH_128TH;
2471 1 : noteToBraille[DurationType::V_128TH]["A"] = noteToBraille[DurationType::V_EIGHTH]["A"] = BRAILLE_A_8TH_128TH;
2472 1 : noteToBraille[DurationType::V_128TH]["B"] = noteToBraille[DurationType::V_EIGHTH]["B"] = BRAILLE_B_8TH_128TH;
2473 :
2474 : //64th and quarter notes have the same representation in Braille
2475 3 : noteToBraille[DurationType::V_64TH]["C"] = noteToBraille[DurationType::V_QUARTER]["C"]
2476 3 : = BRAILLE_C_64TH_QUARTER;
2477 3 : noteToBraille[DurationType::V_64TH]["D"] = noteToBraille[DurationType::V_QUARTER]["D"]
2478 3 : = BRAILLE_D_64TH_QUARTER;
2479 3 : noteToBraille[DurationType::V_64TH]["E"] = noteToBraille[DurationType::V_QUARTER]["E"]
2480 3 : = BRAILLE_E_64TH_QUARTER;
2481 3 : noteToBraille[DurationType::V_64TH]["F"] = noteToBraille[DurationType::V_QUARTER]["F"]
2482 3 : = BRAILLE_F_64TH_QUARTER;
2483 3 : noteToBraille[DurationType::V_64TH]["G"] = noteToBraille[DurationType::V_QUARTER]["G"]
2484 3 : = BRAILLE_G_64TH_QUARTER;
2485 3 : noteToBraille[DurationType::V_64TH]["A"] = noteToBraille[DurationType::V_QUARTER]["A"]
2486 3 : = BRAILLE_A_64TH_QUARTER;
2487 3 : noteToBraille[DurationType::V_64TH]["B"] = noteToBraille[DurationType::V_QUARTER]["B"]
2488 3 : = BRAILLE_B_64TH_QUARTER;
2489 :
2490 : //32nd and half notes have the same representation in Braille
2491 1 : noteToBraille[DurationType::V_32ND]["C"] = noteToBraille[DurationType::V_HALF]["C"] = BRAILLE_C_32ND_HALF;
2492 1 : noteToBraille[DurationType::V_32ND]["D"] = noteToBraille[DurationType::V_HALF]["D"] = BRAILLE_D_32ND_HALF;
2493 1 : noteToBraille[DurationType::V_32ND]["E"] = noteToBraille[DurationType::V_HALF]["E"] = BRAILLE_E_32ND_HALF;
2494 1 : noteToBraille[DurationType::V_32ND]["F"] = noteToBraille[DurationType::V_HALF]["F"] = BRAILLE_F_32ND_HALF;
2495 1 : noteToBraille[DurationType::V_32ND]["G"] = noteToBraille[DurationType::V_HALF]["G"] = BRAILLE_G_32ND_HALF;
2496 1 : noteToBraille[DurationType::V_32ND]["A"] = noteToBraille[DurationType::V_HALF]["A"] = BRAILLE_A_32ND_HALF;
2497 1 : noteToBraille[DurationType::V_32ND]["B"] = noteToBraille[DurationType::V_HALF]["B"] = BRAILLE_B_32ND_HALF;
2498 :
2499 : //16th and whole notes have the same representation in Braille.
2500 : // Breve has the same representation, but with an extra suffix;
2501 : // 256th has the same representation, but with an extra prefix;
2502 3 : noteToBraille[DurationType::V_256TH]["C"] = noteToBraille[DurationType::V_16TH]["C"]
2503 2 : =noteToBraille[DurationType::V_WHOLE]["C"]
2504 2 : = noteToBraille[DurationType::V_BREVE]["C"]
2505 5 : = BRAILLE_C_16TH_WHOLE;
2506 :
2507 3 : noteToBraille[DurationType::V_256TH]["D"] = noteToBraille[DurationType::V_16TH]["D"]
2508 2 : =noteToBraille[DurationType::V_WHOLE]["D"]
2509 2 : = noteToBraille[DurationType::V_BREVE]["D"]
2510 5 : = BRAILLE_D_16TH_WHOLE;
2511 :
2512 3 : noteToBraille[DurationType::V_256TH]["E"] = noteToBraille[DurationType::V_16TH]["E"]
2513 2 : =noteToBraille[DurationType::V_WHOLE]["E"]
2514 2 : = noteToBraille[DurationType::V_BREVE]["E"]
2515 5 : = BRAILLE_E_16TH_WHOLE;
2516 :
2517 3 : noteToBraille[DurationType::V_256TH]["F"] = noteToBraille[DurationType::V_16TH]["F"]
2518 2 : =noteToBraille[DurationType::V_WHOLE]["F"]
2519 2 : = noteToBraille[DurationType::V_BREVE]["F"]
2520 5 : = BRAILLE_F_16TH_WHOLE;
2521 :
2522 3 : noteToBraille[DurationType::V_256TH]["G"] = noteToBraille[DurationType::V_16TH]["G"]
2523 2 : =noteToBraille[DurationType::V_WHOLE]["G"]
2524 2 : = noteToBraille[DurationType::V_BREVE]["G"]
2525 5 : = BRAILLE_G_16TH_WHOLE;
2526 :
2527 3 : noteToBraille[DurationType::V_256TH]["A"] = noteToBraille[DurationType::V_16TH]["A"]
2528 2 : =noteToBraille[DurationType::V_WHOLE]["A"]
2529 2 : = noteToBraille[DurationType::V_BREVE]["A"]
2530 5 : = BRAILLE_A_16TH_WHOLE;
2531 :
2532 3 : noteToBraille[DurationType::V_256TH]["B"] = noteToBraille[DurationType::V_16TH]["B"]
2533 2 : =noteToBraille[DurationType::V_WHOLE]["B"]
2534 2 : = noteToBraille[DurationType::V_BREVE]["B"]
2535 6 : = BRAILLE_B_16TH_WHOLE;
2536 : }
2537 :
2538 1061 : switch (durationType) {
2539 0 : case DurationType::V_LONG: break; //TODO
2540 1 : case DurationType::V_BREVE:
2541 1 : noteBraille = noteToBraille[DurationType::V_BREVE][pitchName] + BRAILLE_BREVE_SUFFIX;
2542 1 : break;
2543 1060 : case DurationType::V_WHOLE:
2544 : case DurationType::V_HALF:
2545 : case DurationType::V_QUARTER:
2546 : case DurationType::V_EIGHTH:
2547 : case DurationType::V_16TH:
2548 : case DurationType::V_32ND:
2549 : case DurationType::V_64TH:
2550 : case DurationType::V_128TH:
2551 1060 : noteBraille = QString(noteToBraille[durationType][pitchName]);
2552 1060 : break;
2553 0 : case DurationType::V_256TH:
2554 0 : noteBraille = BRAILLE_256TH_PREFIX + QString(noteToBraille[DurationType::V_256TH][pitchName]);
2555 0 : break;
2556 0 : case DurationType::V_512TH: break; //TODO not supported in braille?
2557 0 : case DurationType::V_1024TH: break; //TODO not supported in braille?
2558 0 : case DurationType::V_ZERO: break; //TODO
2559 0 : case DurationType::V_MEASURE: break; //TODO
2560 0 : case DurationType::V_INVALID: break;
2561 : }
2562 :
2563 1110 : for (int i = 0; i < dots; ++i) {
2564 49 : noteBraille += BRAILLE_DURATION_DOT;
2565 : }
2566 :
2567 1061 : return noteBraille;
2568 0 : }
2569 :
2570 224 : QString Braille::brailleOctave(int octave)
2571 : {
2572 : //Table 9. Page 7. Music Braille Code 2015.
2573 224 : if (octave < 1) {
2574 2 : return BRAILLE_BELOW_FIRST_OCTAVE;
2575 : }
2576 222 : if (octave == 1) {
2577 1 : return BRAILLE_1ST_OCTAVE;
2578 : }
2579 221 : if (octave == 2) {
2580 47 : return BRAILLE_2ND_OCTAVE;
2581 : }
2582 174 : if (octave == 3) {
2583 44 : return BRAILLE_3RD_OCTAVE;
2584 : }
2585 130 : if (octave == 4) {
2586 78 : return BRAILLE_4TH_OCTAVE;
2587 : }
2588 52 : if (octave == 5) {
2589 48 : return BRAILLE_5TH_OCTAVE;
2590 : }
2591 4 : if (octave == 6) {
2592 1 : return BRAILLE_6TH_OCTAVE;
2593 : }
2594 3 : if (octave == 7) {
2595 1 : return BRAILLE_7TH_OCTAVE;
2596 : }
2597 2 : if (octave > 7) {
2598 2 : return BRAILLE_ABOVE_7TH_OCTAVE;
2599 : }
2600 :
2601 0 : return QString();
2602 : }
2603 :
2604 54 : QString Braille::brailleRest(Rest* rest)
2605 : {
2606 54 : QString restBraille;
2607 54 : switch (rest->durationType().type()) {
2608 0 : case DurationType::V_LONG: restBraille = BRAILLE_REST_LONG;
2609 0 : break;
2610 0 : case DurationType::V_BREVE: restBraille = BRAILLE_REST_BREVE;
2611 0 : break;
2612 0 : case DurationType::V_WHOLE: restBraille = BRAILLE_REST_WHOLE;
2613 0 : break;
2614 6 : case DurationType::V_HALF: restBraille = BRAILLE_REST_HALF;
2615 6 : break;
2616 29 : case DurationType::V_QUARTER: restBraille = BRAILLE_REST_QUARTER;
2617 29 : break;
2618 19 : case DurationType::V_EIGHTH: restBraille = BRAILLE_REST_EIGHTH;
2619 19 : break;
2620 0 : case DurationType::V_16TH: restBraille = BRAILLE_REST_16TH;
2621 0 : break;
2622 0 : case DurationType::V_32ND: restBraille = BRAILLE_REST_32ND;
2623 0 : break;
2624 0 : case DurationType::V_64TH: restBraille = BRAILLE_REST_64TH;
2625 0 : break;
2626 0 : case DurationType::V_128TH: restBraille = BRAILLE_REST_128TH;
2627 0 : break;
2628 0 : case DurationType::V_256TH: restBraille = BRAILLE_REST_256TH;
2629 0 : break;
2630 0 : case DurationType::V_512TH: restBraille = QString();
2631 0 : break; //not supported in braille
2632 0 : case DurationType::V_1024TH: restBraille = QString();
2633 0 : break; //not supported in braille
2634 0 : case DurationType::V_ZERO: restBraille = QString();
2635 0 : break; //not sure what this means
2636 0 : case DurationType::V_MEASURE: restBraille = BRAILLE_REST_MEASURE;
2637 0 : break;
2638 0 : case DurationType::V_INVALID: restBraille = QString();
2639 0 : break;
2640 : }
2641 :
2642 56 : for (int i = 0; i < rest->dots(); ++i) {
2643 2 : restBraille += BRAILLE_DURATION_DOT;
2644 : }
2645 :
2646 54 : QString fermata = QString();
2647 54 : for (EngravingItem* el : rest->segment()->annotations()) {
2648 0 : if (el->isFermata()) {
2649 0 : fermata = brailleFermata(toFermata(el));
2650 : }
2651 : }
2652 108 : std::vector<Slur*> restSlurs = slurs(rest);
2653 108 : QString slurBrailleBefore = brailleSlurBefore(rest, restSlurs);
2654 108 : QString slurBrailleAfter = brailleSlurAfter(rest, restSlurs);
2655 108 : std::vector<Hairpin*> restHairpins = hairpins(rest);
2656 108 : QString hairpinBrailleBefore = brailleHairpinBefore(rest, restHairpins);
2657 108 : QString hairpinBrailleAfter = brailleHairpinAfter(rest, restHairpins);
2658 :
2659 54 : QString tupletBraille = brailleTuplet(rest->tuplet(), rest);
2660 :
2661 54 : QString result = QString();
2662 54 : result += hairpinBrailleBefore;
2663 54 : result += slurBrailleBefore;
2664 54 : result += tupletBraille;
2665 54 : result += restBraille;
2666 54 : result += slurBrailleAfter;
2667 54 : result += hairpinBrailleAfter;
2668 54 : result += fermata;
2669 :
2670 108 : return result;
2671 54 : }
2672 :
2673 4 : QString Braille::brailleTempoText(TempoText* tempoText, int staffIdx)
2674 : {
2675 4 : if (!tempoText) {
2676 0 : return QString();
2677 : }
2678 4 : resetOctave(staffIdx);
2679 : // Sections 1.8 and 1.8.1. Page 42. Music Braille Code 2015.
2680 4 : TDuration t1;
2681 4 : TDuration t2;
2682 : int len1;
2683 : int len2;
2684 4 : QString text = tempoText->plainText();
2685 4 : QString firstPart = text.split(" = ").first();
2686 4 : QString secondPart = text.split(" = ").back();
2687 4 : int x1 = TempoText::findTempoDuration(firstPart, len1, t1);
2688 4 : int x2 = TempoText::findTempoDuration(secondPart, len2, t2);
2689 :
2690 4 : if (x1 != -1) {
2691 3 : QString dots1;
2692 3 : QString dots2;
2693 3 : dots1 = brailleNote("C", t1.type(), t1.dots());
2694 3 : if (x2 != -1) {
2695 1 : dots2 = brailleNote("C", t2.type(), t2.dots());
2696 1 : QString result = BRAILLE_MUSIC_PARENTHESES + dots1 + BRAILLE_EQUALS_METRONOME + dots2 + BRAILLE_MUSIC_PARENTHESES;
2697 1 : result += " ";
2698 1 : return result;
2699 1 : } else {
2700 4 : QString result = BRAILLE_MUSIC_PARENTHESES + dots1 + BRAILLE_EQUALS_METRONOME + TextToUEBBraille().braille(secondPart)
2701 6 : + BRAILLE_MUSIC_PARENTHESES;
2702 2 : result += " ";
2703 2 : return result;
2704 2 : }
2705 3 : } else {
2706 1 : return ">" + TextToUEBBraille().braille(text.toLower()) + "'";
2707 : }
2708 4 : }
2709 :
2710 1099 : QString Braille::brailleTie(Chord* chord)
2711 : {
2712 : // This is not a chord
2713 1099 : if (!chord || chord->notes().size() < 2) {
2714 974 : return QString();
2715 : }
2716 :
2717 125 : int nrTies = 0;
2718 125 : Tie* firstTie = nullptr;
2719 490 : for (Note* note : chord->notes()) {
2720 365 : if (note->tieFor() != nullptr) {
2721 94 : if (firstTie == nullptr) {
2722 39 : firstTie = note->tieFor();
2723 : }
2724 94 : nrTies++;
2725 : }
2726 : }
2727 :
2728 : // There are no notes in this chord with ties
2729 : // or there is just one note with tie
2730 125 : if (nrTies < 2) {
2731 88 : return QString();
2732 : }
2733 :
2734 : // There is at least one tie in the chord
2735 37 : Chord* nextChord = firstTie->endNote()->chord();
2736 136 : for (Note* chord1Note : chord->notes()) {
2737 465 : for (Note* chord2Note : nextChord->notes()) {
2738 366 : if (chord1Note->epitch() == chord2Note->epitch()
2739 443 : && (!chord1Note->tieFor()
2740 77 : || chord1Note->tieFor() != chord2Note->tieBack())) {
2741 : // Not all notes with the same pitch are tied in the
2742 : // two chords, so we cannot use the chord tie symbol;
2743 : // Each note that is tied will receive individual note tie symbol.
2744 : // 10.2-3. Page 83. Music Braille Code 2015.
2745 9 : return QString();
2746 : }
2747 : }
2748 : }
2749 :
2750 28 : return BRAILLE_TIE_CHORD;
2751 : }
2752 :
2753 1229 : QString Braille::brailleTie(Note* note)
2754 : {
2755 1229 : if (!note || !note->tieFor() || !brailleTie(note->chord()).isEmpty()) {
2756 1207 : return QString();
2757 : }
2758 :
2759 22 : return BRAILLE_TIE;
2760 : }
2761 :
2762 74 : QString Braille::brailleTimeSig(TimeSig* timeSig)
2763 : {
2764 74 : if (!timeSig || timeSig->segment()->isTimeSigAnnounceType()) {
2765 7 : return QString();
2766 : }
2767 67 : resetOctave(timeSig->staffIdx());
2768 :
2769 67 : QString rez;
2770 67 : QTextStream rezult(&rez);
2771 67 : if (timeSig->timeSigType() == TimeSigType::FOUR_FOUR) {
2772 3 : return QString(".c");
2773 64 : } else if (timeSig->timeSigType() == TimeSigType::ALLA_BREVE) {
2774 0 : return QString("_c");
2775 : }
2776 64 : QMap<QString, QString> numeratorToBraille;
2777 64 : numeratorToBraille["1"] = 'a';
2778 64 : numeratorToBraille["2"] = 'b';
2779 64 : numeratorToBraille["3"] = 'c';
2780 64 : numeratorToBraille["4"] = 'd';
2781 64 : numeratorToBraille["5"] = 'e';
2782 64 : numeratorToBraille["6"] = 'f';
2783 64 : numeratorToBraille["7"] = 'g';
2784 64 : numeratorToBraille["8"] = 'h';
2785 64 : numeratorToBraille["9"] = 'i';
2786 64 : numeratorToBraille["0"] = 'j';
2787 :
2788 64 : QMap<QString, QString> denominatorToBraille;
2789 64 : denominatorToBraille["1"] = '1';
2790 64 : denominatorToBraille["2"] = '2';
2791 64 : denominatorToBraille["3"] = '3';
2792 64 : denominatorToBraille["4"] = '4';
2793 64 : denominatorToBraille["5"] = '5';
2794 64 : denominatorToBraille["6"] = '6';
2795 64 : denominatorToBraille["7"] = '7';
2796 64 : denominatorToBraille["8"] = '8';
2797 64 : denominatorToBraille["9"] = '9';
2798 64 : denominatorToBraille["0"] = '0';
2799 :
2800 64 : rezult << "#";
2801 :
2802 130 : for (QChar n : QString::number(timeSig->numerator())) {
2803 66 : rezult << numeratorToBraille[n];
2804 64 : }
2805 :
2806 130 : for (QChar d : QString::number(timeSig->denominator())) {
2807 66 : rezult << denominatorToBraille[d];
2808 64 : }
2809 :
2810 64 : rezult << " ";
2811 64 : rezult.flush();
2812 64 : return rez;
2813 67 : }
2814 :
2815 1057 : QString Braille::brailleTremolo(Chord* chord)
2816 : {
2817 1057 : if (chord->tremoloChordType() == TremoloChordType::TremoloSecondChord) {
2818 6 : return QString();
2819 : }
2820 :
2821 1051 : switch (chord->tremoloType()) {
2822 11 : case TremoloType::R8: return BRAILLE_TREMOLO_8THS;
2823 6 : case TremoloType::R16: return BRAILLE_TREMOLO_16THS;
2824 1 : case TremoloType::R32: return BRAILLE_TREMOLO_32NDS;
2825 0 : case TremoloType::R64: return BRAILLE_TREMOLO_64THS;
2826 0 : case TremoloType::R128: return BRAILLE_TREMOLO_128THS;
2827 0 : case TremoloType::R256: return QString(); // unsupported in braille
2828 0 : case TremoloType::C8: return BRAILLE_TREMOLO_8THS_ALT;
2829 2 : case TremoloType::C16: return BRAILLE_TREMOLO_16THS_ALT;
2830 4 : case TremoloType::C32: return BRAILLE_TREMOLO_32NDS_ALT;
2831 0 : case TremoloType::C64: return BRAILLE_TREMOLO_64THS_ALT;
2832 0 : case TremoloType::C128: return BRAILLE_TREMOLO_128THS_ALT;
2833 0 : case TremoloType::C256: return QString(); // unsupported in braille
2834 0 : case TremoloType::BUZZ_ROLL: return QString(); //TODO
2835 1027 : case TremoloType::INVALID_TREMOLO: return QString();
2836 : }
2837 0 : return QString();
2838 : }
2839 :
2840 1111 : QString Braille::brailleTuplet(Tuplet* tuplet, DurationElement* el)
2841 : {
2842 1111 : if (tuplet == nullptr || *tuplet->elements().begin() != el) {
2843 1093 : return QString();
2844 : }
2845 :
2846 18 : if (tuplet->ratio().numerator() == 3) {
2847 : // Special handling for triplets.
2848 10 : return QString("2"); // '⠆' (dots 2-3)
2849 : }
2850 :
2851 16 : return QString("_") + QString::number(tuplet->ratio().numerator()) + QString("'");
2852 : }
2853 :
2854 17 : QString Braille::brailleVolta(Measure* measure, Volta* volta, int staffCount)
2855 : {
2856 17 : if (!volta || volta->startMeasure() != measure || volta->text().isEmpty()) {
2857 10 : return QString();
2858 : }
2859 :
2860 : // 17.1.1. Page 121. Music Braille Code 2015.
2861 7 : resetOctave(staffCount);
2862 7 : static const QRegularExpression regex("(,|\\.| )");
2863 14 : const QStringList voltaNumbers = volta->text().toQString().split(regex);
2864 7 : QString result = QString();
2865 24 : for (const QString& voltaNumber : voltaNumbers) {
2866 17 : if (voltaNumber.isEmpty()) {
2867 8 : continue;
2868 : }
2869 9 : result += QString("#") + voltaNumber;
2870 : }
2871 :
2872 : // Note: Normally the separator is only added in certain
2873 : // conditions, but for simplicity we add it everytime
2874 7 : result += "'";
2875 :
2876 7 : return result;
2877 7 : }
2878 :
2879 1111 : QString Braille::brailleHairpinBefore(ChordRest* chordRest, const std::vector<Hairpin*>& hairpins)
2880 : {
2881 1111 : if (!chordRest) {
2882 0 : return QString();
2883 : }
2884 : //TODO we are supposed to use line continuation 1 and 2 if there are multiple lines overlapping
2885 1111 : QString result = QString();
2886 1137 : for (Hairpin* hairpin : hairpins) {
2887 26 : if (!hairpin || hairpin->startCR() != chordRest) {
2888 20 : continue;
2889 : }
2890 6 : QString beginTextBraille = QString();
2891 6 : if (!hairpin->beginText().isEmpty()) {
2892 : //TODO handle symbols
2893 0 : QString beginText = hairpin->beginText().toLower();
2894 0 : if (beginText.endsWith(".")) {
2895 0 : beginText = beginText.left(beginText.lastIndexOf("."));
2896 : }
2897 0 : if (beginText.endsWith("'")) {
2898 0 : beginText = beginText.left(beginText.lastIndexOf("'"));
2899 : }
2900 0 : beginTextBraille = QString(">") + TextToUEBBraille().braille(beginText);
2901 0 : resetOctave(hairpin->staffIdx());
2902 0 : }
2903 :
2904 6 : switch (hairpin->hairpinType()) {
2905 2 : case HairpinType::CRESC_HAIRPIN:
2906 2 : result += beginTextBraille + BRAILLE_HAIRPIN_DIV_START;
2907 2 : resetOctave(hairpin->staffIdx());
2908 2 : break;
2909 4 : case HairpinType::DIM_HAIRPIN:
2910 4 : result += beginTextBraille + BRAILLE_HAIRPIN_CONV_START;
2911 4 : resetOctave(hairpin->staffIdx());
2912 4 : break;
2913 0 : case HairpinType::CRESC_LINE:
2914 : case HairpinType::DIM_LINE:
2915 0 : result += beginTextBraille + BRAILLE_LINE_CONT_START_1;
2916 0 : resetOctave(hairpin->staffIdx());
2917 0 : break;
2918 6 : case HairpinType::INVALID:
2919 : ;
2920 : }
2921 6 : }
2922 :
2923 1111 : return result;
2924 1111 : }
2925 :
2926 1111 : QString Braille::brailleHairpinAfter(ChordRest* chordRest, const std::vector<Hairpin*>& hairpins)
2927 : {
2928 1111 : if (!chordRest) {
2929 0 : return QString();
2930 : }
2931 : //TODO we are supposed to use line continuation 1 and 2 if there are multiple lines overlapping
2932 :
2933 : // 23.3.3.C says end of *may* be omitted in some specific cases,
2934 : // but since it is not mandatory, we don't do it for simplicity.
2935 : // This needs to be accounted when using examples from MBC2015 for tests
2936 1111 : QString result = QString();
2937 1137 : for (Hairpin* hairpin : hairpins) {
2938 26 : if (!hairpin || hairpin->endCR() != chordRest) {
2939 20 : continue;
2940 : }
2941 6 : switch (hairpin->hairpinType()) {
2942 2 : case HairpinType::CRESC_HAIRPIN:
2943 2 : result += BRAILLE_HAIRPIN_DIV_END;
2944 2 : resetOctave(hairpin->staffIdx());
2945 2 : break;
2946 4 : case HairpinType::DIM_HAIRPIN:
2947 4 : result += BRAILLE_HAIRPIN_CONV_END;
2948 4 : resetOctave(hairpin->staffIdx());
2949 4 : break;
2950 0 : case HairpinType::CRESC_LINE:
2951 : case HairpinType::DIM_LINE:
2952 0 : result += BRAILLE_LINE_CONT_END_1;
2953 0 : resetOctave(hairpin->staffIdx());
2954 0 : break;
2955 26 : case HairpinType::INVALID:
2956 : ;
2957 : }
2958 : }
2959 1111 : return result;
2960 1111 : }
2961 :
2962 1111 : QString Braille::brailleSlurBefore(ChordRest* chordRest, const std::vector<Slur*>& slurs)
2963 : {
2964 1111 : if (!chordRest || slurs.empty()) {
2965 914 : return QString();
2966 : }
2967 :
2968 : // 13.4 Page 98. Music Braille Code 2015.
2969 197 : if (isLongLongSlurConvergence(slurs)) {
2970 2 : return BRAILLE_SLUR_BRACKET_START + BRAILLE_SLUR_BRACKET_END;
2971 : }
2972 :
2973 196 : QString longSlur = QString();
2974 418 : for (Slur* slur : slurs) {
2975 : //13.3. Page 94. Braille Music Code 2015.
2976 222 : if (isLongSlur(slur) && chordRest->segment() == slur->startSegment()) {
2977 17 : longSlur += BRAILLE_SLUR_BRACKET_START;
2978 : }
2979 : }
2980 :
2981 : // TODO Implement 13.6 - 13.10. Page 98. Music Braille Code 2015.
2982 :
2983 196 : return longSlur;
2984 196 : }
2985 :
2986 1111 : QString Braille::brailleSlurAfter(ChordRest* chordRest, const std::vector<Slur*>& crSlurs)
2987 : {
2988 1111 : if (!chordRest || crSlurs.empty()) {
2989 914 : return QString();
2990 : }
2991 :
2992 : // 13.4 Page 98. Music Braille Code 2015.
2993 197 : if (isLongLongSlurConvergence(crSlurs)) {
2994 1 : return QString();
2995 : }
2996 :
2997 196 : bool hasShortSlurSymbol = false;
2998 196 : QString longSlurBraille = QString();
2999 196 : QString shortSlurBraille = QString();
3000 :
3001 418 : for (Slur* slur : crSlurs) {
3002 : // 13.2. Page 94. Braille Music Code 2015.
3003 : // 13.5. Page 98. Music Braille Code 2015. In Braille, slurs are redundant on notes with ties
3004 222 : if (isShortSlur(slur) && chordRest->segment() != slur->endSegment() && !hasTies(chordRest)) {
3005 62 : hasShortSlurSymbol = true;
3006 : }
3007 :
3008 : //13.3. Page 94. Braille Music Code 2015.
3009 222 : if (isLongSlur(slur) && chordRest->segment() == slur->endSegment() && !isLongLongSlurConvergence(crSlurs)) {
3010 15 : longSlurBraille += BRAILLE_SLUR_BRACKET_END;
3011 : }
3012 : }
3013 :
3014 196 : if (hasShortSlurSymbol) {
3015 62 : std::vector<Slur*> nextCRSlurs;
3016 62 : if (chordRest->segment()->next1()) {
3017 62 : ChordRest* nextCR = chordRest->segment()->next1()->nextChordRest(chordRest->track());
3018 62 : nextCRSlurs = slurs(nextCR);
3019 : }
3020 :
3021 : // 13.4 Page 98. Music Braille Code 2015.
3022 62 : if (isShortShortSlurConvergence(nextCRSlurs)) {
3023 3 : shortSlurBraille = BRAILLE_SLUR_SHORT_CONVERGENCE;
3024 : }
3025 : // 13.2. Page 94. Braille Music Code 2015.
3026 : else {
3027 59 : shortSlurBraille = BRAILLE_SLUR_SHORT;
3028 : }
3029 62 : }
3030 : // TODO Implement 13.6 - 13.10. Page 98. Music Braille Code 2015.
3031 :
3032 196 : return shortSlurBraille + longSlurBraille;
3033 196 : }
3034 : }
|