]> git.donarmstrong.com Git - lilypond.git/blob - lily/pitch.cc
release: 1.5.29
[lilypond.git] / lily / pitch.cc
1 /*   
2   musical-pitch.cc --  implement Pitch
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1998--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9 #include "pitch.hh"
10 #include "debug.hh"
11 #include "main.hh"
12 #include "ly-smobs.icc"
13
14
15
16 Pitch::Pitch (int o, int n, int a)
17 {
18   notename_i_ = n;
19   alteration_i_ = a;
20   octave_i_ = o;
21
22   if (n < 0 || n >= 7 ||
23       a < -2 || a > 2)
24     {
25       String s = _ ("Pitch arguments out of range");
26       s += ": alteration = " + to_str (a);
27       s += ", notename = " + to_str (n);
28       warning (s);
29     }
30   normalise ();
31 }
32
33 Pitch::Pitch ()
34 {
35   notename_i_ = 0;
36   alteration_i_ = 0;
37   octave_i_ = 0;
38 }
39
40 int
41 Pitch::compare (Pitch const &m1, Pitch const &m2)
42 {
43   int o=  m1.octave_i_ - m2.octave_i_;
44   int n = m1.notename_i_ - m2.notename_i_;
45   int a = m1.alteration_i_ - m2.alteration_i_;
46
47   if (o)
48         return o;
49   if (n)
50         return n;
51   if (a)
52         return a;
53   return 0;
54 }
55
56 int
57 Pitch::steps () const
58 {
59   return  notename_i_ + octave_i_*7;
60 }
61
62 /*
63   should be settable from input?
64  */
65 static Byte pitch_byte_a[  ] = { 0, 2, 4, 5, 7, 9, 11 };
66
67
68 /* Calculate pitch height in 12th octave steps.  Don't assume
69    normalised pitch as this function is used to normalise the pitch.  */
70 int
71 Pitch::semitone_pitch () const
72 {
73   int o = octave_i_;
74   int n = notename_i_;
75   while (n < 0)
76     {
77       n += 7;
78       o --;
79     }
80   return (o + n / 7) * 12 + pitch_byte_a[n % 7] + alteration_i_;
81 }
82
83 void
84 Pitch::normalise ()
85 {
86   int pitch = semitone_pitch ();
87   while (notename_i_ >= 7)
88     {
89       notename_i_ -= 7;
90       octave_i_++;
91       alteration_i_ -= semitone_pitch () - pitch;
92     }
93   while (notename_i_ < 0)
94     {
95       notename_i_ += 7;
96       octave_i_--;
97       alteration_i_ -= semitone_pitch () - pitch;
98     }
99   while (alteration_i_ >= 3)
100     {
101       if (notename_i_ == 6)
102         {
103           notename_i_ = 0;
104           octave_i_++;
105         }
106       else
107         notename_i_++;
108
109       alteration_i_ = 0;
110       alteration_i_ -= semitone_pitch () - pitch;
111     }
112   while (alteration_i_ <= -3)
113     {
114       if (notename_i_ == 0)
115         {
116           notename_i_ = 6;
117           octave_i_--;
118         }
119       else
120         notename_i_--;
121
122       alteration_i_ = 0;
123       alteration_i_ -= semitone_pitch () - pitch;
124     }
125 }
126
127 /* WHugh, wat een intervaas */
128 void
129 Pitch::transpose (Pitch delta)
130 {
131   int old_semi = semitone_pitch ();
132   int delta_semi = delta.semitone_pitch ();
133   octave_i_ += delta.octave_i_;
134   notename_i_ += delta.notename_i_;
135
136   int new_semi = semitone_pitch ();
137   int delta_acc = new_semi - old_semi - delta_semi;
138   alteration_i_ -= delta_acc;
139
140   normalise ();
141 }
142
143
144 /* FIXME
145    Merge with *pitch->text* funcs in chord-name.scm
146  */
147 char const *accname[] = {"eses", "es", "", "is" , "isis"};
148
149 String
150 Pitch::str () const
151 {
152   int n = (notename_i_ + 2) % 7;
153   String s = to_str (char (n + 'a'));
154   if (alteration_i_)
155     s += String (accname[alteration_i_ + 2]);
156
157   if (octave_i_ >= 0)
158     {
159       int o = octave_i_ + 1;
160       while (o--)
161         s += "'";
162     }
163   else if (octave_i_ < 0)
164     {
165       int o = (-octave_i_) - 1;
166       while (o--)
167         s += to_str (',');
168     }
169
170   return s;
171 }
172
173 /*
174   change me to relative, counting from last pitch p
175   return copy of resulting pitch
176  */
177 Pitch
178 Pitch::to_relative_octave (Pitch p)
179 {
180   int oct_mod = octave_i_  + 1; // account for c' = octave 1 iso. 0 4
181   Pitch up_pitch (p);
182   Pitch down_pitch (p);
183
184   up_pitch.alteration_i_ = alteration_i_;
185   down_pitch.alteration_i_ = alteration_i_;
186   
187   Pitch n = *this;
188   up_pitch.up_to (notename_i_);
189   down_pitch.down_to (notename_i_);
190
191   int h = p.steps ();
192   if (abs (up_pitch.steps () - h) < abs (down_pitch.steps () - h))
193     n = up_pitch;
194   else
195     n = down_pitch;
196   
197   n.octave_i_ += oct_mod;
198
199   *this = n;
200   return *this;
201 }
202
203 void
204 Pitch::up_to (int notename)
205 {
206   if (notename_i_  > notename)
207     {
208       octave_i_ ++;
209     }
210   notename_i_  = notename;
211 }
212
213 void
214 Pitch::down_to (int notename)
215 {
216   if (notename_i_ < notename)
217     {
218       octave_i_ --;
219     }
220   notename_i_ = notename;
221 }
222
223 ///MAKE_SCHEME_CALLBACK (Pitch, transpose, 2);
224 ///transpose_proc?
225 SCM
226 Pitch::transpose (SCM p, SCM delta)
227 {
228   Pitch t = *unsmob_pitch (p);
229   t.transpose (*unsmob_pitch (delta));
230   return t.smobbed_copy ();
231 }
232
233 static SCM
234 pitch_transpose (SCM p, SCM delta)
235 {
236   return Pitch::transpose (p, delta);
237 }
238
239 /****************************************************************/
240
241
242 IMPLEMENT_TYPE_P (Pitch, "pitch?");
243
244 SCM
245 Pitch::mark_smob (SCM)
246 {
247   return SCM_EOL;
248 }
249
250 IMPLEMENT_SIMPLE_SMOBS (Pitch);
251
252
253 int
254 Pitch::print_smob (SCM s, SCM port, scm_print_state *)
255 {
256   Pitch  *r = (Pitch *) ly_cdr (s);
257      
258   scm_puts ("#<Pitch ", port);
259   scm_display (ly_str02scm (r->str ().ch_C ()), port);
260   scm_puts (" >", port);
261   
262   return 1;
263 }
264
265 SCM
266 Pitch::equal_p (SCM a , SCM b)
267 {
268   Pitch  *p = (Pitch *) ly_cdr (a);
269   Pitch  *q = (Pitch *) ly_cdr (b);  
270
271   bool eq = p->notename_i_ == q->notename_i_
272     && p->octave_i_ == q->octave_i_
273     && p->alteration_i_ == q->alteration_i_;
274
275   return eq ? SCM_BOOL_T : SCM_BOOL_F;
276 }
277
278 MAKE_SCHEME_CALLBACK (Pitch, less_p, 2);
279 SCM
280 Pitch::less_p (SCM p1, SCM p2)
281 {
282   Pitch *a = unsmob_pitch (p1);
283   Pitch *b = unsmob_pitch (p2);
284
285   if (compare (*a, *b) < 0)
286     return SCM_BOOL_T;
287   else
288     return SCM_BOOL_F;
289 }
290
291 /*
292   should add optional args
293  */
294
295 static SCM
296 make_pitch (SCM o, SCM n, SCM a)
297 {
298   Pitch p (gh_scm2int (o), gh_scm2int (n), gh_scm2int (a));
299   return p.smobbed_copy ();
300 }
301
302 static SCM
303 pitch_octave (SCM pp)
304 {
305   Pitch *p = unsmob_pitch (pp);
306   int q = 0;
307   if (!p)
308     warning ("Not a pitch");
309   else
310     q = p->octave_i ();
311
312   return gh_int2scm (q);
313 }
314
315 static SCM
316 pitch_alteration (SCM pp)
317 {
318   Pitch *p = unsmob_pitch (pp);
319   int q = 0;
320   if (!p)
321     warning ("Not a pitch");
322   else
323     q = p->alteration_i ();
324
325   return gh_int2scm (q);
326 }
327
328 static SCM
329 pitch_notename (SCM pp)
330 {
331   Pitch *p = unsmob_pitch (pp);
332   int q = 0;
333   if (!p)
334     warning ("Not a pitch");
335   else
336     q = p->notename_i ();
337
338   return gh_int2scm (q);
339 }
340
341 static SCM
342 pitch_semitones (SCM pp)
343 {
344   Pitch *p = unsmob_pitch (pp);
345   int q = 0;
346   if (!p)
347     warning ("Not a pitch");
348   else
349     q = p->steps ();
350
351   return gh_int2scm (q);
352 }
353
354 static void
355 add_funcs ()
356 {
357   // should take list?: (make-pitch ' (octave name accidental))
358   scm_c_define_gsubr ("make-pitch", 3, 0, 0, (Scheme_function_unknown)make_pitch);
359
360   scm_c_define_gsubr ("pitch-octave", 1, 0, 0, (Scheme_function_unknown)pitch_octave);
361   scm_c_define_gsubr ("pitch-notename", 1, 0, 0, (Scheme_function_unknown)pitch_notename);
362   scm_c_define_gsubr ("pitch-alteration", 1, 0, 0, (Scheme_function_unknown)pitch_alteration);
363   scm_c_define_gsubr ("pitch-semitones", 1, 0, 0, (Scheme_function_unknown)pitch_semitones);
364   scm_c_define_gsubr ("Pitch::transpose", 2, 0, 0, (Scheme_function_unknown) pitch_transpose);
365 }
366
367 ADD_SCM_INIT_FUNC (pitch, add_funcs);
368
369 SCM
370 Pitch::smobbed_copy ()const
371 {
372   Pitch *  p = new Pitch (*this);
373   return p->smobbed_self ();
374 }
375
376 int
377 Pitch::octave_i ()const
378 {
379   return octave_i_;
380 }
381
382 int
383 Pitch::notename_i () const
384 {
385   return notename_i_;
386 }
387
388 int
389 Pitch::alteration_i () const
390 {
391   return alteration_i_;
392 }