1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2007-2011 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 // This file contains the implementation of an pitch spelling
14 // algorithmus from Emilios Cambouropoulos as published in:
15 // "Automatic Pitch Spelling: From Numbers to Sharps and Flats"
16
17 #include "note.h"
18 #include "key.h"
19 #include "pitchspelling.h"
20 #include "staff.h"
21 #include "chord.h"
22 #include "score.h"
23 #include "part.h"
24 #include "utils.h"
25
26 #include "audio/midi/event.h"
27
28 namespace Ms {
29
30 //---------------------------------------------------------
31 // tpcIsValid
32 //---------------------------------------------------------
33
tpcIsValid(int val)34 bool tpcIsValid(int val)
35 {
36 return val >= Tpc::TPC_MIN && val <= Tpc::TPC_MAX;
37 }
38
39 //---------------------------------------------------------
40 // step2tpc
41 //---------------------------------------------------------
42
step2tpc(int step,AccidentalVal alter)43 int step2tpc(int step, AccidentalVal alter)
44 {
45 // TPC - tonal pitch classes
46 // "line of fifth's" LOF
47
48 static const int spellings[] = {
49 // bbb bb b - # ## ###
50 -7, 0, 7, 14, 21, 28, 35, // C
51 -5, 2, 9, 16, 23, 30, 37, // D
52 -3, 4, 11, 18, 25, 32, 39, // E
53 -8, -1, 6, 13, 20, 27, 34, // F
54 -6, 1, 8, 15, 22, 29, 36, // G
55 -4, 3, 10, 17, 24, 31, 38, // A
56 -2, 5, 12, 19, 26, 33, 40, // B
57 };
58
59 int i = (step * TPCS_PER_STEP) + (int(alter) - int(AccidentalVal::MIN));
60 Q_ASSERT(i >= 0 && (i < int(sizeof(spellings)/sizeof(*spellings))));
61 return spellings[i];
62 }
63
64 static const int tpcByStepAndKey[int(Key::NUM_OF)][STEP_DELTA_OCTAVE] = {
65 // step C D E F G A B Key
66 { Tpc::TPC_C_B, Tpc::TPC_D_B, Tpc::TPC_E_B, Tpc::TPC_F_B, Tpc::TPC_G_B, Tpc::TPC_A_B, Tpc::TPC_B_B}, // Cb
67 { Tpc::TPC_C_B, Tpc::TPC_D_B, Tpc::TPC_E_B, Tpc::TPC_F, Tpc::TPC_G_B, Tpc::TPC_A_B, Tpc::TPC_B_B}, // Gb
68 { Tpc::TPC_C, Tpc::TPC_D_B, Tpc::TPC_E_B, Tpc::TPC_F, TPC_G_B, Tpc::TPC_A_B, Tpc::TPC_B_B}, // Db
69 { Tpc::TPC_C, Tpc::TPC_D_B, Tpc::TPC_E_B, Tpc::TPC_F, Tpc::TPC_G, Tpc::TPC_A_B, Tpc::TPC_B_B}, // Ab
70 { Tpc::TPC_C, Tpc::TPC_D, Tpc::TPC_E_B, Tpc::TPC_F, Tpc::TPC_G, Tpc::TPC_A_B, Tpc::TPC_B_B}, // Eb
71 { Tpc::TPC_C, Tpc::TPC_D, Tpc::TPC_E_B, Tpc::TPC_F, Tpc::TPC_G, Tpc::TPC_A, Tpc::TPC_B_B}, // B
72 { Tpc::TPC_C, Tpc::TPC_D, Tpc::TPC_E, Tpc::TPC_F, Tpc::TPC_G, Tpc::TPC_A, Tpc::TPC_B_B}, // F
73 { Tpc::TPC_C, Tpc::TPC_D, Tpc::TPC_E, Tpc::TPC_F, Tpc::TPC_G, Tpc::TPC_A, Tpc::TPC_B}, // C
74 { Tpc::TPC_C, Tpc::TPC_D, Tpc::TPC_E, Tpc::TPC_F_S, Tpc::TPC_G, Tpc::TPC_A, Tpc::TPC_B}, // G
75 { Tpc::TPC_C_S, Tpc::TPC_D, Tpc::TPC_E, Tpc::TPC_F_S, Tpc::TPC_G, Tpc::TPC_A, Tpc::TPC_B}, // D
76 { Tpc::TPC_C_S, Tpc::TPC_D, Tpc::TPC_E, Tpc::TPC_F_S, Tpc::TPC_G_S, Tpc::TPC_A, Tpc::TPC_B}, // A
77 { Tpc::TPC_C_S, Tpc::TPC_D_S, Tpc::TPC_E, Tpc::TPC_F_S, Tpc::TPC_G_S, Tpc::TPC_A, Tpc::TPC_B}, // E
78 { Tpc::TPC_C_S, Tpc::TPC_D_S, Tpc::TPC_E, Tpc::TPC_F_S, Tpc::TPC_G_S, Tpc::TPC_A_S, Tpc::TPC_B}, // H
79 { Tpc::TPC_C_S, Tpc::TPC_D_S, Tpc::TPC_E_S, Tpc::TPC_F_S, Tpc::TPC_G_S, Tpc::TPC_A_S, Tpc::TPC_B}, // F#
80 { Tpc::TPC_C_S, Tpc::TPC_D_S, Tpc::TPC_E_S, Tpc::TPC_F_S, Tpc::TPC_G_S, Tpc::TPC_A_S, Tpc::TPC_B_S}, // C#
81 };
82
step2tpcByKey(int step,Key key)83 int step2tpcByKey(int step, Key key)
84 {
85 while (step < 0)
86 step += STEP_DELTA_OCTAVE;
87 while (key < Key::MIN)
88 key += Key::DELTA_ENHARMONIC;
89 while (key > Key::MAX)
90 key -= Key::DELTA_ENHARMONIC;
91 return tpcByStepAndKey[int(key) - int(Key::MIN)][step % STEP_DELTA_OCTAVE];
92 }
93
94 //---------------------------------------------------------
95 // tpc2step
96 //---------------------------------------------------------
97
tpc2step(int tpc)98 int tpc2step(int tpc)
99 {
100 // 14 - C
101 // 15 % 7 = 1
102 // f c g d a e b
103 static const int steps[STEP_DELTA_OCTAVE] = { 3, 0, 4, 1, 5, 2, 6 };
104 // TODO: optimize -TCP_MIN
105 return steps[(tpc-Tpc::TPC_MIN) % STEP_DELTA_OCTAVE];
106 // without a table, could also be rendered as:
107 // return ((tpc-Tpc::TPC_MIN) * STEP_DELTA_TPC) / STEP_DELTA_OCTAVE + TPC_FIRST_STEP;
108 }
109
110 //---------------------------------------------------------
111 // tpc2stepByKey
112 //---------------------------------------------------------
113
tpc2stepByKey(int tpc,Key key,int & alter)114 int tpc2stepByKey(int tpc, Key key, int& alter)
115 {
116 alter = tpc2alterByKey(tpc, key);
117 return tpc2step(tpc);
118 }
119
120 //---------------------------------------------------------
121 // step2tpc
122 //---------------------------------------------------------
123
step2tpc(const QString & stepName,AccidentalVal alter)124 int step2tpc(const QString& stepName, AccidentalVal alter)
125 {
126 if (stepName.isEmpty())
127 return Tpc::TPC_INVALID;
128 int r;
129 switch (stepName[0].toLower().toLatin1()) {
130 case 'c': r = 0; break;
131 case 'd': r = 1; break;
132 case 'e': r = 2; break;
133 case 'f': r = 3; break;
134 case 'g': r = 4; break;
135 case 'a': r = 5; break;
136 case 'b': r = 6; break;
137 default:
138 return Tpc::TPC_INVALID;
139 }
140 return step2tpc(r, alter);
141 }
142
143 //---------------------------------------------------------
144 // step2deltaPitchByKey
145 //
146 // returns the delta pitch above natural C for the given step in the given key
147 // step: 0 - 6
148 // key: -7 - +7
149 //---------------------------------------------------------
150
151 static const int pitchByStepAndKey[int(Key::NUM_OF)][STEP_DELTA_OCTAVE] = {
152 // step C D E F G A B Key
153 { -1, 1, 3, 4, 6, 8, 10}, // Cb
154 { -1, 1, 3, 5, 6, 8, 10}, // Gb
155 { 0, 1, 3, 5, 6, 8, 10}, // Db
156 { 0, 1, 3, 5, 7, 8, 10}, // Ab
157 { 0, 2, 3, 5, 7, 8, 10}, // Eb
158 { 0, 2, 3, 5, 7, 9, 10}, // B
159 { 0, 2, 4, 5, 7, 9, 10}, // F
160 { 0, 2, 4, 5, 7, 9, 11}, // C
161 { 0, 2, 4, 6, 7, 9, 11}, // G
162 { 1, 2, 4, 6, 7, 9, 11}, // D
163 { 1, 2, 4, 6, 8, 9, 11}, // A
164 { 1, 3, 4, 6, 8, 9, 11}, // E
165 { 1, 3, 4, 6, 8, 10, 11}, // H
166 { 1, 3, 5, 6, 8, 10, 11}, // F#
167 { 1, 3, 5, 6, 8, 10, 12}, // C#
168 };
169
step2deltaPitchByKey(int step,Key key)170 int step2deltaPitchByKey(int step, Key key)
171 {
172 while (step < 0)
173 step+= STEP_DELTA_OCTAVE;
174 while (key < Key::MIN)
175 key += Key::DELTA_ENHARMONIC;
176 while (key > Key::MAX)
177 key -= Key::DELTA_ENHARMONIC;
178 return pitchByStepAndKey[int(key)-int(Key::MIN)][step % STEP_DELTA_OCTAVE];
179 }
180
181 //---------------------------------------------------------
182 // tpc2pitch
183 //---------------------------------------------------------
184
tpc2pitch(int tpc)185 int tpc2pitch(int tpc)
186 {
187 Q_ASSERT(tpcIsValid(tpc));
188
189 static int pitches[] = {
190 //step: F C G D A E B
191 2, -3, 4, -1, 6, 1, 8, // bbb
192 3, -2, 5, 0, 7, 2, 9, // bb
193 4, -1, 6, 1, 8, 3, 10, // b
194 5, 0, 7, 2, 9, 4, 11, // -
195 6, 1, 8, 3, 10, 5, 12, // #
196 7, 2, 9, 4, 11, 6, 13, // ##
197 8, 3, 10, 5, 12, 7, 14 // ###
198 };
199 return pitches[tpc - Tpc::TPC_MIN];
200 }
201
202 //---------------------------------------------------------
203 // tpc2alterByKey
204 //
205 // returns the alteration (-3 to 3) of a given tpc in the given key
206 // to understand the formula:
207 // in the highest key (C#Maj), each of the first 7 tpcs (Fbb to Bbb; tpc-Tpc::TPC_MIN: 0 to 7)
208 // is 3 semitones below its key degree (alter = -3)
209 // the second 7 tpcs (Fb to Bb; tpc-Tpc::TPC_MIN: 8 to 13) are 2 semitones below (alter = -2) and so on up to 1
210 // thus, for C#Maj:
211 // (1) (tpc-Tpc::TPC_MIN) - 0 = 0 to 34 (for tcp-TCP_MIN from 0 to 34)
212 // (2) (tpc-Tpc::TPC_MIN) - 0) / 7 = 0 to 4 (for each settuple of tcp's) and finally
213 // (3) (tcp-Tpc::TPC_MIN) - 0) / 7 -3 = -3 to 1 (for each settuple of tcp's)
214 // where 0 = Key::C_S - Key::MAX
215 // for each previous key, the result of (1) increases by 1 and the classes of alter are shifted 1 TPC 'up':
216 // F#Maj: Fbb-Ebb => -3, Bbb to Eb => -2 and so on
217 // BMaj: Fbb-Abb => -3, Ebb to Ab => -2 and so on
218 // and so on
219 // thus, for any 'key', the formula is:
220 // ((tcp-Tpc::TPC_MIN) - (key-Key::MAX)) / TCP_DELTA_SEMITONE - 3
221 //---------------------------------------------------------
222
tpc2alterByKey(int tpc,Key key)223 int tpc2alterByKey(int tpc, Key key) {
224 return (tpc - int(key) - int(Tpc::TPC_MIN) + int(Key::MAX)) / TPC_DELTA_SEMITONE - (int(AccidentalVal::MAX) + 1);
225 }
226
227 //---------------------------------------------------------
228 // tpc2name
229 // return note name
230 //---------------------------------------------------------
231
tpc2name(int tpc,NoteSpellingType noteSpelling,NoteCaseType noteCase,bool explicitAccidental)232 QString tpc2name(int tpc, NoteSpellingType noteSpelling, NoteCaseType noteCase, bool explicitAccidental)
233 {
234 QString s;
235 QString acc;
236 tpc2name(tpc, noteSpelling, noteCase, s, acc, explicitAccidental);
237 return s + (explicitAccidental ? " " : "") + acc;
238 }
239
240 //---------------------------------------------------------
241 // tpc2name
242 //---------------------------------------------------------
243
tpc2name(int tpc,NoteSpellingType noteSpelling,NoteCaseType noteCase,QString & s,QString & acc,bool explicitAccidental)244 void tpc2name(int tpc, NoteSpellingType noteSpelling, NoteCaseType noteCase, QString& s, QString& acc, bool explicitAccidental)
245 {
246 AccidentalVal accVal;
247 tpc2name(tpc, noteSpelling, noteCase, s, accVal);
248 switch (accVal) {
249 case AccidentalVal::FLAT3:
250 if (explicitAccidental) {
251 acc = QObject::tr("triple ♭");
252 }
253 else if (noteSpelling == NoteSpellingType::GERMAN_PURE) {
254 switch (tpc) {
255 case TPC_A_BBB: acc = "sasas"; break;
256 case TPC_E_BBB: acc = "seses"; break;
257 default: acc = "eseses";
258 }
259 }
260 else {
261 acc = "bbb";
262 }
263 break;
264 case AccidentalVal::FLAT2:
265 if (explicitAccidental) {
266 acc = QObject::tr("double ♭");
267 }
268 else if (noteSpelling == NoteSpellingType::GERMAN_PURE) {
269 switch (tpc) {
270 case TPC_A_BB: acc = "sas"; break;
271 case TPC_E_BB: acc = "ses"; break;
272 default: acc = "eses";
273 }
274 }
275 else {
276 acc = "bb";
277 }
278 break;
279 case AccidentalVal::FLAT:
280 if (explicitAccidental)
281 acc = QObject::tr("♭");
282 else if (noteSpelling == NoteSpellingType::GERMAN_PURE)
283 acc = (tpc == TPC_A_B || tpc == TPC_E_B) ? "s" : "es";
284 else
285 acc = "b";
286 break;
287 case AccidentalVal::NATURAL: acc = ""; break;
288 case AccidentalVal::SHARP:
289 if (explicitAccidental)
290 acc = QObject::tr("♯");
291 else
292 acc = (noteSpelling == NoteSpellingType::GERMAN_PURE) ? "is" : "#";
293 break;
294 case AccidentalVal::SHARP2:
295 if (explicitAccidental)
296 acc = QObject::tr("double ♯");
297 else
298 acc = (noteSpelling == NoteSpellingType::GERMAN_PURE) ? "isis" : "##";
299 break;
300 case AccidentalVal::SHARP3:
301 if (explicitAccidental)
302 acc = QObject::tr("triple ♯");
303 else
304 acc = (noteSpelling == NoteSpellingType::GERMAN_PURE) ? "isisis" : "###";
305 break;
306 }
307 }
308
309 //---------------------------------------------------------
310 // tpc2name
311 //---------------------------------------------------------
312
tpc2name(int tpc,NoteSpellingType noteSpelling,NoteCaseType noteCase,QString & s,AccidentalVal & acc)313 void tpc2name(int tpc, NoteSpellingType noteSpelling, NoteCaseType noteCase, QString& s, AccidentalVal& acc)
314 {
315 const char names[] = "FCGDAEB";
316 const char gnames[] = "FCGDAEH";
317 const QString snames[] = { "Fa", "Do", "Sol", "Re", "La", "Mi", "Si" };
318
319 acc = tpc2alter(tpc);
320 int idx = (tpc - Tpc::TPC_MIN) % TPC_DELTA_SEMITONE;
321 switch (noteSpelling) {
322 case NoteSpellingType::GERMAN:
323 case NoteSpellingType::GERMAN_PURE:
324 s = gnames[idx];
325 if (s == "H" && acc == AccidentalVal::FLAT) {
326 s = "B";
327 if (noteSpelling == NoteSpellingType::GERMAN_PURE)
328 acc = AccidentalVal::NATURAL;
329 }
330 break;
331 case NoteSpellingType::SOLFEGGIO:
332 s = snames[idx];
333 break;
334 case NoteSpellingType::FRENCH:
335 s = snames[idx];
336 if (s == "Re")
337 s = "Ré";
338 break;
339 default:
340 s = names[idx];
341 break;
342 }
343 switch (noteCase) {
344 case NoteCaseType::LOWER: s = s.toLower(); break;
345 case NoteCaseType::UPPER: s = s.toUpper(); break;
346 case NoteCaseType::CAPITAL:
347 case NoteCaseType::AUTO:
348 default:
349 break;
350 }
351 }
352
353 //---------------------------------------------------------
354 // tpc2stepName
355 //---------------------------------------------------------
356
tpc2stepName(int tpc)357 QString tpc2stepName(int tpc)
358 {
359 const char names[] = "FCGDAEB";
360 return QString(names[(tpc - Tpc::TPC_MIN) % 7]);
361 }
362
363 // table of alternative spellings for one octave
364 // each entry is the TPC of the note
365 // tab1 does not contain double sharps
366 // tab2 does not contain double flats
367
368 static const int tab1[24] = {
369 14, 2, // 60 C Dbb
370 21, 9, // 61 C# Db
371 16, 4, // 62 D Ebb
372 23, 11, // 63 D# Eb
373 18, 6, // 64 E Fb
374 13, 1, // 65 F Gbb
375 20, 8, // 66 F# Gb
376 15, 3, // 67 G Abb
377 22, 10, // 68 G# Ab
378 17, 5, // 69 A Bbb
379 24, 12, // 70 A# Bb
380 19, 7, // 71 B Cb
381 };
382
383 static const int tab2[24] = {
384 26, 14, // 60 B# C
385 21, 9, // 61 C# Db
386 28, 16, // 62 C## D
387 23, 11, // 63 D# Eb
388 30, 18, // 64 D## E
389 25, 13, // 65 E# F
390 20, 8, // 66 F# Gb
391 27, 15, // 67 F## G
392 22, 10, // 68 G# Ab
393 29, 17, // 69 G## A
394 24, 12, // 70 A# Bb
395 31, 19, // 71 A## B
396 };
397
398 int intervalPenalty[13] = {
399 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 1, 3, 3
400 };
401
402 //---------------------------------------------------------
403 // enharmonicSpelling
404 //---------------------------------------------------------
405
406 static const int enharmonicSpelling[15][34] = {
407 {
408 //Ces f c g d a e b
409 1, 1, 1, 1, 1, 1, // bb
410 0, 0, 0, 0, 0, 0, 0, // b
411 1, 1, 1, 1, 1, 1, 1,
412 1, 1, 1, 1, 1, 1, 1, // #
413 1, 1, 1, 1, 1, 1, 1 // ##
414 },
415 {
416 //Ges f c g d a e b
417 1, 1, 1, 1, 1, 1, // bb
418 1, 0, 0, 0, 0, 0, 0, // b
419 0, 1, 1, 1, 1, 1, 1,
420 1, 1, 1, 1, 1, 1, 1, // #
421 1, 1, 1, 1, 1, 1, 1 // ##
422 },
423 {
424 //Des f c g d a e b
425 1, 1, 1, 1, 1, 1, // bb
426 1, 1, 0, 0, 0, 0, 0, // b
427 0, 0, 1, 1, 1, 1, 1,
428 1, 1, 1, 1, 1, 1, 1, // #
429 1, 1, 1, 1, 1, 1, 1 // ##
430 },
431 {
432 //As f c g d a e b
433 1, 1, 1, 1, 1, 1, // bb
434 1, 1, 0, 0, 0, 0, 0, // b
435 0, 0, 0, 0, 0, 0, 0,
436 0, 1, 1, 1, 1, 1, 1, // #
437 1, 1, 1, 1, 1, 1, 1 // ##
438 },
439 {
440 //Es f c g d a e b
441 1, 1, 1, 1, 1, 1, // bb
442 1, 1, 0, 0, 0, 0, 0, // b
443 0, 0, 0, 0, 1, 1, 1,
444 0, 0, 1, 1, 1, 1, 1, // #
445 1, 1, 1, 1, 1, 1, 1 // ##
446 },
447 {
448 //Bb f c g d a e b
449 1, 1, 1, 1, 1, 1, // bb
450 1, 1, 0, 0, 0, 0, 0, // b
451 0, 0, 0, 0, 0, 1, 1,
452 1, 0, 0, 1, 1, 1, 1, // # // (ws) penalty for f#
453 1, 1, 1, 1, 1, 1, 1 // ##
454 },
455 {
456 //F f c g d a e b // extra penalty for a# b
457 1, 1, 1, 1, 1, 1, // bb
458 1, 1, 0, 0, 0, 0, 0, // b
459 0, 0, 0, 0, 0, 0, 1,
460 0, 0, 0, 0, 1, 1, 1, // #
461 1, 1, 1, 1, 1, 1, 1 // ##
462 },
463 {
464 //C f c g d a e b
465 1, 1, 1, 1, 1, 1, // bb
466 1, 1, 0, 0, 0, 0, 0, // b
467 0, 0, 0, 0, 0, 0, 0,
468 0, 0, 0, 0, 0, 1, 1, // #
469 1, 1, 1, 1, 1, 1, 1 // ##
470 },
471 {
472 //G f c g d a e b
473 1, 1, 1, 1, 1, 1, // bb
474 1, 1, 1, 0, 0, 0, 0, // b
475 1, 0, 0, 0, 0, 0, 0,
476 0, 0, 0, 0, 0, 1, 1, // #
477 1, 1, 1, 1, 1, 1, 1 // ##
478 },
479 {
480 //D f c g d a e b
481 1, 1, 1, 1, 1, 1, // bb
482 1, 1, 1, 1, 0, 0, 0, // b
483 1, 1, 0, 0, 0, 0, 0,
484 0, 0, 0, 0, 0, 1, 1, // #
485 1, 1, 1, 1, 1, 1, 1 // ##
486 },
487 {
488 //A f c g d a e b
489 1, 1, 1, 1, 1, 1, // bb
490 1, 1, 1, 1, 1, 0, 0, // b
491 1, 1, 1, 0, 0, 0, 0,
492 0, 0, 0, 0, 0, 1, 1, // #
493 1, 1, 1, 1, 1, 1, 1 // ##
494 },
495 {
496 //E f c g d a e b
497 1, 1, 1, 1, 1, 1, // bb
498 1, 1, 1, 1, 1, 1, 0, // b
499 1, 1, 1, 1, 0, 0, 0,
500 0, 0, 0, 0, 0, 1, 1, // #
501 0, 0, 1, 1, 1, 1, 1 // ##
502 },
503 {
504 //H f c g d a e b
505 1, 1, 1, 1, 1, 1, // bb
506 1, 1, 1, 1, 1, 1, 1, // b
507 1, 1, 1, 1, 1, 0, 0,
508 0, 0, 0, 0, 0, 1, 1, // #
509 1, 1, 1, 1, 1, 1, 1 // ##
510 },
511 {
512 //Fis f c g d a e b
513 1, 1, 1, 1, 1, 1, // bb
514 1, 1, 1, 1, 1, 1, 1, // b
515 100, 1, 1, 1, 1, 1, 0,
516 0, 0, 0, 0, 0, 0, 0, // #
517 0, 1, 1, 1, 1, 1, 1 // ##
518 },
519 {
520 //Cis f c g d a e b
521 1, 1, 1, 1, 1, 1, // bb
522 1, 1, 0, 0, 0, 0, 0, // b //Fis
523 100, 1, 1, 1, 1, 0, 0,
524 0, 0, 0, 0, 0, 0, 0, // #
525 0, 0, 1, 1, 1, 1, 1 // ##
526 }
527 };
528
529 //---------------------------------------------------------
530 // penalty
531 //---------------------------------------------------------
532
penalty(int lof1,int lof2,int k)533 static int penalty(int lof1, int lof2, int k)
534 {
535 if (k < 0 || k >= 15)
536 qFatal("Illegal key %d >= 15", k);
537 Q_ASSERT(lof1 >= 0 && lof1 < 34);
538 Q_ASSERT(lof2 >= 0 && lof2 < 34);
539 int penalty = enharmonicSpelling[k][lof1] * 4 + enharmonicSpelling[k][lof2] * 4;
540 int distance = lof2 > lof1 ? lof2 - lof1 : lof1 - lof2;
541 if (distance > 12)
542 penalty += 3;
543 else
544 penalty += intervalPenalty[distance];
545 return penalty;
546 }
547
548 static const int WINDOW = 9;
549 #if 0 // yet(?) unused
550 static const int WINDOW_SHIFT = 3;
551 static const int ASIZE = 1024; // 2 ** WINDOW
552 #endif
553
554 //---------------------------------------------------------
555 // tpc
556 //---------------------------------------------------------
557
tpc(int idx,int pitch,int opt)558 int tpc(int idx, int pitch, int opt)
559 {
560 const int* tab;
561 if (opt < 0) {
562 tab = tab2;
563 opt *= -1;
564 }
565 else
566 tab = tab1;
567 int i = (pitch % 12) * 2 + ((opt & (1 << idx)) >> idx);
568 Q_ASSERT(i >= 0 && i < 24);
569 return tab[i];
570 }
571
572 //---------------------------------------------------------
573 // computeWindow
574 //---------------------------------------------------------
575
computeWindow(const std::vector<Note * > & notes,int start,int end)576 int computeWindow(const std::vector<Note*>& notes, int start, int end)
577 {
578 int p = 10000;
579 int idx = -1;
580 int pitch[10];
581 int key[10];
582
583 int i = start;
584 int k = 0;
585 while (i < end) {
586 pitch[k] = notes[i]->pitch() % 12;
587 Fraction tick = notes[i]->chord()->tick();
588 key[k] = int(notes[i]->staff()->key(tick)) + 7;
589 if (key[k] < 0 || key[k] > 14) {
590 qDebug("illegal key at tick %d: %d, window %d-%d",
591 tick.ticks(), key[k] - 7, start, end);
592 return 0;
593 // abort();
594 }
595 ++k;
596 ++i;
597 }
598
599 for (; k < 10; ++k) {
600 pitch[k] = pitch[k-1];
601 key[k] = key[k-1];
602 }
603
604 for (i = 0; i < 512; ++i) {
605 int pa = 0;
606 int pb = 0;
607 int l = pitch[0] * 2 + (i & 1);
608 Q_ASSERT(l >= 0 && l <= static_cast<int>(sizeof(tab1)/sizeof(*tab1)));
609 int lof1a = tab1[l];
610 int lof1b = tab2[l];
611
612 for (k = 1; k < 10; ++k) {
613 int l1 = pitch[k] * 2 + ((i & (1 << k)) >> k);
614 Q_ASSERT(l1 >= 0 && l1 <= static_cast<int>(sizeof(tab1)/sizeof(*tab1)));
615 int lof2a = tab1[l1];
616 int lof2b = tab2[l1];
617 pa += penalty(lof1a, lof2a, key[k]);
618 pb += penalty(lof1b, lof2b, key[k]);
619 lof1a = lof2a;
620 lof1b = lof2b;
621 }
622 if (pa < pb) {
623 if (pa < p) {
624 p = pa;
625 idx = i;
626 }
627 }
628 else {
629 if (pb < p) {
630 p = pb;
631 idx = i * -1;
632 }
633 }
634 }
635 /* qDebug("compute window\n ");
636 for (int i = 0; i < 10; ++i)
637 qDebug("%2d ", pitch[i]);
638 qDebug("\n ");
639 for (int i = 0; i < 10; ++i)
640 qDebug("%2d ", key[i]);
641 qDebug("\n ");
642 for (int i = 0; i < 10; ++i)
643 qDebug("%2d ", tpc(i, pitch[i], idx));
644 */
645 return idx;
646 }
647
648 //---------------------------------------------------------
649 // changeAllTpcs
650 //---------------------------------------------------------
651
changeAllTpcs(Note * n,int tpc1)652 void changeAllTpcs(Note* n, int tpc1)
653 {
654 if (!n)
655 return;
656 Interval v;
657 Fraction tick = n->chord() ? n->chord()->tick() : Fraction(-1,1);
658 if (n->part() && n->part()->instrument(tick)) {
659 v = n->part()->instrument(tick)->transpose();
660 v.flip();
661 }
662 int tpc2 = Ms::transposeTpc(tpc1, v, true);
663 n->undoChangeProperty(Pid::TPC1, tpc1);
664 n->undoChangeProperty(Pid::TPC2, tpc2);
665 }
666
667 //---------------------------------------------------------
668 // spell
669 //---------------------------------------------------------
670
spellNotelist(std::vector<Note * > & notes)671 void Score::spellNotelist(std::vector<Note*>& notes)
672 {
673 int n = int(notes.size());
674
675 int start = 0;
676 while (start < n) {
677 int end = start + WINDOW;
678 if (end > n)
679 end = n;
680 int opt = computeWindow(notes, start, end);
681 const int* tab;
682 if (opt < 0) {
683 tab = tab2;
684 opt *= -1;
685 }
686 else
687 tab = tab1;
688
689 if (start == 0) {
690 changeAllTpcs(notes[0], tab[(notes[0]->pitch() % 12) * 2 + (opt & 1)]);
691 if (n > 1)
692 changeAllTpcs(notes[1], tab[(notes[1]->pitch() % 12) * 2 + ((opt & 2)>>1)]);
693 if (n > 2)
694 changeAllTpcs(notes[2], tab[(notes[2]->pitch() % 12) * 2 + ((opt & 4)>>2)]);
695 }
696 if ((end - start) >= 6) {
697 changeAllTpcs(notes[start+3], tab[(notes[start+3]->pitch() % 12) * 2 + ((opt & 8) >> 3)]);
698 changeAllTpcs(notes[start+4], tab[(notes[start+4]->pitch() % 12) * 2 + ((opt & 16) >> 4)]);
699 changeAllTpcs(notes[start+5], tab[(notes[start+5]->pitch() % 12) * 2 + ((opt & 32) >> 5)]);
700 }
701 if (end == n) {
702 int n1 = end - start;
703 int k;
704 switch(n1 - 6) {
705 case 3:
706 k = end - start - 3;
707 changeAllTpcs(notes[end-3], tab[(notes[end-3]->pitch() % 12) * 2 + ((opt & (1<<k)) >> k)]);
708 Q_FALLTHROUGH();
709 case 2:
710 k = end - start - 2;
711 changeAllTpcs(notes[end-2], tab[(notes[end-2]->pitch() % 12) * 2 + ((opt & (1<<k)) >> k)]);
712 Q_FALLTHROUGH();
713 case 1:
714 k = end - start - 1;
715 changeAllTpcs(notes[end-1], tab[(notes[end-1]->pitch() % 12) * 2 + ((opt & (1<<k)) >> k)]);
716 }
717 break;
718 }
719 // advance to next window
720 start += 3;
721 }
722 }
723
724 //---------------------------------------------------------
725 // pitch2tpc2
726 //---------------------------------------------------------
727
728 // pitch2tpc2(pitch, false) replaced by pitch2tpc(pitch, Key::C, Prefer::FLATS)
729 // pitch2tpc2(pitch, true) replaced by pitch2tpc(pitch, Key::C, Prefer::SHARPS)
730
731 //---------------------------------------------------------
732 // pitch2tpc
733 // preferred pitch spelling depending on key
734 // key -7 to +7
735 //
736 // The value of prefer sets the preferred mix of flats and sharps
737 // for pitches that are non-diatonic in the key specified, by
738 // positioning the window along the tpc sequence.
739 //
740 // Scale tones are the range shown in [ ].
741 // A value of 8 (Prefer::FLATS) specifies 5b 2b 6b 3b 7b [4 1 5 2 6 3 7]
742 // A value of 11 (Prefer::NEAREST) specifies 3b 7b [4 1 5 2 6 3 7] 4# 1# 5#
743 // A value of 13 (Prefer::SHARPS) specifies [4 1 5 2 6 3 7] 4# 1# 5# 2# 6#
744 //
745 // Examples for Prefer::NEAREST (n indicates explicit natural):
746 // C major will use Eb Bb [F C G D A E B] F# C# G#.
747 // E major will use Gn Dn [A E B F# C# G# D#] A# E# B#.
748 // F# major will use An En [B F# C# G# D# A# E#] B# Fx Cx.
749 // Eb major will use Gb Db [Ab Eb Bb F C G D] An En Bn.
750 // Gb major will use Bbb Fb [Cb Gb Db Ab Eb Bb F] Cn Gn Dn.
751 //---------------------------------------------------------
752
pitch2tpc(int pitch,Key key,Prefer prefer)753 int pitch2tpc(int pitch, Key key, Prefer prefer)
754 {
755 return (pitch * 7 + 26 - (int(prefer) + int(key))) % 12 + (int(prefer) + int(key));
756 }
757
758 //---------------------------------------------------------
759 // pitch2absStepByKey
760 // absolute step (C0 = 0, D0 = 1, ... C1 = 7, D2 = 8, ...) for a pitch/tpc according to key
761 // if pAlter not null, returns in it the alteration with respect to the corresponding key degree (-3 to 3)
762 // (for instance, an F in GMaj yields alteration -1 i.e. 1 semitone below corresp. deg. of GMaj which is F#)
763 // key: between Key::MIN and Key::MAX
764 //---------------------------------------------------------
765
pitch2absStepByKey(int pitch,int tpc,Key key,int & alter)766 int pitch2absStepByKey(int pitch, int tpc, Key key, int& alter)
767 {
768 // sanitize input data
769 if (pitch < 0)
770 pitch += PITCH_DELTA_OCTAVE;
771 if (pitch > 127)
772 pitch -= PITCH_DELTA_OCTAVE;
773 if (tpc < Tpc::TPC_MIN)
774 tpc += TPC_DELTA_ENHARMONIC;
775 if (tpc > Tpc::TPC_MAX)
776 tpc -= TPC_DELTA_ENHARMONIC;
777 if (key < Key::MIN)
778 key += Key::DELTA_ENHARMONIC;
779 if (key > Key::MAX)
780 key -= Key::DELTA_ENHARMONIC;
781
782 int octave = (pitch - int(tpc2alter(tpc))) / PITCH_DELTA_OCTAVE;
783 int step = tpc2step(tpc);
784 alter = tpc2alterByKey(tpc, key);
785 return octave * STEP_DELTA_OCTAVE + step;
786 }
787
788 //---------------------------------------------------------
789 // absStep2pitchByKey
790 // the default pitch for the given absolute step in the given key
791 //---------------------------------------------------------
792
absStep2pitchByKey(int step,Key key)793 int absStep2pitchByKey(int step, Key key)
794 {
795 // sanitize input data
796 if (step < 0)
797 step += STEP_DELTA_OCTAVE;
798 if (step > 74)
799 step -= STEP_DELTA_OCTAVE;
800 if (key < Key::MIN)
801 key += Key::DELTA_ENHARMONIC;
802 if (key > Key::MAX)
803 key -= Key::DELTA_ENHARMONIC;
804
805 int octave = step / STEP_DELTA_OCTAVE;
806 int deltaPitch = step2deltaPitchByKey(step % STEP_DELTA_OCTAVE, key);
807 return octave * PITCH_DELTA_OCTAVE + deltaPitch;
808 }
809
810 //---------------------------------------------------------
811 // tpc2degree
812 // the scale degree of a TPC for a given Key
813 //---------------------------------------------------------
814
tpc2degree(int tpc,Key key)815 int tpc2degree(int tpc, Key key)
816 {
817 const QString names("CDEFGAB");
818 const QString scales("CGDAEBFCGDAEBFC");
819 QString scale = scales[int(key)+7];
820 QString stepName = tpc2stepName(tpc);
821 return (names.indexOf(stepName) - names.indexOf(scale) +28) % 7;
822 }
823
824 //---------------------------------------------------------
825 // tpcInterval
826 /// Finds tpc of a note based on an altered interval
827 /// from a starting note
828 //---------------------------------------------------------
829
tpcInterval(int startTpc,int interval,int alter)830 int tpcInterval(int startTpc, int interval, int alter)
831 {
832 Q_ASSERT(interval > 0);
833 static const int intervals[7] = {
834 // 1 2 3 4 5 6 7
835 0, 2, 4, -1, 1, 3, 5
836 };
837
838 int result = startTpc + intervals[(interval - 1) % 7] + alter * TPC_DELTA_SEMITONE;
839 //ensure that we don't have anything more than double sharp or double flat
840 //(I know, breaking some convention, but it's the best we can do for now)
841 while (result > Tpc::TPC_MAX)
842 result -= TPC_DELTA_ENHARMONIC;
843 while (result < Tpc::TPC_MIN)
844 result += TPC_DELTA_ENHARMONIC;
845
846 return result;
847 }
848
849 //---------------------------------------------------------
850 // step2pitchInterval
851 /// Finds pitch between notes a specified altered interval away
852 ///
853 /// For example:
854 /// step = 3, alter = 0 means major 3rd
855 /// step = 5, alter = -1 means diminished 5
856 /// step = 6, alter = 2 means augmented sixth
857 //---------------------------------------------------------
858
step2pitchInterval(int step,int alter)859 int step2pitchInterval(int step, int alter)
860 {
861 Q_ASSERT(step > 0);
862 static const int intervals[7] = {
863 // 1 2 3 4 5 6 7
864 0, 2, 4, 5, 7, 9, 11
865 };
866
867 return intervals[(step - 1) % 7] + alter;
868 }
869
870 //----------------------------------------------
871 // function2Tpc
872 /// might be temporary, just used to parse nashville notation now
873 ///
874 //----------------------------------------------
function2Tpc(const QString & s,Key key)875 int function2Tpc(const QString& s, Key key) {
876 //TODO - PHV: allow for alternate spellings
877 int alter = 0;
878 int step;
879 if (!s.isEmpty() && s[0].isDigit()) {
880 step = s[0].digitValue();
881 }
882 else if (s.size() > 1 && s[1].isDigit()) {
883 step = s[1].digitValue();
884 if (s[0] == 'b')
885 alter = -1;
886 else if (s[0] == '#')
887 alter = 1;
888 }
889 else
890 return Tpc::TPC_INVALID;
891
892 int keyTpc = int(key) + 14; //tpc of key (ex. F# major would be Tpc::F_S)
893 return tpcInterval(keyTpc, step, alter);
894 }
895
896 }
897
898