]> git.donarmstrong.com Git - lilypond.git/blob - lily/pitch.cc
Merge branch 'master' of git://git.sv.gnu.org/lilypond
[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--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "pitch.hh"
10
11 #include "main.hh"
12 #include "scale.hh"
13 #include "string-convert.hh"
14 #include "warn.hh"
15
16 #include "ly-smobs.icc"
17
18
19 Pitch::Pitch (int o, int n, Rational a)
20 {
21   notename_ = n;
22   alteration_ = a;
23   octave_ = o;
24   scale_ = default_global_scale; 
25   normalize ();
26 }
27
28 /* FIXME: why is octave == 0 and default not middleC ? */
29 Pitch::Pitch ()
30 {
31   notename_ = 0;
32   scale_ = default_global_scale; 
33   octave_ = 0;
34 }
35
36 int
37 Pitch::compare (Pitch const &m1, Pitch const &m2)
38 {
39   int o = m1.octave_ - m2.octave_;
40   int n = m1.notename_ - m2.notename_;
41   Rational a = m1.alteration_ - m2.alteration_;
42
43   if (o)
44     return o;
45   if (n)
46     return n;
47   if (a)
48     return a;
49   
50   return 0;
51 }
52
53 int
54 Pitch::steps () const
55 {
56   return notename_ + octave_ * scale_->step_tones_.size ();
57 }
58
59 Rational
60 Pitch::tone_pitch () const
61 {
62   int o = octave_;
63   int n = notename_;
64   while (n < 0)
65     {
66       n += scale_->step_tones_.size ();
67       o--;
68     }
69
70   Rational tones ((o + n / scale_->step_tones_.size ()) * 6, 1);
71   tones += scale_->step_tones_[n % scale_->step_tones_.size ()];
72
73   tones += alteration_;
74   
75   return tones;
76 }
77
78 /* Calculate pitch height in 12th octave steps.  Don't assume
79    normalized pitch as this function is used to normalize the pitch.  */
80 int
81 Pitch::rounded_semitone_pitch () const
82 {
83   return int (double (tone_pitch () * Rational (2)));
84 }
85
86 int
87 Pitch::rounded_quartertone_pitch () const
88 {
89   return int (double (tone_pitch () * Rational (4)));
90 }
91
92 void
93 Pitch::normalize ()
94 {
95   Rational pitch = tone_pitch ();
96   while (notename_ >= (int) scale_->step_tones_.size ())
97     {
98       notename_ -= scale_->step_tones_.size ();
99       octave_++;
100       alteration_ -= tone_pitch () - pitch;
101     }
102   while (notename_ < 0)
103     {
104       notename_ += scale_->step_tones_.size ();
105       octave_--;
106       alteration_ -= tone_pitch () - pitch;
107     }
108
109   while (alteration_ > Rational (1))
110     {
111       if (notename_ == int (scale_->step_tones_.size ()))
112         {
113           notename_ = 0;
114           octave_++;
115         }
116       else
117         notename_++;
118
119       alteration_ = Rational (0);
120       alteration_ -= tone_pitch () - pitch;
121     }
122   while (alteration_ < Rational(-1))
123     {
124       if (notename_ == 0)
125         {
126           notename_ = scale_->step_tones_.size ();
127           octave_--;
128         }
129       else
130         notename_--;
131
132       alteration_ = 0;
133       alteration_ -= tone_pitch () - pitch;
134     }
135 }
136
137 void
138 Pitch::transpose (Pitch delta)
139 {
140   Rational new_alter = tone_pitch () + delta.tone_pitch ();
141
142   octave_ += delta.octave_;
143   notename_ += delta.notename_;
144   alteration_ += new_alter - tone_pitch ();
145
146   normalize ();
147 }
148
149 Pitch
150 pitch_interval (Pitch const &from, Pitch const &to)
151 {
152   Rational sound = to.tone_pitch () - from.tone_pitch ();
153   Pitch pt (to.get_octave () - from.get_octave (),
154             to.get_notename () - from.get_notename (),
155
156             to.get_alteration () - from.get_alteration ());
157
158   return pt.transposed (Pitch (0, 0, sound - pt.tone_pitch ()));
159 }
160
161 /* FIXME
162    Merge with *pitch->text* funcs in chord-name.scm  */
163 char const *accname[] = {"eses", "eseh", "es", "eh", "",
164                          "ih", "is", "isih", "isis"};
165
166 string
167 Pitch::to_string () const
168 {
169   int n = (notename_ + 2) % scale_->step_tones_.size ();
170   string s = ::to_string (char (n + 'a'));
171       Rational qtones = alteration_ * Rational (4,1);
172       int qt = int (rint (Real (qtones)));
173       
174       s += string (accname[qt + 4]);
175   if (octave_ >= 0)
176     {
177       int o = octave_ + 1;
178       while (o--)
179         s += "'";
180     }
181   else if (octave_ < 0)
182     {
183       int o = (-octave_) - 1;
184       while (o--)
185         s += ::to_string (',');
186     }
187
188   return s;
189 }
190
191 /* Change me to relative, counting from last pitch p
192    return copy of resulting pitch.  */
193 Pitch
194 Pitch::to_relative_octave (Pitch p) const
195 {
196   /* account for c' = octave 1 iso. 0 4 */
197   int oct_mod = octave_ + 1;
198   Pitch up_pitch (p);
199   Pitch down_pitch (p);
200
201   up_pitch.alteration_ = alteration_;
202   down_pitch.alteration_ = alteration_;
203
204   Pitch n = *this;
205   up_pitch.up_to (notename_);
206   down_pitch.down_to (notename_);
207
208   int h = p.steps ();
209   if (abs (up_pitch.steps () - h) < abs (down_pitch.steps () - h))
210     n = up_pitch;
211   else
212     n = down_pitch;
213
214   n.octave_ += oct_mod;
215   return n;
216 }
217
218 void
219 Pitch::up_to (int notename)
220 {
221   if (notename_ > notename)
222     octave_++;
223   notename_ = notename;
224 }
225
226 void
227 Pitch::down_to (int notename)
228 {
229   if (notename_ < notename)
230     octave_--;
231   notename_ = notename;
232 }
233
234 IMPLEMENT_TYPE_P (Pitch, "ly:pitch?");
235 SCM
236 Pitch::mark_smob (SCM x)
237 {
238   Pitch *p = (Pitch*) SCM_CELL_WORD_1 (x);
239   return p->scale_->self_scm ();
240 }
241
242 IMPLEMENT_SIMPLE_SMOBS (Pitch);
243 int
244 Pitch::print_smob (SCM s, SCM port, scm_print_state *)
245 {
246   Pitch *r = (Pitch *) SCM_CELL_WORD_1 (s);
247   scm_puts ("#<Pitch ", port);
248   scm_display (scm_makfrom0str (r->to_string ().c_str ()), port);
249   scm_puts (" >", port);
250   return 1;
251 }
252
253 SCM
254 Pitch::equal_p (SCM a, SCM b)
255 {
256   Pitch *p = (Pitch *) SCM_CELL_WORD_1 (a);
257   Pitch *q = (Pitch *) SCM_CELL_WORD_1 (b);
258
259   bool eq = p->notename_ == q->notename_
260     && p->octave_ == q->octave_
261     && p->alteration_ == q->alteration_;
262
263   return eq ? SCM_BOOL_T : SCM_BOOL_F;
264 }
265
266 MAKE_SCHEME_CALLBACK (Pitch, less_p, 2);
267 SCM
268 Pitch::less_p (SCM p1, SCM p2)
269 {
270   Pitch *a = unsmob_pitch (p1);
271   Pitch *b = unsmob_pitch (p2);
272
273   if (compare (*a, *b) < 0)
274     return SCM_BOOL_T;
275   else
276     return SCM_BOOL_F;
277 }
278
279 int
280 Pitch::get_octave () const
281 {
282   return octave_;
283 }
284
285 int
286 Pitch::get_notename () const
287 {
288   return notename_;
289 }
290
291 Rational
292 Pitch::get_alteration () const
293 {
294   return alteration_;
295 }
296
297 Pitch
298 Pitch::transposed (Pitch d) const
299 {
300   Pitch p = *this;
301   p.transpose (d);
302   return p;
303 }
304
305 Rational FLAT_ALTERATION (-1, 2);
306 Rational SHARP_ALTERATION (1, 2);