lilypond-1.3.130
[lilypond.git] / lily / pitch.cc
blob576054389e3b609ef0bbd66539d6bc0d1db5ee70
1 /*
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>
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);
32 Pitch::Pitch ()
34 notename_i_ = 0;
35 alteration_i_ = 0;
36 octave_i_ = 0;
39 int
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_;
46 if (o)
47 return o;
48 if (n)
49 return n;
50 if (a)
51 return a;
52 return 0;
55 int
56 Pitch::steps () const
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 };
66 int
67 Pitch::semitone_pitch () const
69 return pitch_byte_a[ notename_i_ % 7 ] + alteration_i_ + octave_i_ * 12;
72 /* WHugh, wat een intervaas */
73 void
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)
84 notename_i_ -= 7;
85 octave_i_ ++;
88 int new_pitch = semitone_pitch ();
89 int delta_acc = new_pitch - old_pitch - delta_pitch;
90 alteration_i_ -= delta_acc;
96 /* FIXME */
97 #if 0
98 // nice test for internationalisation strings
99 char const *accname[] = {"double flat", "flat", "natural",
100 "sharp" , "double sharp"};
101 #else
102 char const *accname[] = {"eses", "es", "", "is" , "isis"};
103 #endif
105 String
106 Pitch::str () const
108 int n = (notename_i_ + 2) % 7;
109 String s = to_str (char(n + 'a'));
110 if (alteration_i_)
111 s += String (accname[alteration_i_ + 2]);
113 if (octave_i_ > 0)
115 int o = octave_i_ + 1;
116 while (o--)
117 s += "'";
119 else if (octave_i_ <0)
121 int o = (-octave_i_) - 1;
122 while (o--)
123 s += to_str (',');
127 return s;
131 change me to relative, counting from last pitch p
132 return copy of resulting pitch
134 Pitch
135 Pitch::to_relative_octave (Pitch p)
137 int oct_mod = octave_i_ + 1; // account for c' = octave 1 iso. 0 4
138 Pitch up_pitch (p);
139 Pitch down_pitch (p);
141 up_pitch.alteration_i_ = alteration_i_;
142 down_pitch.alteration_i_ = alteration_i_;
144 Pitch n = *this;
145 up_pitch.up_to (notename_i_);
146 down_pitch.down_to (notename_i_);
148 int h = p.steps ();
149 if (abs (up_pitch.steps () - h) < abs (down_pitch.steps () - h))
150 n = up_pitch;
151 else
152 n = down_pitch;
154 n.octave_i_ += oct_mod;
156 *this = n;
157 return *this;
160 void
161 Pitch::up_to (int notename)
163 if (notename_i_ > notename)
165 octave_i_ ++;
167 notename_i_ = notename;
170 void
171 Pitch::down_to (int notename)
173 if (notename_i_ < notename)
175 octave_i_ --;
177 notename_i_ = notename;
180 ///MAKE_SCHEME_CALLBACK (Pitch, transpose, 2);
181 ///transpose_proc?
183 Pitch::transpose (SCM p, SCM delta)
185 Pitch t = *unsmob_pitch (p);
186 t.transpose (*unsmob_pitch (delta));
187 return t.smobbed_copy ();
190 static SCM
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 )
204 return SCM_EOL;
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);
219 return 1;
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 )
243 return SCM_BOOL_T;
244 else
245 return SCM_BOOL_F;
249 should add optional args
252 static SCM
253 make_pitch (SCM o, SCM n, SCM a)
255 Pitch p;
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 ();
262 static SCM
263 pitch_octave (SCM pp)
265 Pitch *p = unsmob_pitch (pp);
266 int q = 0;
267 if (!p)
268 warning ("Not a pitch");
269 else
270 q = p->octave_i();
272 return gh_int2scm (q);
275 static SCM
276 pitch_alteration (SCM pp)
278 Pitch *p = unsmob_pitch (pp);
279 int q = 0;
280 if (!p)
281 warning ("Not a pitch");
282 else
283 q = p->alteration_i();
285 return gh_int2scm (q);
288 static SCM
289 pitch_notename (SCM pp)
291 Pitch *p = unsmob_pitch (pp);
292 int q = 0;
293 if (!p)
294 warning ("Not a pitch");
295 else
296 q = p->notename_i();
298 return gh_int2scm (q);
301 static SCM
302 pitch_semitones (SCM pp)
304 Pitch *p = unsmob_pitch (pp);
305 int q = 0;
306 if (!p)
307 warning ("Not a pitch");
308 else
309 q = p->steps();
311 return gh_int2scm (q);
314 static void
315 add_funcs()
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
339 return octave_i_;
343 Pitch::notename_i () const
345 return notename_i_;
349 Pitch::alteration_i () const
351 return alteration_i_;