lilypond-1.5.8
[lilypond.git] / midi2ly / mudela-item.cc
blob1415acd93375273708eb1d6e891b27d6420a231b
1 //
2 // mudela-item.cc -- implement Mudela_item
3 //
4 // copyright 1997 Jan Nieuwenhuizen <janneke@gnu.org>
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 "mudela-column.hh"
12 #include "mudela-item.hh"
13 #include "mudela-stream.hh"
14 #include "mudela-score.hh"
16 Mudela_item::Mudela_item (Mudela_column* mudela_column_l)
18 mudela_column_l_ = mudela_column_l;
21 Mudela_item::~Mudela_item ()
25 Rational
26 Mudela_item::at_mom ()
28 return mudela_column_l_->at_mom ();
31 Rational
32 Mudela_item::duration_mom ()
34 return Rational (0);
37 void
38 Mudela_item::output (Mudela_stream& mudela_stream_r)
40 mudela_stream_r << str () << " ";
43 Mudela_key::Mudela_key (int accidentals_i, int minor_i)
44 : Mudela_item (0)
46 accidentals_i_ = accidentals_i;
47 minor_i_ = minor_i;
50 char const *accname[] = {"eses", "es", "", "is" , "isis"};
52 String
53 Mudela_key::str ()
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;
59 String notename_str = !minor_i_
60 ? to_str ((char) ((key_i + 2) % 7 + 'a'))
61 : to_str ((char) ((key_i + 2) % 7 + 'a'));
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;
71 if (accidentals_i)
72 notename_str += String (accname [accidentals_i + 2]);
74 return "\\key " + notename_str + (minor_i_ ? "\\minor" : "\\major") + ";\n";
77 String
78 Mudela_key::notename_str (int pitch_i)
80 // this may seem very smart,
81 // but it-s only an excuse not to read a notename table
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];
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))
92 accidental_i *= -1;
93 notename_i = (notename_i + 1) % 7;
96 String notename_str = to_str ((char)(((notename_i + 2) % 7) + 'a'));
97 if (accidental_i)
98 notename_str += String (accname [accidental_i + 2]);
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.)
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...)
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.
118 John Sankey <bf250@freenet.carleton.ca>
120 Let's also do a-minor: a b c d e f gis a
122 --jcn
126 /* ok, bit ugly, but here we go -- jcn */
129 if (minor_i_)
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";
144 if ((accidentals_i_ <= -6) && (notename_str == "b"))
145 notename_str = "ces";
146 if ((accidentals_i_ <= -7) && (notename_str == "e"))
147 notename_str = "fes";
150 String de_octavate_str = to_str (',', (Mudela_note::c0_pitch_i_c_ + 11 - pitch_i) / 12);
151 String octavate_str = to_str ('\'', (pitch_i - Mudela_note::c0_pitch_i_c_) / 12);
152 return notename_str +de_octavate_str + octavate_str;
155 Mudela_time_signature::Mudela_time_signature (int num_i, int den_i, int clocks_4_i, int count_32_i)
156 : Mudela_item (0)
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;
167 Rational
168 Mudela_time_signature::bar_mom ()
170 Duration d;
171 d.durlog_i_ = den_i_;
172 return Rational (num_i_) * Duration_convert::dur2_mom (d);
176 Mudela_time_signature::clocks_1_i ()
178 return clocks_1_i_;
182 Mudela_time_signature::den_i ()
184 return den_i_;
188 Mudela_time_signature::num_i ()
190 return num_i_;
193 String
194 Mudela_time_signature::str ()
196 String str = "\\time "
197 + to_str (num_i_) + "/" + to_str (1 << den_i_)
198 + ";\n";
199 return str;
203 // statics Mudela_note
205 this switch can be used to write simple plets like
206 c4*2/3
208 \plet 2/3; c4 \plet 1/1;
211 UGH: .hh says false, .cc says true.
212 FIXME.
214 bool const Mudela_note::simple_plet_b_s;
216 Mudela_note::Mudela_note (Mudela_column* mudela_column_l,
217 int channel_i, int pitch_i, int dyn_i)
218 : Mudela_item (mudela_column_l)
220 // junk dynamics
221 (void)dyn_i;
222 channel_i_ = channel_i;
223 pitch_i_ = pitch_i;
224 end_column_l_ = 0;
227 Duration
228 Mudela_note::duration ()
230 assert (end_column_l_);
231 Rational mom = end_column_l_->at_mom () - at_mom ();
232 return Duration_convert::mom2_dur (mom);
235 Rational
236 Mudela_note::duration_mom ()
238 assert (end_column_l_);
239 return end_column_l_->at_mom () - at_mom ();
242 String
243 Mudela_note::str ()
245 Duration dur = duration ();
246 if (dur.durlog_i_ < -10)
247 return "";
249 String name_str
250 = mudela_column_l_->mudela_score_l_->mudela_key_l_->notename_str (pitch_i_);
252 if (simple_plet_b_s)
253 return name_str + Duration_convert::dur2_str (dur) + " ";
255 String str;
257 //ugh
258 if (dur.plet_b ())
259 str += String ("\\times ")
260 + String_convert::i2dec_str (dur.plet_.iso_i_, 0, 0)
261 + "/"
262 + String_convert::i2dec_str (dur.plet_.type_i_, 0, 0)
263 + " { ";
266 str += name_str;
268 Duration tmp = dur;
269 tmp.set_plet (1,1);
270 str += Duration_convert::dur2_str (tmp);
272 if (dur.plet_b ())
273 str += String (" }");
276 note of zero duration is nonsense,
277 but let's output anyway for convenient debugging
279 if (!duration_mom ())
280 return String ("\n% ") + str + "\n";
282 return str + " ";
285 Mudela_skip::Mudela_skip (Mudela_column* mudela_column_l, Rational skip_mom)
286 : Mudela_item (mudela_column_l)
288 mom_ = skip_mom;
291 Duration
292 Mudela_skip::duration ()
294 return Duration_convert::mom2_dur (mom_);
297 Rational
298 Mudela_skip::duration_mom ()
300 return Duration_convert::dur2_mom (duration ());
303 String
304 Mudela_skip::str ()
306 if (!mom_)
307 return String ("");
309 Duration dur = duration ();
310 if (dur.durlog_i_<-10)
311 return "";
313 String str = "\\skip ";
314 str += Duration_convert::dur2_str (dur) + "; ";
316 return str;
319 Mudela_tempo::Mudela_tempo (int useconds_per_4_i)
320 : Mudela_item (0)
322 useconds_per_4_i_ = useconds_per_4_i;
323 seconds_per_1_mom_ = Rational(useconds_per_4_i_ *4, 1e6);
326 String
327 Mudela_tempo::str ()
329 String str = "\\tempo 4=";
330 str += to_str (get_tempo_i (Rational (1, 4)));
331 str += ";\n";
332 return str;
336 Mudela_tempo::useconds_per_4_i ()
338 return useconds_per_4_i_;
342 Mudela_tempo::get_tempo_i (Rational rational)
344 Rational m1 = Rational (60) / rational;
345 Rational m2 = seconds_per_1_mom_;
346 return m1 / m2;
349 Mudela_text::Mudela_text (Mudela_text::Type type, String text_str)
350 : Mudela_item (0)
352 type_ = type;
353 text_str_ = text_str;
356 String
357 Mudela_text::str ()
359 if (!text_str_.length_i ()
360 || (text_str_.length_i () != (int)strlen (text_str_.ch_C ())))
361 return "";
363 return "% " + text_str_ + "\n";