]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord.cc
patch::: 1.3.4.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 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     mol.add_at_edge (X_AXIS, RIGHT, 
498                      paper_l ()->lookup_l (-2)->accidental (p.accidental_i_, 0), 0);
499   return mol;
500 }
501
502 Musical_pitch
503 diff_pitch (Musical_pitch tonic, Musical_pitch  p)
504 {
505   Musical_pitch diff (p.notename_i_ - tonic.notename_i_, 
506     p.accidental_i_ - tonic.accidental_i_, 
507     p.octave_i_ - tonic.octave_i_);
508
509   while  (diff.notename_i_ >= 7)
510     {
511       diff.notename_i_ -= 7;
512       diff.octave_i_ ++;
513     }
514   while  (diff.notename_i_ < 0)
515     {
516       diff.notename_i_ += 7;
517       diff.octave_i_ --;
518     }
519
520   diff.accidental_i_ -= (tonic.semitone_pitch () + diff.semitone_pitch ())
521     - p.semitone_pitch ();
522
523   return diff;
524 }
525
526 bool
527 Chord::user_chord_name (Array<Musical_pitch> pitch_arr, Chord_name* name_p) const
528 {
529   SCM chord = SCM_EOL;
530   Array<Musical_pitch> chord_type = pitch_arr;
531   rebuild_transpose (&chord_type, diff_pitch (pitch_arr[0], Musical_pitch (0)), false);
532
533   for (int i= chord_type.size (); i--; )
534     chord = gh_cons (pitch2scm (chord_type[i]), chord);
535
536   SCM name = scm_eval (gh_list (gh_symbol2scm ("user-chord-name"), ly_quote_scm (chord), SCM_UNDEFINED));
537   if (name != SCM_UNSPECIFIED)
538     {
539       name_p->modifier_mol = ly_text2molecule (gh_car (name));
540       name_p->addition_mol = ly_text2molecule (gh_cdr (name));
541       return true;
542     }
543   return false;
544 }
545
546 void
547 Chord::banter (Array<Musical_pitch> pitch_arr, Chord_name* name_p) const
548 {
549   Array<Musical_pitch> add_arr;
550   Array<Musical_pitch> sub_arr;
551   find_additions_and_subtractions (pitch_arr, &add_arr, &sub_arr);
552                            
553   Array<Musical_pitch> scale;
554   for (int i=0; i < 7; i++)
555     scale.push (Musical_pitch (i));
556
557   Musical_pitch tonic = pitch_arr[0];
558   rebuild_transpose (&scale, tonic, true);
559   
560   /*
561     Does chord include this step?  -1 if flat
562    */
563   int has[16];
564   for (int i=0; i<16; i++)
565     has[i] = 0;
566
567   String mod_str;
568   String add_str;
569   String sep_str;
570   for (int i = 0; i < add_arr.size (); i++)
571     {
572       Musical_pitch p = add_arr[i];
573       int step = step_i (tonic, p);
574       int accidental = p.accidental_i_ - scale[(step - 1) % 7].accidental_i_;
575       if ((step < 16) && (has[step] != -1))
576         has[step] = accidental == -1 ? -1 : 1;
577       // only from guile table ?
578       if ((step == 3) && (accidental == -1))
579         {
580           mod_str = "m";
581         }
582       else if (accidental
583                || (!(step % 2) 
584                || ((i == add_arr.size () - 1) && (step > 5))))
585         {
586           add_str += sep_str;
587           sep_str = "/";
588           if ((step == 7) && (accidental == 1))
589             {
590               add_str += "maj7";
591             }
592           else
593             {
594               add_str += to_str (step);
595               if (accidental)
596                 add_str += accidental < 0 ? "-" : "+";
597             }
598         }
599     }
600
601   for (int i = 0; i < sub_arr.size (); i++)
602     {
603       Musical_pitch p = sub_arr[i];
604       int step = step_i (tonic, p);
605       /*
606         if additions include 2 or 4, assume sus2/4 and don't display 'no3'
607       */
608       if (!((step == 3) && (has[2] || has[4])))
609         {
610           add_str += sep_str + "no" + to_str (step);
611           sep_str = "/";
612         }
613     }
614
615   if (mod_str.length_i ())
616     name_p->modifier_mol.add_at_edge (X_AXIS, RIGHT, 
617       lookup_l ()->text ("roman", mod_str, paper_l ()), 0);
618   if (add_str.length_i ())
619     {
620       if (!name_p->addition_mol.empty_b ())
621         add_str = "/" + add_str;
622       name_p->addition_mol.add_at_edge (X_AXIS, RIGHT,
623        lookup_l ()->text ("script", add_str, paper_l ()), 0);
624     }
625 }
626
627 /*
628   This routine tries to guess tonic in a possibly inversed chord, ie
629   <e g c'> should produce: C.
630   This is only used for chords that are entered as simultaneous notes,
631   chords entered in \chord mode are fully defined.
632  */
633 int
634 Chord::find_tonic_i (Array<Musical_pitch> const* pitch_arr_p)
635 {
636   /*
637     find tonic
638     
639     first try: base of longest line of thirds
640    */
641   int tonic_i = 0;
642   int longest_i = 0;
643   for (int i = 0; i < pitch_arr_p->size (); i++)
644     {
645       int no_third_i = 0;
646       int last_i = (*pitch_arr_p)[i % pitch_arr_p->size ()].notename_i_;
647       int j = 0;
648       for (; j < pitch_arr_p->size (); j++)
649         {
650           int cur_i = (*pitch_arr_p)[(i + j + 1) % pitch_arr_p->size ()].notename_i_;
651           int gap = cur_i - last_i;
652           while (gap < 0)
653             gap += 7;
654           gap %= 7;
655           if (gap == 2)
656             last_i = cur_i;
657           else
658             no_third_i++;
659         }
660       if (j - no_third_i > longest_i)
661         {
662           longest_i = j - no_third_i;
663           tonic_i = i;
664         }
665     }
666
667   /*
668     second try: note after biggest gap
669    */
670   int biggest_i = 0;
671   //  if (longest_i)
672   if (longest_i <= 1)
673     for (int i = 0; i < pitch_arr_p->size (); i++)
674       {
675         int gap = (*pitch_arr_p)[i].notename_i_
676           - (*pitch_arr_p)[(i - 1 + pitch_arr_p->size ()) 
677           % pitch_arr_p->size ()].notename_i_;
678         while (gap < 0)
679           gap += 7;
680         gap %= 7;
681         if (gap > biggest_i)
682           {
683             biggest_i = gap;
684             tonic_i = i;
685           }
686       }
687   return tonic_i;
688 }
689
690 void
691 Chord::rebuild_from_base (Array<Musical_pitch>* pitch_arr_p, int base_i)
692 {
693   assert (base_i >= 0);
694   Musical_pitch last (0, 0, -5);
695   Array<Musical_pitch> new_arr;
696   for (int i = 0; i < pitch_arr_p->size (); i++)
697     {
698       Musical_pitch p = (*pitch_arr_p)[(base_i + i) % pitch_arr_p->size ()];
699       if (p < last)
700         {
701           p.octave_i_ = last.octave_i_;
702           if (p < last)
703             p.octave_i_++;
704         }
705       new_arr.push (p);
706       last = p;
707     }
708   *pitch_arr_p = new_arr;
709 }
710
711 void
712 Chord::rebuild_insert_inversion (Array<Musical_pitch>* pitch_arr_p, int tonic_i)
713 {
714   assert (tonic_i > 0);
715   Musical_pitch inversion = pitch_arr_p->get (0);
716   rebuild_from_base (pitch_arr_p, tonic_i - 1);
717   if (pitch_arr_p->size ())
718     {
719       inversion.octave_i_ = (*pitch_arr_p)[0].octave_i_ - 1;
720       while (inversion < (*pitch_arr_p)[0])
721         inversion.octave_i_++;
722     }
723   for (int i = 0; i < pitch_arr_p->size (); i++)
724     if ((*pitch_arr_p)[i] > inversion)
725       {
726         pitch_arr_p->insert (inversion, i);
727         break;
728       }
729 }
730
731 void
732 Chord::rebuild_with_bass (Array<Musical_pitch>* pitch_arr_p, int bass_i)
733 {
734   assert (bass_i >= 0);
735   Musical_pitch bass = pitch_arr_p->get (bass_i);
736   // is lowering fine, or should others be raised?
737   if (pitch_arr_p->size ())
738     while (bass > (*pitch_arr_p)[0])
739       bass.octave_i_--;
740   pitch_arr_p->insert (bass, 0);
741 }
742
743 Molecule*
744 Chord::do_brew_molecule_p () const
745 {
746   Musical_pitch tonic = pitch_arr_[0];
747   
748   Chord_name name;
749   name.tonic_mol = pitch2molecule (tonic);
750
751   /*
752     if user has explicitely listed chord name, use that
753     
754     TODO
755     urg
756     maybe we should check all sub-lists of pitches, not
757     just full list and base triad?
758    */
759   if (!user_chord_name (pitch_arr_, &name))
760     {
761       /*
762         else, check if user has listed base triad
763         use user base name and add banter for remaining part
764        */
765       if ((pitch_arr_.size () > 2)
766           && user_chord_name (pitch_arr_.slice (0, 3), &name))
767         {
768           Array<Musical_pitch> base = base_arr (tonic);
769           base.concat (pitch_arr_.slice (3, pitch_arr_.size ()));
770           banter (base, &name);
771         }
772       /*
773         else, use pure banter
774        */
775       else
776         {
777           banter (pitch_arr_, &name);
778         }
779     }
780
781   if (inversion_p_)
782     {
783       name.inversion_mol = lookup_l ()->text ("", "/", paper_l ());
784       // zucht  const&
785       Molecule mol = pitch2molecule (*inversion_p_);
786       name.inversion_mol.add_at_edge (X_AXIS, RIGHT, mol, 0);
787     }
788
789   if (bass_p_)
790     {
791       name.bass_mol = lookup_l ()->text ("", "/", paper_l ());
792       Molecule mol = pitch2molecule (*bass_p_);
793       name.bass_mol.add_at_edge (X_AXIS, RIGHT, mol, 0);
794     }
795
796   // urg, howto get a good superscript_y?
797   Real super_y = lookup_l ()->text ("", "x", paper_l ()).dim_.y ().length ()/2;
798   if (!name.addition_mol.empty_b ())
799     name.addition_mol.translate (Offset (0, super_y));
800
801   Molecule* mol_p = new Molecule;
802   mol_p->add_at_edge (X_AXIS, RIGHT, name.tonic_mol, 0);
803   // huh?
804   if (!name.modifier_mol.empty_b ())
805     mol_p->add_at_edge (X_AXIS, RIGHT, name.modifier_mol, 0);
806   if (!name.addition_mol.empty_b ())
807     mol_p->add_at_edge (X_AXIS, RIGHT, name.addition_mol, 0);
808   if (!name.inversion_mol.empty_b ())
809     mol_p->add_at_edge (X_AXIS, RIGHT, name.inversion_mol, 0);
810   if (!name.bass_mol.empty_b ())
811     mol_p->add_at_edge (X_AXIS, RIGHT, name.bass_mol, 0);
812   return mol_p;
813 }
814
815 void
816 Chord::do_print () const
817 {
818 #ifndef NPRINT
819   //DEBUG_OUT <<  "chord = " ...
820 #endif
821 }