2 chord.cc -- implement Chord
4 source file of the GNU LilyPond music typesetter
6 (c) 1999 Jan Nieuwenhuizen <janneke@gnu.org>
12 Chord::Chord (Array<Musical_pitch> pitch_arr)
14 pitch_arr_ = pitch_arr;
17 // construct from parser output
18 // urg: should split this up into understandable chunks
19 Chord::Chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p)
21 for (int i = 0; i < add_arr_p->size (); i++)
23 Musical_pitch p = tonic;
24 Musical_pitch q = (*add_arr_p)[i];
25 // duh, c7 should mean <c bes>
26 if (q.notename_i_ == 6)
31 add_arr_p->sort (Musical_pitch::compare);
32 for (int i = 0; i < sub_arr_p->size (); i++)
34 Musical_pitch p = tonic;
35 Musical_pitch q = (*sub_arr_p)[i];
36 // duh, c7 should mean <c bes>
37 if (q.notename_i_ == 6)
42 sub_arr_p->sort (Musical_pitch::compare);
44 Musical_pitch third (2);
45 Musical_pitch mthird (2, -1);
46 Musical_pitch missing;
48 missing.transpose (third);
56 must have minimum at 5 (3 is added automatically as missing)
58 if (!add_arr_p->size ())
60 else if ((add_arr_p->top () < p) && (add_arr_p->top ().notename_i_ != p.notename_i_))
62 add_arr_p->sort (Musical_pitch::compare);
64 Array<Musical_pitch> triads;
65 triads.push (third); // c e
66 triads.push (mthird); // d f
67 triads.push (mthird); // e g
68 triads.push (third); // f a
69 triads.push (third); // g b
70 triads.push (mthird); // a c
71 triads.push (mthird); // b d
74 if first addition is 4, assume sus4 and don't add third implicitely
76 Musical_pitch sus (3);
77 sus.transpose (tonic);
78 if (add_arr_p->size ())
79 if ((*add_arr_p)[0] == sus)
80 missing.transpose (mthird);
85 for (int i = 0; i < add_arr_p->size ();)
87 Musical_pitch p = (*add_arr_p)[i];
91 if (p.notename_i_ != missing.notename_i_)
93 if ((missing.notename_i_ - tonic.notename_i_ + 7) % 7 == 6)
95 Musical_pitch special_seven = missing;
96 Musical_pitch lower (0, -1);
97 special_seven.transpose (lower);
98 add_arr_p->insert (special_seven, i++);
101 add_arr_p->insert (missing, i++);
103 missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 7) % 7]);
105 else if (p.notename_i_ == missing.notename_i_)
106 missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 7) % 7]);
114 if (!add_arr_p->size () || ((*add_arr_p)[0] != tonic))
115 add_arr_p->insert (tonic, 0);
118 add all that aren't subtracted
120 for (int i = 0; i < add_arr_p->size (); i++)
122 Musical_pitch p = (*add_arr_p)[i];
124 for (; j < sub_arr_p->size (); j++)
125 if (p == (*sub_arr_p)[j])
131 if (j == sub_arr_p->size ())
135 for (int i = 0; i < sub_arr_p->size (); i++)
136 warning (_f ("invalid subtraction: not part of chord: %s",
137 (*sub_arr_p)[i].str ()));
142 for (; i < pitch_arr_.size (); i++)
143 if ((pitch_arr_[i].notename_i_ == inversion_p->notename_i_)
144 && (pitch_arr_[i].accidental_i_ == inversion_p->accidental_i_))
146 if (i == pitch_arr_.size ())
147 warning (_f ("invalid inversion pitch: not part of chord: %s",
148 inversion_p->str ()));
153 should be run-time switchable "chordInversionPreserve", howto?
155 there are two ways commonly used to rearrange a chord with
158 1. rebuild pitch list, taking inversion as base
161 rebuild_from_base (i);
165 2. insert inversion as lowest (at first position)
167 rebuild_with_bass (i);
175 Chord::banter_str (Musical_pitch* inversion) const
177 Musical_pitch tonic = pitch_arr_[0];
179 Array<Musical_pitch> scale;
180 scale.push (Musical_pitch (0)); // c
181 scale.push (Musical_pitch (1)); // d
182 scale.push (Musical_pitch (2)); // e
183 scale.push (Musical_pitch (3)); // f
184 scale.push (Musical_pitch (4)); // g
185 scale.push (Musical_pitch (5)); // a
186 // 7 always means 7-...
187 scale.push (Musical_pitch (6, -1)); // b
190 for (int i = 0; i < scale.size (); i++)
191 scale[i].transpose (tonic);
193 //urg, should do translation in scheme.
194 char const *acc[] = {"\\textflat\\textflat ", "\\textflat ", "", "\\textsharp " , "\\textsharp\\textsharp "};
195 String tonic_str = tonic.str ();
196 tonic_str = tonic_str.left_str (1).upper_str ()
197 + acc[tonic.accidental_i_ + 2];
204 for (int i=1; i < pitch_arr_.size (); i++)
206 Musical_pitch p = pitch_arr_[i];
207 int trap = p.notename_i_ - tonic.notename_i_
208 + (p.octave_i_ - tonic.octave_i_) * 7;
212 while (trap - last_trap > 2)
215 sub_str += sub_sep_str + "no" + to_str (last_trap);
219 int accidental = p.accidental_i_ - scale[(trap - 1) % 7].accidental_i_;
220 if ((trap == 3) && (accidental == -1))
221 tonic_str += "m"; // hmm
222 else if (accidental || (!(trap % 2) || ((i + 1 == pitch_arr_.size ()) && (trap > 5))))
225 if ((trap == 7) && (accidental == 1))
229 add_str += to_str (trap);
231 add_str += accidental < 0 ? "-" : "+";
232 // catch "C4/no3"; remove "no3"
235 int i = sub_str.index_i ("no3");
237 sub_str = sub_str.nomid_str (i, 3);
238 if (!sub_str.length_i ())
246 String inversion_str;
249 inversion_str = inversion->str ();
250 inversion_str = "/" + inversion_str.left_str (1).upper_str ()
251 + acc[tonic.accidental_i_ + 2];
255 if (sub_str.length_i ())
256 sub_str = sep_str + sub_str;
257 String str = tonic_str + "$^{" + add_str + sub_str + "}$" + inversion_str;
262 Chord::find_tonic_i () const
267 first try: base of longest line of triads
271 for (int i = 0; i < pitch_arr_.size (); i++)
274 int last_i = pitch_arr_[i % pitch_arr_.size ()].notename_i_;
276 for (; j < pitch_arr_.size (); j++)
278 int cur_i = pitch_arr_[(i + j + 1) % pitch_arr_.size ()].notename_i_;
279 int gap = cur_i - last_i;
288 if (j - no_triad_i > longest_i)
290 longest_i = j - no_triad_i;
296 second try: note after biggest gap
301 for (int i = 0; i < pitch_arr_.size (); i++)
303 int gap = pitch_arr_[i].notename_i_
304 - pitch_arr_[(i - 1 + pitch_arr_.size ())
305 % pitch_arr_.size ()].notename_i_;
319 Chord::rebuild_from_base (int base_i)
321 Musical_pitch last (0, 0, -5);
322 Array<Musical_pitch> new_arr;
323 for (int i = 0; i < pitch_arr_.size (); i++)
325 Musical_pitch p = pitch_arr_[(base_i + i) % pitch_arr_.size ()];
328 p.octave_i_ = last.octave_i_;
335 pitch_arr_ = new_arr;
339 Chord::rebuild_insert_inversion (int tonic_i)
341 Musical_pitch inversion = pitch_arr_.get (0);
342 rebuild_from_base (tonic_i - 1);
343 if (pitch_arr_.size ())
345 inversion.octave_i_ = pitch_arr_[0].octave_i_ - 1;
346 while (inversion < pitch_arr_[0])
347 inversion.octave_i_++;
349 for (int i = 0; i < pitch_arr_.size (); i++)
350 if (pitch_arr_[i] > inversion)
352 pitch_arr_.insert (inversion, i);
358 Chord::rebuild_with_bass (int bass_i)
360 Musical_pitch inversion = pitch_arr_.get (bass_i);
361 // is lowering fine, or should others be raised?
362 if (pitch_arr_.size ())
363 while (inversion > pitch_arr_[0])
364 inversion.octave_i_--;
365 pitch_arr_.insert (inversion, 0);