2 musical-pitch.cc -- implement Pitch
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2000 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
);
40 Pitch::compare (Pitch
const &m1
, Pitch
const &m2
)
42 int o
= m1
.octave_i_
- m2
.octave_i_
;
43 int n
= m1
.notename_i_
- m2
.notename_i_
;
44 int a
= m1
.alteration_i_
- m2
.alteration_i_
;
58 return notename_i_
+ octave_i_
*7;
62 should be settable from input?
64 static Byte pitch_byte_a
[ ] = { 0, 2, 4, 5, 7, 9, 11 };
67 Pitch::semitone_pitch () const
69 return pitch_byte_a
[ notename_i_
% 7 ] + alteration_i_
+ octave_i_
* 12;
72 /* WHugh, wat een intervaas */
74 Pitch::transpose (Pitch delta
)
76 int old_pitch
= semitone_pitch ();
77 int delta_pitch
= delta
.semitone_pitch ();
78 octave_i_
+= delta
.octave_i_
;
79 notename_i_
+= delta
.notename_i_
;
82 while (notename_i_
>= 7)
88 int new_pitch
= semitone_pitch ();
89 int delta_acc
= new_pitch
- old_pitch
- delta_pitch
;
90 alteration_i_
-= delta_acc
;
98 // nice test for internationalisation strings
99 char const *accname
[] = {"double flat", "flat", "natural",
100 "sharp" , "double sharp"};
102 char const *accname
[] = {"eses", "es", "", "is" , "isis"};
108 int n
= (notename_i_
+ 2) % 7;
109 String s
= to_str (char(n
+ 'a'));
111 s
+= String (accname
[alteration_i_
+ 2]);
115 int o
= octave_i_
+ 1;
119 else if (octave_i_
<0)
121 int o
= (-octave_i_
) - 1;
131 change me to relative, counting from last pitch p
132 return copy of resulting pitch
135 Pitch::to_relative_octave (Pitch p
)
137 int oct_mod
= octave_i_
+ 1; // account for c' = octave 1 iso. 0 4
139 Pitch
down_pitch (p
);
141 up_pitch
.alteration_i_
= alteration_i_
;
142 down_pitch
.alteration_i_
= alteration_i_
;
145 up_pitch
.up_to (notename_i_
);
146 down_pitch
.down_to (notename_i_
);
149 if (abs (up_pitch
.steps () - h
) < abs (down_pitch
.steps () - h
))
154 n
.octave_i_
+= oct_mod
;
161 Pitch::up_to (int notename
)
163 if (notename_i_
> notename
)
167 notename_i_
= notename
;
171 Pitch::down_to (int notename
)
173 if (notename_i_
< notename
)
177 notename_i_
= notename
;
180 ///MAKE_SCHEME_CALLBACK (Pitch, transpose, 2);
183 Pitch::transpose (SCM p
, SCM delta
)
185 Pitch t
= *unsmob_pitch (p
);
186 t
.transpose (*unsmob_pitch (delta
));
187 return t
.smobbed_copy ();
191 pitch_transpose (SCM p
, SCM delta
)
193 return Pitch::transpose (p
, delta
);
196 /****************************************************************/
199 IMPLEMENT_TYPE_P(Pitch
, "pitch?");
200 IMPLEMENT_UNSMOB(Pitch
, pitch
);
202 Pitch::mark_smob (SCM
)
207 IMPLEMENT_SIMPLE_SMOBS(Pitch
);
211 Pitch::print_smob (SCM s
, SCM port
, scm_print_state
*)
213 Pitch
*r
= (Pitch
*) gh_cdr (s
);
215 scm_puts ("#<Pitch ", port
);
216 scm_display (ly_str02scm (r
->str().ch_C()), port
);
217 scm_puts (" >", port
);
223 Pitch::equal_p (SCM a
, SCM b
)
225 Pitch
*p
= (Pitch
*) gh_cdr (a
);
226 Pitch
*q
= (Pitch
*) gh_cdr (b
);
228 bool eq
= p
->notename_i_
== q
->notename_i_
229 && p
->octave_i_
== q
->octave_i_
230 && p
->alteration_i_
== q
->alteration_i_
;
232 return eq
? SCM_BOOL_T
: SCM_BOOL_F
;
235 MAKE_SCHEME_CALLBACK(Pitch
, less_p
, 2);
237 Pitch::less_p (SCM p1
, SCM p2
)
239 Pitch
*a
= unsmob_pitch (p1
);
240 Pitch
*b
= unsmob_pitch (p2
);
242 if (compare(*a
, *b
) < 0 )
249 should add optional args
253 make_pitch (SCM o
, SCM n
, SCM a
)
256 p
.octave_i_
= gh_scm2int (o
);
257 p
.notename_i_
= gh_scm2int (n
);
258 p
.alteration_i_
= gh_scm2int (a
);
259 return p
.smobbed_copy ();
263 pitch_octave (SCM pp
)
265 Pitch
*p
= unsmob_pitch (pp
);
268 warning ("Not a pitch");
272 return gh_int2scm (q
);
276 pitch_alteration (SCM pp
)
278 Pitch
*p
= unsmob_pitch (pp
);
281 warning ("Not a pitch");
283 q
= p
->alteration_i();
285 return gh_int2scm (q
);
289 pitch_notename (SCM pp
)
291 Pitch
*p
= unsmob_pitch (pp
);
294 warning ("Not a pitch");
298 return gh_int2scm (q
);
302 pitch_semitones (SCM pp
)
304 Pitch
*p
= unsmob_pitch (pp
);
307 warning ("Not a pitch");
311 return gh_int2scm (q
);
317 // should take list?: (make-pitch '(octave name accidental))
318 scm_make_gsubr ("make-pitch", 3, 0, 0, (Scheme_function_unknown
)make_pitch
);
320 scm_make_gsubr ("pitch-octave", 1, 0, 0, (Scheme_function_unknown
)pitch_octave
);
321 scm_make_gsubr ("pitch-notename", 1, 0, 0, (Scheme_function_unknown
)pitch_notename
);
322 scm_make_gsubr ("pitch-alteration", 1, 0, 0, (Scheme_function_unknown
)pitch_alteration
);
323 scm_make_gsubr ("pitch-semitones", 1, 0, 0, (Scheme_function_unknown
)pitch_semitones
);
324 scm_make_gsubr ("Pitch::transpose", 2, 0, 0, (Scheme_function_unknown
) pitch_transpose
);
327 ADD_SCM_INIT_FUNC(pitch
, add_funcs
);
330 Pitch::smobbed_copy ()const
332 Pitch
* p
= new Pitch (*this);
333 return p
->smobbed_self ();
337 Pitch::octave_i ()const
343 Pitch::notename_i () const
349 Pitch::alteration_i () const
351 return alteration_i_
;