]> git.donarmstrong.com Git - lilypond.git/blob - lily/musical-pitch.cc
release: 0.1.65
[lilypond.git] / lily / musical-pitch.cc
1 /*   
2   musical-pitch.cc --  implement Musical_pitch
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1998 Han-Wen Nienhuys <hanwen@cs.ruu.nl>
7   
8  */
9 #include "musical-pitch.hh"
10 #include "debug.hh"
11
12 Musical_pitch::Musical_pitch ()
13 {
14   init ();
15 }
16
17 void
18 Musical_pitch::init ()
19 {
20   notename_i_ = 0;
21   octave_i_ = 0;
22   accidental_i_ = 0;
23 }
24
25 void
26 Musical_pitch::print () const
27 {
28 #ifndef NPRINT
29   DOUT << str();
30 #endif
31 }
32
33 int
34 Musical_pitch::compare (Musical_pitch const &m1, Musical_pitch const &m2)
35 {
36     int o=  m1.octave_i_ - m2.octave_i_;
37   int n = m1.notename_i_ - m2.notename_i_;
38   int a = m1.accidental_i_ - m2.accidental_i_;
39
40   if (o)
41         return o;
42   if (n)
43         return n;
44   if (a)
45         return a;
46   return 0;
47 }
48
49 int
50 Musical_pitch::steps () const
51 {
52   return  notename_i_ + octave_i_*7;
53 }
54
55 /*
56   should be settable from input to allow "viola"-mode
57  */
58 static Byte pitch_byte_a[  ] = { 0, 2, 4, 5, 7, 9, 11 };
59
60 int
61 Musical_pitch::semitone_pitch () const
62 {
63   return  pitch_byte_a[ notename_i_ % 7 ] + accidental_i_ + octave_i_ * 12;
64 }
65
66 void
67 Musical_pitch::transpose (Musical_pitch delta)
68 {
69   int old_pitch = semitone_pitch ();
70   int delta_pitch = delta.semitone_pitch ();
71   octave_i_ += delta.octave_i_;
72   notename_i_ += delta.notename_i_;
73
74   
75   while  (notename_i_ >= 7)
76     {
77       notename_i_ -= 7;
78       octave_i_ ++;
79     }
80
81   int new_pitch = semitone_pitch ();
82   int delta_acc = new_pitch - old_pitch - delta_pitch;
83   accidental_i_ -= delta_acc;
84 }
85
86
87 char const *accname[] = {"double flat", "flat", "natural",
88                          "sharp" , "double sharp"};
89
90 String
91 Musical_pitch::str () const
92 {
93   int n = (notename_i_ + 2) % 7;
94   String s (char(n + 'a'));
95   if (accidental_i_)
96     s +=   " " + String (accname[accidental_i_ + 2]);
97
98   if (octave_i_)
99     s  += String ((octave_i_> 0)? "^": "_") + String(octave_i_);
100   
101
102   return s;
103 }
104
105 Musical_pitch
106 Musical_pitch::to_relative_octave (Musical_pitch p)
107 {
108   int oct_mod = octave_i_  + 1; // account for c' = octave 1 iso. 0 4
109   Musical_pitch up_pitch (p);
110   Musical_pitch down_pitch (p);
111
112   up_pitch.accidental_i_ = accidental_i_;
113   down_pitch.accidental_i_ = accidental_i_;
114   
115   up_pitch.up_to (notename_i_);
116   down_pitch.down_to (notename_i_);
117   int h = p.steps ();
118   if (abs (up_pitch.steps () - h) < abs (down_pitch.steps () - h))
119     {
120       *this =  up_pitch;
121       /* this sux imnsho
122       if (oct_mod > 0)          // ugh
123       oct_mod --;*/
124     }
125   else
126     {
127       *this = down_pitch;
128       /*      if (oct_mod < 0)
129               oct_mod ++;*/
130     }
131   
132   octave_i_ += oct_mod;
133   return *this;
134 }
135
136 void
137 Musical_pitch::up_to (int notename)
138 {
139   if (notename_i_  > notename)
140     {
141       octave_i_ ++;
142     }
143   notename_i_  = notename;
144 }
145
146 void
147 Musical_pitch::down_to (int notename)
148 {
149   if (notename_i_ < notename)
150     {
151       octave_i_ --;
152     }
153   notename_i_ = notename;
154 }
155
156 #if 0
157
158 Musical_pitch
159 My_lily_parser::get_melodic_req (Musical_pitch p, int quotes)
160 {
161   if (relative_octave_mode_b_)
162     {
163       set_nearest (melodic);
164       int d = melodic->pitch () - last_melodic_->pitch ();
165       int shift = 0;
166       if (quotes && (sign (d) == sign (quotes)))
167         shift -= sign (quotes);
168       if (!quotes && (abs (d) == 6))
169         {
170           String str = _("Octave ambiguity; assuming ");
171           /*
172             [TODO]
173             figure this out.
174
175             If the distance is exactly*) half an octave, there is 
176             no nearest pitch.  In that case, we'll try to guess what 
177             composer/ typist meant.
178             Firstly, we'll do this by comparing the 'notename distance':
179                 
180             f b'   % name-distance: f g a b: 3
181
182             is surely a shorter notename distance than
183
184             f 'b  % name-distance: b c d e f: 4
185
186             (should we give a warning at all, or can we safely assume
187             this is a positive interval up?)
188
189             *) It is conceivable that, musically speaking, the interval
190             with the greater pitch-distance is thought to be smaller?
191
192           */
193
194           int name_delta = melodic->notename_i_ - last_melodic_->notename_i_;
195           int name_near = abs (name_delta) % 7;
196           int name_wrap = (7 - abs (name_delta)) % 7;
197           if (name_near != name_wrap)
198             shift = name_near < name_wrap ? sign (name_delta) : -sign (name_delta);
199           else if (sign (last_melodic_->accidental_i_) 
200                    != sign (melodic->accidental_i_))
201             shift = last_melodic_->accidental_i_ - melodic->accidental_i_;
202           else
203             shift = -1;
204           String name_str = notename_str (melodic);
205           str += shift > 0 ? name_str + "'" : "'" + name_str;
206           if (sign (d) == sign (shift))
207             shift = 0;
208           melodic->warning (str);
209         }
210       melodic->octave_i_ += quotes + shift;
211     }
212   else
213     {
214       Melodic_req nearest (*melodic);
215       set_nearest (&nearest);
216       melodic->octave_i_ += quotes;
217
218       if (find_quarts_global_b)
219         {
220           int e = melodic->pitch () - nearest.pitch ();
221           if (e)
222             {
223               int d = melodic->pitch () - last_melodic_->pitch ();
224               String str = _("Interval greater than quart");
225               int n = 1 + (abs (d) - 1) / 12;
226               String quote_str ('\'', n);
227               str += _(", relative: ");
228               String name_str = notename_str (melodic);
229               str += d < 0 ? quote_str + name_str : name_str + quote_str;
230               melodic->warning (str);
231             }
232         }
233     }
234   delete last_melodic_;
235   last_melodic_ = melodic->clone ()->musical ()->melodic ();
236   return melodic;
237 }
238 #endif