]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord.cc
release: 1.3.69
[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--2000 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "chord.hh"
10 #include "musical-request.hh"
11 #include "warn.hh"
12 #include "debug.hh"
13 #include "molecule.hh"
14 #include "paper-def.hh"
15 #include "lookup.hh"
16
17 /*
18   FIXME: should use SCM iso. arrays and have-to-delete pointers.
19
20   FIXME: this contains memleaks.
21  */
22   
23 /*
24   construct from parser output
25 */
26 Chord
27 to_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p, Musical_pitch* bass_p)
28 {
29   // urg: catch dim modifier: 3rd, 5th, 7th, .. should be lowered
30   bool dim_b = false;
31   for (int i=0; i < add_arr_p->size (); i++)
32     {
33       Musical_pitch* p = &(*add_arr_p)[i];
34       if (p->octave_i_ == -100)
35         {
36           p->octave_i_ = 0;
37           dim_b = true;
38         }
39     }
40   Chord::rebuild_transpose (add_arr_p, tonic, true);
41   Chord::rebuild_transpose (sub_arr_p, tonic, true);
42
43   Musical_pitch fifth = Chord::base_arr (tonic).top ();
44
45   /*
46     remove double adds (urg: sus4)
47    */
48   for (int i = add_arr_p->size () - 1; i >= 0 ; i--)
49     {
50       int j = Chord::find_pitch_i (add_arr_p, (*add_arr_p)[i]);
51       if ((j != -1) && (i != j))
52         {
53           add_arr_p->get (i);
54         } 
55     }
56
57   /*
58     default chord includes upto 5: <1, 3, 5>
59    */
60   add_arr_p->insert (tonic, 0);
61   Array<Musical_pitch> tmp = *add_arr_p;
62   int highest_step = Chord::step_i (tonic, tmp.top ());
63   if (highest_step < 5)
64     tmp.push (fifth);
65   else if (dim_b)
66     {
67       Musical_pitch* p = &add_arr_p->top ();
68       p->accidental_i_--;
69     }
70
71   /*
72     find missing thirds
73    */
74   Array<Musical_pitch> missing_arr = Chord::missing_thirds_pitch_arr (&tmp);
75   if (highest_step < 5)
76     missing_arr.push (fifth);
77
78   /*
79     if dim modifier is given: lower all missing
80    */
81   if (dim_b)
82     {
83       for (int i=0; i < missing_arr.size (); i++)
84         {
85           missing_arr[i].accidental_i_--;
86         }
87     }
88
89   /*
90     if additions include some 3, don't add third
91    */
92   Musical_pitch third = Chord::base_arr (tonic)[1];
93   if (Chord::find_notename_i (add_arr_p, third) != -1)
94     {
95       int i = Chord::find_pitch_i (&missing_arr, third);
96       if (i != -1)
97         missing_arr.get (i);
98     }
99   
100   /*
101     if additions include 4, assume sus4 and don't add third implicitely
102      C-sus (4) = c f g (1 4 5)
103    */
104   Musical_pitch sus = tonic;
105   sus.transpose (Musical_pitch (3));
106   if (Chord::find_pitch_i (add_arr_p, sus) != -1)
107     {
108       int i = Chord::find_pitch_i (&missing_arr, third);
109       if (i != -1)
110         missing_arr.get (i);
111     }
112
113   /*
114     if additions include some 5, don't add fifth
115    */
116   if (Chord::find_notename_i (add_arr_p, fifth) != -1)
117     {
118       int i = Chord::find_pitch_i (&missing_arr, fifth);
119       if (i != -1)
120         missing_arr.get (i);
121     }
122   
123   
124   /*
125     complete the list of thirds to be added
126    */
127   add_arr_p->concat (missing_arr);
128   add_arr_p->sort (Musical_pitch::compare);
129
130   Array<Musical_pitch> pitch_arr;
131   /*
132    add all that aren't subtracted
133    */
134   for (int i = 0; i < add_arr_p->size (); i++)
135     {
136       Musical_pitch p = (*add_arr_p)[i];
137       int j = 0;
138       for (; j < sub_arr_p->size (); j++)
139         if (p == (*sub_arr_p)[j])
140           {
141             sub_arr_p->del (j);
142             j = -1;
143             break;
144           }
145       if (j == sub_arr_p->size ())
146         pitch_arr.push (p);
147     }
148
149   pitch_arr.sort (Musical_pitch::compare);
150
151   for (int i = 0; i < sub_arr_p->size (); i++)
152     warning (_f ("invalid subtraction: not part of chord: %s",
153                  (*sub_arr_p)[i].str ()));
154  
155   return Chord (pitch_arr, inversion_p, bass_p);
156 }
157
158 /*
159   Construct from list of pitches and requests
160  */
161 Chord
162 to_chord (Array<Musical_pitch> pitch_arr, Tonic_req* tonic_req, Inversion_req* inversion_req, Bass_req* bass_req, bool find_inversion_b)
163 {
164   Musical_pitch* inversion_p = 0;
165   Musical_pitch* bass_p = 0;
166
167   if (bass_req)
168     {
169       assert (pitch_arr[0].notename_i_ == bass_req->pitch_.notename_i_);
170       bass_p = new Musical_pitch (pitch_arr.get (0));
171     }
172     
173   if (inversion_req)
174     {
175       assert (pitch_arr[0].notename_i_ == inversion_req->pitch_.notename_i_);
176       inversion_p = new Musical_pitch (inversion_req->pitch_);
177       assert (tonic_req);
178       int tonic_i = Chord::find_notename_i (&pitch_arr, tonic_req->pitch_);
179       if (tonic_i)
180         Chord::rebuild_insert_inversion (&pitch_arr, tonic_i);
181     }
182     
183   if (find_inversion_b && !inversion_p)
184     {
185       int tonic_i = tonic_req
186         ? Chord::find_notename_i (&pitch_arr, tonic_req->pitch_) 
187         : Chord::find_tonic_i (&pitch_arr);
188         
189       if (tonic_i)
190         {
191           inversion_p = &pitch_arr[0];
192           Chord::rebuild_insert_inversion (&pitch_arr, tonic_i);
193         }
194     }
195
196   if (tonic_req)
197     {
198       assert (pitch_arr[0].notename_i_ == tonic_req->pitch_.notename_i_);
199     }
200
201   return Chord (pitch_arr, inversion_p, bass_p);
202 }
203
204 Chord::Chord ()
205 {
206   inversion_b_ = false;
207   bass_b_ = false;
208 }
209
210 Chord::Chord (Array<Musical_pitch> pitch_arr, Musical_pitch* inversion_p, Musical_pitch* bass_p)
211 {
212   pitch_arr_ = pitch_arr;
213   inversion_b_ = false;
214   bass_b_ = false;
215   if (inversion_p)
216     {
217       inversion_pitch_ = *inversion_p;
218       inversion_b_ = true;
219     }
220   if (bass_p)
221     {
222       bass_pitch_ = *bass_p;
223       bass_b_ = true;
224     }
225 }
226   
227 Chord::Chord (Chord const& chord)
228 {
229   pitch_arr_ = chord.pitch_arr_;
230   inversion_b_ = chord.inversion_b_;
231   inversion_pitch_ = chord.inversion_pitch_;
232   bass_b_ = chord.bass_b_;
233   bass_pitch_ = chord.bass_pitch_;
234 }
235   
236
237 /*
238   JUNKME. 
239   do something smarter.
240  */
241 Array<Musical_pitch>
242 Chord::base_arr (Musical_pitch p)
243 {
244   Array<Musical_pitch> base;
245   base.push (p);
246   p.transpose (Musical_pitch (2));
247   base.push (p);
248   p.transpose (Musical_pitch (2, -1));
249   base.push (p);
250   return base;
251 }
252
253 void
254 Chord::rebuild_transpose (Array<Musical_pitch>* pitch_arr_p, Musical_pitch tonic, bool fix7_b)
255 {
256   for (int i = 0; i < pitch_arr_p->size (); i++)
257     {
258       Musical_pitch p = tonic;
259       Musical_pitch q = (*pitch_arr_p)[i];
260       p.transpose (q);
261       // duh, c7 should mean <c bes>
262       if (fix7_b && (step_i (tonic, p) == 7))
263         p.accidental_i_--;
264       (*pitch_arr_p)[i] = p;
265     }
266   pitch_arr_p->sort (Musical_pitch::compare);
267 }
268
269 int
270 Chord::find_pitch_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
271 {
272   for (int i = 0; i < pitch_arr_p->size (); i++)
273     if (p == (*pitch_arr_p)[i])
274       return i;
275   return -1;
276 }
277
278 int
279 Chord::find_notename_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
280 {
281   int i = find_pitch_i (pitch_arr_p, p);
282   if (i == -1)
283     {
284       for (int i = 0; i < pitch_arr_p->size (); i++)
285         {
286           p.octave_i_ = (*pitch_arr_p)[i].octave_i_;
287           if (p == (*pitch_arr_p)[i])
288             return i;
289         }
290     }
291   return i;
292 }
293
294 int
295 Chord::step_i (Musical_pitch tonic, Musical_pitch p)
296 {
297   int i = p.notename_i_ - tonic.notename_i_
298     + (p.octave_i_ - tonic.octave_i_) * 7;
299   while (i < 0)
300     i += 7;
301   i++;
302   return i;
303 }
304
305 /*
306   JUNKME. 
307   do something smarter.
308  */
309 Array<Musical_pitch>
310 Chord::missing_thirds_pitch_arr (Array<Musical_pitch> const* pitch_arr_p)
311 {
312   Array<Musical_pitch> thirds;
313
314   /* is the third c-e, d-f, etc. small or large? */
315   int minormajor_a[] = {0, -1, -1, 0,0,-1,-1};
316   for (int i=0; i < 7; i++)
317     thirds.push (Musical_pitch( 2, minormajor_a[i]));
318
319   Musical_pitch tonic = (*pitch_arr_p)[0];
320   Musical_pitch last = tonic;
321   Array<Musical_pitch> missing_arr;
322
323   for (int i = 0; i < pitch_arr_p->size ();)
324     {
325       Musical_pitch p = (*pitch_arr_p)[i];
326       int step = step_i (tonic, p);
327       if (last.notename_i_ == p.notename_i_)
328         last.transpose (thirds[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
329       if (step > step_i (tonic, last))
330         {
331           while (step > step_i (tonic, last))
332             {
333               if ((last.notename_i_ - tonic.notename_i_ + 7) % 7 == 6)
334                 {
335                   Musical_pitch special_seven = last;
336                   Musical_pitch lower (0, -1);
337                   special_seven.transpose (lower);
338                   missing_arr.push (special_seven);
339                 }
340               else
341                 {
342                   missing_arr.push (last);
343                 }
344               last.transpose (thirds[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
345             }
346         }
347       else
348         {
349           i++;
350         }
351     }
352   return missing_arr;
353 }
354
355
356 /*
357  Mangle into list of pitches.
358  For normal chord entry, inversion and bass pitches are retained in
359  specific *_requests
360  */
361 Array<Musical_pitch>
362 Chord::to_pitch_arr () const
363 {
364   Array<Musical_pitch> pitch_arr = pitch_arr_;
365   if (inversion_b_)
366     {
367       int i = 0;
368       for (; i < pitch_arr.size (); i++)
369         {
370           if ((pitch_arr[i].notename_i_ == inversion_pitch_.notename_i_)
371               && (pitch_arr[i].accidental_i_ == inversion_pitch_.accidental_i_))
372             break;
373         }
374       if (i == pitch_arr.size ())
375         {
376           warning (_f ("invalid inversion pitch: not part of chord: %s",
377                        inversion_pitch_.str ()));
378         }
379       else
380         rebuild_with_bass (&pitch_arr, i);
381     }
382
383   if (bass_b_)
384     {
385       pitch_arr.insert (bass_pitch_, 0);
386       rebuild_with_bass (&pitch_arr, 0);
387     }
388   return pitch_arr;
389 }
390
391 /*
392   This routine tries to guess tonic in a possibly inversed chord, ie
393   <e g c'> should produce: C.
394   This is only used for chords that are entered as simultaneous notes,
395   chords entered in \chord mode are fully defined.
396  */
397 int
398 Chord::find_tonic_i (Array<Musical_pitch> const* pitch_arr_p)
399 {
400   /*
401     find tonic
402     
403     first try: base of longest line of thirds
404   */
405   int tonic_i = 0;
406   int longest_i = 0;
407   for (int i = 0; i < pitch_arr_p->size (); i++)
408     {
409       int no_third_i = 0;
410       int last_i = (*pitch_arr_p)[i % pitch_arr_p->size ()].notename_i_;
411       int j = 0;
412       for (; j < pitch_arr_p->size (); j++)
413         {
414           int cur_i = (*pitch_arr_p)[(i + j + 1) % pitch_arr_p->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_third_i++;
423         }
424       if (j - no_third_i > longest_i)
425         {
426           longest_i = j - no_third_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_p->size (); i++)
438       {
439         int gap = (*pitch_arr_p)[i].notename_i_
440           - (*pitch_arr_p)[(i - 1 + pitch_arr_p->size ()) 
441                           % pitch_arr_p->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 (Array<Musical_pitch>* pitch_arr_p, 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_p->size (); i++)
461     {
462       Musical_pitch p = (*pitch_arr_p)[(base_i + i) % pitch_arr_p->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_p = new_arr;
473 }
474
475 void
476 Chord::rebuild_insert_inversion (Array<Musical_pitch>* pitch_arr_p, int tonic_i)
477 {
478   assert (tonic_i > 0);
479   Musical_pitch inversion = pitch_arr_p->get (0);
480   rebuild_from_base (pitch_arr_p, tonic_i - 1);
481   if (pitch_arr_p->size ())
482     {
483       inversion.octave_i_ = (*pitch_arr_p)[0].octave_i_ - 1;
484       while (inversion < (*pitch_arr_p)[0])
485         inversion.octave_i_++;
486     }
487   for (int i = 0; i < pitch_arr_p->size (); i++)
488     if ((*pitch_arr_p)[i] > inversion)
489       {
490         pitch_arr_p->insert (inversion, i);
491         break;
492       }
493 }
494
495 void
496 Chord::rebuild_with_bass (Array<Musical_pitch>* pitch_arr_p, int bass_i)
497 {
498   assert (bass_i >= 0);
499   Musical_pitch bass = pitch_arr_p->get (bass_i);
500   // is lowering fine, or should others be raised?
501   if (pitch_arr_p->size ())
502     while (bass > (*pitch_arr_p)[0])
503       bass.octave_i_--;
504   pitch_arr_p->insert (bass, 0);
505 }
506