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-staff.hh"
17 Midi_track_parser::Midi_track_parser (Midi_parser_info* info_l)
22 mudela_staff_p_ = new Mudela_staff (0, "", "", "");
27 Midi_track_parser::~Midi_track_parser ()
29 delete mudela_staff_p_;
34 Midi_track_parser::at_mom ()
40 Midi_track_parser::eot ()
42 if ( info_l_->byte_L_ < info_l_->end_byte_L_ )
48 Midi_track_parser::note_end (Mudela_column* col_l, int channel_i, int pitch_i, int aftertouch_i )
53 for (PCursor<Mudela_note*> i (open_note_l_list_.top ()); i.ok (); i++)
55 if ((i->pitch_i_ == pitch_i) && (i->channel_i_ == channel_i))
57 i->end_column_l_ = col_l;
58 // LOGOUT(DEBUG_ver) << "Note: " << pitch_i;
59 // LOGOUT(DEBUG_ver) << "; " << i->mudela_column_l_->at_mom_;
60 // LOGOUT(DEBUG_ver) << ", " << i->end_column_l_->at_mom_ << "\n";
65 warning (String ("junking note-end event: ")
66 + " channel = " + String_convert::i2dec_str (channel_i, 0, ' ')
67 + ", pitch = " + String_convert::i2dec_str (pitch_i, 0, ' '));
71 Midi_track_parser::note_end_all (Mudela_column* col_l)
74 for (PCursor<Mudela_note*> i (open_note_l_list_.top ()); i.ok (); i++)
76 i->end_column_l_ = col_l;
85 Midi_track_parser::parse (Mudela_column* col_l)
87 Moment mom = at_mom ();
88 while (!eot () && (mom == at_mom ()))
90 Mudela_item* p = parse_event (col_l);
92 mudela_staff_p_->add_item (p);
98 Mudela_staff* p = mudela_staff_p_;
104 Midi_track_parser::parse_delta_time ()
108 int delta_i = get_var_i ();
109 at_mom_ += Moment (delta_i, info_l_->division_1_i_);
113 Midi_track_parser::parse_event (Mudela_column* col_l)
115 Byte byte = peek_byte ();
116 // RUNNING_STATUS [\x00-\x5f]
119 if (running_byte_ <= 0x5f)
120 exit ("Invalid running status");
122 'running status' rather means 'missing status'.
123 we'll just pretend we read the running status byte.
125 byte = running_byte_;
130 Mudela_item* item_p = 0;
131 // DATA_ENTRY [\x60-\x79]
132 if ((byte >= 0x60) && (byte <= 0x79))
136 // ALL_NOTES_OFF [\x7a-\x7f]
137 else if ((byte >= 0x7a) && (byte <= 0x7f))
141 note_end_all (col_l);
143 // NOTE_OFF [\x80-\x8f]
144 else if ((byte >= 0x80) && (byte <= 0x8f))
146 running_byte_ = byte;
147 int channel_i = byte & ~0x90;
148 int pitch_i = (int)next_byte ();
149 int dyn_i = (int)next_byte ();
150 note_end (col_l, channel_i, pitch_i, dyn_i);
152 // NOTE_ON [\x90-\x9f]
153 else if ((byte >= 0x90) && (byte <= 0x9f))
155 running_byte_ = byte;
156 int channel_i = byte & ~0x90;
157 int pitch_i = (int)next_byte ();
158 int dyn_i = (int)next_byte ();
160 sss: some broken devices encode NOTE_OFF as
161 NOTE_ON with zero volume
165 Mudela_note* p = new Mudela_note (col_l, channel_i, pitch_i, dyn_i);
167 open_note_l_list_.bottom ().add (p);
171 note_end (col_l, channel_i, pitch_i, dyn_i);
174 // POLYPHONIC_AFTERTOUCH [\xa0-\xaf]
175 else if ((byte >= 0xa0) && (byte <= 0xaf))
177 running_byte_ = byte;
181 // CONTROLMODE_CHANGE [\xb0-\xbf]
182 else if ((byte >= 0xb0) && (byte <= 0xbf))
184 running_byte_ = byte;
188 // PROGRAM_CHANGE [\xc0-\xcf]
189 else if ((byte >= 0xc0) && (byte <= 0xcf))
191 running_byte_ = byte;
194 // CHANNEL_AFTERTOUCH [\xd0-\xdf]
195 else if ((byte >= 0xd0) && (byte <= 0xdf))
197 running_byte_ = byte;
201 // PITCHWHEEL_RANGE [\xe0-\xef]
202 else if ((byte >= 0xe0) && (byte <= 0xef))
204 running_byte_ = byte;
208 // SYSEX_EVENT1 [\xf0]
209 else if (byte == 0xf0)
211 int length_i = get_var_i ();
212 String str = get_str (length_i);
214 // SYSEX_EVENT2 [\xf7]
215 else if (byte == 0xf7)
217 int length_i = get_var_i ();
218 String str = get_str (length_i);
221 else if (byte == 0xff)
223 // SEQUENCE [\x00][\x02]
231 // YYCOPYRIGHT [\x02]
232 // YYTRACK_NAME [\x03]
233 // YYINSTRUMENT_NAME [\x04]
236 // YYCUE_POINT [\x07]
237 else if ((byte >= 0x01) && (byte <= 0x07))
239 // LOGOUT (DEBUG_ver) << "\n% Text(" << (int)byte << "):" << flush;
240 int length_i = get_var_i ();
241 String str = get_str (length_i);
242 // LOGOUT (DEBUG_ver) << str << endl;
243 item_p = new Mudela_text ((Mudela_text::Type)byte, str);
245 // END_OF_TRACK [\x2f][\x00]
248 Byte next = peek_byte ();
249 if ((byte == 0x2f) && (next == 0x00))
252 info_l_->byte_L_ = info_l_->end_byte_L_;
254 // TEMPO [\x51][\x03]
255 else if ((byte == 0x51) && (next == 0x03))
258 unsigned useconds_per_4_u = get_u (3);
259 // $$ = new Mudela_tempo ( ($2 << 16) + ($3 << 8) + $4);
260 // LOGOUT (DEBUG_ver) << $$->str() << endl;
261 item_p = new Mudela_tempo ( useconds_per_4_u );
263 // SMPTE_OFFSET [\x54][\x05]
264 else if ((byte == 0x54) && (next == 0x05))
274 else if ((byte == 0x58) && (next == 0x04))
277 int num_i = (int)next_byte ();
278 int den_i = (int)next_byte ();
279 int clocks_4_i = (int)next_byte ();
280 int count_32_i = (int)next_byte ();
281 Mudela_meter* p = new Mudela_meter ( num_i, den_i, clocks_4_i, count_32_i );
283 info_l_->bar_mom_ = p->bar_mom ();
286 else if ((byte == 0x59) && (next == 0x02))
289 int accidentals_i = (int)next_byte ();
290 int minor_i = (int)next_byte ();
291 item_p = new Mudela_key (accidentals_i, minor_i);
293 // SSME [\0x7f][\x03]
294 else if ((byte == 0x7f) && (next == 0x03))
297 int length_i = get_var_i ();
298 String str = get_str (length_i);
299 item_p = new Mudela_text ((Mudela_text::Type)byte, str);
302 exit ("Invalid MIDI meta-event");
306 exit ("Invalid MIDI event");
309 item_p->mudela_column_l_ = col_l;
317 Midi_track_parser::parse_header ()
319 String str = get_str (4);
321 exit ("MIDI track expected");
323 int length_i = get_i (4);
326 exit ("Invalid track length");
327 assert (!track_info_p_);
328 track_info_p_ = new Midi_parser_info (*info_l_);
329 track_info_p_->end_byte_L_ = track_info_p_->byte_L_ + length_i;
330 forward_byte_L (length_i);
331 // forward_byte_L (length_i-1);
332 info_l_ = track_info_p_;