]> git.donarmstrong.com Git - lilypond.git/blob - mi2mu/midi-parser.y
ce33c6bc83d4d18a46f7244efdf7ee79c7bbb104
[lilypond.git] / mi2mu / midi-parser.y
1 %{
2
3 #include "mi2mu.hh"
4
5 #ifndef NDEBUG
6 #define YYDEBUG 1
7 #endif
8
9 %}
10
11 %union {
12     Byte byte;
13     char c;
14     int i;
15     String* str_p;
16     Midi_event* midi_event_p;   // Voice_element* ?
17     Midi_score* midi_score_p;   // Input_score* ?
18     Midi_track* midi_track_p;   // Input_music* ?
19 }
20
21 %token HEADER TRACK
22 %token SYSEX_EVENT1 SYSEX_EVENT2
23 %token META_EVENT
24 %token SEQUENCE
25 %token END_OF_TRACK TEMPO SMPTE_OFFSET TIME KEY SSME
26
27 %token<i> I8 U8 INT16 INT32 INT7_8UNSET INT7_8SET VARINT
28 %token<i> RUNNING_STATUS DATA_ENTRY ALL_NOTES_OFF
29 %token<i> NOTE_OFF NOTE_ON 
30 %token<i> POLYPHONIC_AFTERTOUCH CONTROLMODE_CHANGE PROGRAM_CHANGE 
31 %token<i> CHANNEL_AFTERTOUCH PITCHWHEEL_RANGE
32 %token<i> YYTEXT YYCOPYRIGHT YYTRACK_NAME YYINSTRUMENT_NAME YYLYRIC YYMARKER YYCUE_POINT
33 %token<str_p> DATA
34
35 %type <i> varint
36 %type <midi_score_p> header midi_score
37 %type <midi_track_p> track
38 %type <midi_event_p> event
39 %type <midi_event_p> the_event meta_event the_meta_event text_event midi_event sysex_event
40 %type <midi_event_p> running_status data_entry all_notes_off
41 %type <midi_event_p> note_off note_on
42 %type <midi_event_p> polyphonic_aftertouch controlmode_change program_change
43 %type <midi_event_p> channel_aftertouch pitchwheel_range
44
45 %%
46
47 midi:   /* empty */
48         | midi midi_score {
49                 midi_parser_l_g->add_score( $2 );               
50         }
51         ;
52
53 midi_score:
54         header {
55         }
56         | midi_score track {
57                 $$->add_track( $2 );
58                 // ugh
59                 $2->set_tempo( midi_parser_l_g->midi_tempo_p_->useconds_per_4_i() );
60                 $2->set_time( midi_parser_l_g->midi_time_p_->num_i(), 
61                         midi_parser_l_g->midi_time_p_->den_i(), 
62                         midi_parser_l_g->midi_time_p_->clocks_1_i(), 
63                         8 );
64                 if ( midi_parser_l_g->copyright_str_.length_i() )
65                         $2->copyright_str_ = midi_parser_l_g->copyright_str_;
66                 if ( midi_parser_l_g->track_name_str_.length_i() )
67                         $2->name_str_ = midi_parser_l_g->track_name_str_;
68                 if ( midi_parser_l_g->instrument_str_.length_i() )
69                         $2->instrument_str_ = midi_parser_l_g->instrument_str_;
70                 midi_parser_l_g->reset();
71         }
72         ;
73
74 header: 
75         HEADER INT32 INT16 INT16 INT16 {
76                 $$ = new Midi_score( $3, $4, $5 );
77                 midi_parser_l_g->set_division_4( $5 );
78         }
79         ;
80
81 track: 
82         TRACK INT32 {
83                 tor( NORMAL_ver ) << "\ntrack " << midi_parser_l_g->track_i_ << ": " << flush;
84                 $$ = new Midi_track( midi_parser_l_g->track_i_++,
85                         // silly, cause not set yet!
86                         midi_parser_l_g->copyright_str_,
87                         midi_parser_l_g->track_name_str_,
88                         midi_parser_l_g->instrument_str_ );
89         }
90         | track event {
91                 $$->add_event( midi_parser_l_g->mom(), $2 );
92         }
93         ;
94
95 event:  
96         varint the_event {
97                 $$ = $2;
98                 if ( $2 ) {
99                         String str = $2->mudela_str( false );
100                         if ( str.length_i() )
101                                 tor( DEBUG_ver ) << str << " " << flush;
102                 }
103         }
104         ;
105         
106 varint:
107         VARINT {
108                 midi_parser_l_g->forward( $1 );
109                 if ( $1 ) {
110                         int bars_i = (int)( midi_parser_l_g->mom() / midi_parser_l_g->midi_time_p_->bar_mom() );
111                         if ( bars_i > midi_parser_l_g->bar_i_ ) {
112                                 tor( NORMAL_ver ) << '[' << midi_parser_l_g->bar_i_ << ']' << flush; 
113                         midi_parser_l_g->bar_i_ = bars_i;       
114                         }
115                 }
116         }
117         ;
118
119 the_event: 
120         meta_event { 
121         }
122         | midi_event {
123         }
124         | sysex_event {
125         }
126         ;
127
128 meta_event:
129         META_EVENT the_meta_event {
130                 $$ = $2;
131         }
132         |
133         META_EVENT U8 U8 U8 {
134                 $$ = 0;
135         }
136         ;
137
138 the_meta_event:
139         SEQUENCE INT16 {
140         }
141         | text_event DATA {
142                 Midi_text::Type type = (Midi_text::Type)$1;
143                 $$ = 0;
144                 switch ( type )
145                         {
146                         case Midi_text::COPYRIGHT:
147                                 midi_parser_l_g->copyright_str_ = *$2;
148                                 break;
149                         case Midi_text::TRACK_NAME:
150                                 midi_parser_l_g->track_name_str_ = *$2;
151                                 while ( midi_parser_l_g->track_name_str_.index_i( ' ' ) != -1 )
152                                         *(midi_parser_l_g->track_name_str_.ch_l() + midi_parser_l_g->track_name_str_.index_i( ' ' ) ) = '_';
153                                 break;
154                         case Midi_text::INSTRUMENT_NAME:
155                                 midi_parser_l_g->instrument_str_ = *$2;
156                                 break;
157                         default:
158                                 $$ = new Midi_text( type, *$2 );
159                                 break;
160                         }
161                 tor( DEBUG_ver ) << *$2 << endl;
162                 delete $2;
163         }
164         | END_OF_TRACK {
165                 $$ = 0;
166         }
167         | TEMPO U8 U8 U8 { 
168                 $$ = new Midi_tempo( ( $2 << 16 ) + ( $3 << 8 ) + $4 );
169                 tor( DEBUG_ver ) << $$->mudela_str( false ) << endl;
170                 midi_parser_l_g->set_tempo( ( $2 << 16 ) + ( $3 << 8 ) + $4 );
171         }
172         | SMPTE_OFFSET U8 U8 U8 U8 U8 { 
173                 $$ = 0;
174         }
175         | TIME U8 U8 U8 U8 { 
176                 $$ = new Midi_time( $2, $3, $4, $5 );
177                 tor( DEBUG_ver ) << $$->mudela_str( true ) << endl;
178                 midi_parser_l_g->set_time( $2, $3, $4, $5 );
179         }
180         | KEY I8 I8 { 
181                 $$ = new Midi_key( $2, $3 );
182                 midi_parser_l_g->set_key( $2, $3  );
183         }
184         | SSME DATA {
185                 $$ = new Midi_text( (Midi_text::Type)0, *$2 );
186                 delete $2;
187         }
188         ;
189
190 text_event: 
191         YYTEXT {
192                 tor( DEBUG_ver ) << "\n% Text: ";
193         }
194         | YYCOPYRIGHT {
195                 tor( DEBUG_ver ) << "\n% Copyright: ";
196         }
197         | YYTRACK_NAME {
198                 tor( DEBUG_ver ) << "\n% Track  name: ";
199         }
200         | YYINSTRUMENT_NAME {
201                 tor( DEBUG_ver ) << "\n% Instrument  name: ";
202         }
203         | YYLYRIC {
204                 tor( DEBUG_ver ) << "\n% Lyric: ";
205         }
206         | YYMARKER {
207                 tor( DEBUG_ver ) << "\n% Marker: ";
208         }
209         | YYCUE_POINT {
210                 tor( DEBUG_ver ) << "\n% Cue point: ";
211         }
212         ;
213
214 midi_event: 
215         running_status {
216         }
217         | data_entry {
218         }
219         | all_notes_off {
220         }
221         | note_off {
222         }
223         | note_on {
224         }
225         | polyphonic_aftertouch {
226         }
227         | controlmode_change {
228         }
229         | program_change {
230         }
231         | channel_aftertouch {
232         }
233         | pitchwheel_range {
234         }
235         ;
236
237 running_status:
238         RUNNING_STATUS midi_event {
239                 $$ = $2;
240         }
241         ;
242
243 data_entry:
244         DATA_ENTRY U8 {
245                 $$ = 0;
246         }
247         ;
248
249 all_notes_off:
250         ALL_NOTES_OFF U8 U8 {
251                 $$ = 0;
252         }
253         ;
254
255 note_off:
256         NOTE_OFF U8 U8 {
257                 int i = $1;
258                 i = i & ~0x80;
259                 $$ = midi_parser_l_g->note_end_midi_event_p( $1 & ~0x80, $2, $3 );
260         }
261         ;
262
263 note_on:
264         NOTE_ON U8 U8 {
265                 int i = $1;
266                 i = i & ~0x90;
267                 $$ = 0;
268                 if ( $3 )
269                         midi_parser_l_g->note_begin( $1 & ~0x90, $2, $3 );
270                 /*
271                   sss: some broken devices encode NOTE_OFF as 
272                        NOTE_ON with zero volume
273                  */
274                 else 
275                         $$ = midi_parser_l_g->note_end_midi_event_p( $1 & ~0x90, $2, $3 );
276         }
277         ;
278
279 polyphonic_aftertouch:
280         POLYPHONIC_AFTERTOUCH U8 U8 {
281                 $$ = 0;
282         }
283         ;
284
285 controlmode_change:
286         CONTROLMODE_CHANGE U8 U8 {
287                 $$ = 0;
288         }
289         ;
290
291 program_change:
292         PROGRAM_CHANGE U8 {
293                 $$ = 0;
294         }
295         ;
296
297 channel_aftertouch:
298         CHANNEL_AFTERTOUCH U8 U8 {
299                 $$ = 0;
300         }
301         ;
302
303 pitchwheel_range:
304         PITCHWHEEL_RANGE U8 U8 {
305                 $$ = 0;
306         }
307         ;
308
309 sysex_event:
310         SYSEX_EVENT1 DATA {
311                 $$ = 0;
312         }
313         | SYSEX_EVENT2 DATA { // U8 ?
314                 $$ = 0;
315         }
316         ;