release commit
[lilypond.git] / lily / pitch.cc
blob895f18ef6265fe5c80308d044134e12d533fe86e
1 /*
2 musical-pitch.cc -- implement Pitch
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
9 #include "pitch.hh"
10 #include "warn.hh"
11 #include "main.hh"
12 #include "ly-smobs.icc"
16 Pitch::Pitch (int o, int n, int a)
18 notename_ = n;
19 alteration_ = a;
20 octave_ = o;
21 normalise ();
24 Pitch::Pitch ()
26 notename_ = 0;
27 alteration_ = 0;
28 octave_ = 0;
31 int
32 Pitch::compare (Pitch const &m1, Pitch const &m2)
34 int o= m1.octave_ - m2.octave_;
35 int n = m1.notename_ - m2.notename_;
36 int a = m1.alteration_ - m2.alteration_;
38 if (o)
39 return o;
40 if (n)
41 return n;
42 if (a)
43 return a;
44 return 0;
47 int
48 Pitch::steps () const
50 return notename_ + octave_*7;
54 should be settable from input?
56 static Byte pitch_byte_a[ ] = { 0, 2, 4, 5, 7, 9, 11 };
59 /* Calculate pitch height in 12th octave steps. Don't assume
60 normalised pitch as this function is used to normalise the pitch. */
61 int
62 Pitch::semitone_pitch () const
64 int o = octave_;
65 int n = notename_;
66 while (n < 0)
68 n += 7;
69 o --;
71 return (o + n / 7) * 12 + pitch_byte_a[n % 7] + alteration_;
74 void
75 Pitch::normalise ()
77 int pitch = semitone_pitch ();
78 while (notename_ >= 7)
80 notename_ -= 7;
81 octave_++;
82 alteration_ -= semitone_pitch () - pitch;
84 while (notename_ < 0)
86 notename_ += 7;
87 octave_--;
88 alteration_ -= semitone_pitch () - pitch;
90 while (alteration_ >= 3)
92 if (notename_ == 6)
94 notename_ = 0;
95 octave_++;
97 else
98 notename_++;
100 alteration_ = 0;
101 alteration_ -= semitone_pitch () - pitch;
103 while (alteration_ <= -3)
105 if (notename_ == 0)
107 notename_ = 6;
108 octave_--;
110 else
111 notename_--;
113 alteration_ = 0;
114 alteration_ -= semitone_pitch () - pitch;
118 /* WHugh, wat een intervaas */
119 void
120 Pitch::transpose (Pitch delta)
122 int new_semi = semitone_pitch () +delta.semitone_pitch();
123 octave_ += delta.octave_;
124 notename_ += delta.notename_;
125 alteration_ += new_semi - semitone_pitch();
127 normalise ();
130 Pitch
131 interval (Pitch const & from , Pitch const & to )
133 int sound = to.semitone_pitch() - from.semitone_pitch ();
134 Pitch pt (to.get_octave () - from.get_octave (),
135 to.get_notename() - from.get_notename(),
136 to.get_alteration() - from.get_alteration());
138 return pt.transposed (Pitch(0,0,sound - pt.semitone_pitch()));
142 /* FIXME
143 Merge with *pitch->text* funcs in chord-name.scm
145 char const *accname[] = {"eses", "es", "", "is" , "isis"};
147 String
148 Pitch::to_string () const
150 int n = (notename_ + 2) % 7;
151 String s = ::to_string (char (n + 'a'));
152 if (alteration_)
153 s += String (accname[alteration_ + 2]);
155 if (octave_ >= 0)
157 int o = octave_ + 1;
158 while (o--)
159 s += "'";
161 else if (octave_ < 0)
163 int o = (-octave_) - 1;
164 while (o--)
165 s += ::to_string (',');
168 return s;
172 change me to relative, counting from last pitch p
173 return copy of resulting pitch
175 Pitch
176 Pitch::to_relative_octave (Pitch p) const
178 int oct_mod = octave_ + 1; // account for c' = octave 1 iso. 0 4
179 Pitch up_pitch (p);
180 Pitch down_pitch (p);
182 up_pitch.alteration_ = alteration_;
183 down_pitch.alteration_ = alteration_;
185 Pitch n = *this;
186 up_pitch.up_to (notename_);
187 down_pitch.down_to (notename_);
189 int h = p.steps ();
190 if (abs (up_pitch.steps () - h) < abs (down_pitch.steps () - h))
191 n = up_pitch;
192 else
193 n = down_pitch;
195 n.octave_ += oct_mod;
196 return n;
199 void
200 Pitch::up_to (int notename)
202 if (notename_ > notename)
204 octave_ ++;
206 notename_ = notename;
209 void
210 Pitch::down_to (int notename)
212 if (notename_ < notename)
214 octave_ --;
216 notename_ = notename;
219 LY_DEFINE(ly_pitch_transpose,
220 "ly:pitch-transpose", 2, 0, 0,
221 (SCM p, SCM delta),
222 "Transpose @var{p} by the amount @var{delta}, where @var{delta} is the "
223 " pitch that central C is transposed to.")
225 Pitch* t = unsmob_pitch (p);
226 Pitch *d = unsmob_pitch (delta);
227 SCM_ASSERT_TYPE(t, p, SCM_ARG1, __FUNCTION__, "pitch") ;
228 SCM_ASSERT_TYPE(d, delta, SCM_ARG1, __FUNCTION__, "pitch") ;
230 return t->transposed (*d).smobbed_copy ();
233 /****************************************************************/
236 IMPLEMENT_TYPE_P (Pitch, "ly:pitch?");
239 Pitch::mark_smob (SCM)
241 return SCM_EOL;
244 IMPLEMENT_SIMPLE_SMOBS (Pitch);
246 Pitch::print_smob (SCM s, SCM port, scm_print_state *)
248 Pitch *r = (Pitch *) ly_cdr (s);
250 scm_puts ("#<Pitch ", port);
251 scm_display (scm_makfrom0str (r->to_string ().to_str0 ()), port);
252 scm_puts (" >", port);
254 return 1;
258 Pitch::equal_p (SCM a , SCM b)
260 Pitch *p = (Pitch *) ly_cdr (a);
261 Pitch *q = (Pitch *) ly_cdr (b);
263 bool eq = p->notename_ == q->notename_
264 && p->octave_ == q->octave_
265 && p->alteration_ == q->alteration_;
267 return eq ? SCM_BOOL_T : SCM_BOOL_F;
270 MAKE_SCHEME_CALLBACK (Pitch, less_p, 2);
272 Pitch::less_p (SCM p1, SCM p2)
274 Pitch *a = unsmob_pitch (p1);
275 Pitch *b = unsmob_pitch (p2);
277 if (compare (*a, *b) < 0)
278 return SCM_BOOL_T;
279 else
280 return SCM_BOOL_F;
284 should add optional args
287 LY_DEFINE(make_pitch, "ly:make-pitch", 3, 0, 0,
288 (SCM o, SCM n, SCM a),
289 "@var{octave} is specified by an integer, zero for the octave containing "
290 "middle C. @var{note} is a number from 0 to 6, with 0 corresponding to C "
291 "and 6 corresponding to B. The shift is zero for a natural, negative for "
292 "flats, or positive for sharps. ")
294 SCM_ASSERT_TYPE(gh_number_p (o), o, SCM_ARG1, __FUNCTION__, "number");
295 SCM_ASSERT_TYPE(gh_number_p (n), n, SCM_ARG2, __FUNCTION__, "number");
296 SCM_ASSERT_TYPE(gh_number_p (a), a, SCM_ARG3, __FUNCTION__, "number");
298 Pitch p (gh_scm2int (o), gh_scm2int (n), gh_scm2int (a));
299 return p.smobbed_copy ();
302 LY_DEFINE(pitch_steps, "ly:pitch-steps", 1, 0,0,
303 (SCM p),
304 "Number of steps counted from central C of the pitch @var{p}.")
306 Pitch *pp = unsmob_pitch (p);
307 SCM_ASSERT_TYPE(pp, p, SCM_ARG1, __FUNCTION__, "Pitch");
309 return gh_int2scm (pp->steps());
312 LY_DEFINE(pitch_octave, "ly:pitch-octave", 1, 0, 0,
313 (SCM pp),
314 "extract the octave from pitch @var{p}.")
316 Pitch *p = unsmob_pitch (pp);
317 SCM_ASSERT_TYPE(p, pp, SCM_ARG1, __FUNCTION__, "Pitch");
318 int q = p->get_octave ();
320 return gh_int2scm (q);
323 LY_DEFINE(pitch_alteration, "ly:pitch-alteration", 1, 0, 0,
324 (SCM pp),
325 "extract the alteration from pitch @var{p}.")
327 Pitch *p = unsmob_pitch (pp);
328 SCM_ASSERT_TYPE(p, pp, SCM_ARG1, __FUNCTION__, "Pitch");
329 int q = p->get_alteration ();
331 return gh_int2scm (q);
334 LY_DEFINE(pitch_notename, "ly:pitch-notename", 1, 0, 0,
335 (SCM pp),
336 "extract the note name from pitch @var{pp}.")
338 Pitch *p = unsmob_pitch (pp);
339 SCM_ASSERT_TYPE(p, pp, SCM_ARG1, __FUNCTION__, "Pitch");
340 int q = p->get_notename ();
342 return gh_int2scm (q);
345 LY_DEFINE(pitch_semitones, "ly:pitch-semitones", 1, 0, 0,
346 (SCM pp),
347 "calculate the number of semitones of @var{p} from central C.")
349 Pitch *p = unsmob_pitch (pp);
350 SCM_ASSERT_TYPE(p, pp, SCM_ARG1, __FUNCTION__, "Pitch");
352 int q = p->semitone_pitch ();
354 return gh_int2scm (q);
357 LY_DEFINE(pitch_less, "ly:pitch<?", 2,0,0, (SCM p1, SCM p2),
358 "Is @var{p1} lower than @var{p2}? This uses lexicographic ordening.")
360 Pitch *a = unsmob_pitch (p1);
361 Pitch *b = unsmob_pitch (p2);
363 SCM_ASSERT_TYPE(a, p1, SCM_ARG1, __FUNCTION__, "Pitch");
364 SCM_ASSERT_TYPE(b, p2, SCM_ARG2, __FUNCTION__, "Pitch");
366 if (Pitch::compare (*a, *b) < 0)
367 return SCM_BOOL_T;
368 else
369 return SCM_BOOL_F;
372 LY_DEFINE(ly_pitch_diff, "ly:pitch-diff", 2 ,0 ,0,
373 (SCM pitch, SCM root),
374 "Return pitch with value DELTA = PITCH - ROOT, ie, "
375 "ROOT == (ly:pitch-transpose root delta).")
377 Pitch *p = unsmob_pitch (pitch);
378 Pitch *r = unsmob_pitch (root);
379 SCM_ASSERT_TYPE(p, pitch, SCM_ARG1, __FUNCTION__, "Pitch");
380 SCM_ASSERT_TYPE(r, root, SCM_ARG2, __FUNCTION__, "Pitch");
382 return interval (*r, *p).smobbed_copy();
390 Pitch::smobbed_copy ()const
392 Pitch * p = new Pitch (*this);
393 return p->smobbed_self ();
397 Pitch::get_octave ()const
399 return octave_;
403 Pitch::get_notename () const
405 return notename_;
409 Pitch::get_alteration () const
411 return alteration_;
414 Pitch
415 Pitch::transposed (Pitch d) const
417 Pitch p =*this;
418 p.transpose (d);
419 return p;