]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord.cc
release: 1.1.68
[lilypond.git] / lily / chord.cc
1 /*
2   chord.cc -- implement Chord
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1999 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 /*
10   FIXME:
11
12   A triad is a chord of three tones, and not an interval of a third.
13  */
14
15 #include "chord.hh"
16 #include "warn.hh"
17
18 // doesn't seem common, and we should know about this during parsing
19 // #define INVERSION_ADDED_AS_BASE 1
20
21 Chord::Chord (Array<Musical_pitch> pitch_arr)
22 {
23   pitch_arr_ = pitch_arr;
24 }
25
26 static void
27 rebuild_transpose (Musical_pitch tonic, Array<Musical_pitch>* pitch_arr_p)
28 {
29   for (int i = 0; i < pitch_arr_p->size (); i++)
30     {
31       Musical_pitch p = tonic;
32       Musical_pitch q = (*pitch_arr_p)[i];
33       // duh, c7 should mean <c bes>
34       if (q.notename_i_ == 6)
35         q.accidental_i_--;
36       p.transpose (q);
37       (*pitch_arr_p)[i] = p;
38     }
39   pitch_arr_p->sort (Musical_pitch::compare);
40 }
41
42 static int
43 find_pitch_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
44 {
45   for (int i = 0; i < pitch_arr_p->size (); i++)
46     if (p == (*pitch_arr_p)[i])
47       return i;
48   return -1;
49 }
50
51 static int
52 find_notename_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
53 {
54   int i = find_pitch_i (pitch_arr_p, p);
55   if (i == -1)
56     {
57       for (int i = 0; i < pitch_arr_p->size (); i++)
58         {
59           p.octave_i_ = (*pitch_arr_p)[i].octave_i_;
60           if (p == (*pitch_arr_p)[i])
61             return i;
62         }
63     }
64   return i;
65 }
66
67 /*
68   trap (NL) != trap(english)
69  */
70 static int
71 trap_i (Musical_pitch tonic, Musical_pitch p)
72 {
73   int i = p.notename_i_ - tonic.notename_i_
74     + (p.octave_i_ - tonic.octave_i_) * 7;
75   while (i < 0)
76     i += 7;
77   i++;
78   return i;
79 }
80
81 static Array<Musical_pitch>
82 missing_triads_pitch_arr (Array<Musical_pitch>const* pitch_arr_p)
83 {
84   Array<Musical_pitch> triads;
85
86   /* is the third c-e, d-f, etc. small or large? */
87   int minormajor_a[] = {0, -1, -1, 0,0,-1,-1};
88   for (int i=0; i < 7; i++)
89     triads.push (Musical_pitch( 2, minormajor_a[i]));
90
91   Musical_pitch tonic = (*pitch_arr_p)[0];
92   Musical_pitch last = tonic;
93   Array<Musical_pitch> missing_arr;
94
95   for (int i = 0; i < pitch_arr_p->size ();)
96     {
97       Musical_pitch p = (*pitch_arr_p)[i];
98       int trap = trap_i (tonic, p);
99       if (last.notename_i_ == p.notename_i_)
100         last.transpose (triads[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
101       if (trap > trap_i (tonic, last))
102         {
103           while (trap > trap_i (tonic, last))
104             {
105               if ((last.notename_i_ - tonic.notename_i_ + 7) % 7 == 6)
106                 {
107                   Musical_pitch special_seven = last;
108                   Musical_pitch lower (0, -1);
109                   special_seven.transpose (lower);
110                   missing_arr.push (special_seven);
111                 }
112               else
113                 {
114                   missing_arr.push (last);
115                 }
116               last.transpose (triads[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
117             }
118         }
119       else
120         {
121           i++;
122         }
123     }
124   return missing_arr;
125 }
126
127
128 /*
129   construct from parser output
130 */
131 Chord::Chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p)
132 {
133   rebuild_transpose (tonic, add_arr_p);
134   rebuild_transpose (tonic, sub_arr_p);
135
136   Musical_pitch fifth = tonic;
137   fifth.transpose (Musical_pitch (2));
138   fifth.transpose (Musical_pitch (2, -1));
139
140   /*
141     remove double adds (urg: sus4)
142    */
143   for (int i = add_arr_p->size () - 1; i >= 0 ; i--)
144     {
145       int j = ::find_pitch_i (add_arr_p, (*add_arr_p)[i]);
146       if ((j != -1) && (i != j))
147         {
148             add_arr_p->get (i);
149         } 
150     }
151
152   /*
153     default chord includes upto 5: <1, 3, 5>
154    */
155   add_arr_p->insert (tonic, 0);
156   Array<Musical_pitch> tmp = *add_arr_p;
157   int highest_trap = trap_i (tonic, tmp.top ());
158   if (highest_trap < 5)
159     tmp.push (fifth);
160
161   /*
162     find missing triads
163    */
164   Array<Musical_pitch> missing_arr = missing_triads_pitch_arr (&tmp);
165   if (highest_trap < 5)
166     missing_arr.push (fifth);
167
168   /*
169     if additions include some 3, don't add third
170    */
171   Musical_pitch third = tonic;
172   third.transpose (Musical_pitch (2));
173   if (::find_notename_i (add_arr_p, third) != -1)
174     {
175       int i = ::find_pitch_i (&missing_arr, third);
176       if (i != -1)
177         missing_arr.get (i);
178     }
179   
180   /*
181     if additions include 4, assume sus4 and don't add third implicitely
182      C-sus (4) = c f g (1 4 5)
183    */
184   Musical_pitch sus = tonic;
185   sus.transpose (Musical_pitch (3));
186   if (::find_pitch_i (add_arr_p, sus) != -1)
187     {
188       int i = ::find_pitch_i (&missing_arr, third);
189       if (i != -1)
190         missing_arr.get (i);
191     }
192
193   /*
194     if additions include some 5, don't add fifth
195    */
196   if (::find_notename_i (add_arr_p, fifth) != -1)
197     {
198       int i = ::find_pitch_i (&missing_arr, fifth);
199       if (i != -1)
200         missing_arr.get (i);
201     }
202   
203   
204   /*
205     complete the list of triads to be added
206    */
207   add_arr_p->concat (missing_arr);
208   add_arr_p->sort (Musical_pitch::compare);
209
210   /*
211    add all that aren't subtracted
212    */
213   for (int i = 0; i < add_arr_p->size (); i++)
214     {
215       Musical_pitch p = (*add_arr_p)[i];
216       int j = 0;
217       for (; j < sub_arr_p->size (); j++)
218         if (p == (*sub_arr_p)[j])
219           {
220             sub_arr_p->del (j);
221             j = -1;
222             break;
223           }
224       if (j == sub_arr_p->size ())
225         pitch_arr_.push (p);
226     }
227
228   pitch_arr_.sort (Musical_pitch::compare);
229
230   for (int i = 0; i < sub_arr_p->size (); i++)
231     warning (_f ("invalid subtraction: not part of chord: %s",
232                  (*sub_arr_p)[i].str ()));
233
234   if (inversion_p)
235     {
236       int i = 0;
237       for (; i < pitch_arr_.size (); i++)
238         {
239           if ((pitch_arr_[i].notename_i_ == inversion_p->notename_i_)
240               && (pitch_arr_[i].accidental_i_ == inversion_p->accidental_i_))
241             break;
242         }
243       if (i == pitch_arr_.size ())
244         {
245           warning (_f ("invalid inversion pitch: not part of chord: %s",
246                        inversion_p->str ()));
247         }
248       else
249         {
250 #if INVERSION_ADDED_AS_BASE
251           pitch_arr_.insert (pitch_arr_[i], 0);
252           rebuild_with_bass (0);
253 #else
254           rebuild_with_bass (i);
255 #endif
256           
257         }
258       delete inversion_p;
259     }
260 }
261
262 void
263 Chord::find_additions_and_subtractions(Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p)
264 {
265   Musical_pitch tonic = pitch_arr_[0];
266   /*
267     construct an array of triads for a normal chord
268    */
269   Array<Musical_pitch> all_arr;
270   all_arr.push (tonic);
271   all_arr.push (pitch_arr_.top ());
272   all_arr.concat (missing_triads_pitch_arr (&all_arr));
273   all_arr.sort (Musical_pitch::compare);
274   
275   int i = 0;
276   int j = 0;
277   while ((i < all_arr.size ()) || (j < pitch_arr_.size ()))
278     {
279       Musical_pitch a = all_arr [i <? all_arr.size () - 1];
280       Musical_pitch p = pitch_arr_ [j <? pitch_arr_.size () - 1];
281       /*
282         this pitch is present: do nothing, check next
283        */
284       if (a == p)
285         {
286           i++;
287           j++;
288         }
289       /*
290         found an extra pitch: chord addition
291        */
292       else if ((p < a) || (p.notename_i_ == a.notename_i_))
293         {
294           add_arr_p->push (p);
295           (j < pitch_arr_.size ()) ? j++ : i++;
296         }
297       /*
298         a triad is missing: chord subtraction
299        */
300       else
301         {
302           sub_arr_p->push (a);
303           (i < all_arr.size ()) ? i++ : j++;
304         }
305     }
306       
307   /*
308     add highest addition, because it names chord
309     (1, 3 and) 5 not an addition: part of normal chord
310    */
311   if (trap_i (tonic, pitch_arr_.top () > 5))
312     add_arr_p->push (pitch_arr_.top ());
313 }
314
315 String
316 Chord::banter_str (Musical_pitch* inversion) const
317 {
318   Musical_pitch tonic = pitch_arr_[0];
319
320   //urg, should do translation in scheme.
321   char const *acc[] = {"\\textflat\\textflat ", "\\textflat ", "", "\\textsharp " , "\\textsharp\\textsharp "};
322   String tonic_str = tonic.str ();
323   tonic_str = tonic_str.left_str (1).upper_str ()
324     + acc[tonic.accidental_i_ + 2];
325
326   Array<Musical_pitch> add_arr;
327   Array<Musical_pitch> sub_arr;
328   find_additions_and_subtractions (&add_arr, &sub_arr);
329                            
330
331   Array<Musical_pitch> scale;
332   for (int i=0; i < 7; i++)
333     scale.push (Musical_pitch (i));
334
335   // 7 always means 7-...
336   //  scale.push (Musical_pitch (6, -1)); // b
337
338   rebuild_transpose (tonic, &scale);
339   
340   bool has3m_b = false;
341   bool has4_b = false;
342   String str;
343   String sep_str;
344   for (int i = 0; i < add_arr.size (); i++)
345     {
346       Musical_pitch p = add_arr[i];
347       int trap = trap_i (tonic, p);
348       if (trap == 4)
349         has4_b = true;
350       int accidental = p.accidental_i_ - scale[(trap - 1) % 7].accidental_i_;
351       if ((trap == 3) && (accidental == -1))
352         {
353           tonic_str += "m";
354           has3m_b = true;
355         }
356       else if (accidental
357                || (!(trap % 2) || ((i + 1 == add_arr.size ()) && (trap > 5))))
358         {
359           str += sep_str;
360           if ((trap == 7) && (accidental == 1))
361             str += "maj7";
362           else
363             {
364               str += to_str (trap);
365               if (accidental)
366                 str += accidental < 0 ? "-" : "+";
367             }
368           sep_str = "/";
369         }
370     }
371
372   for (int i = 0; i < sub_arr.size (); i++)
373     {
374       Musical_pitch p = sub_arr[i];
375       int trap = trap_i (tonic, p);
376       /*
377         if chord has 3-, assume minor and don't display 'no3'
378         if additions include 4, assume sus4 and don't display 'no3'
379       */
380       if (!((trap == 3) && (has3m_b || has4_b)))
381         {
382           str += sep_str + "no" + to_str (trap);
383           sep_str = "/";
384         }
385     }
386
387   String inversion_str;
388   if (inversion)
389     {
390       inversion_str = inversion->str ();
391       inversion_str = "/" + inversion_str.left_str (1).upper_str ()
392         + acc[inversion->accidental_i_ + 2];
393
394     }
395
396   return tonic_str + "$^{" + str + "}$" + inversion_str;
397 }
398
399 int
400 Chord::find_notename_i (Musical_pitch p) const
401 {
402   return ::find_notename_i (&pitch_arr_, p);
403 }
404
405 int
406 Chord::find_pitch_i (Musical_pitch p) const
407 {
408   return ::find_pitch_i (&pitch_arr_, p);
409 }
410
411 int
412 Chord::find_tonic_i () const
413 {
414   /*
415     find tonic
416     
417     first try: base of longest line of triads
418    */
419   int tonic_i = 0;
420   int longest_i = 0;
421   for (int i = 0; i < pitch_arr_.size (); i++)
422     {
423       int no_triad_i = 0;
424       int last_i = pitch_arr_[i % pitch_arr_.size ()].notename_i_;
425       int j = 0;
426       for (; j < pitch_arr_.size (); j++)
427         {
428           int cur_i = pitch_arr_[(i + j + 1) % pitch_arr_.size ()].notename_i_;
429           int gap = cur_i - last_i;
430           while (gap < 0)
431             gap += 7;
432           gap %= 7;
433           if (gap == 2)
434             last_i = cur_i;
435           else
436             no_triad_i++;
437         }
438       if (j - no_triad_i > longest_i)
439         {
440           longest_i = j - no_triad_i;
441           tonic_i = i;
442         }
443     }
444
445   /*
446     second try: note after biggest gap
447    */
448   int biggest_i = 0;
449   //  if (longest_i)
450   if (longest_i <= 1)
451     for (int i = 0; i < pitch_arr_.size (); i++)
452       {
453         int gap = pitch_arr_[i].notename_i_
454           - pitch_arr_[(i - 1 + pitch_arr_.size ()) 
455           % pitch_arr_.size ()].notename_i_;
456         while (gap < 0)
457           gap += 7;
458         gap %= 7;
459         if (gap > biggest_i)
460           {
461             biggest_i = gap;
462             tonic_i = i;
463           }
464       }
465   return tonic_i;
466 }
467
468 void
469 Chord::rebuild_from_base (int base_i)
470 {
471   assert (base_i >= 0);
472   Musical_pitch last (0, 0, -5);
473   Array<Musical_pitch> new_arr;
474   for (int i = 0; i < pitch_arr_.size (); i++)
475     {
476       Musical_pitch p = pitch_arr_[(base_i + i) % pitch_arr_.size ()];
477       if (p < last)
478         {
479           p.octave_i_ = last.octave_i_;
480           if (p < last)
481             p.octave_i_++;
482         }
483       new_arr.push (p);
484       last = p;
485     }
486   pitch_arr_ = new_arr;
487 }
488
489 void
490 Chord::rebuild_insert_inversion (int tonic_i)
491 {
492   assert (tonic_i > 0);
493 #if INVERSION_ADDED_AS_BASE
494   // inversion was added; don't insert
495   Musical_pitch inversion = pitch_arr_.get (0);
496   (void)inversion;
497 #else
498   Musical_pitch inversion = pitch_arr_.get (0);
499   rebuild_from_base (tonic_i - 1);
500   if (pitch_arr_.size ())
501     {
502       inversion.octave_i_ = pitch_arr_[0].octave_i_ - 1;
503       while (inversion < pitch_arr_[0])
504         inversion.octave_i_++;
505     }
506   for (int i = 0; i < pitch_arr_.size (); i++)
507     if (pitch_arr_[i] > inversion)
508       {
509         pitch_arr_.insert (inversion, i);
510         break;
511       }
512 #endif
513 }
514
515 void
516 Chord::rebuild_with_bass (int bass_i)
517 {
518   assert (bass_i >= 0);
519   Musical_pitch inversion = pitch_arr_.get (bass_i);
520   // is lowering fine, or should others be raised?
521   if (pitch_arr_.size ())
522     while (inversion > pitch_arr_[0])
523       inversion.octave_i_--;
524   pitch_arr_.insert (inversion, 0);
525 }