]> git.donarmstrong.com Git - lilypond.git/blob - lily/pitch.cc
Issue 4550 (1/2) Avoid "using namespace std;" in included files
[lilypond.git] / lily / pitch.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1998--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "pitch.hh"
21
22 #include "main.hh"
23 #include "scale.hh"
24 #include "string-convert.hh"
25 #include "warn.hh"
26
27 #include <cmath>
28
29 using std::string;
30
31 Pitch::Pitch (int o, int n, Rational a)
32 {
33   notename_ = n;
34   alteration_ = a;
35   octave_ = o;
36   scale_ = default_global_scale;
37   normalize_octave ();
38 }
39
40 /* FIXME: why is octave == 0 and default not middleC ? */
41 Pitch::Pitch ()
42 {
43   notename_ = 0;
44   scale_ = default_global_scale;
45   octave_ = 0;
46   alteration_ = (Rational)0;
47 }
48
49 int
50 Pitch::compare (Pitch const &m1, Pitch const &m2)
51 {
52   int o = m1.octave_ - m2.octave_;
53   int n = m1.notename_ - m2.notename_;
54   Rational a = m1.alteration_ - m2.alteration_;
55
56   if (o)
57     return o;
58   if (n)
59     return n;
60   if (a)
61     return a > (Rational)0 ? 1 : -1;
62
63   return 0;
64 }
65
66 int
67 Pitch::steps () const
68 {
69   return notename_ + octave_ * scale_->step_count ();
70 }
71
72 Rational
73 Pitch::tone_pitch () const
74 {
75   return scale_->tones_at_step (notename_, octave_) + alteration_;
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 (floor (double (tone_pitch () * Rational (2) + Rational (1, 2))));
84 }
85
86 int
87 Pitch::rounded_quartertone_pitch () const
88 {
89   return int (floor (double (tone_pitch () * Rational (4) + Rational (1, 2))));
90 }
91
92 void
93 Pitch::normalize_octave ()
94 {
95   int normalized_step = notename_ % scale_->step_count ();
96   if (normalized_step < 0)
97     normalized_step += scale_->step_count ();
98
99   octave_ += (notename_ - normalized_step) / scale_->step_count ();
100   notename_ = normalized_step;
101 }
102
103 void
104 Pitch::normalize_alteration ()
105 {
106   while (alteration_ > Rational (1))
107     {
108       alteration_ -= scale_->step_size (notename_);
109       notename_++;
110     }
111   while (alteration_ < Rational (-1))
112     {
113       notename_--;
114       alteration_ += scale_->step_size (notename_);
115     }
116 }
117
118 void
119 Pitch::normalize ()
120 {
121   normalize_alteration ();
122   normalize_octave ();
123 }
124
125 void
126 Pitch::transpose (Pitch delta)
127 {
128   Rational new_alter = tone_pitch () + delta.tone_pitch ();
129
130   octave_ += delta.octave_;
131   notename_ += delta.notename_;
132   alteration_ += new_alter - tone_pitch ();
133
134   normalize_octave ();
135 }
136
137 Pitch
138 pitch_interval (Pitch const &from, Pitch const &to)
139 {
140   Rational sound = to.tone_pitch () - from.tone_pitch ();
141   Pitch pt (to.get_octave () - from.get_octave (),
142             to.get_notename () - from.get_notename (),
143
144             to.get_alteration () - from.get_alteration ());
145
146   return pt.transposed (Pitch (0, 0, sound - pt.tone_pitch ()));
147 }
148
149 /* FIXME
150    Merge with *pitch->text* funcs in chord-name.scm  */
151 char const *accname[] = {"eses", "eseh", "es", "eh", "",
152                          "ih", "is", "isih", "isis"
153                         };
154
155 string
156 Pitch::to_string () const
157 {
158   int n = (notename_ + 2) % scale_->step_count ();
159   string s = ::to_string (char (n + 'a'));
160   Rational qtones = alteration_ * Rational (4, 1);
161   int qt = int (rint (Real (qtones)));
162
163   s += string (accname[qt + 4]);
164   if (octave_ >= 0)
165     {
166       int o = octave_ + 1;
167       while (o--)
168         s += "'";
169     }
170   else if (octave_ < 0)
171     {
172       int o = (-octave_) - 1;
173       while (o--)
174         s += ::to_string (',');
175     }
176
177   return s;
178 }
179
180 /* Change me to relative, counting from last pitch p
181    return copy of resulting pitch.  */
182 Pitch
183 Pitch::to_relative_octave (Pitch p) const
184 {
185   /* account for c' = octave 1 iso. 0 4 */
186   int oct_mod = octave_ + 1;
187   Pitch up_pitch (p);
188   Pitch down_pitch (p);
189
190   up_pitch.alteration_ = alteration_;
191   down_pitch.alteration_ = alteration_;
192
193   Pitch n = *this;
194   up_pitch.up_to (notename_);
195   down_pitch.down_to (notename_);
196
197   int h = p.steps ();
198   if (abs (up_pitch.steps () - h) < abs (down_pitch.steps () - h))
199     n = up_pitch;
200   else
201     n = down_pitch;
202
203   n.octave_ += oct_mod;
204   return n;
205 }
206
207 void
208 Pitch::up_to (int notename)
209 {
210   if (notename_ > notename)
211     octave_++;
212   notename_ = notename;
213 }
214
215 void
216 Pitch::down_to (int notename)
217 {
218   if (notename_ < notename)
219     octave_--;
220   notename_ = notename;
221 }
222
223 const char Pitch::type_p_name_[] = "ly:pitch?";
224
225 SCM
226 Pitch::mark_smob () const
227 {
228   return scale_->self_scm ();
229 }
230
231 int
232 Pitch::print_smob (SCM port, scm_print_state *) const
233 {
234   scm_puts ("#<Pitch ", port);
235   scm_display (ly_string2scm (to_string ()), port);
236   scm_puts (" >", port);
237   return 1;
238 }
239
240 SCM
241 Pitch::equal_p (SCM a, SCM b)
242 {
243   Pitch *p = (Pitch *) SCM_CELL_WORD_1 (a);
244   Pitch *q = (Pitch *) SCM_CELL_WORD_1 (b);
245
246   bool eq = p->notename_ == q->notename_
247             && p->octave_ == q->octave_
248             && p->alteration_ == q->alteration_;
249
250   return eq ? SCM_BOOL_T : SCM_BOOL_F;
251 }
252
253 MAKE_SCHEME_CALLBACK (Pitch, less_p, 2);
254 SCM
255 Pitch::less_p (SCM p1, SCM p2)
256 {
257   Pitch *a = unsmob<Pitch> (p1);
258   Pitch *b = unsmob<Pitch> (p2);
259
260   if (compare (*a, *b) < 0)
261     return SCM_BOOL_T;
262   else
263     return SCM_BOOL_F;
264 }
265
266 int
267 Pitch::get_octave () const
268 {
269   return octave_;
270 }
271
272 int
273 Pitch::get_notename () const
274 {
275   return notename_;
276 }
277
278 Rational
279 Pitch::get_alteration () const
280 {
281   return alteration_;
282 }
283
284 Pitch
285 Pitch::transposed (Pitch d) const
286 {
287   Pitch p = *this;
288   p.transpose (d);
289   return p;
290 }
291
292 Pitch
293 Pitch::normalized () const
294 {
295   Pitch p = *this;
296   p.normalize ();
297   return p;
298 }
299
300 Rational NATURAL_ALTERATION (0);
301 Rational FLAT_ALTERATION (-1, 2);
302 Rational DOUBLE_FLAT_ALTERATION (-1);
303 Rational SHARP_ALTERATION (1, 2);
304
305 Pitch
306 Pitch::negated () const
307 {
308   return pitch_interval (*this, Pitch ());
309 }