]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord.cc
patch::: 1.3.2.jcn3
[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 "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 SCM
18 pitch2scm (Musical_pitch p)
19 {
20   return gh_cons (gh_int2scm (p.notename_i_), gh_int2scm (p.accidental_i_));
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 (Array<Musical_pitch> pitch_arr, Musical_pitch* inversion_p, Musical_pitch* bass_p)
205 {
206   pitch_arr_ = pitch_arr;
207   inversion_p_ = inversion_p;
208   bass_p_ = bass_p;
209 }
210
211 Chord::Chord (Chord const& chord)
212   : Item (chord)
213 {
214   pitch_arr_ = chord.pitch_arr_;
215   inversion_p_ = chord.inversion_p_ ? new Musical_pitch (*chord.inversion_p_) : 0;
216   bass_p_ = chord.bass_p_ ? new Musical_pitch (*chord.bass_p_) : 0;
217 }
218
219 Chord::~Chord ()
220 {
221   delete inversion_p_;
222   delete bass_p_;
223   // AAARGH, why doesn't Score_elt do this?
224   unsmobify_self ();
225 }
226
227 Array<Musical_pitch>
228 Chord::base_arr (Musical_pitch p)
229 {
230   Array<Musical_pitch> base;
231   base.push (p);
232   p.transpose (Musical_pitch (2));
233   base.push (p);
234   p.transpose (Musical_pitch (2, -1));
235   base.push (p);
236   return base;
237 }
238
239 void
240 Chord::rebuild_transpose (Array<Musical_pitch>* pitch_arr_p, Musical_pitch tonic, bool fix7_b)
241 {
242   for (int i = 0; i < pitch_arr_p->size (); i++)
243     {
244       Musical_pitch p = tonic;
245       Musical_pitch q = (*pitch_arr_p)[i];
246       p.transpose (q);
247       // duh, c7 should mean <c bes>
248       if (fix7_b && (step_i (tonic, p) == 7))
249         p.accidental_i_--;
250       (*pitch_arr_p)[i] = p;
251     }
252   pitch_arr_p->sort (Musical_pitch::compare);
253 }
254
255 int
256 Chord::find_pitch_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
257 {
258   for (int i = 0; i < pitch_arr_p->size (); i++)
259     if (p == (*pitch_arr_p)[i])
260       return i;
261   return -1;
262 }
263
264 int
265 Chord::find_notename_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
266 {
267   int i = find_pitch_i (pitch_arr_p, p);
268   if (i == -1)
269     {
270       for (int i = 0; i < pitch_arr_p->size (); i++)
271         {
272           p.octave_i_ = (*pitch_arr_p)[i].octave_i_;
273           if (p == (*pitch_arr_p)[i])
274             return i;
275         }
276     }
277   return i;
278 }
279
280 int
281 Chord::step_i (Musical_pitch tonic, Musical_pitch p)
282 {
283   int i = p.notename_i_ - tonic.notename_i_
284     + (p.octave_i_ - tonic.octave_i_) * 7;
285   while (i < 0)
286     i += 7;
287   i++;
288   return i;
289 }
290
291 Array<Musical_pitch>
292 Chord::missing_thirds_pitch_arr (Array<Musical_pitch> const* pitch_arr_p)
293 {
294   Array<Musical_pitch> thirds;
295
296   /* is the third c-e, d-f, etc. small or large? */
297   int minormajor_a[] = {0, -1, -1, 0,0,-1,-1};
298   for (int i=0; i < 7; i++)
299     thirds.push (Musical_pitch( 2, minormajor_a[i]));
300
301   Musical_pitch tonic = (*pitch_arr_p)[0];
302   Musical_pitch last = tonic;
303   Array<Musical_pitch> missing_arr;
304
305   for (int i = 0; i < pitch_arr_p->size ();)
306     {
307       Musical_pitch p = (*pitch_arr_p)[i];
308       int step = step_i (tonic, p);
309       if (last.notename_i_ == p.notename_i_)
310         last.transpose (thirds[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
311       if (step > step_i (tonic, last))
312         {
313           while (step > step_i (tonic, last))
314             {
315               if ((last.notename_i_ - tonic.notename_i_ + 7) % 7 == 6)
316                 {
317                   Musical_pitch special_seven = last;
318                   Musical_pitch lower (0, -1);
319                   special_seven.transpose (lower);
320                   missing_arr.push (special_seven);
321                 }
322               else
323                 {
324                   missing_arr.push (last);
325                 }
326               last.transpose (thirds[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
327             }
328         }
329       else
330         {
331           i++;
332         }
333     }
334   return missing_arr;
335 }
336
337
338 /*
339  Mangle into list of pitches.
340  For normal chord entry, inversion and bass pitches are retained in
341  specific *_requests
342  */
343 Array<Musical_pitch>
344 Chord::to_pitch_arr () const
345 {
346   Array<Musical_pitch> pitch_arr = pitch_arr_;
347   if (inversion_p_)
348     {
349       int i = 0;
350       for (; i < pitch_arr.size (); i++)
351         {
352           if ((pitch_arr[i].notename_i_ == inversion_p_->notename_i_)
353               && (pitch_arr[i].accidental_i_ == inversion_p_->accidental_i_))
354             break;
355         }
356       if (i == pitch_arr.size ())
357         {
358           warning (_f ("invalid inversion pitch: not part of chord: %s",
359                        inversion_p_->str ()));
360         }
361       else
362         rebuild_with_bass (&pitch_arr, i);
363     }
364
365   if (bass_p_)
366     {
367       pitch_arr.insert (*bass_p_, 0);
368       rebuild_with_bass (&pitch_arr, 0);
369     }
370   return pitch_arr;
371 }
372
373 void
374 Chord::find_additions_and_subtractions (Array<Musical_pitch> pitch_arr, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p) const
375 {
376   Musical_pitch tonic = pitch_arr[0];
377   /*
378     construct an array of thirds for a normal chord
379    */
380   Array<Musical_pitch> all_arr;
381   all_arr.push (tonic);
382   if (step_i (tonic, pitch_arr.top ()) >= 5)
383     all_arr.push (pitch_arr.top ());
384   else
385     all_arr.push (base_arr (tonic).top ());
386   all_arr.concat (missing_thirds_pitch_arr (&all_arr));
387   all_arr.sort (Musical_pitch::compare);
388   
389   int i = 0;
390   int j = 0;
391   Musical_pitch last_extra = tonic;
392   while ((i < all_arr.size ()) || (j < pitch_arr.size ()))
393     {
394       Musical_pitch a = all_arr [i <? all_arr.size () - 1];
395       Musical_pitch p = pitch_arr[j <? pitch_arr.size () - 1];
396       /*
397         this pitch is present: do nothing, check next
398        */
399       if (a == p)
400         {
401           i++;
402           j++;
403           last_extra = tonic;
404         }
405       /*
406         found an extra pitch: chord addition
407        */
408       else if ((p < a) || (p.notename_i_ == a.notename_i_))
409         {
410           add_arr_p->push (p);
411           last_extra = p;
412           (j < pitch_arr.size ()) ? j++ : i++;
413         }
414       /*
415         a third is missing: chord subtraction
416        */
417       else
418         {
419           if (last_extra.notename_i_ != a.notename_i_)
420             sub_arr_p->push (a);
421           (i < all_arr.size ()) ? i++ : j++;
422           last_extra = tonic;
423         }
424     }
425       
426   /* add missing basic steps */
427   if (step_i (tonic, pitch_arr.top ()) < 3)
428     sub_arr_p->push (base_arr (tonic)[1]);
429   if (step_i (tonic, pitch_arr.top ()) < 5)
430     sub_arr_p->push (base_arr (tonic).top ());
431
432   /*
433     add highest addition, because it names chord, if greater than 5
434     or non-standard
435     (1, 3 and) 5 not additions: part of normal chord
436    */
437   if ((step_i (tonic, pitch_arr.top ()) > 5)
438        || pitch_arr.top ().accidental_i_)
439     add_arr_p->push (pitch_arr.top ());
440 }
441
442
443 /*
444   word is roman text or styled text:
445    "text"
446    ("style" . "text")
447  */
448 Molecule
449 Chord::ly_word2molecule (SCM scm) const
450 {
451   String style;
452   if (gh_pair_p (scm))
453     {
454       style = ly_scm2string (gh_car (scm));
455       scm = gh_cdr (scm);
456     }
457   String text = ly_scm2string (scm);
458   return lookup_l ()->text (style, text, paper_l ());
459 }
460
461 /*
462  scm is word or list of words:
463    word
464    (word word)
465  */
466 Molecule
467 Chord::ly_text2molecule (SCM scm) const
468 {
469   Molecule mol;
470   if (gh_list_p (scm))
471     {
472       while (gh_cdr (scm) != SCM_EOL)
473         {
474           mol.add_at_edge (X_AXIS, RIGHT, 
475             ly_word2molecule (gh_car (scm)), 0);
476           scm = gh_cdr (scm);
477         }
478       scm = gh_car (scm);
479     }  
480   mol.add_at_edge (X_AXIS, RIGHT, 
481     ly_word2molecule (scm), 0);
482   return mol;
483 }
484
485 Molecule
486 Chord::pitch2molecule (Musical_pitch p) const
487 {
488   SCM name = scm_eval (gh_list (gh_symbol2scm ("user-pitch-name"), ly_quote_scm (pitch2scm (p)), SCM_UNDEFINED));
489
490   if (name != SCM_UNSPECIFIED)
491     {
492       return ly_text2molecule (name);
493     }
494
495   Molecule mol = lookup_l ()->text ("", p.str ().left_str (1).upper_str (), paper_l ());
496   if (p.accidental_i_)
497     // urg, how to select the feta-1 font?
498     mol.add_at_edge (X_AXIS, RIGHT, 
499                      lookup_l ()->accidental (p.accidental_i_, 0), 0);
500   return mol;
501 }
502
503 Musical_pitch
504 diff_pitch (Musical_pitch tonic, Musical_pitch  p)
505 {
506   Musical_pitch diff (p.notename_i_ - tonic.notename_i_, 
507     p.accidental_i_ - tonic.accidental_i_, 
508     p.octave_i_ - tonic.octave_i_);
509
510   while  (diff.notename_i_ >= 7)
511     {
512       diff.notename_i_ -= 7;
513       diff.octave_i_ ++;
514     }
515   while  (diff.notename_i_ < 0)
516     {
517       diff.notename_i_ += 7;
518       diff.octave_i_ --;
519     }
520
521   diff.accidental_i_ -= (tonic.semitone_pitch () + diff.semitone_pitch ())
522     - p.semitone_pitch ();
523
524   return diff;
525 }
526
527 bool
528 Chord::user_chord_name (Array<Musical_pitch> pitch_arr, Chord_name* name_p) const
529 {
530   SCM chord = SCM_EOL;
531   Array<Musical_pitch> chord_type = pitch_arr;
532   rebuild_transpose (&chord_type, diff_pitch (pitch_arr[0], Musical_pitch (0)), false);
533
534   for (int i= chord_type.size (); i--; )
535     chord = gh_cons (pitch2scm (chord_type[i]), chord);
536
537   SCM name = scm_eval (gh_list (gh_symbol2scm ("user-chord-name"), ly_quote_scm (chord), SCM_UNDEFINED));
538   if (name != SCM_UNSPECIFIED)
539     {
540       name_p->modifier_mol = ly_text2molecule (gh_car (name));
541       name_p->addition_mol = ly_text2molecule (gh_cdr (name));
542       return true;
543     }
544   return false;
545 }
546
547 void
548 Chord::banter (Array<Musical_pitch> pitch_arr, Chord_name* name_p) const
549 {
550   Array<Musical_pitch> add_arr;
551   Array<Musical_pitch> sub_arr;
552   find_additions_and_subtractions (pitch_arr, &add_arr, &sub_arr);
553                            
554   Array<Musical_pitch> scale;
555   for (int i=0; i < 7; i++)
556     scale.push (Musical_pitch (i));
557
558   Musical_pitch tonic = pitch_arr[0];
559   rebuild_transpose (&scale, tonic, true);
560   
561   /*
562     Does chord include this step?  -1 if flat
563    */
564   int has[16];
565   for (int i=0; i<16; i++)
566     has[i] = 0;
567
568   String mod_str;
569   String add_str;
570   String sep_str;
571   for (int i = 0; i < add_arr.size (); i++)
572     {
573       Musical_pitch p = add_arr[i];
574       int step = step_i (tonic, p);
575       int accidental = p.accidental_i_ - scale[(step - 1) % 7].accidental_i_;
576       if ((step < 16) && (has[step] != -1))
577         has[step] = accidental == -1 ? -1 : 1;
578       if ((step == 3) && (accidental == -1))
579         {
580           mod_str = "m";
581         }
582       /*
583         urg.
584         This routine gets a lot simpler, if we don't try to be catch
585         the 'dim' chords.  However, we'll have to list every exceptional
586         'dim' chord in scm: otherwise we'll get stuff like Cdim7-, iso
587         Cdim7, etc
588        */
589 #ifdef SMART_DIM
590       else if ((step == 5) && (accidental == -1) && (has[3] == -1))
591         {
592           mod_str = "dim";
593         }
594 #endif
595       else if (accidental
596                || (!(step % 2) 
597                || ((i == add_arr.size () - 1) && (step > 5))))
598         {
599           add_str += sep_str;
600           sep_str = "/";
601           if ((step == 7) && (accidental == 1))
602             {
603               add_str += "maj7";
604             }
605           else
606 #ifdef SMART_DIM
607             {
608               if ((step % 2) && (accidental == -1) 
609                  && (has[3] == -1) && (has[5] == -1))
610                 {               
611                   if (i != add_arr.size () - 1)
612                     sep_str = "";
613                   else
614                     add_str += to_str (step);
615                 }
616               else
617 #endif
618                 {
619                   add_str += to_str (step);
620                   if (accidental)
621                     add_str += accidental < 0 ? "-" : "+";
622                 }
623 #ifdef SMART_DIM
624             }
625 #endif
626         }
627     }
628
629   for (int i = 0; i < sub_arr.size (); i++)
630     {
631       Musical_pitch p = sub_arr[i];
632       int step = step_i (tonic, p);
633       /*
634         if additions include 2 or 4, assume sus2/4 and don't display 'no3'
635       */
636       if (!((step == 3) && (has[2] || has[4])))
637         {
638           add_str += sep_str + "no" + to_str (step);
639           sep_str = "/";
640         }
641     }
642
643   if (mod_str.length_i ())
644     name_p->modifier_mol.add_at_edge (X_AXIS, RIGHT, 
645       lookup_l ()->text ("roman", mod_str, paper_l ()), 0);
646   if (add_str.length_i ())
647     {
648       if (!name_p->addition_mol.empty_b ())
649         add_str = "/" + add_str;
650       name_p->addition_mol.add_at_edge (X_AXIS, RIGHT,
651        lookup_l ()->text ("script", add_str, paper_l ()), 0);
652     }
653 }
654
655
656 int
657 Chord::find_tonic_i (Array<Musical_pitch> const* pitch_arr_p)
658 {
659   /*
660     find tonic
661     
662     first try: base of longest line of thirds
663    */
664   int tonic_i = 0;
665   int longest_i = 0;
666   for (int i = 0; i < pitch_arr_p->size (); i++)
667     {
668       int no_third_i = 0;
669       int last_i = (*pitch_arr_p)[i % pitch_arr_p->size ()].notename_i_;
670       int j = 0;
671       for (; j < pitch_arr_p->size (); j++)
672         {
673           int cur_i = (*pitch_arr_p)[(i + j + 1) % pitch_arr_p->size ()].notename_i_;
674           int gap = cur_i - last_i;
675           while (gap < 0)
676             gap += 7;
677           gap %= 7;
678           if (gap == 2)
679             last_i = cur_i;
680           else
681             no_third_i++;
682         }
683       if (j - no_third_i > longest_i)
684         {
685           longest_i = j - no_third_i;
686           tonic_i = i;
687         }
688     }
689
690   /*
691     second try: note after biggest gap
692    */
693   int biggest_i = 0;
694   //  if (longest_i)
695   if (longest_i <= 1)
696     for (int i = 0; i < pitch_arr_p->size (); i++)
697       {
698         int gap = (*pitch_arr_p)[i].notename_i_
699           - (*pitch_arr_p)[(i - 1 + pitch_arr_p->size ()) 
700           % pitch_arr_p->size ()].notename_i_;
701         while (gap < 0)
702           gap += 7;
703         gap %= 7;
704         if (gap > biggest_i)
705           {
706             biggest_i = gap;
707             tonic_i = i;
708           }
709       }
710   return tonic_i;
711 }
712
713 void
714 Chord::rebuild_from_base (Array<Musical_pitch>* pitch_arr_p, int base_i)
715 {
716   assert (base_i >= 0);
717   Musical_pitch last (0, 0, -5);
718   Array<Musical_pitch> new_arr;
719   for (int i = 0; i < pitch_arr_p->size (); i++)
720     {
721       Musical_pitch p = (*pitch_arr_p)[(base_i + i) % pitch_arr_p->size ()];
722       if (p < last)
723         {
724           p.octave_i_ = last.octave_i_;
725           if (p < last)
726             p.octave_i_++;
727         }
728       new_arr.push (p);
729       last = p;
730     }
731   *pitch_arr_p = new_arr;
732 }
733
734 void
735 Chord::rebuild_insert_inversion (Array<Musical_pitch>* pitch_arr_p, int tonic_i)
736 {
737   assert (tonic_i > 0);
738   Musical_pitch inversion = pitch_arr_p->get (0);
739   rebuild_from_base (pitch_arr_p, tonic_i - 1);
740   if (pitch_arr_p->size ())
741     {
742       inversion.octave_i_ = (*pitch_arr_p)[0].octave_i_ - 1;
743       while (inversion < (*pitch_arr_p)[0])
744         inversion.octave_i_++;
745     }
746   for (int i = 0; i < pitch_arr_p->size (); i++)
747     if ((*pitch_arr_p)[i] > inversion)
748       {
749         pitch_arr_p->insert (inversion, i);
750         break;
751       }
752 }
753
754 void
755 Chord::rebuild_with_bass (Array<Musical_pitch>* pitch_arr_p, int bass_i)
756 {
757   assert (bass_i >= 0);
758   Musical_pitch bass = pitch_arr_p->get (bass_i);
759   // is lowering fine, or should others be raised?
760   if (pitch_arr_p->size ())
761     while (bass > (*pitch_arr_p)[0])
762       bass.octave_i_--;
763   pitch_arr_p->insert (bass, 0);
764 }
765
766 Molecule*
767 Chord::do_brew_molecule_p () const
768 {
769   Musical_pitch tonic = pitch_arr_[0];
770   
771   Chord_name name;
772   name.tonic_mol = pitch2molecule (tonic);
773
774   /*
775     if user has explicitely listed chord name, use that
776     
777     TODO
778     urg
779     maybe we should check all sub-lists of pitches, not
780     just full list and base triad?
781    */
782   if (!user_chord_name (pitch_arr_, &name))
783     {
784       /*
785         else, check if user has listed base triad
786         use user base name and add banter for remaining part
787        */
788       if ((pitch_arr_.size () > 2)
789           && user_chord_name (pitch_arr_.slice (0, 3), &name))
790         {
791           Array<Musical_pitch> base = base_arr (tonic);
792           base.concat (pitch_arr_.slice (3, pitch_arr_.size ()));
793           banter (base, &name);
794         }
795       /*
796         else, use pure banter
797        */
798       else
799         {
800           banter (pitch_arr_, &name);
801         }
802     }
803
804   if (inversion_p_)
805     {
806       name.inversion_mol = lookup_l ()->text ("", "/", paper_l ());
807       // zucht  const&
808       Molecule mol = pitch2molecule (*inversion_p_);
809       name.inversion_mol.add_at_edge (X_AXIS, RIGHT, mol, 0);
810     }
811
812   if (bass_p_)
813     {
814       name.bass_mol = lookup_l ()->text ("", "/", paper_l ());
815       Molecule mol = pitch2molecule (*bass_p_);
816       name.bass_mol.add_at_edge (X_AXIS, RIGHT, mol, 0);
817     }
818
819   // urg, howto get a good superscript_y?
820   Real super_y = lookup_l ()->text ("", "x", paper_l ()).dim_.y ().length ()/2;
821   if (!name.addition_mol.empty_b ())
822     name.addition_mol.translate (Offset (0, super_y));
823
824   Molecule* mol_p = new Molecule;
825   mol_p->add_at_edge (X_AXIS, RIGHT, name.tonic_mol, 0);
826   // huh?
827   if (!name.modifier_mol.empty_b ())
828     mol_p->add_at_edge (X_AXIS, RIGHT, name.modifier_mol, 0);
829   if (!name.addition_mol.empty_b ())
830     mol_p->add_at_edge (X_AXIS, RIGHT, name.addition_mol, 0);
831   if (!name.inversion_mol.empty_b ())
832     mol_p->add_at_edge (X_AXIS, RIGHT, name.inversion_mol, 0);
833   if (!name.bass_mol.empty_b ())
834     mol_p->add_at_edge (X_AXIS, RIGHT, name.bass_mol, 0);
835   return mol_p;
836 }
837
838 void
839 Chord::do_print () const
840 {
841 #ifndef NPRINT
842   //DEBUG_OUT <<  "chord = " ...
843 #endif
844 }