lilypond-1.5.9
[lilypond.git] / lily / musical-pitch.cc
blob9a798b59e9cef1ba00d0be6bc29122c9c5daa43b
1 /*
2 musical-pitch.cc -- implement Musical_pitch
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
9 #include "musical-pitch.hh"
10 #include "debug.hh"
11 #include "main.hh"
12 #include "ly-smobs.icc"
14 int
15 compare (Array<Musical_pitch>* left, Array<Musical_pitch>* right)
17 assert (left);
18 assert (right);
20 if (left->size () == right->size ())
22 for (int i = 0; i < left->size (); i++)
24 int r = Musical_pitch::compare ((*left)[i], (*right)[i]);
25 if (r)
26 return r;
29 else
30 return 1;
32 return 0;
35 Musical_pitch::Musical_pitch (int o, int n, int a)
37 notename_i_ = n;
38 alteration_i_ = a;
39 octave_i_ = o;
41 if (n < 0 || n >= 7 ||
42 a < -2 || a > 2)
44 String s = _("Pitch arguments out of range");
45 s += ": alteration = " + to_str (a);
46 s += ", notename = " + to_str (n);
47 warning (s);
51 Musical_pitch::Musical_pitch ()
53 notename_i_ = 0;
54 alteration_i_ = 0;
55 octave_i_ = 0;
58 int
59 Musical_pitch::compare (Musical_pitch const &m1, Musical_pitch const &m2)
61 int o= m1.octave_i_ - m2.octave_i_;
62 int n = m1.notename_i_ - m2.notename_i_;
63 int a = m1.alteration_i_ - m2.alteration_i_;
65 if (o)
66 return o;
67 if (n)
68 return n;
69 if (a)
70 return a;
71 return 0;
74 int
75 Musical_pitch::steps () const
77 return notename_i_ + octave_i_*7;
81 should be settable from input?
83 static Byte pitch_byte_a[ ] = { 0, 2, 4, 5, 7, 9, 11 };
85 int
86 Musical_pitch::semitone_pitch () const
88 return pitch_byte_a[ notename_i_ % 7 ] + alteration_i_ + octave_i_ * 12;
91 void
92 Musical_pitch::transpose (Musical_pitch delta)
94 int old_pitch = semitone_pitch ();
95 int delta_pitch = delta.semitone_pitch ();
96 octave_i_ += delta.octave_i_;
97 notename_i_ += delta.notename_i_;
100 while (notename_i_ >= 7)
102 notename_i_ -= 7;
103 octave_i_ ++;
106 int new_pitch = semitone_pitch ();
107 int delta_acc = new_pitch - old_pitch - delta_pitch;
108 alteration_i_ -= delta_acc;
112 #if 0
113 // nice test for internationalisation strings
114 char const *accname[] = {"double flat", "flat", "natural",
115 "sharp" , "double sharp"};
116 #else
117 char const *accname[] = {"eses", "es", "", "is" , "isis"};
118 #endif
120 String
121 Musical_pitch::str () const
123 int n = (notename_i_ + 2) % 7;
124 String s = to_str (char(n + 'a'));
125 if (alteration_i_)
126 s += String (accname[alteration_i_ + 2]);
128 if (octave_i_ > 0)
130 int o = octave_i_ + 1;
131 while (o--)
132 s += "'";
134 else if (octave_i_ <0)
136 int o = (-octave_i_) - 1;
137 while (o--)
138 s += to_str (',');
142 return s;
146 change me to relative, counting from last pitch p
147 return copy of resulting pitch
149 Musical_pitch
150 Musical_pitch::to_relative_octave (Musical_pitch p)
152 int oct_mod = octave_i_ + 1; // account for c' = octave 1 iso. 0 4
153 Musical_pitch up_pitch (p);
154 Musical_pitch down_pitch (p);
156 up_pitch.alteration_i_ = alteration_i_;
157 down_pitch.alteration_i_ = alteration_i_;
159 Musical_pitch n = *this;
160 up_pitch.up_to (notename_i_);
161 down_pitch.down_to (notename_i_);
163 int h = p.steps ();
164 if (abs (up_pitch.steps () - h) < abs (down_pitch.steps () - h))
165 n = up_pitch;
166 else
167 n = down_pitch;
169 n.octave_i_ += oct_mod;
171 *this = n;
172 return *this;
175 void
176 Musical_pitch::up_to (int notename)
178 if (notename_i_ > notename)
180 octave_i_ ++;
182 notename_i_ = notename;
185 void
186 Musical_pitch::down_to (int notename)
188 if (notename_i_ < notename)
190 octave_i_ --;
192 notename_i_ = notename;
195 /****************************************************************/
198 IMPLEMENT_TYPE_P(Musical_pitch, "pitch?");
199 IMPLEMENT_UNSMOB(Musical_pitch, pitch);
201 Musical_pitch::mark_smob (SCM )
203 return SCM_EOL;
206 IMPLEMENT_SIMPLE_SMOBS(Musical_pitch);
210 Musical_pitch::print_smob (SCM s, SCM port, scm_print_state *)
212 Musical_pitch *r = (Musical_pitch *) gh_cdr (s);
214 scm_puts ("#<Musical_pitch ", port);
215 scm_display (gh_str02scm (r->str().ch_C()), port);
216 scm_puts (" >", port);
218 return 1;
222 Musical_pitch::equal_p (SCM a , SCM b)
224 Musical_pitch *p = (Musical_pitch *) gh_cdr (a);
225 Musical_pitch *q = (Musical_pitch *) gh_cdr (b);
227 bool eq = p->notename_i_ == q->notename_i_
228 && p->octave_i_ == q->octave_i_
229 && p->alteration_i_ == q->alteration_i_;
231 return eq ? SCM_BOOL_T : SCM_BOOL_F;
234 MAKE_SCHEME_CALLBACK(Musical_pitch, less_p, 2);
236 Musical_pitch::less_p (SCM p1, SCM p2)
238 Musical_pitch *a = unsmob_pitch (p1);
239 Musical_pitch *b = unsmob_pitch (p2);
241 if (compare(*a, *b) < 0 )
242 return SCM_BOOL_T;
243 else
244 return SCM_BOOL_F;
248 should add optional args
251 static SCM
252 make_pitch (SCM o, SCM n, SCM a)
254 Musical_pitch p;
255 p.octave_i_ = gh_scm2int (o);
256 p.notename_i_ = gh_scm2int (n);
257 p.alteration_i_ = gh_scm2int (a);
258 return p.smobbed_copy ();
261 static SCM
262 pitch_octave (SCM pp)
264 Musical_pitch *p = unsmob_pitch (pp);
265 int q = 0;
266 if (!p)
267 warning ("Not a pitch");
268 else
269 q = p->octave_i();
271 return gh_int2scm (q);
274 static SCM
275 pitch_alteration (SCM pp)
277 Musical_pitch *p = unsmob_pitch (pp);
278 int q = 0;
279 if (!p)
280 warning ("Not a pitch");
281 else
282 q = p->alteration_i();
284 return gh_int2scm (q);
287 static SCM
288 pitch_notename (SCM pp)
290 Musical_pitch *p = unsmob_pitch (pp);
291 int q = 0;
292 if (!p)
293 warning ("Not a pitch");
294 else
295 q = p->notename_i();
297 return gh_int2scm (q);
300 static SCM
301 pitch_semitones (SCM pp)
303 Musical_pitch *p = unsmob_pitch (pp);
304 int q = 0;
305 if (!p)
306 warning ("Not a pitch");
307 else
308 q = p->steps();
310 return gh_int2scm (q);
313 static void
314 add_funcs()
316 scm_make_gsubr ("make-pitch", 3, 0, 0, (Scheme_function_unknown)make_pitch);
317 scm_make_gsubr ("pitch-octave", 1, 0, 0, (Scheme_function_unknown)pitch_octave);
318 scm_make_gsubr ("pitch-notename", 1, 0, 0, (Scheme_function_unknown)pitch_notename);
319 scm_make_gsubr ("pitch-alteration", 1, 0, 0, (Scheme_function_unknown)pitch_alteration);
320 scm_make_gsubr ("pitch-semitones", 1, 0, 0, (Scheme_function_unknown)pitch_semitones);
323 ADD_SCM_INIT_FUNC(pitch, add_funcs);
326 Musical_pitch::smobbed_copy ()const
328 Musical_pitch * p = new Musical_pitch (*this);
329 return p->smobbed_self ();
333 Musical_pitch::octave_i ()const
335 return octave_i_;
339 Musical_pitch::notename_i () const
341 return notename_i_;
345 Musical_pitch::alteration_i () const
347 return alteration_i_;