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