]> git.donarmstrong.com Git - lilypond.git/blob - midi2ly/lilypond-item.cc
patch::: 1.5.18.moh1: [PATCH] 1.4 Lyric alignment
[lilypond.git] / midi2ly / lilypond-item.cc
1 //
2 // lilypond-item.cc -- implement Lilypond_item
3 //
4 // (c) 1997--2001 Jan Nieuwenhuizen <janneke@gnu.org>
5
6 #include <string.h>
7 #include <assert.h>
8 #include "midi2ly-global.hh"
9 #include "string-convert.hh"
10 #include "duration-convert.hh"
11 #include "lilypond-column.hh"
12 #include "lilypond-item.hh"
13 #include "lilypond-stream.hh"
14 #include "lilypond-score.hh"
15
16 Lilypond_item::Lilypond_item (Lilypond_column* lilypond_column_l)
17 {
18   lilypond_column_l_ = lilypond_column_l;
19 }
20
21 Lilypond_item::~Lilypond_item ()
22 {
23 }
24
25 Rational
26 Lilypond_item::at_mom ()
27 {
28   return lilypond_column_l_->at_mom ();
29 }
30
31 Rational
32 Lilypond_item::duration_mom ()
33 {
34   return Rational (0);
35 }
36
37 void
38 Lilypond_item::output (Lilypond_stream& lilypond_stream_r)
39 {
40   lilypond_stream_r << str () << " ";
41 }
42
43 Lilypond_key::Lilypond_key (int accidentals_i, int minor_i)
44   : Lilypond_item (0)
45 {
46   accidentals_i_ = accidentals_i;
47   minor_i_ = minor_i;
48 }
49
50 char const *accname[] = {"eses", "es", "", "is" , "isis"};
51
52 String
53 Lilypond_key::str ()
54 {
55   int key_i = accidentals_i_ >= 0
56     ? ((accidentals_i_ % 7) ["cgdaebf"] - 'a' - 2 -2 * minor_i_ + 7) % 7
57     : ((-accidentals_i_ % 7) ["cfbeadg"] - 'a' - 2 -2 * minor_i_ + 7) % 7;
58   
59   String notename_str = !minor_i_
60     ? to_str ((char) ((key_i + 2) % 7 + 'a'))
61     : to_str ((char) ((key_i + 2) % 7 + 'a'));
62
63   // fis cis gis dis ais eis bis
64   static int sharps_i_a [7] = { 2, 4, 6, 1, 3, 5, 7 };
65   // bes es as des ges ces fes
66   static int flats_i_a [7] = { 6, 4, 2, 7, 5, 3, 1 };
67   int accidentals_i = accidentals_i_ >= 0
68                               ? sharps_i_a [key_i] <= accidentals_i_ ? 1 : 0
69                               : flats_i_a [key_i] <= -accidentals_i_ ? -1 : 0;
70                                
71   if (accidentals_i)
72     notename_str += String (accname [accidentals_i + 2]);
73
74   return "\\key " + notename_str  + (minor_i_ ? "\\minor" : "\\major") + "\n";
75 }
76
77 String
78 Lilypond_key::notename_str (int pitch_i)
79 {
80   // this may seem very smart,
81   // but it-s only an excuse not to read a notename table
82
83   // major scale: do-do
84   // minor scale: la-la  (= + 5)
85   static int notename_i_a [12] = { 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6 };
86   int notename_i = notename_i_a [pitch_i % 12];
87
88   static int accidentals_i_a [12] = { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 };
89   int accidental_i = accidentals_i_a [(minor_i_ * 5 + pitch_i) % 12];
90   if (accidental_i &&  (accidentals_i_ < 0))
91     {
92       accidental_i *= -1;
93       notename_i =  (notename_i + 1) % 7;
94     }
95
96   String notename_str = to_str ((char)(((notename_i + 2) % 7) + 'a'));
97   if (accidental_i)
98     notename_str += String (accname [accidental_i + 2]);
99
100   /*
101     By tradition, all scales now consist of a sequence of 7 notes each
102     with a distinct name, from amongst a b c d e f g.  But, minor scales
103     have a wide second interval at the top - the 'leading note' is
104     sharped. (Why? it just works that way! Anything else doesn't sound as
105     good and isn't as flexible at saying things. In medieval times,
106     scales only had 6 notes to avoid this problem - the hexachords.)
107     
108     So, the d minor scale is d e f g a b-flat c-sharp d - using d-flat
109     for the leading note would skip the name c and duplicate the name d.
110     Why isn't c-sharp put in the key signature? Tradition. (It's also
111     supposedly based on the Pythagorean theory of the cycle of fifths,
112     but that really only applies to major scales...)
113     
114     Anyway, g minor is g a b-flat c d e-flat f-sharp g, and all the other
115     flat minor keys end up with a natural leading note. And there you
116     have it.
117     
118     John Sankey <bf250@freenet.carleton.ca>
119
120     Let's also do a-minor: a b c d e f gis a
121
122     --jcn
123
124    */
125
126   /* ok, bit ugly, but here we go -- jcn */
127
128
129   if (minor_i_)
130     {
131      if ((accidentals_i_ == 0) && (notename_str == "as"))
132        notename_str = "gis";
133      else if ((accidentals_i_ == -1) && (notename_str == "des"))
134        notename_str = "cis";
135      else if ((accidentals_i_ == -2) && (notename_str == "ges"))
136       notename_str = "fis";
137      else if ((accidentals_i_ == 5) && (notename_str == "g"))
138        notename_str = "fisis";
139      else if ((accidentals_i_ == 6) && (notename_str == "d"))
140       notename_str = "cisis";
141      else if ((accidentals_i_ == 7) && (notename_str == "a"))
142       notename_str = "gisis";
143
144      if ((accidentals_i_ <= -6) && (notename_str == "b"))
145       notename_str = "ces";
146      if ((accidentals_i_ <= -7) && (notename_str == "e"))
147       notename_str = "fes";
148     }
149               
150   String de_octavate_str = to_str (',',  (Lilypond_note::c0_pitch_i_c_ + 11 - pitch_i) / 12);
151   String octavate_str = to_str ('\'',  (pitch_i - Lilypond_note::c0_pitch_i_c_) / 12);
152   return notename_str +de_octavate_str  + octavate_str;
153 }
154
155 Lilypond_time_signature::Lilypond_time_signature (int num_i, int den_i, int clocks_4_i, int count_32_i)
156   : Lilypond_item (0)
157 {
158   sync_dur_.durlog_i_ = 3;
159   sync_f_ = 1.0;
160   if (count_32_i != 8)
161     warning (_f ("#32 in quarter: %d", count_32_i));
162   num_i_ = num_i;
163   den_i_ = den_i;
164   clocks_1_i_ = clocks_4_i * 4;
165 }
166
167 Rational
168 Lilypond_time_signature::bar_mom ()
169 {
170   Duration d;
171   d.durlog_i_ = den_i_;
172   return Rational (num_i_) * Duration_convert::dur2_mom (d);
173 }
174
175 int
176 Lilypond_time_signature::clocks_1_i ()
177 {
178   return clocks_1_i_;
179 }
180
181 int
182 Lilypond_time_signature::den_i ()
183 {
184   return den_i_;
185 }
186
187 int
188 Lilypond_time_signature::num_i ()
189 {
190   return num_i_;
191 }
192
193 String
194 Lilypond_time_signature::str ()
195 {
196   String str = "\\time "
197     + to_str (num_i_) + "/" + to_str (1 << den_i_)
198     + "\n";
199   return str;
200 }
201
202
203 // statics Lilypond_note
204 /*
205   this switch can be used to write simple plets like
206   c4*2/3
207   as
208   \plet 2/3; c4 \plet 1/1;
209  */
210 /*
211   UGH: .hh says false, .cc says true.
212   FIXME.
213  */
214 bool const Lilypond_note::simple_plet_b_s;
215
216 Lilypond_note::Lilypond_note (Lilypond_column* lilypond_column_l,
217                           int channel_i, int pitch_i, int dyn_i)
218   : Lilypond_item (lilypond_column_l)
219 {
220   // junk dynamics
221   (void)dyn_i;
222   channel_i_ = channel_i;
223   pitch_i_ = pitch_i;
224   end_column_l_ = 0;
225 }
226
227 Duration
228 Lilypond_note::duration ()
229 {
230   assert (end_column_l_);
231   Rational mom = end_column_l_->at_mom () - at_mom ();
232   return Duration_convert::mom2_dur (mom);
233 }
234
235 Rational
236 Lilypond_note::duration_mom ()
237 {
238   assert (end_column_l_);
239   return end_column_l_->at_mom () - at_mom ();
240 }
241
242 String
243 Lilypond_note::str ()
244 {
245   Duration dur = duration ();
246   if (dur.durlog_i_ < -10)
247     return "";
248
249   String name_str
250     = lilypond_column_l_->lilypond_score_l_->lilypond_key_l_->notename_str (pitch_i_);
251
252   if (simple_plet_b_s)
253     return name_str + Duration_convert::dur2_str (dur) + " ";
254
255   String str;
256
257   //ugh
258   if (dur.plet_b () && dur.plet_.type_i_ != 1)
259     {
260         {
261           str += String ("\\times ")
262             + String_convert::i2dec_str (dur.plet_.iso_i_, 0, 0)
263             + "/"
264             + String_convert::i2dec_str (dur.plet_.type_i_, 0, 0)
265             + " { ";
266         }
267     }
268   
269   str += name_str;
270
271   Duration tmp = dur;
272   tmp.set_plet (1,1);
273   str += Duration_convert::dur2_str (tmp);
274
275   if (dur.plet_b ())
276     {
277       if (dur.plet_.type_i_ != 1)
278         str += String (" }");
279     else
280       str += String ("*") + to_str (dur.plet_.iso_i_);
281     }
282   
283   /* 
284      note of zero duration is nonsense, 
285      but let's output anyway for convenient debugging
286   */
287   if (!duration_mom ())
288     return String ("\n% ") + str + "\n";
289
290   return str + " ";
291 }
292
293 Lilypond_skip::Lilypond_skip (Lilypond_column* lilypond_column_l, Rational skip_mom)
294   : Lilypond_item (lilypond_column_l)
295 {
296   mom_ = skip_mom;
297 }
298
299 Duration
300 Lilypond_skip::duration ()
301 {
302   return Duration_convert::mom2_dur (mom_);
303 }
304
305 Rational
306 Lilypond_skip::duration_mom ()
307 {
308   return Duration_convert::dur2_mom (duration ());
309 }
310
311 String
312 Lilypond_skip::str ()
313 {
314   String str;
315   Rational m = mom_;
316   if (m.to_int () >= 1)
317     {
318       int n = m.to_int ();
319       str += "\\skip 1";
320       if (n > 1)
321         {
322           str += "*";
323           str += to_str (n);
324         }
325       str += " ";
326       m -= n;
327     }
328
329   if (m > Rational (0))
330     {
331       
332       Duration dur = Duration_convert::mom2_dur (m);
333       str += "\\skip ";
334       str += Duration_convert::dur2_str (dur);
335       str += " ";
336     }
337   return str;
338 }
339
340 Lilypond_tempo::Lilypond_tempo (int useconds_per_4_i)
341   : Lilypond_item (0)
342 {
343   useconds_per_4_i_ = useconds_per_4_i;
344   seconds_per_1_mom_ = Rational(useconds_per_4_i_ *4, 1e6);
345 }
346
347 String
348 Lilypond_tempo::str ()
349 {
350   String str = "\\tempo 4=";
351   str += to_str (get_tempo_i (Rational (1, 4)));
352   str += "\n";
353   return str;
354 }
355
356 int
357 Lilypond_tempo::useconds_per_4_i ()
358 {
359   return useconds_per_4_i_;
360 }
361
362 int
363 Lilypond_tempo::get_tempo_i (Rational rational)
364 {
365   Rational m1 = Rational (60) / rational;
366   Rational m2 = seconds_per_1_mom_;
367   return m1 / m2;
368 }
369
370 Lilypond_text::Lilypond_text (Lilypond_text::Type type, String text_str)
371   : Lilypond_item (0)
372 {
373   type_ = type;
374   text_str_ = text_str;
375 }
376
377 String
378 Lilypond_text::str ()
379 {
380   if (!text_str_.length_i ()
381       ||  (text_str_.length_i () != (int)strlen (text_str_.ch_C ())))
382     return "";
383
384   return "% " + text_str_ + "\n";
385 }