lilypond-1.5.2
[lilypond.git] / lily / pitch.cc
blobaa7774debce072ce1de914f0da4af462446dfc61
1 /*
2 musical-pitch.cc -- implement Pitch
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
9 #include "pitch.hh"
10 #include "debug.hh"
11 #include "main.hh"
12 #include "ly-smobs.icc"
16 Pitch::Pitch (int o, int n, int a)
18 notename_i_ = n;
19 alteration_i_ = a;
20 octave_i_ = o;
22 if (n < 0 || n >= 7 ||
23 a < -2 || a > 2)
25 String s = _ ("Pitch arguments out of range");
26 s += ": alteration = " + to_str (a);
27 s += ", notename = " + to_str (n);
28 warning (s);
30 normalise ();
33 Pitch::Pitch ()
35 notename_i_ = 0;
36 alteration_i_ = 0;
37 octave_i_ = 0;
40 int
41 Pitch::compare (Pitch const &m1, Pitch const &m2)
43 int o= m1.octave_i_ - m2.octave_i_;
44 int n = m1.notename_i_ - m2.notename_i_;
45 int a = m1.alteration_i_ - m2.alteration_i_;
47 if (o)
48 return o;
49 if (n)
50 return n;
51 if (a)
52 return a;
53 return 0;
56 int
57 Pitch::steps () const
59 return notename_i_ + octave_i_*7;
63 should be settable from input?
65 static Byte pitch_byte_a[ ] = { 0, 2, 4, 5, 7, 9, 11 };
68 /* Calculate pitch height in 12th octave steps. Don't assume
69 normalised pitch as this function is used to normalise the pitch. */
70 int
71 Pitch::semitone_pitch () const
73 int o = octave_i_;
74 int n = notename_i_;
75 while (n < 0)
77 n += 7;
78 o --;
80 return (o + n / 7) * 12 + pitch_byte_a[n % 7] + alteration_i_;
83 void
84 Pitch::normalise ()
86 int pitch = semitone_pitch ();
87 while (notename_i_ >= 7)
89 notename_i_ -= 7;
90 octave_i_++;
91 alteration_i_ -= semitone_pitch () - pitch;
93 while (notename_i_ < 0)
95 notename_i_ += 7;
96 octave_i_--;
97 alteration_i_ -= semitone_pitch () - pitch;
99 while (alteration_i_ >= 3)
101 if (notename_i_ == 6)
103 notename_i_ = 0;
104 octave_i_++;
106 else
107 notename_i_++;
109 alteration_i_ = 0;
110 alteration_i_ -= semitone_pitch () - pitch;
112 while (alteration_i_ <= -3)
114 if (notename_i_ == 0)
116 notename_i_ = 6;
117 octave_i_--;
119 else
120 notename_i_--;
122 alteration_i_ = 0;
123 alteration_i_ -= semitone_pitch () - pitch;
127 /* WHugh, wat een intervaas */
128 void
129 Pitch::transpose (Pitch delta)
131 int old_semi = semitone_pitch ();
132 int delta_semi = delta.semitone_pitch ();
133 octave_i_ += delta.octave_i_;
134 notename_i_ += delta.notename_i_;
136 int new_semi = semitone_pitch ();
137 int delta_acc = new_semi - old_semi - delta_semi;
138 alteration_i_ -= delta_acc;
140 normalise ();
144 /* FIXME
145 Merge with *pitch->text* funcs in chord-name.scm
147 char const *accname[] = {"eses", "es", "", "is" , "isis"};
149 String
150 Pitch::str () const
152 int n = (notename_i_ + 2) % 7;
153 String s = to_str (char (n + 'a'));
154 if (alteration_i_)
155 s += String (accname[alteration_i_ + 2]);
157 if (octave_i_ > 0)
159 int o = octave_i_ + 1;
160 while (o--)
161 s += "'";
163 else if (octave_i_ <0)
165 int o = (-octave_i_) - 1;
166 while (o--)
167 s += to_str (',');
170 return s;
174 change me to relative, counting from last pitch p
175 return copy of resulting pitch
177 Pitch
178 Pitch::to_relative_octave (Pitch p)
180 int oct_mod = octave_i_ + 1; // account for c' = octave 1 iso. 0 4
181 Pitch up_pitch (p);
182 Pitch down_pitch (p);
184 up_pitch.alteration_i_ = alteration_i_;
185 down_pitch.alteration_i_ = alteration_i_;
187 Pitch n = *this;
188 up_pitch.up_to (notename_i_);
189 down_pitch.down_to (notename_i_);
191 int h = p.steps ();
192 if (abs (up_pitch.steps () - h) < abs (down_pitch.steps () - h))
193 n = up_pitch;
194 else
195 n = down_pitch;
197 n.octave_i_ += oct_mod;
199 *this = n;
200 return *this;
203 void
204 Pitch::up_to (int notename)
206 if (notename_i_ > notename)
208 octave_i_ ++;
210 notename_i_ = notename;
213 void
214 Pitch::down_to (int notename)
216 if (notename_i_ < notename)
218 octave_i_ --;
220 notename_i_ = notename;
223 ///MAKE_SCHEME_CALLBACK (Pitch, transpose, 2);
224 ///transpose_proc?
226 Pitch::transpose (SCM p, SCM delta)
228 Pitch t = *unsmob_pitch (p);
229 t.transpose (*unsmob_pitch (delta));
230 return t.smobbed_copy ();
233 static SCM
234 pitch_transpose (SCM p, SCM delta)
236 return Pitch::transpose (p, delta);
239 /****************************************************************/
242 IMPLEMENT_TYPE_P (Pitch, "pitch?");
243 IMPLEMENT_UNSMOB (Pitch, pitch);
245 Pitch::mark_smob (SCM)
247 return SCM_EOL;
250 IMPLEMENT_SIMPLE_SMOBS (Pitch);
254 Pitch::print_smob (SCM s, SCM port, scm_print_state *)
256 Pitch *r = (Pitch *) gh_cdr (s);
258 scm_puts ("#<Pitch ", port);
259 scm_display (ly_str02scm (r->str ().ch_C ()), port);
260 scm_puts (" >", port);
262 return 1;
266 Pitch::equal_p (SCM a , SCM b)
268 Pitch *p = (Pitch *) gh_cdr (a);
269 Pitch *q = (Pitch *) gh_cdr (b);
271 bool eq = p->notename_i_ == q->notename_i_
272 && p->octave_i_ == q->octave_i_
273 && p->alteration_i_ == q->alteration_i_;
275 return eq ? SCM_BOOL_T : SCM_BOOL_F;
278 MAKE_SCHEME_CALLBACK (Pitch, less_p, 2);
280 Pitch::less_p (SCM p1, SCM p2)
282 Pitch *a = unsmob_pitch (p1);
283 Pitch *b = unsmob_pitch (p2);
285 if (compare (*a, *b) < 0)
286 return SCM_BOOL_T;
287 else
288 return SCM_BOOL_F;
292 should add optional args
295 static SCM
296 make_pitch (SCM o, SCM n, SCM a)
298 Pitch p (gh_scm2int (o), gh_scm2int (n), gh_scm2int (a));
299 return p.smobbed_copy ();
302 static SCM
303 pitch_octave (SCM pp)
305 Pitch *p = unsmob_pitch (pp);
306 int q = 0;
307 if (!p)
308 warning ("Not a pitch");
309 else
310 q = p->octave_i ();
312 return gh_int2scm (q);
315 static SCM
316 pitch_alteration (SCM pp)
318 Pitch *p = unsmob_pitch (pp);
319 int q = 0;
320 if (!p)
321 warning ("Not a pitch");
322 else
323 q = p->alteration_i ();
325 return gh_int2scm (q);
328 static SCM
329 pitch_notename (SCM pp)
331 Pitch *p = unsmob_pitch (pp);
332 int q = 0;
333 if (!p)
334 warning ("Not a pitch");
335 else
336 q = p->notename_i ();
338 return gh_int2scm (q);
341 static SCM
342 pitch_semitones (SCM pp)
344 Pitch *p = unsmob_pitch (pp);
345 int q = 0;
346 if (!p)
347 warning ("Not a pitch");
348 else
349 q = p->steps ();
351 return gh_int2scm (q);
354 static void
355 add_funcs ()
357 // should take list?: (make-pitch ' (octave name accidental))
358 scm_c_define_gsubr ("make-pitch", 3, 0, 0, (Scheme_function_unknown)make_pitch);
360 scm_c_define_gsubr ("pitch-octave", 1, 0, 0, (Scheme_function_unknown)pitch_octave);
361 scm_c_define_gsubr ("pitch-notename", 1, 0, 0, (Scheme_function_unknown)pitch_notename);
362 scm_c_define_gsubr ("pitch-alteration", 1, 0, 0, (Scheme_function_unknown)pitch_alteration);
363 scm_c_define_gsubr ("pitch-semitones", 1, 0, 0, (Scheme_function_unknown)pitch_semitones);
364 scm_c_define_gsubr ("Pitch::transpose", 2, 0, 0, (Scheme_function_unknown) pitch_transpose);
367 ADD_SCM_INIT_FUNC (pitch, add_funcs);
370 Pitch::smobbed_copy ()const
372 Pitch * p = new Pitch (*this);
373 return p->smobbed_self ();
377 Pitch::octave_i ()const
379 return octave_i_;
383 Pitch::notename_i () const
385 return notename_i_;
389 Pitch::alteration_i () const
391 return alteration_i_;