]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord.cc
release: 1.1.37
[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 static int
62 trap_i (Musical_pitch tonic, Musical_pitch p)
63 {
64   int i = p.notename_i_ - tonic.notename_i_
65     + (p.octave_i_ - tonic.octave_i_) * 7;
66   while (i < 0)
67     i += 7;
68   i++;
69   return i;
70 }
71
72 static Array<Musical_pitch>
73 missing_triads_pitch_arr (Array<Musical_pitch>const* pitch_arr_p)
74 {
75   Array<Musical_pitch> triads;
76
77   /* is the third c-e, d-f, etc. small or large? */
78   int minormajor_a[] = {0, -1, -1, 0,0,-1,-1};
79   for (int i=0; i < 7; i++)
80     triads.push (Musical_pitch( 2, minormajor_a[i]));
81
82   Musical_pitch tonic = (*pitch_arr_p)[0];
83   Musical_pitch last = tonic;
84   Array<Musical_pitch> missing_arr;
85
86   for (int i = 0; i < pitch_arr_p->size ();)
87     {
88       Musical_pitch p = (*pitch_arr_p)[i];
89       int trap = trap_i (tonic, p);
90       if (last.notename_i_ == p.notename_i_)
91         last.transpose (triads[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
92       if (trap > trap_i (tonic, last))
93         {
94           while (trap > trap_i (tonic, last))
95             {
96               if ((last.notename_i_ - tonic.notename_i_ + 7) % 7 == 6)
97                 {
98                   Musical_pitch special_seven = last;
99                   Musical_pitch lower (0, -1);
100                   special_seven.transpose (lower);
101                   missing_arr.push (special_seven);
102                 }
103               else
104                 {
105                   missing_arr.push (last);
106                 }
107               last.transpose (triads[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
108             }
109         }
110       else
111         {
112           i++;
113         }
114     }
115   return missing_arr;
116 }
117
118
119 /*
120   construct from parser output
121 */
122 Chord::Chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p)
123 {
124   rebuild_transpose (tonic, add_arr_p);
125   rebuild_transpose (tonic, sub_arr_p);
126
127   Musical_pitch fifth = tonic;
128   fifth.transpose (Musical_pitch (2));
129   fifth.transpose (Musical_pitch (2, -1));
130
131   /*
132     default chord includes upto 5: <1, 3, 5>
133    */
134   add_arr_p->insert (tonic, 0);
135   int highest_trap = trap_i (tonic, add_arr_p->top ());
136   if (highest_trap < 5)
137     add_arr_p->push (fifth);
138
139   /*
140     find missing triads
141    */
142   Array<Musical_pitch> missing_arr = missing_triads_pitch_arr (add_arr_p);
143
144   /*
145     if additions include 4, assume sus4 and don't add third implicitely
146    */
147   Musical_pitch third = tonic;
148   third.transpose (Musical_pitch (2));
149   Musical_pitch sus = tonic;
150   sus.transpose (Musical_pitch (3));
151   if (::find_pitch_i (add_arr_p, sus) != -1)
152     {
153       int i = ::find_pitch_i (&missing_arr, third);
154       if (i != -1)
155         missing_arr.get (i);
156     }
157   
158   /*
159     complete the list of triads to be added
160    */
161   add_arr_p->concat (missing_arr);
162   add_arr_p->sort (Musical_pitch::compare);
163
164   /*
165    add all that aren't subtracted
166    */
167   for (int i = 0; i < add_arr_p->size (); i++)
168     {
169       Musical_pitch p = (*add_arr_p)[i];
170       int j = 0;
171       for (; j < sub_arr_p->size (); j++)
172         if (p == (*sub_arr_p)[j])
173           {
174             sub_arr_p->del (j);
175             j = -1;
176             break;
177           }
178       if (j == sub_arr_p->size ())
179         pitch_arr_.push (p);
180     }
181
182   pitch_arr_.sort (Musical_pitch::compare);
183
184   for (int i = 0; i < sub_arr_p->size (); i++)
185     warning (_f ("invalid subtraction: not part of chord: %s",
186                  (*sub_arr_p)[i].str ()));
187
188   if (inversion_p)
189     {
190       int i = 0;
191       for (; i < pitch_arr_.size (); i++)
192         {
193           if ((pitch_arr_[i].notename_i_ == inversion_p->notename_i_)
194               && (pitch_arr_[i].accidental_i_ == inversion_p->accidental_i_))
195             break;
196         }
197       if (i == pitch_arr_.size ())
198         {
199           warning (_f ("invalid inversion pitch: not part of chord: %s",
200                        inversion_p->str ()));
201         }
202       else
203         {
204 #if INVERSION_ADDED_AS_BASE
205           pitch_arr_.insert (pitch_arr_[i], 0);
206           rebuild_with_bass (0);
207 #else
208           rebuild_with_bass (i);
209 #endif
210           
211         }
212       delete inversion_p;
213     }
214 }
215
216 void
217 Chord::find_additions_and_subtractions(Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p)
218 {
219   Musical_pitch tonic = pitch_arr_[0];
220   /*
221     all the triads that should be there
222    */
223   Array<Musical_pitch> all_arr;
224   all_arr.push (tonic);
225   all_arr.push (pitch_arr_.top ());
226   all_arr.concat (missing_triads_pitch_arr (&all_arr));
227   all_arr.sort (Musical_pitch::compare);
228   
229   int i = 0;
230   int j = 0;
231   while ((i < all_arr.size ()) || (j < pitch_arr_.size ()))
232     {
233       i = i <? all_arr.size () - 1;
234       j = j <? pitch_arr_.size () - 1;
235       Musical_pitch a = all_arr[i];
236       Musical_pitch p = pitch_arr_[j];
237       if (a == p)
238         {
239           i++;
240           j++;
241         }
242       else if ((p < a) || (p.notename_i_ == a.notename_i_))
243         {
244           add_arr_p->push (p);
245           j++;
246         }
247       else
248         {
249           sub_arr_p->push (a);
250           i++;
251         }
252     }
253       
254   /*
255     add highest addition, because it names chord
256    */
257   if (trap_i (tonic, pitch_arr_.top () > 5))
258     add_arr_p->push (pitch_arr_.top ());
259 }
260
261 String
262 Chord::banter_str (Musical_pitch* inversion) const
263 {
264   Musical_pitch tonic = pitch_arr_[0];
265
266   //urg, should do translation in scheme.
267   char const *acc[] = {"\\textflat\\textflat ", "\\textflat ", "", "\\textsharp " , "\\textsharp\\textsharp "};
268   String tonic_str = tonic.str ();
269   tonic_str = tonic_str.left_str (1).upper_str ()
270     + acc[tonic.accidental_i_ + 2];
271
272   Array<Musical_pitch> add_arr;
273   Array<Musical_pitch> sub_arr;
274   find_additions_and_subtractions (&add_arr, &sub_arr);
275                            
276
277   Array<Musical_pitch> scale;
278   for (int i=0; i < 7; i++)
279     scale.push (Musical_pitch (i));
280
281   // 7 always means 7-...
282   //  scale.push (Musical_pitch (6, -1)); // b
283
284   rebuild_transpose (tonic, &scale);
285   
286   bool has3m_b = false;
287   bool has4_b = false;
288   String str;
289   String sep_str;
290   for (int i = 0; i < add_arr.size (); i++)
291     {
292       Musical_pitch p = add_arr[i];
293       int trap = trap_i (tonic, p);
294       if (trap == 4)
295         has4_b = true;
296       int accidental = p.accidental_i_ - scale[(trap - 1) % 7].accidental_i_;
297       if ((trap == 3) && (accidental == -1))
298         {
299           tonic_str += "m";
300           has3m_b = true;
301         }
302       else if (accidental
303                || (!(trap % 2) || ((i + 1 == add_arr.size ()) && (trap > 5))))
304         {
305           str += sep_str;
306           if ((trap == 7) && (accidental == 1))
307             str += "maj7";
308           else
309             {
310               str += to_str (trap);
311               if (accidental)
312                 str += accidental < 0 ? "-" : "+";
313             }
314           sep_str = "/";
315         }
316     }
317
318   for (int i = 0; i < sub_arr.size (); i++)
319     {
320       Musical_pitch p = sub_arr[i];
321       int trap = trap_i (tonic, p);
322       /*
323         if chord has 3-, assume minor and don't display 'no3'
324         if additions include 4, assume sus4 and don't display 'no3'
325       */
326       if (!((trap == 3) && (has3m_b || has4_b)))
327         {
328           str += sep_str + "no" + to_str (trap);
329           sep_str = "/";
330         }
331     }
332
333   String inversion_str;
334   if (inversion)
335     {
336       inversion_str = inversion->str ();
337       inversion_str = "/" + inversion_str.left_str (1).upper_str ()
338         + acc[inversion->accidental_i_ + 2];
339
340     }
341
342   return tonic_str + "$^{" + str + "}$" + inversion_str;
343 }
344
345 int
346 Chord::find_notename_i (Musical_pitch p) const
347 {
348   return ::find_notename_i (&pitch_arr_, p);
349 }
350
351 int
352 Chord::find_pitch_i (Musical_pitch p) const
353 {
354   return ::find_pitch_i (&pitch_arr_, p);
355 }
356
357 int
358 Chord::find_tonic_i () const
359 {
360   /*
361     find tonic
362     
363     first try: base of longest line of triads
364    */
365   int tonic_i = 0;
366   int longest_i = 0;
367   for (int i = 0; i < pitch_arr_.size (); i++)
368     {
369       int no_triad_i = 0;
370       int last_i = pitch_arr_[i % pitch_arr_.size ()].notename_i_;
371       int j = 0;
372       for (; j < pitch_arr_.size (); j++)
373         {
374           int cur_i = pitch_arr_[(i + j + 1) % pitch_arr_.size ()].notename_i_;
375           int gap = cur_i - last_i;
376           while (gap < 0)
377             gap += 7;
378           gap %= 7;
379           if (gap == 2)
380             last_i = cur_i;
381           else
382             no_triad_i++;
383         }
384       if (j - no_triad_i > longest_i)
385         {
386           longest_i = j - no_triad_i;
387           tonic_i = i;
388         }
389     }
390
391   /*
392     second try: note after biggest gap
393    */
394   int biggest_i = 0;
395   //  if (longest_i)
396   if (longest_i <= 1)
397     for (int i = 0; i < pitch_arr_.size (); i++)
398       {
399         int gap = pitch_arr_[i].notename_i_
400           - pitch_arr_[(i - 1 + pitch_arr_.size ()) 
401           % pitch_arr_.size ()].notename_i_;
402         while (gap < 0)
403           gap += 7;
404         gap %= 7;
405         if (gap > biggest_i)
406           {
407             biggest_i = gap;
408             tonic_i = i;
409           }
410       }
411   return tonic_i;
412 }
413
414 void
415 Chord::rebuild_from_base (int base_i)
416 {
417   assert (base_i >= 0);
418   Musical_pitch last (0, 0, -5);
419   Array<Musical_pitch> new_arr;
420   for (int i = 0; i < pitch_arr_.size (); i++)
421     {
422       Musical_pitch p = pitch_arr_[(base_i + i) % pitch_arr_.size ()];
423       if (p < last)
424         {
425           p.octave_i_ = last.octave_i_;
426           if (p < last)
427             p.octave_i_++;
428         }
429       new_arr.push (p);
430       last = p;
431     }
432   pitch_arr_ = new_arr;
433 }
434
435 void
436 Chord::rebuild_insert_inversion (int tonic_i)
437 {
438   assert (tonic_i > 0);
439 #if INVERSION_ADDED_AS_BASE
440   // inversion was added; don't insert
441   Musical_pitch inversion = pitch_arr_.get (0);
442   (void)inversion;
443 #else
444   Musical_pitch inversion = pitch_arr_.get (0);
445   rebuild_from_base (tonic_i - 1);
446   if (pitch_arr_.size ())
447     {
448       inversion.octave_i_ = pitch_arr_[0].octave_i_ - 1;
449       while (inversion < pitch_arr_[0])
450         inversion.octave_i_++;
451     }
452   for (int i = 0; i < pitch_arr_.size (); i++)
453     if (pitch_arr_[i] > inversion)
454       {
455         pitch_arr_.insert (inversion, i);
456         break;
457       }
458 #endif
459 }
460
461 void
462 Chord::rebuild_with_bass (int bass_i)
463 {
464   assert (bass_i >= 0);
465   Musical_pitch inversion = pitch_arr_.get (bass_i);
466   // is lowering fine, or should others be raised?
467   if (pitch_arr_.size ())
468     while (inversion > pitch_arr_[0])
469       inversion.octave_i_--;
470   pitch_arr_.insert (inversion, 0);
471 }