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