lilypond-1.3.153
[lilypond.git] / mi2mu / midi-track-parser.cc
blob49840ec77cfbd6d5a9f0f7a418524800e32246ad
1 /*
2 midi-track-parser.cc -- implement
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1998 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
9 #include <assert.h>
10 #include "string-convert.hh"
11 #include "mi2mu-global.hh"
12 #include "midi-track-parser.hh"
13 #include "mudela-column.hh"
14 #include "mudela-item.hh"
15 #include "mudela-score.hh"
16 #include "mudela-staff.hh"
18 Midi_track_parser::Midi_track_parser (Midi_parser_info* info_l, int i)
20 info_l_ = info_l;
21 at_mom_ = 0;
22 track_info_p_ = 0;
23 mudela_staff_p_ = new Mudela_staff (i, "", "", "");
24 parse_header ();
25 parse_delta_time ();
28 Midi_track_parser::~Midi_track_parser ()
30 delete mudela_staff_p_;
31 delete track_info_p_;
34 Moment
35 Midi_track_parser::at_mom ()
37 return at_mom_;
40 bool
41 Midi_track_parser::eot ()
43 if ( info_l_->byte_L_ < info_l_->end_byte_L_ )
44 return false;
45 return true;
48 void
49 Midi_track_parser::note_end (Mudela_column* col_l, int channel_i, int pitch_i, int aftertouch_i )
51 // junk dynamics
52 (void)aftertouch_i;
54 assert (col_l);
56 for (Cons<Mudela_note>** pp = &open_note_l_list_.head_; *pp;)
58 Cons<Mudela_note>* i = *pp;
59 if ((i->car_->pitch_i_ == pitch_i) && (i->car_->channel_i_ == channel_i))
61 i->car_->end_column_l_ = col_l;
62 delete open_note_l_list_.remove_cons (pp);
63 return;
65 else
66 pp = &i->next_;
68 warning (_f ("junking note-end event: channel = %d, pitch = %d",
69 channel_i, pitch_i));
72 void
73 Midi_track_parser::note_end_all (Mudela_column* col_l)
75 // find
76 assert (col_l);
77 for (Cons<Mudela_note>* i = open_note_l_list_.head_; i; i = i->next_)
79 i->car_->end_column_l_ = col_l;
81 // UGH UGH. MEMORY LEAK.
82 open_note_l_list_.init ();
85 Mudela_staff*
86 Midi_track_parser::parse (Mudela_column* col_l)
88 Moment mom = at_mom ();
89 while (!eot () && (mom == at_mom ()))
91 Mudela_item* p = parse_event (col_l);
92 if (p)
93 mudela_staff_p_->add_item (p);
96 if (!eot())
97 return 0;
99 // catch-all
100 note_end_all (col_l);
102 Mudela_staff* p = mudela_staff_p_;
103 mudela_staff_p_ = 0;
104 return p;
107 void
108 Midi_track_parser::parse_delta_time ()
110 if (eot ())
111 return;
112 int delta_i = get_var_i ();
113 at_mom_ += Moment (delta_i, info_l_->division_1_i_);
116 Mudela_item*
117 Midi_track_parser::parse_event (Mudela_column* col_l)
119 Byte byte = peek_byte ();
120 // RUNNING_STATUS [\x00-\x5f]
121 if (byte <= 0x5f)
123 if (running_byte_ <= 0x5f)
124 exit (_ ("invalid running status"));
126 'running status' rather means 'missing status'.
127 we'll just pretend we read the running status byte.
129 byte = running_byte_;
131 else
132 byte = next_byte ();
134 Mudela_item* item_p = 0;
135 // DATA_ENTRY [\x60-\x79]
136 if ((byte >= 0x60) && (byte <= 0x79))
138 next_byte ();
140 // ALL_NOTES_OFF [\x7a-\x7f]
141 else if ((byte >= 0x7a) && (byte <= 0x7f))
143 next_byte ();
144 next_byte ();
145 note_end_all (col_l);
147 // NOTE_OFF [\x80-\x8f]
148 else if ((byte >= 0x80) && (byte <= 0x8f))
150 running_byte_ = byte;
151 int channel_i = byte & ~0x90;
152 int pitch_i = (int)next_byte ();
153 int dyn_i = (int)next_byte ();
154 note_end (col_l, channel_i, pitch_i, dyn_i);
156 // NOTE_ON [\x90-\x9f]
157 else if ((byte >= 0x90) && (byte <= 0x9f))
159 running_byte_ = byte;
160 int channel_i = byte & ~0x90;
161 int pitch_i = (int)next_byte ();
162 int dyn_i = (int)next_byte ();
164 sss: some broken devices encode NOTE_OFF as
165 NOTE_ON with zero volume
167 if (dyn_i)
169 Mudela_note* p = new Mudela_note (col_l, channel_i, pitch_i, dyn_i);
170 item_p = p;
171 open_note_l_list_.append (new Cons<Mudela_note> (p, 0));
173 else
175 note_end (col_l, channel_i, pitch_i, dyn_i);
179 // POLYPHONIC_AFTERTOUCH [\xa0-\xaf]
180 else if ((byte >= 0xa0) && (byte <= 0xaf))
182 running_byte_ = byte;
183 next_byte ();
184 next_byte ();
186 // CONTROLMODE_CHANGE [\xb0-\xbf]
187 else if ((byte >= 0xb0) && (byte <= 0xbf))
189 running_byte_ = byte;
190 next_byte ();
191 next_byte ();
193 // PROGRAM_CHANGE [\xc0-\xcf]
194 else if ((byte >= 0xc0) && (byte <= 0xcf))
196 running_byte_ = byte;
197 next_byte ();
199 // CHANNEL_AFTERTOUCH [\xd0-\xdf]
200 else if ((byte >= 0xd0) && (byte <= 0xdf))
202 running_byte_ = byte;
203 next_byte ();
204 next_byte ();
206 // PITCHWHEEL_RANGE [\xe0-\xef]
207 else if ((byte >= 0xe0) && (byte <= 0xef))
209 running_byte_ = byte;
210 next_byte ();
211 next_byte ();
213 // SYSEX_EVENT1 [\xf0]
214 else if (byte == 0xf0)
216 int length_i = get_var_i ();
217 String str = get_str (length_i);
219 // SYSEX_EVENT2 [\xf7]
220 else if (byte == 0xf7)
222 int length_i = get_var_i ();
223 String str = get_str (length_i);
225 // META_EVENT [\xff]
226 else if (byte == 0xff)
228 // SEQUENCE [\x00][\x02]
229 byte = next_byte ();
230 if (byte == 0)
232 next_byte ();
233 get_i (2);
235 // YYTEXT [\x01]
236 // YYCOPYRIGHT [\x02]
237 // YYTRACK_NAME [\x03]
238 // YYINSTRUMENT_NAME [\x04]
239 // YYLYRIC [\x05]
240 // YYMARKER [\x06]
241 // YYCUE_POINT [\x07]
242 else if ((byte >= 0x01) && (byte <= 0x07))
244 // LOGOUT (DEBUG_ver) << "\n% Text(" << (int)byte << "):" << flush;
245 int length_i = get_var_i ();
246 String str = get_str (length_i);
247 // LOGOUT (DEBUG_ver) << str << endl;
248 Mudela_text::Type t = (Mudela_text::Type)byte;
249 Mudela_text* p = new Mudela_text (t, str);
250 item_p = p;
251 if (t == Mudela_text::COPYRIGHT)
252 mudela_staff_p_->copyright_str_ = p->text_str_;
253 else if (t == Mudela_text::TRACK_NAME)
254 mudela_staff_p_->name_str_ = p->text_str_;
255 else if (t == Mudela_text::INSTRUMENT_NAME)
256 mudela_staff_p_->instrument_str_ = p->text_str_;
258 // END_OF_TRACK [\x2f][\x00]
259 else
261 Byte next = peek_byte ();
262 if ((byte == 0x2f) && (next == 0x00))
264 next_byte ();
265 info_l_->byte_L_ = info_l_->end_byte_L_;
267 // TEMPO [\x51][\x03]
268 else if ((byte == 0x51) && (next == 0x03))
270 next_byte ();
271 unsigned useconds_per_4_u = get_u (3);
272 // $$ = new Mudela_tempo ( ($2 << 16) + ($3 << 8) + $4);
273 // LOGOUT (DEBUG_ver) << $$->str() << endl;
274 Mudela_tempo* p = new Mudela_tempo ( useconds_per_4_u );
275 item_p = p;
276 info_l_->score_l_->mudela_tempo_l_ = p;
277 mudela_staff_p_->mudela_tempo_l_ = p;
279 // SMPTE_OFFSET [\x54][\x05]
280 else if ((byte == 0x54) && (next == 0x05))
282 next_byte ();
283 (int)next_byte ();
284 (int)next_byte ();
285 (int)next_byte ();
286 (int)next_byte ();
287 (int)next_byte ();
289 // TIME [\x58][\x04]
290 else if ((byte == 0x58) && (next == 0x04))
292 next_byte ();
293 int num_i = (int)next_byte ();
294 int den_i = (int)next_byte ();
295 int clocks_4_i = (int)next_byte ();
296 int count_32_i = (int)next_byte ();
297 Mudela_time_signature* p = new Mudela_time_signature ( num_i, den_i, clocks_4_i, count_32_i );
298 item_p = p;
299 info_l_->score_l_->mudela_time_signature_l_ = p;
300 info_l_->bar_mom_ = p->bar_mom ();
301 mudela_staff_p_->mudela_time_signature_l_ = p;
303 // KEY [\x59][\x02]
304 else if ((byte == 0x59) && (next == 0x02))
306 next_byte ();
307 int accidentals_i = (int)(signed char)next_byte ();
308 int minor_i = (int)(bool)next_byte ();
309 Mudela_key* p = new Mudela_key (accidentals_i, minor_i);
310 item_p = p;
311 #if 0
312 info_l_->score_l_->mudela_key_l_ = p;
313 mudela_staff_p_->mudela_key_l_ = p;
314 #endif
316 // SSME [\0x7f][\x03]
317 else if ((byte == 0x7f) && (next == 0x03))
319 next_byte ();
320 int length_i = get_var_i ();
321 String str = get_str (length_i);
322 item_p = new Mudela_text ((Mudela_text::Type)byte, str);
324 else
326 next_byte ();
327 next_byte ();
328 warning (_ ("unimplemented MIDI meta-event"));
332 else
333 exit (_ ("invalid MIDI event"));
335 if (item_p)
336 item_p->mudela_column_l_ = col_l;
338 parse_delta_time ();
340 return item_p;
343 void
344 Midi_track_parser::parse_header ()
346 String str = get_str (4);
347 if ( str != "MTrk" )
348 exit (_ ("MIDI track expected"));
350 int length_i = get_i (4);
351 // is this signed?
352 if (length_i < 0)
353 exit (_ ("invalid track length"));
354 assert (!track_info_p_);
355 track_info_p_ = new Midi_parser_info (*info_l_);
356 track_info_p_->end_byte_L_ = track_info_p_->byte_L_ + length_i;
357 forward_byte_L (length_i);
358 // forward_byte_L (length_i-1);
359 info_l_ = track_info_p_;