lilypond-1.1.67
[lilypond.git] / lily / chord.cc
blob7a42576502ce3554f20013c0548561b824291824
1 /*
2 chord.cc -- implement Chord
4 source file of the GNU LilyPond music typesetter
6 (c) 1999 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
9 #include "chord.hh"
10 #include "warn.hh"
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;
20 static void
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)
29 q.accidental_i_--;
30 p.transpose (q);
31 (*pitch_arr_p)[i] = p;
33 pitch_arr_p->sort (Musical_pitch::compare);
36 static int
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])
41 return i;
42 return -1;
45 static int
46 find_notename_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
48 int i = find_pitch_i (pitch_arr_p, p);
49 if (i == -1)
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])
55 return i;
58 return i;
62 trap (NL) != trap(english)
64 static int
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;
69 while (i < 0)
70 i += 7;
71 i++;
72 return i;
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);
106 else
108 missing_arr.push (last);
110 last.transpose (triads[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
113 else
115 i++;
118 return missing_arr;
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))
142 add_arr_p->get (i);
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)
153 tmp.push (fifth);
156 find missing triads
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);
170 if (i != -1)
171 missing_arr.get (i);
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);
183 if (i != -1)
184 missing_arr.get (i);
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);
193 if (i != -1)
194 missing_arr.get (i);
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];
210 int j = 0;
211 for (; j < sub_arr_p->size (); j++)
212 if (p == (*sub_arr_p)[j])
214 sub_arr_p->del (j);
215 j = -1;
216 break;
218 if (j == sub_arr_p->size ())
219 pitch_arr_.push (p);
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 ()));
228 if (inversion_p)
230 int i = 0;
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_))
235 break;
237 if (i == pitch_arr_.size ())
239 warning (_f ("invalid inversion pitch: not part of chord: %s",
240 inversion_p->str ()));
242 else
244 #if INVERSION_ADDED_AS_BASE
245 pitch_arr_.insert (pitch_arr_[i], 0);
246 rebuild_with_bass (0);
247 #else
248 rebuild_with_bass (i);
249 #endif
252 delete inversion_p;
256 void
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);
269 int i = 0;
270 int j = 0;
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];
277 if (a == p)
279 i++;
280 j++;
282 else if ((p < a) || (p.notename_i_ == a.notename_i_))
284 add_arr_p->push (p);
285 j++;
287 else
289 sub_arr_p->push (a);
290 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 ());
301 String
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;
327 bool has4_b = false;
328 String str;
329 String sep_str;
330 for (int i = 0; i < add_arr.size (); i++)
332 Musical_pitch p = add_arr[i];
333 int trap = trap_i (tonic, p);
334 if (trap == 4)
335 has4_b = true;
336 int accidental = p.accidental_i_ - scale[(trap - 1) % 7].accidental_i_;
337 if ((trap == 3) && (accidental == -1))
339 tonic_str += "m";
340 has3m_b = true;
342 else if (accidental
343 || (!(trap % 2) || ((i + 1 == add_arr.size ()) && (trap > 5))))
345 str += sep_str;
346 if ((trap == 7) && (accidental == 1))
347 str += "maj7";
348 else
350 str += to_str (trap);
351 if (accidental)
352 str += accidental < 0 ? "-" : "+";
354 sep_str = "/";
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);
369 sep_str = "/";
373 String inversion_str;
374 if (inversion)
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
401 find tonic
403 first try: base of longest line of triads
405 int tonic_i = 0;
406 int longest_i = 0;
407 for (int i = 0; i < pitch_arr_.size (); i++)
409 int no_triad_i = 0;
410 int last_i = pitch_arr_[i % pitch_arr_.size ()].notename_i_;
411 int j = 0;
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;
416 while (gap < 0)
417 gap += 7;
418 gap %= 7;
419 if (gap == 2)
420 last_i = cur_i;
421 else
422 no_triad_i++;
424 if (j - no_triad_i > longest_i)
426 longest_i = j - no_triad_i;
427 tonic_i = i;
432 second try: note after biggest gap
434 int biggest_i = 0;
435 // if (longest_i)
436 if (longest_i <= 1)
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_;
442 while (gap < 0)
443 gap += 7;
444 gap %= 7;
445 if (gap > biggest_i)
447 biggest_i = gap;
448 tonic_i = i;
451 return tonic_i;
454 void
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 ()];
463 if (p < last)
465 p.octave_i_ = last.octave_i_;
466 if (p < last)
467 p.octave_i_++;
469 new_arr.push (p);
470 last = p;
472 pitch_arr_ = new_arr;
475 void
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);
482 (void)inversion;
483 #else
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);
496 break;
498 #endif
501 void
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);