2 chord.cc -- implement Chord
4 source file of the GNU LilyPond music typesetter
6 (c) 1999 Jan Nieuwenhuizen <janneke@gnu.org>
12 // doesn't seem common, and we should know about this during parsing
13 // #define INVERSION_ADDED_AS_BASE 1
15 Chord::Chord (Array
<Musical_pitch
> pitch_arr
)
17 pitch_arr_
= pitch_arr
;
21 rebuild_transpose (Musical_pitch tonic
, Array
<Musical_pitch
>* pitch_arr_p
)
23 for (int i
= 0; i
< pitch_arr_p
->size (); i
++)
25 Musical_pitch p
= tonic
;
26 Musical_pitch q
= (*pitch_arr_p
)[i
];
27 // duh, c7 should mean <c bes>
28 if (q
.notename_i_
== 6)
31 (*pitch_arr_p
)[i
] = p
;
33 pitch_arr_p
->sort (Musical_pitch::compare
);
37 find_pitch_i (Array
<Musical_pitch
> const* pitch_arr_p
, Musical_pitch p
)
39 for (int i
= 0; i
< pitch_arr_p
->size (); i
++)
40 if (p
== (*pitch_arr_p
)[i
])
46 find_notename_i (Array
<Musical_pitch
> const* pitch_arr_p
, Musical_pitch p
)
48 int i
= find_pitch_i (pitch_arr_p
, p
);
51 for (int i
= 0; i
< pitch_arr_p
->size (); i
++)
53 p
.octave_i_
= (*pitch_arr_p
)[i
].octave_i_
;
54 if (p
== (*pitch_arr_p
)[i
])
62 trap (NL) != trap(english)
65 trap_i (Musical_pitch tonic
, Musical_pitch p
)
67 int i
= p
.notename_i_
- tonic
.notename_i_
68 + (p
.octave_i_
- tonic
.octave_i_
) * 7;
75 static Array
<Musical_pitch
>
76 missing_triads_pitch_arr (Array
<Musical_pitch
>const* pitch_arr_p
)
78 Array
<Musical_pitch
> triads
;
80 /* is the third c-e, d-f, etc. small or large? */
81 int minormajor_a
[] = {0, -1, -1, 0,0,-1,-1};
82 for (int i
=0; i
< 7; i
++)
83 triads
.push (Musical_pitch( 2, minormajor_a
[i
]));
85 Musical_pitch tonic
= (*pitch_arr_p
)[0];
86 Musical_pitch last
= tonic
;
87 Array
<Musical_pitch
> missing_arr
;
89 for (int i
= 0; i
< pitch_arr_p
->size ();)
91 Musical_pitch p
= (*pitch_arr_p
)[i
];
92 int trap
= trap_i (tonic
, p
);
93 if (last
.notename_i_
== p
.notename_i_
)
94 last
.transpose (triads
[(last
.notename_i_
- tonic
.notename_i_
+ 7) % 7]);
95 if (trap
> trap_i (tonic
, last
))
97 while (trap
> trap_i (tonic
, last
))
99 if ((last
.notename_i_
- tonic
.notename_i_
+ 7) % 7 == 6)
101 Musical_pitch special_seven
= last
;
102 Musical_pitch
lower (0, -1);
103 special_seven
.transpose (lower
);
104 missing_arr
.push (special_seven
);
108 missing_arr
.push (last
);
110 last
.transpose (triads
[(last
.notename_i_
- tonic
.notename_i_
+ 7) % 7]);
123 construct from parser output
125 Chord::Chord (Musical_pitch tonic
, Array
<Musical_pitch
>* add_arr_p
, Array
<Musical_pitch
>* sub_arr_p
, Musical_pitch
* inversion_p
)
127 rebuild_transpose (tonic
, add_arr_p
);
128 rebuild_transpose (tonic
, sub_arr_p
);
130 Musical_pitch fifth
= tonic
;
131 fifth
.transpose (Musical_pitch (2));
132 fifth
.transpose (Musical_pitch (2, -1));
135 remove double adds (urg: sus4)
137 for (int i
= add_arr_p
->size () - 1; i
>= 0 ; i
--)
139 int j
= ::find_pitch_i (add_arr_p
, (*add_arr_p
)[i
]);
140 if ((j
!= -1) && (i
!= j
))
147 default chord includes upto 5: <1, 3, 5>
149 add_arr_p
->insert (tonic
, 0);
150 Array
<Musical_pitch
> tmp
= *add_arr_p
;
151 int highest_trap
= trap_i (tonic
, tmp
.top ());
152 if (highest_trap
< 5)
158 Array
<Musical_pitch
> missing_arr
= missing_triads_pitch_arr (&tmp
);
159 if (highest_trap
< 5)
160 missing_arr
.push (fifth
);
163 if additions include some 3, don't add third
165 Musical_pitch third
= tonic
;
166 third
.transpose (Musical_pitch (2));
167 if (::find_notename_i (add_arr_p
, third
) != -1)
169 int i
= ::find_pitch_i (&missing_arr
, third
);
175 if additions include 4, assume sus4 and don't add third implicitely
176 C-sus (4) = c f g (1 4 5)
178 Musical_pitch sus
= tonic
;
179 sus
.transpose (Musical_pitch (3));
180 if (::find_pitch_i (add_arr_p
, sus
) != -1)
182 int i
= ::find_pitch_i (&missing_arr
, third
);
188 if additions include some 5, don't add fifth
190 if (::find_notename_i (add_arr_p
, fifth
) != -1)
192 int i
= ::find_pitch_i (&missing_arr
, fifth
);
199 complete the list of triads to be added
201 add_arr_p
->concat (missing_arr
);
202 add_arr_p
->sort (Musical_pitch::compare
);
205 add all that aren't subtracted
207 for (int i
= 0; i
< add_arr_p
->size (); i
++)
209 Musical_pitch p
= (*add_arr_p
)[i
];
211 for (; j
< sub_arr_p
->size (); j
++)
212 if (p
== (*sub_arr_p
)[j
])
218 if (j
== sub_arr_p
->size ())
222 pitch_arr_
.sort (Musical_pitch::compare
);
224 for (int i
= 0; i
< sub_arr_p
->size (); i
++)
225 warning (_f ("invalid subtraction: not part of chord: %s",
226 (*sub_arr_p
)[i
].str ()));
231 for (; i
< pitch_arr_
.size (); i
++)
233 if ((pitch_arr_
[i
].notename_i_
== inversion_p
->notename_i_
)
234 && (pitch_arr_
[i
].accidental_i_
== inversion_p
->accidental_i_
))
237 if (i
== pitch_arr_
.size ())
239 warning (_f ("invalid inversion pitch: not part of chord: %s",
240 inversion_p
->str ()));
244 #if INVERSION_ADDED_AS_BASE
245 pitch_arr_
.insert (pitch_arr_
[i
], 0);
246 rebuild_with_bass (0);
248 rebuild_with_bass (i
);
257 Chord::find_additions_and_subtractions(Array
<Musical_pitch
>* add_arr_p
, Array
<Musical_pitch
>* sub_arr_p
)
259 Musical_pitch tonic
= pitch_arr_
[0];
261 all the triads that should be there
263 Array
<Musical_pitch
> all_arr
;
264 all_arr
.push (tonic
);
265 all_arr
.push (pitch_arr_
.top ());
266 all_arr
.concat (missing_triads_pitch_arr (&all_arr
));
267 all_arr
.sort (Musical_pitch::compare
);
271 while ((i
< all_arr
.size ()) || (j
< pitch_arr_
.size ()))
273 i
= i
<? all_arr
.size () - 1;
274 j
= j
<? pitch_arr_
.size () - 1;
275 Musical_pitch a
= all_arr
[i
];
276 Musical_pitch p
= pitch_arr_
[j
];
282 else if ((p
< a
) || (p
.notename_i_
== a
.notename_i_
))
295 add highest addition, because it names chord
297 if (trap_i (tonic
, pitch_arr_
.top () > 5))
298 add_arr_p
->push (pitch_arr_
.top ());
302 Chord::banter_str (Musical_pitch
* inversion
) const
304 Musical_pitch tonic
= pitch_arr_
[0];
306 //urg, should do translation in scheme.
307 char const *acc
[] = {"\\textflat\\textflat ", "\\textflat ", "", "\\textsharp " , "\\textsharp\\textsharp "};
308 String tonic_str
= tonic
.str ();
309 tonic_str
= tonic_str
.left_str (1).upper_str ()
310 + acc
[tonic
.accidental_i_
+ 2];
312 Array
<Musical_pitch
> add_arr
;
313 Array
<Musical_pitch
> sub_arr
;
314 find_additions_and_subtractions (&add_arr
, &sub_arr
);
317 Array
<Musical_pitch
> scale
;
318 for (int i
=0; i
< 7; i
++)
319 scale
.push (Musical_pitch (i
));
321 // 7 always means 7-...
322 // scale.push (Musical_pitch (6, -1)); // b
324 rebuild_transpose (tonic
, &scale
);
326 bool has3m_b
= false;
330 for (int i
= 0; i
< add_arr
.size (); i
++)
332 Musical_pitch p
= add_arr
[i
];
333 int trap
= trap_i (tonic
, p
);
336 int accidental
= p
.accidental_i_
- scale
[(trap
- 1) % 7].accidental_i_
;
337 if ((trap
== 3) && (accidental
== -1))
343 || (!(trap
% 2) || ((i
+ 1 == add_arr
.size ()) && (trap
> 5))))
346 if ((trap
== 7) && (accidental
== 1))
350 str
+= to_str (trap
);
352 str
+= accidental
< 0 ? "-" : "+";
358 for (int i
= 0; i
< sub_arr
.size (); i
++)
360 Musical_pitch p
= sub_arr
[i
];
361 int trap
= trap_i (tonic
, p
);
363 if chord has 3-, assume minor and don't display 'no3'
364 if additions include 4, assume sus4 and don't display 'no3'
366 if (!((trap
== 3) && (has3m_b
|| has4_b
)))
368 str
+= sep_str
+ "no" + to_str (trap
);
373 String inversion_str
;
376 inversion_str
= inversion
->str ();
377 inversion_str
= "/" + inversion_str
.left_str (1).upper_str ()
378 + acc
[inversion
->accidental_i_
+ 2];
382 return tonic_str
+ "$^{" + str
+ "}$" + inversion_str
;
386 Chord::find_notename_i (Musical_pitch p
) const
388 return ::find_notename_i (&pitch_arr_
, p
);
392 Chord::find_pitch_i (Musical_pitch p
) const
394 return ::find_pitch_i (&pitch_arr_
, p
);
398 Chord::find_tonic_i () const
403 first try: base of longest line of triads
407 for (int i
= 0; i
< pitch_arr_
.size (); i
++)
410 int last_i
= pitch_arr_
[i
% pitch_arr_
.size ()].notename_i_
;
412 for (; j
< pitch_arr_
.size (); j
++)
414 int cur_i
= pitch_arr_
[(i
+ j
+ 1) % pitch_arr_
.size ()].notename_i_
;
415 int gap
= cur_i
- last_i
;
424 if (j
- no_triad_i
> longest_i
)
426 longest_i
= j
- no_triad_i
;
432 second try: note after biggest gap
437 for (int i
= 0; i
< pitch_arr_
.size (); i
++)
439 int gap
= pitch_arr_
[i
].notename_i_
440 - pitch_arr_
[(i
- 1 + pitch_arr_
.size ())
441 % pitch_arr_
.size ()].notename_i_
;
455 Chord::rebuild_from_base (int base_i
)
457 assert (base_i
>= 0);
458 Musical_pitch
last (0, 0, -5);
459 Array
<Musical_pitch
> new_arr
;
460 for (int i
= 0; i
< pitch_arr_
.size (); i
++)
462 Musical_pitch p
= pitch_arr_
[(base_i
+ i
) % pitch_arr_
.size ()];
465 p
.octave_i_
= last
.octave_i_
;
472 pitch_arr_
= new_arr
;
476 Chord::rebuild_insert_inversion (int tonic_i
)
478 assert (tonic_i
> 0);
479 #if INVERSION_ADDED_AS_BASE
480 // inversion was added; don't insert
481 Musical_pitch inversion
= pitch_arr_
.get (0);
484 Musical_pitch inversion
= pitch_arr_
.get (0);
485 rebuild_from_base (tonic_i
- 1);
486 if (pitch_arr_
.size ())
488 inversion
.octave_i_
= pitch_arr_
[0].octave_i_
- 1;
489 while (inversion
< pitch_arr_
[0])
490 inversion
.octave_i_
++;
492 for (int i
= 0; i
< pitch_arr_
.size (); i
++)
493 if (pitch_arr_
[i
] > inversion
)
495 pitch_arr_
.insert (inversion
, i
);
502 Chord::rebuild_with_bass (int bass_i
)
504 assert (bass_i
>= 0);
505 Musical_pitch inversion
= pitch_arr_
.get (bass_i
);
506 // is lowering fine, or should others be raised?
507 if (pitch_arr_
.size ())
508 while (inversion
> pitch_arr_
[0])
509 inversion
.octave_i_
--;
510 pitch_arr_
.insert (inversion
, 0);