lilypond-0.1.36
[lilypond.git] / mi2mu / midi-track-parser.cc
blobfd87d2a7e96b755b7ad226aab59a4d9ee7f2221d
1 /*
2 midi-track-parser.cc -- implement
4 source file of the GNU LilyPond music typesetter
6 (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
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 (PCursor<Mudela_note*> i (open_note_l_list_.top ()); i.ok (); )
58 if ((i->pitch_i_ == pitch_i) && (i->channel_i_ == channel_i))
60 i->end_column_l_ = col_l;
61 // LOGOUT(DEBUG_ver) << "Note: " << pitch_i;
62 // LOGOUT(DEBUG_ver) << "; " << i->mudela_column_l_->at_mom_;
63 // LOGOUT(DEBUG_ver) << ", " << i->end_column_l_->at_mom_ << "\n";
64 i.remove_p();
65 return;
67 else
68 i++;
70 warning (String (_("junking note-end event: "))
71 + _(" channel = ") + String_convert::i2dec_str (channel_i, 0, ' ')
72 + _(", pitch = ") + String_convert::i2dec_str (pitch_i, 0, ' '));
75 void
76 Midi_track_parser::note_end_all (Mudela_column* col_l)
78 // find
79 assert (col_l);
80 for (PCursor<Mudela_note*> i (open_note_l_list_.top ()); i.ok (); )
82 i->end_column_l_ = col_l;
83 i.remove_p ();
87 Mudela_staff*
88 Midi_track_parser::parse (Mudela_column* col_l)
90 Moment mom = at_mom ();
91 while (!eot () && (mom == at_mom ()))
93 Mudela_item* p = parse_event (col_l);
94 if (p)
95 mudela_staff_p_->add_item (p);
98 if (!eot())
99 return 0;
101 // vangnet
102 note_end_all (col_l);
104 Mudela_staff* p = mudela_staff_p_;
105 mudela_staff_p_ = 0;
106 return p;
109 void
110 Midi_track_parser::parse_delta_time ()
112 if (eot ())
113 return;
114 int delta_i = get_var_i ();
115 at_mom_ += Moment (delta_i, info_l_->division_1_i_);
118 Mudela_item*
119 Midi_track_parser::parse_event (Mudela_column* col_l)
121 Byte byte = peek_byte ();
122 // RUNNING_STATUS [\x00-\x5f]
123 if (byte <= 0x5f)
125 if (running_byte_ <= 0x5f)
126 exit (_("Invalid running status"));
128 'running status' rather means 'missing status'.
129 we'll just pretend we read the running status byte.
131 byte = running_byte_;
133 else
134 byte = next_byte ();
136 Mudela_item* item_p = 0;
137 // DATA_ENTRY [\x60-\x79]
138 if ((byte >= 0x60) && (byte <= 0x79))
140 next_byte ();
142 // ALL_NOTES_OFF [\x7a-\x7f]
143 else if ((byte >= 0x7a) && (byte <= 0x7f))
145 next_byte ();
146 next_byte ();
147 note_end_all (col_l);
149 // NOTE_OFF [\x80-\x8f]
150 else if ((byte >= 0x80) && (byte <= 0x8f))
152 running_byte_ = byte;
153 int channel_i = byte & ~0x90;
154 int pitch_i = (int)next_byte ();
155 int dyn_i = (int)next_byte ();
156 note_end (col_l, channel_i, pitch_i, dyn_i);
158 // NOTE_ON [\x90-\x9f]
159 else if ((byte >= 0x90) && (byte <= 0x9f))
161 running_byte_ = byte;
162 int channel_i = byte & ~0x90;
163 int pitch_i = (int)next_byte ();
164 int dyn_i = (int)next_byte ();
166 sss: some broken devices encode NOTE_OFF as
167 NOTE_ON with zero volume
169 if (dyn_i)
171 Mudela_note* p = new Mudela_note (col_l, channel_i, pitch_i, dyn_i);
172 item_p = p;
173 open_note_l_list_.bottom ().add (p);
175 else
177 note_end (col_l, channel_i, pitch_i, dyn_i);
180 // POLYPHONIC_AFTERTOUCH [\xa0-\xaf]
181 else if ((byte >= 0xa0) && (byte <= 0xaf))
183 running_byte_ = byte;
184 next_byte ();
185 next_byte ();
187 // CONTROLMODE_CHANGE [\xb0-\xbf]
188 else if ((byte >= 0xb0) && (byte <= 0xbf))
190 running_byte_ = byte;
191 next_byte ();
192 next_byte ();
194 // PROGRAM_CHANGE [\xc0-\xcf]
195 else if ((byte >= 0xc0) && (byte <= 0xcf))
197 running_byte_ = byte;
198 next_byte ();
200 // CHANNEL_AFTERTOUCH [\xd0-\xdf]
201 else if ((byte >= 0xd0) && (byte <= 0xdf))
203 running_byte_ = byte;
204 next_byte ();
205 next_byte ();
207 // PITCHWHEEL_RANGE [\xe0-\xef]
208 else if ((byte >= 0xe0) && (byte <= 0xef))
210 running_byte_ = byte;
211 next_byte ();
212 next_byte ();
214 // SYSEX_EVENT1 [\xf0]
215 else if (byte == 0xf0)
217 int length_i = get_var_i ();
218 String str = get_str (length_i);
220 // SYSEX_EVENT2 [\xf7]
221 else if (byte == 0xf7)
223 int length_i = get_var_i ();
224 String str = get_str (length_i);
226 // META_EVENT [\xff]
227 else if (byte == 0xff)
229 // SEQUENCE [\x00][\x02]
230 byte = next_byte ();
231 if (byte == 0)
233 next_byte ();
234 get_i (2);
236 // YYTEXT [\x01]
237 // YYCOPYRIGHT [\x02]
238 // YYTRACK_NAME [\x03]
239 // YYINSTRUMENT_NAME [\x04]
240 // YYLYRIC [\x05]
241 // YYMARKER [\x06]
242 // YYCUE_POINT [\x07]
243 else if ((byte >= 0x01) && (byte <= 0x07))
245 // LOGOUT (DEBUG_ver) << "\n% Text(" << (int)byte << "):" << flush;
246 int length_i = get_var_i ();
247 String str = get_str (length_i);
248 // LOGOUT (DEBUG_ver) << str << endl;
249 Mudela_text::Type t = (Mudela_text::Type)byte;
250 Mudela_text* p = new Mudela_text (t, str);
251 item_p = p;
252 if (t == Mudela_text::COPYRIGHT)
253 mudela_staff_p_->copyright_str_ = p->text_str_;
254 else if (t == Mudela_text::TRACK_NAME)
255 mudela_staff_p_->name_str_ = p->text_str_;
256 else if (t == Mudela_text::INSTRUMENT_NAME)
257 mudela_staff_p_->instrument_str_ = p->text_str_;
259 // END_OF_TRACK [\x2f][\x00]
260 else
262 Byte next = peek_byte ();
263 if ((byte == 0x2f) && (next == 0x00))
265 next_byte ();
266 info_l_->byte_L_ = info_l_->end_byte_L_;
268 // TEMPO [\x51][\x03]
269 else if ((byte == 0x51) && (next == 0x03))
271 next_byte ();
272 unsigned useconds_per_4_u = get_u (3);
273 // $$ = new Mudela_tempo ( ($2 << 16) + ($3 << 8) + $4);
274 // LOGOUT (DEBUG_ver) << $$->str() << endl;
275 Mudela_tempo* p = new Mudela_tempo ( useconds_per_4_u );
276 item_p = p;
277 info_l_->score_l_->mudela_tempo_l_ = p;
278 mudela_staff_p_->mudela_tempo_l_ = p;
280 // SMPTE_OFFSET [\x54][\x05]
281 else if ((byte == 0x54) && (next == 0x05))
283 next_byte ();
284 (int)next_byte ();
285 (int)next_byte ();
286 (int)next_byte ();
287 (int)next_byte ();
288 (int)next_byte ();
290 // TIME [\x58][\x04]
291 else if ((byte == 0x58) && (next == 0x04))
293 next_byte ();
294 int num_i = (int)next_byte ();
295 int den_i = (int)next_byte ();
296 int clocks_4_i = (int)next_byte ();
297 int count_32_i = (int)next_byte ();
298 Mudela_meter* p = new Mudela_meter ( num_i, den_i, clocks_4_i, count_32_i );
299 item_p = p;
300 info_l_->score_l_->mudela_meter_l_ = p;
301 info_l_->bar_mom_ = p->bar_mom ();
302 mudela_staff_p_->mudela_meter_l_ = p;
304 // KEY [\x59][\x02]
305 else if ((byte == 0x59) && (next == 0x02))
307 next_byte ();
308 int accidentals_i = (int)next_byte ();
309 int minor_i = (int)next_byte ();
310 Mudela_key* p = new Mudela_key (accidentals_i, minor_i);
311 item_p = p;
312 info_l_->score_l_->mudela_key_l_ = p;
313 mudela_staff_p_->mudela_key_l_ = p;
315 // SSME [\0x7f][\x03]
316 else if ((byte == 0x7f) && (next == 0x03))
318 next_byte ();
319 int length_i = get_var_i ();
320 String str = get_str (length_i);
321 item_p = new Mudela_text ((Mudela_text::Type)byte, str);
323 else
325 next_byte ();
326 next_byte ();
327 warning (_("Unimplemented MIDI meta-event"));
331 else
332 exit (_("Invalid MIDI event"));
334 if (item_p)
335 item_p->mudela_column_l_ = col_l;
337 parse_delta_time ();
339 return item_p;
342 void
343 Midi_track_parser::parse_header ()
345 String str = get_str (4);
346 if ( str != "MTrk" )
347 exit (_("MIDI track expected"));
349 int length_i = get_i (4);
350 // is this signed?
351 if (length_i < 0)
352 exit (_("Invalid track length"));
353 assert (!track_info_p_);
354 track_info_p_ = new Midi_parser_info (*info_l_);
355 track_info_p_->end_byte_L_ = track_info_p_->byte_L_ + length_i;
356 forward_byte_L (length_i);
357 // forward_byte_L (length_i-1);
358 info_l_ = track_info_p_;