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>
12 #include "ly-smobs.icc"
16 Pitch::Pitch (int o, int n, int a)
22 if (n < 0 || n >= 7 ||
25 String s = _("Pitch arguments out of range");
26 s += ": alteration = " + to_str (a);
27 s += ", notename = " + to_str (n);
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_;
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 sign_safe_div (int n, int d)
71 return - (-n / d) - 1;
75 /* Calculate pitch height in 12th octave steps. Don't assume
76 normalised pitch as this function is used to normalise the pitch. */
78 Pitch::semitone_pitch () const
80 return (octave_i_ + sign_safe_div (notename_i_, 7)) * 12
81 + pitch_byte_a[notename_i_ % 7]
88 int pitch = semitone_pitch ();
89 while (notename_i_ >= 7)
93 alteration_i_ -= semitone_pitch () - pitch;
95 while (notename_i_ < 0)
99 alteration_i_ -= semitone_pitch () - pitch;
101 while (alteration_i_ >= 3)
103 if (notename_i_ == 6)
112 alteration_i_ -= semitone_pitch () - pitch;
114 while (alteration_i_ <= -3)
116 if (notename_i_ == 0)
125 alteration_i_ -= semitone_pitch () - pitch;
129 /* WHugh, wat een intervaas */
131 Pitch::transpose (Pitch delta)
133 int old_semi = semitone_pitch ();
134 int delta_semi = delta.semitone_pitch ();
135 octave_i_ += delta.octave_i_;
136 notename_i_ += delta.notename_i_;
138 int new_semi = semitone_pitch ();
139 int delta_acc = new_semi - old_semi - delta_semi;
140 alteration_i_ -= delta_acc;
147 Merge with *pitch->text* funcs in chord-name.scm
149 char const *accname[] = {"eses", "es", "", "is" , "isis"};
154 int n = (notename_i_ + 2) % 7;
155 String s = to_str (char(n + 'a'));
157 s += String (accname[alteration_i_ + 2]);
161 int o = octave_i_ + 1;
165 else if (octave_i_ <0)
167 int o = (-octave_i_) - 1;
176 change me to relative, counting from last pitch p
177 return copy of resulting pitch
180 Pitch::to_relative_octave (Pitch p)
182 int oct_mod = octave_i_ + 1; // account for c' = octave 1 iso. 0 4
184 Pitch down_pitch (p);
186 up_pitch.alteration_i_ = alteration_i_;
187 down_pitch.alteration_i_ = alteration_i_;
190 up_pitch.up_to (notename_i_);
191 down_pitch.down_to (notename_i_);
194 if (abs (up_pitch.steps () - h) < abs (down_pitch.steps () - h))
199 n.octave_i_ += oct_mod;
206 Pitch::up_to (int notename)
208 if (notename_i_ > notename)
212 notename_i_ = notename;
216 Pitch::down_to (int notename)
218 if (notename_i_ < notename)
222 notename_i_ = notename;
225 ///MAKE_SCHEME_CALLBACK (Pitch, transpose, 2);
228 Pitch::transpose (SCM p, SCM delta)
230 Pitch t = *unsmob_pitch (p);
231 t.transpose (*unsmob_pitch (delta));
232 return t.smobbed_copy ();
236 pitch_transpose (SCM p, SCM delta)
238 return Pitch::transpose (p, delta);
241 /****************************************************************/
244 IMPLEMENT_TYPE_P(Pitch, "pitch?");
245 IMPLEMENT_UNSMOB(Pitch, pitch);
247 Pitch::mark_smob (SCM )
252 IMPLEMENT_SIMPLE_SMOBS(Pitch);
256 Pitch::print_smob (SCM s, SCM port, scm_print_state *)
258 Pitch *r = (Pitch *) gh_cdr (s);
260 scm_puts ("#<Pitch ", port);
261 scm_display (ly_str02scm (r->str().ch_C()), port);
262 scm_puts (" >", port);
268 Pitch::equal_p (SCM a , SCM b)
270 Pitch *p = (Pitch *) gh_cdr (a);
271 Pitch *q = (Pitch *) gh_cdr (b);
273 bool eq = p->notename_i_ == q->notename_i_
274 && p->octave_i_ == q->octave_i_
275 && p->alteration_i_ == q->alteration_i_;
277 return eq ? SCM_BOOL_T : SCM_BOOL_F;
280 MAKE_SCHEME_CALLBACK(Pitch, less_p, 2);
282 Pitch::less_p (SCM p1, SCM p2)
284 Pitch *a = unsmob_pitch (p1);
285 Pitch *b = unsmob_pitch (p2);
287 if (compare(*a, *b) < 0 )
294 should add optional args
298 make_pitch (SCM o, SCM n, SCM a)
300 Pitch p (gh_scm2int (o), gh_scm2int (n), gh_scm2int (a));
301 return p.smobbed_copy ();
305 pitch_octave (SCM pp)
307 Pitch *p = unsmob_pitch (pp);
310 warning ("Not a pitch");
314 return gh_int2scm (q);
318 pitch_alteration (SCM pp)
320 Pitch *p = unsmob_pitch (pp);
323 warning ("Not a pitch");
325 q = p->alteration_i();
327 return gh_int2scm (q);
331 pitch_notename (SCM pp)
333 Pitch *p = unsmob_pitch (pp);
336 warning ("Not a pitch");
340 return gh_int2scm (q);
344 pitch_semitones (SCM pp)
346 Pitch *p = unsmob_pitch (pp);
349 warning ("Not a pitch");
353 return gh_int2scm (q);
359 // should take list?: (make-pitch '(octave name accidental))
360 scm_make_gsubr ("make-pitch", 3, 0, 0, (Scheme_function_unknown)make_pitch);
362 scm_make_gsubr ("pitch-octave", 1, 0, 0, (Scheme_function_unknown)pitch_octave);
363 scm_make_gsubr ("pitch-notename", 1, 0, 0, (Scheme_function_unknown)pitch_notename);
364 scm_make_gsubr ("pitch-alteration", 1, 0, 0, (Scheme_function_unknown)pitch_alteration);
365 scm_make_gsubr ("pitch-semitones", 1, 0, 0, (Scheme_function_unknown)pitch_semitones);
366 scm_make_gsubr ("Pitch::transpose", 2, 0, 0, (Scheme_function_unknown) pitch_transpose);
369 ADD_SCM_INIT_FUNC(pitch, add_funcs);
372 Pitch::smobbed_copy ()const
374 Pitch * p = new Pitch (*this);
375 return p->smobbed_self ();
379 Pitch::octave_i ()const
385 Pitch::notename_i () const
391 Pitch::alteration_i () const
393 return alteration_i_;