2 midi-track-parser.cc -- implement
4 source file of the GNU LilyPond music typesetter
6 (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
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
)
23 mudela_staff_p_
= new Mudela_staff (i
, "", "", "");
28 Midi_track_parser::~Midi_track_parser ()
30 delete mudela_staff_p_
;
35 Midi_track_parser::at_mom ()
41 Midi_track_parser::eot ()
43 if ( info_l_
->byte_L_
< info_l_
->end_byte_L_
)
49 Midi_track_parser::note_end (Mudela_column
* col_l
, int channel_i
, int pitch_i
, int aftertouch_i
)
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";
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, ' '));
76 Midi_track_parser::note_end_all (Mudela_column
* col_l
)
80 for (PCursor
<Mudela_note
*> i (open_note_l_list_
.top ()); i
.ok (); )
82 i
->end_column_l_
= col_l
;
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
);
95 mudela_staff_p_
->add_item (p
);
102 note_end_all (col_l
);
104 Mudela_staff
* p
= mudela_staff_p_
;
110 Midi_track_parser::parse_delta_time ()
114 int delta_i
= get_var_i ();
115 at_mom_
+= Moment (delta_i
, info_l_
->division_1_i_
);
119 Midi_track_parser::parse_event (Mudela_column
* col_l
)
121 Byte byte
= peek_byte ();
122 // RUNNING_STATUS [\x00-\x5f]
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_
;
136 Mudela_item
* item_p
= 0;
137 // DATA_ENTRY [\x60-\x79]
138 if ((byte
>= 0x60) && (byte
<= 0x79))
142 // ALL_NOTES_OFF [\x7a-\x7f]
143 else if ((byte
>= 0x7a) && (byte
<= 0x7f))
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
171 Mudela_note
* p
= new Mudela_note (col_l
, channel_i
, pitch_i
, dyn_i
);
173 open_note_l_list_
.bottom ().add (p
);
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
;
187 // CONTROLMODE_CHANGE [\xb0-\xbf]
188 else if ((byte
>= 0xb0) && (byte
<= 0xbf))
190 running_byte_
= byte
;
194 // PROGRAM_CHANGE [\xc0-\xcf]
195 else if ((byte
>= 0xc0) && (byte
<= 0xcf))
197 running_byte_
= byte
;
200 // CHANNEL_AFTERTOUCH [\xd0-\xdf]
201 else if ((byte
>= 0xd0) && (byte
<= 0xdf))
203 running_byte_
= byte
;
207 // PITCHWHEEL_RANGE [\xe0-\xef]
208 else if ((byte
>= 0xe0) && (byte
<= 0xef))
210 running_byte_
= 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
);
227 else if (byte
== 0xff)
229 // SEQUENCE [\x00][\x02]
237 // YYCOPYRIGHT [\x02]
238 // YYTRACK_NAME [\x03]
239 // YYINSTRUMENT_NAME [\x04]
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
);
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]
262 Byte next
= peek_byte ();
263 if ((byte
== 0x2f) && (next
== 0x00))
266 info_l_
->byte_L_
= info_l_
->end_byte_L_
;
268 // TEMPO [\x51][\x03]
269 else if ((byte
== 0x51) && (next
== 0x03))
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
);
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))
291 else if ((byte
== 0x58) && (next
== 0x04))
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
);
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
;
305 else if ((byte
== 0x59) && (next
== 0x02))
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
);
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))
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
);
327 warning (_("Unimplemented MIDI meta-event"));
332 exit (_("Invalid MIDI event"));
335 item_p
->mudela_column_l_
= col_l
;
343 Midi_track_parser::parse_header ()
345 String str
= get_str (4);
347 exit (_("MIDI track expected"));
349 int length_i
= get_i (4);
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_
;