2 chord-name.cc -- implement Chord_name
4 source file of the GNU LilyPond music typesetter
6 (c) 1999 Jan Nieuwenhuizen <janneke@gnu.org>
9 #include "chord-name.hh"
10 #include "musical-request.hh"
13 #include "molecule.hh"
14 #include "paper-def.hh"
18 pitch2scm (Musical_pitch p)
20 return gh_cons (gh_int2scm (p.notename_i_), gh_int2scm (p.accidental_i_));
23 Chord_name::Chord_name (Chord const& c)
29 word is roman text or styled text:
34 Chord_name::ly_word2molecule (SCM scm) const
39 style = ly_scm2string (gh_car (scm));
42 String text = ly_scm2string (scm);
43 return lookup_l ()->text (style, text, paper_l ());
47 scm is word or list of words:
52 Chord_name::ly_text2molecule (SCM scm) const
57 while (gh_cdr (scm) != SCM_EOL)
59 mol.add_at_edge (X_AXIS, RIGHT,
60 ly_word2molecule (gh_car (scm)), 0);
65 mol.add_at_edge (X_AXIS, RIGHT,
66 ly_word2molecule (scm), 0);
71 Chord_name::pitch2molecule (Musical_pitch p) const
73 SCM name = scm_eval (gh_list (ly_symbol2scm ("user-pitch-name"), ly_quote_scm (pitch2scm (p)), SCM_UNDEFINED));
75 if (name != SCM_UNSPECIFIED)
77 return ly_text2molecule (name);
80 Molecule mol = lookup_l ()->text ("", p.str ().left_str (1).upper_str (), paper_l ());
83 We want the smaller size, even if we're big ourselves.
86 mol.add_at_edge (X_AXIS, RIGHT,
88 paper_l ()->lookup_l (-2)->afm_find (String ("accidentals-") + to_str (p.accidental_i_)), 0.0);
93 diff_pitch (Musical_pitch tonic, Musical_pitch p)
95 Musical_pitch diff (p.notename_i_ - tonic.notename_i_,
96 p.accidental_i_ - tonic.accidental_i_,
97 p.octave_i_ - tonic.octave_i_);
99 while (diff.notename_i_ >= 7)
101 diff.notename_i_ -= 7;
104 while (diff.notename_i_ < 0)
106 diff.notename_i_ += 7;
110 diff.accidental_i_ -= (tonic.semitone_pitch () + diff.semitone_pitch ())
111 - p.semitone_pitch ();
117 Chord_name::user_chord_name (Array<Musical_pitch> pitch_arr, Chord_mol* name_p) const
120 Array<Musical_pitch> chord_type = pitch_arr;
121 Chord::rebuild_transpose (&chord_type, diff_pitch (pitch_arr[0], Musical_pitch (0)), false);
123 for (int i= chord_type.size (); i--; )
124 chord = gh_cons (pitch2scm (chord_type[i]), chord);
126 SCM name = scm_eval (gh_list (ly_symbol2scm ("user-chord-name"), ly_quote_scm (chord), SCM_UNDEFINED));
127 if (gh_pair_p (name))
129 name_p->modifier_mol = ly_text2molecule (gh_car (name));
130 name_p->addition_mol = ly_text2molecule (gh_cdr (name));
137 Chord_name::banter (Array<Musical_pitch> pitch_arr, Chord_mol* name_p) const
139 Array<Musical_pitch> add_arr;
140 Array<Musical_pitch> sub_arr;
141 Chord::find_additions_and_subtractions (pitch_arr, &add_arr, &sub_arr);
143 Array<Musical_pitch> scale;
144 for (int i=0; i < 7; i++)
145 scale.push (Musical_pitch (i));
147 Musical_pitch tonic = pitch_arr[0];
148 chord_.rebuild_transpose (&scale, tonic, true);
151 Does chord include this step? -1 if flat
154 for (int i=0; i<16; i++)
160 for (int i = 0; i < add_arr.size (); i++)
162 Musical_pitch p = add_arr[i];
163 int step = Chord::step_i (tonic, p);
164 int accidental = p.accidental_i_ - scale[(step - 1) % 7].accidental_i_;
165 if ((step < 16) && (has[step] != -1))
166 has[step] = accidental == -1 ? -1 : 1;
167 // only from guile table ?
168 if ((step == 3) && (accidental == -1))
174 || ((i == add_arr.size () - 1) && (step > 5))))
178 if ((step == 7) && (accidental == 1))
184 add_str += to_str (step);
186 add_str += accidental < 0 ? "-" : "+";
191 for (int i = 0; i < sub_arr.size (); i++)
193 Musical_pitch p = sub_arr[i];
194 int step = Chord::step_i (tonic, p);
196 if additions include 2 or 4, assume sus2/4 and don't display 'no3'
198 if (!((step == 3) && (has[2] || has[4])))
200 add_str += sep_str + "no" + to_str (step);
205 if (mod_str.length_i ())
206 name_p->modifier_mol.add_at_edge (X_AXIS, RIGHT,
207 lookup_l ()->text ("roman", mod_str, paper_l ()), 0);
208 if (add_str.length_i ())
210 if (!name_p->addition_mol.empty_b ())
211 add_str = "/" + add_str;
212 name_p->addition_mol.add_at_edge (X_AXIS, RIGHT,
213 lookup_l ()->text ("script", add_str, paper_l ()), 0);
218 Chord_name::do_brew_molecule_p () const
220 Musical_pitch tonic = chord_.pitch_arr_[0];
223 name.tonic_mol = pitch2molecule (tonic);
226 if user has explicitely listed chord name, use that
230 maybe we should check all sub-lists of pitches, not
231 just full list and base triad?
233 if (!user_chord_name (chord_.pitch_arr_, &name))
236 else, check if user has listed base triad
237 use user base name and add banter for remaining part
239 if ((chord_.pitch_arr_.size () > 2)
240 && user_chord_name (chord_.pitch_arr_.slice (0, 3), &name))
242 Array<Musical_pitch> base = Chord::base_arr (tonic);
243 base.concat (chord_.pitch_arr_.slice (3, chord_.pitch_arr_.size ()));
244 banter (base, &name);
247 else, use pure banter
251 banter (chord_.pitch_arr_, &name);
255 if (chord_.inversion_b_)
257 name.inversion_mol = lookup_l ()->text ("", "/", paper_l ());
259 Molecule mol = pitch2molecule (chord_.inversion_pitch_);
260 name.inversion_mol.add_at_edge (X_AXIS, RIGHT, mol, 0);
265 name.bass_mol = lookup_l ()->text ("", "/", paper_l ());
266 Molecule mol = pitch2molecule (chord_.bass_pitch_);
267 name.bass_mol.add_at_edge (X_AXIS, RIGHT, mol, 0);
270 // urg, howto get a good superscript_y?
271 Real super_y = lookup_l ()->text ("", "x", paper_l ()).dim_.y ().length ()/2;
272 if (!name.addition_mol.empty_b ())
273 name.addition_mol.translate (Offset (0, super_y));
275 Molecule* mol_p = new Molecule;
276 mol_p->add_at_edge (X_AXIS, RIGHT, name.tonic_mol, 0);
278 if (!name.modifier_mol.empty_b ())
279 mol_p->add_at_edge (X_AXIS, RIGHT, name.modifier_mol, 0);
280 if (!name.addition_mol.empty_b ())
281 mol_p->add_at_edge (X_AXIS, RIGHT, name.addition_mol, 0);
282 if (!name.inversion_mol.empty_b ())
283 mol_p->add_at_edge (X_AXIS, RIGHT, name.inversion_mol, 0);
284 if (!name.bass_mol.empty_b ())
285 mol_p->add_at_edge (X_AXIS, RIGHT, name.bass_mol, 0);