]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord.cc
release: 1.1.67
[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 #include "chord.hh"
10 #include "warn.hh"
11
12 // doesn't seem common, and we should know about this during parsing
13 // #define INVERSION_ADDED_AS_BASE 1
14
15 Chord::Chord (Array<Musical_pitch> pitch_arr)
16 {
17   pitch_arr_ = pitch_arr;
18 }
19
20 static void
21 rebuild_transpose (Musical_pitch tonic, Array<Musical_pitch>* pitch_arr_p)
22 {
23   for (int i = 0; i < pitch_arr_p->size (); i++)
24     {
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;
32     }
33   pitch_arr_p->sort (Musical_pitch::compare);
34 }
35
36 static int
37 find_pitch_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
38 {
39   for (int i = 0; i < pitch_arr_p->size (); i++)
40     if (p == (*pitch_arr_p)[i])
41       return i;
42   return -1;
43 }
44
45 static int
46 find_notename_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
47 {
48   int i = find_pitch_i (pitch_arr_p, p);
49   if (i == -1)
50     {
51       for (int i = 0; i < pitch_arr_p->size (); i++)
52         {
53           p.octave_i_ = (*pitch_arr_p)[i].octave_i_;
54           if (p == (*pitch_arr_p)[i])
55             return i;
56         }
57     }
58   return i;
59 }
60
61 /*
62   trap (NL) != trap(english)
63  */
64 static int
65 trap_i (Musical_pitch tonic, Musical_pitch p)
66 {
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;
73 }
74
75 static Array<Musical_pitch>
76 missing_triads_pitch_arr (Array<Musical_pitch>const* pitch_arr_p)
77 {
78   Array<Musical_pitch> triads;
79
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]));
84
85   Musical_pitch tonic = (*pitch_arr_p)[0];
86   Musical_pitch last = tonic;
87   Array<Musical_pitch> missing_arr;
88
89   for (int i = 0; i < pitch_arr_p->size ();)
90     {
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))
96         {
97           while (trap > trap_i (tonic, last))
98             {
99               if ((last.notename_i_ - tonic.notename_i_ + 7) % 7 == 6)
100                 {
101                   Musical_pitch special_seven = last;
102                   Musical_pitch lower (0, -1);
103                   special_seven.transpose (lower);
104                   missing_arr.push (special_seven);
105                 }
106               else
107                 {
108                   missing_arr.push (last);
109                 }
110               last.transpose (triads[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
111             }
112         }
113       else
114         {
115           i++;
116         }
117     }
118   return missing_arr;
119 }
120
121
122 /*
123   construct from parser output
124 */
125 Chord::Chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p)
126 {
127   rebuild_transpose (tonic, add_arr_p);
128   rebuild_transpose (tonic, sub_arr_p);
129
130   Musical_pitch fifth = tonic;
131   fifth.transpose (Musical_pitch (2));
132   fifth.transpose (Musical_pitch (2, -1));
133
134   /*
135     remove double adds (urg: sus4)
136    */
137   for (int i = add_arr_p->size () - 1; i >= 0 ; i--)
138     {
139       int j = ::find_pitch_i (add_arr_p, (*add_arr_p)[i]);
140       if ((j != -1) && (i != j))
141         {
142             add_arr_p->get (i);
143         } 
144     }
145
146   /*
147     default chord includes upto 5: <1, 3, 5>
148    */
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);
154
155   /*
156     find missing triads
157    */
158   Array<Musical_pitch> missing_arr = missing_triads_pitch_arr (&tmp);
159   if (highest_trap < 5)
160     missing_arr.push (fifth);
161
162   /*
163     if additions include some 3, don't add third
164    */
165   Musical_pitch third = tonic;
166   third.transpose (Musical_pitch (2));
167   if (::find_notename_i (add_arr_p, third) != -1)
168     {
169       int i = ::find_pitch_i (&missing_arr, third);
170       if (i != -1)
171         missing_arr.get (i);
172     }
173   
174   /*
175     if additions include 4, assume sus4 and don't add third implicitely
176      C-sus (4) = c f g (1 4 5)
177    */
178   Musical_pitch sus = tonic;
179   sus.transpose (Musical_pitch (3));
180   if (::find_pitch_i (add_arr_p, sus) != -1)
181     {
182       int i = ::find_pitch_i (&missing_arr, third);
183       if (i != -1)
184         missing_arr.get (i);
185     }
186
187   /*
188     if additions include some 5, don't add fifth
189    */
190   if (::find_notename_i (add_arr_p, fifth) != -1)
191     {
192       int i = ::find_pitch_i (&missing_arr, fifth);
193       if (i != -1)
194         missing_arr.get (i);
195     }
196   
197   
198   /*
199     complete the list of triads to be added
200    */
201   add_arr_p->concat (missing_arr);
202   add_arr_p->sort (Musical_pitch::compare);
203
204   /*
205    add all that aren't subtracted
206    */
207   for (int i = 0; i < add_arr_p->size (); i++)
208     {
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])
213           {
214             sub_arr_p->del (j);
215             j = -1;
216             break;
217           }
218       if (j == sub_arr_p->size ())
219         pitch_arr_.push (p);
220     }
221
222   pitch_arr_.sort (Musical_pitch::compare);
223
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 ()));
227
228   if (inversion_p)
229     {
230       int i = 0;
231       for (; i < pitch_arr_.size (); i++)
232         {
233           if ((pitch_arr_[i].notename_i_ == inversion_p->notename_i_)
234               && (pitch_arr_[i].accidental_i_ == inversion_p->accidental_i_))
235             break;
236         }
237       if (i == pitch_arr_.size ())
238         {
239           warning (_f ("invalid inversion pitch: not part of chord: %s",
240                        inversion_p->str ()));
241         }
242       else
243         {
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
250           
251         }
252       delete inversion_p;
253     }
254 }
255
256 void
257 Chord::find_additions_and_subtractions(Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p)
258 {
259   Musical_pitch tonic = pitch_arr_[0];
260   /*
261     all the triads that should be there
262    */
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);
268   
269   int i = 0;
270   int j = 0;
271   while ((i < all_arr.size ()) || (j < pitch_arr_.size ()))
272     {
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)
278         {
279           i++;
280           j++;
281         }
282       else if ((p < a) || (p.notename_i_ == a.notename_i_))
283         {
284           add_arr_p->push (p);
285           j++;
286         }
287       else
288         {
289           sub_arr_p->push (a);
290           i++;
291         }
292     }
293       
294   /*
295     add highest addition, because it names chord
296    */
297   if (trap_i (tonic, pitch_arr_.top () > 5))
298     add_arr_p->push (pitch_arr_.top ());
299 }
300
301 String
302 Chord::banter_str (Musical_pitch* inversion) const
303 {
304   Musical_pitch tonic = pitch_arr_[0];
305
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];
311
312   Array<Musical_pitch> add_arr;
313   Array<Musical_pitch> sub_arr;
314   find_additions_and_subtractions (&add_arr, &sub_arr);
315                            
316
317   Array<Musical_pitch> scale;
318   for (int i=0; i < 7; i++)
319     scale.push (Musical_pitch (i));
320
321   // 7 always means 7-...
322   //  scale.push (Musical_pitch (6, -1)); // b
323
324   rebuild_transpose (tonic, &scale);
325   
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++)
331     {
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))
338         {
339           tonic_str += "m";
340           has3m_b = true;
341         }
342       else if (accidental
343                || (!(trap % 2) || ((i + 1 == add_arr.size ()) && (trap > 5))))
344         {
345           str += sep_str;
346           if ((trap == 7) && (accidental == 1))
347             str += "maj7";
348           else
349             {
350               str += to_str (trap);
351               if (accidental)
352                 str += accidental < 0 ? "-" : "+";
353             }
354           sep_str = "/";
355         }
356     }
357
358   for (int i = 0; i < sub_arr.size (); i++)
359     {
360       Musical_pitch p = sub_arr[i];
361       int trap = trap_i (tonic, p);
362       /*
363         if chord has 3-, assume minor and don't display 'no3'
364         if additions include 4, assume sus4 and don't display 'no3'
365       */
366       if (!((trap == 3) && (has3m_b || has4_b)))
367         {
368           str += sep_str + "no" + to_str (trap);
369           sep_str = "/";
370         }
371     }
372
373   String inversion_str;
374   if (inversion)
375     {
376       inversion_str = inversion->str ();
377       inversion_str = "/" + inversion_str.left_str (1).upper_str ()
378         + acc[inversion->accidental_i_ + 2];
379
380     }
381
382   return tonic_str + "$^{" + str + "}$" + inversion_str;
383 }
384
385 int
386 Chord::find_notename_i (Musical_pitch p) const
387 {
388   return ::find_notename_i (&pitch_arr_, p);
389 }
390
391 int
392 Chord::find_pitch_i (Musical_pitch p) const
393 {
394   return ::find_pitch_i (&pitch_arr_, p);
395 }
396
397 int
398 Chord::find_tonic_i () const
399 {
400   /*
401     find tonic
402     
403     first try: base of longest line of triads
404    */
405   int tonic_i = 0;
406   int longest_i = 0;
407   for (int i = 0; i < pitch_arr_.size (); i++)
408     {
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++)
413         {
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++;
423         }
424       if (j - no_triad_i > longest_i)
425         {
426           longest_i = j - no_triad_i;
427           tonic_i = i;
428         }
429     }
430
431   /*
432     second try: note after biggest gap
433    */
434   int biggest_i = 0;
435   //  if (longest_i)
436   if (longest_i <= 1)
437     for (int i = 0; i < pitch_arr_.size (); i++)
438       {
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)
446           {
447             biggest_i = gap;
448             tonic_i = i;
449           }
450       }
451   return tonic_i;
452 }
453
454 void
455 Chord::rebuild_from_base (int base_i)
456 {
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++)
461     {
462       Musical_pitch p = pitch_arr_[(base_i + i) % pitch_arr_.size ()];
463       if (p < last)
464         {
465           p.octave_i_ = last.octave_i_;
466           if (p < last)
467             p.octave_i_++;
468         }
469       new_arr.push (p);
470       last = p;
471     }
472   pitch_arr_ = new_arr;
473 }
474
475 void
476 Chord::rebuild_insert_inversion (int tonic_i)
477 {
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 ())
487     {
488       inversion.octave_i_ = pitch_arr_[0].octave_i_ - 1;
489       while (inversion < pitch_arr_[0])
490         inversion.octave_i_++;
491     }
492   for (int i = 0; i < pitch_arr_.size (); i++)
493     if (pitch_arr_[i] > inversion)
494       {
495         pitch_arr_.insert (inversion, i);
496         break;
497       }
498 #endif
499 }
500
501 void
502 Chord::rebuild_with_bass (int bass_i)
503 {
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);
511 }