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>
12 #include "ly-smobs.icc"
16 Pitch::Pitch (int o
, int n
, int a
)
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_
;
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. */
62 Pitch::semitone_pitch () const
71 return (o
+ n
/ 7) * 12 + pitch_byte_a
[n
% 7] + alteration_
;
77 int pitch
= semitone_pitch ();
78 while (notename_
>= 7)
82 alteration_
-= semitone_pitch () - pitch
;
88 alteration_
-= semitone_pitch () - pitch
;
90 while (alteration_
>= 3)
101 alteration_
-= semitone_pitch () - pitch
;
103 while (alteration_
<= -3)
114 alteration_
-= semitone_pitch () - pitch
;
118 /* WHugh, wat een intervaas */
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();
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()));
143 Merge with *pitch->text* funcs in chord-name.scm
145 char const *accname
[] = {"eses", "es", "", "is" , "isis"};
148 Pitch::to_string () const
150 int n
= (notename_
+ 2) % 7;
151 String s
= ::to_string (char (n
+ 'a'));
153 s
+= String (accname
[alteration_
+ 2]);
161 else if (octave_
< 0)
163 int o
= (-octave_
) - 1;
165 s
+= ::to_string (',');
172 change me to relative, counting from last pitch p
173 return copy of resulting pitch
176 Pitch::to_relative_octave (Pitch p
) const
178 int oct_mod
= octave_
+ 1; // account for c' = octave 1 iso. 0 4
180 Pitch
down_pitch (p
);
182 up_pitch
.alteration_
= alteration_
;
183 down_pitch
.alteration_
= alteration_
;
186 up_pitch
.up_to (notename_
);
187 down_pitch
.down_to (notename_
);
190 if (abs (up_pitch
.steps () - h
) < abs (down_pitch
.steps () - h
))
195 n
.octave_
+= oct_mod
;
200 Pitch::up_to (int notename
)
202 if (notename_
> notename
)
206 notename_
= notename
;
210 Pitch::down_to (int notename
)
212 if (notename_
< notename
)
216 notename_
= notename
;
219 LY_DEFINE(ly_pitch_transpose
,
220 "ly:pitch-transpose", 2, 0, 0,
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
)
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
);
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)
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,
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,
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,
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,
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,
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)
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
403 Pitch::get_notename () const
409 Pitch::get_alteration () const
415 Pitch::transposed (Pitch d
) const