1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 #include "general.h"
7 #include "fileoutput.h"
8
9 /*
10
11 Ringtone Tools - Copyright 2001-2005 Michael Kohn (mike@mikekohn.net)
12 This falls under the Kohnian license. Please read
13 it at http://ringtonetools.mikekohn.net/
14
15 This program is NOT opensourced. You may not use any part
16 of this program for your own software.
17
18 */
19
20 int default_channel,default_track;
21 int header_flag;
22 int current_note;
23 int running_status=0x90;
24
25 struct _header_chunk
26 {
27 int header_length;
28 int format;
29 int tracks;
30 short int division;
31 };
32
33 struct _meta_events
34 {
35 int sequence_number;
36 int tempo;
37 char smpte_offset[6];
38 char time_signature[5];
39 char key_signature[3];
40 int quarter_note;
41 };
42
read_string(FILE * in,char * s,int n)43 int read_string(FILE *in, char *s, int n)
44 {
45 int t,ch;
46
47 for(t=0; t<n; t++)
48 {
49 ch=getc(in);
50 if (ch==EOF) return -1;
51
52 s[t]=ch;
53 }
54
55 s[t]=0;
56 return 0;
57 }
58
print_string(FILE * in,int n)59 int print_string(FILE *in, int n)
60 {
61 int t,ch;
62
63 for(t=0; t<n; t++)
64 {
65 ch=getc(in);
66 if (ch==EOF) return -1;
67
68 #ifdef DEBUG
69 printf("%c",ch);
70 #endif
71 }
72
73 #ifdef DEBUG
74 printf("\n");
75 #endif
76
77 return 0;
78 }
79
read_count(FILE * in,int n)80 int read_count(FILE *in, int n)
81 {
82 int t,s;
83
84 t=0;
85
86 for (s=0; s<n; s++)
87 { t=(t<<8)+getc(in); }
88
89 return t;
90 }
91
read_var(FILE * in)92 int read_var(FILE *in)
93 {
94 int t,ch;
95
96 t=0;
97
98 while(1)
99 {
100 ch=getc(in);
101
102 if (ch==EOF) return -1;
103
104 t=(t<<7)+(ch&127);
105 if ((ch&128)==0) break;
106 }
107
108 return t;
109 }
110
MThd_parse(FILE * in,struct _header_chunk * header_chunk,int n)111 int MThd_parse(FILE *in, struct _header_chunk *header_chunk, int n)
112 {
113 header_chunk->header_length=n;
114 header_chunk->format=read_word_b(in);
115 header_chunk->tracks=read_word_b(in);
116 header_chunk->division=read_word_b(in);
117
118 return 0;
119 }
120
parse_meta_event(FILE * in,struct _meta_events * meta_events,struct _header_chunk * header_chunk)121 int parse_meta_event(FILE *in, struct _meta_events *meta_events, struct _header_chunk *header_chunk)
122 {
123 int ch,v_length,t;
124
125 ch=getc(in);
126 v_length=read_var(in);
127
128 /* printf("(%d) ",ch); */
129
130 if (ch==0x00)
131 {
132 printf("Sequence Number: ");
133 t=read_count(in,v_length);
134 meta_events->sequence_number=t;
135 printf("%d\n",t);
136 return 0;
137 }
138 else
139 if (ch==0x01)
140 {
141 #ifdef DEBUG
142 printf("Text Event: ");
143 #endif
144 print_string(in, v_length);
145 return 0;
146 }
147 else
148 if (ch==0x02)
149 {
150 #ifdef DEBUG
151 printf("Copyright Notice: ");
152 #endif
153 print_string(in, v_length);
154 return 0;
155 }
156 else
157 if (ch==0x03)
158 {
159 #ifdef DEBUG
160 printf("Track Name: ");
161 #endif
162 print_string(in, v_length);
163 return 0;
164 }
165 else
166 if (ch==0x04)
167 {
168 #ifdef DEBUG
169 printf("Instrument Name: ");
170 #endif
171 print_string(in, v_length);
172 return 0;
173 }
174 else
175 if (ch==0x05)
176 {
177 #ifdef DEBUG
178 printf("Lyric Text: ");
179 #endif
180 print_string(in, v_length);
181 return 0;
182 }
183 else
184 if (ch==0x06)
185 {
186 #ifdef DEBUG
187 printf("Marker Text: ");
188 #endif
189 print_string(in, v_length);
190 return 0;
191 }
192 else
193 if (ch==0x07)
194 {
195 #ifdef DEBUG
196 printf("Cue Point: ");
197 #endif
198 }
199 else
200 if (ch==0x20)
201 {
202 #ifdef DEBUG
203 printf("MIDI Channel Prefix: ");
204 #endif
205 }
206 else
207 if (ch==0x2f)
208 {
209 #ifdef DEBUG
210 printf("End Of Track\n");
211 #endif
212 return -1;
213 }
214 else
215 if (ch==0x51)
216 {
217 t=read_count(in,v_length);
218 meta_events->tempo=t;
219 meta_events->quarter_note=meta_events->tempo/header_chunk->division;
220 #ifdef DEBUG
221 printf("Tempo Setting: ");
222 printf("%d\n",t);
223 #endif
224 return 0;
225 }
226 else
227 if (ch==0x54)
228 {
229 #ifdef DEBUG
230 printf("SMPTE Offset: ");
231 #endif
232 read_string(in,meta_events->smpte_offset,5);
233 for (t=0; t<5; t++)
234 {
235 #ifdef DEBUG
236 printf("%d ",meta_events->smpte_offset[t]);
237 #endif
238 }
239 #ifdef DEBUG
240 printf("\n");
241 #endif
242 return 0;
243 }
244 else
245 if (ch==0x58)
246 {
247 #ifdef DEBUG
248 printf("Time Signature: ");
249 #endif
250 read_string(in,meta_events->time_signature,4);
251 for (t=0; t<4; t++)
252 {
253 #ifdef DEBUG
254 printf("%d ",meta_events->time_signature[t]);
255 #endif
256 }
257 #ifdef DEBUG
258 printf("\n");
259 #endif
260 return 0;
261 }
262 else
263 if (ch==0x59)
264 {
265 #ifdef DEBUG
266 printf("Key Signature: ");
267 #endif
268 read_string(in,meta_events->key_signature,2);
269 for (t=0; t<2; t++)
270 {
271 #ifdef DEBUG
272 printf("%d ",meta_events->key_signature[t]);
273 #endif
274 }
275 #ifdef DEBUG
276 printf("\n");
277 #endif
278 return 0;
279 }
280 else
281 if (ch==0x7F)
282 {
283 #ifdef DEBUG
284 printf("Sequencer Specific Event: ");
285 #endif
286 }
287 else
288 {
289 #ifdef DEBUG
290 printf("\nUnknown Event: ");
291 #endif
292 }
293
294 for (t=0; t<v_length; t++)
295 {
296 ch=getc(in);
297 #ifdef DEBUG
298 printf("%c ",ch);
299 #endif
300 }
301
302 #ifdef DEBUG
303 printf("\n");
304 #endif
305
306 return 0;
307 }
308
parse_extras(FILE * in,int channel)309 int parse_extras(FILE *in, int channel)
310 {
311 if (channel==1)
312 { getc(in); }
313 else
314 if (channel==2)
315 { getc(in); getc(in); }
316 else
317 if (channel==3)
318 { getc(in); }
319
320 return 0;
321 }
322
get_duration(float duration)323 int get_duration(float duration)
324 {
325 int t;
326 float duration_code[16]={ 1.5,1, 0.75,0.5, 0.37,0.25,
327 0.1875,0.125, 0.09375,0.0625,
328 0.046875,0.03125, 0 };
329
330 if (duration>1.5) duration=1.5;
331
332 for (t=0; t<13; t++)
333 {
334 if (duration_code[t]==duration) return t;
335
336 if (duration_code[t]>duration && duration>duration_code[t+1])
337 {
338 if (duration_code[t]-duration<duration-duration_code[t+1])
339 { return t; }
340 else
341 { return t+1; }
342 }
343 }
344
345 return t-1;
346 }
347
add_note(FILE * out,int tone,int v_time,struct note_t * note,struct _header_chunk * header_chunk,int out_type)348 int add_note(FILE *out, int tone, int v_time, struct note_t *note, struct _header_chunk *header_chunk, int out_type)
349 {
350 int t,k,d;
351 float m;
352
353 #ifdef DEBUG
354 printf("In add note.. v_time=%d\n",v_time);
355 #endif
356
357 if (v_time==0) return 0;
358
359 m=(float)v_time/(float)(header_chunk->division*4);
360 d=get_duration(m);
361
362 #ifdef DEBUG
363 if (d==12) printf("cancelling... note too short\n");
364 #endif
365
366 if (d==12) return 0;
367
368 k=d/2;
369 t=1<<k;
370
371 d=(d%2)^1;
372
373 note->length=k;
374
375 #ifdef DEBUG
376 printf("> %d %d < ",t,d%2);
377 #endif
378
379 if (tone==0)
380 {
381 note->tone=0;
382 }
383 else
384 {
385 t=tone-60+(13*(note->transpose));
386
387 if (t<0)
388 {
389 printf("Error: This song uses notes lower than middle C.\n");
390 printf("Please use the -transpose option to raise the note to a higher scale.\n");
391 t=0;
392 }
393
394 note->tone=t%12+1;
395 note->scale=t/12;
396
397 /* if (note->tone>12) { note->tone=note->tone-12; note->scale++; } */
398
399 #ifdef DEBUG
400 printf("***** TONE %d ****** SCALE %d\n",note->tone,note->scale);
401 #endif
402 }
403
404 if (d==1)
405 { note->modifier=1; }
406 else
407 { note->modifier=0; }
408
409 note_route(out,note,5,out_type);
410
411 return 0;
412 }
413
midi_command(FILE * in,FILE * out,int n,struct note_t * note,struct _meta_events * meta_events,int v_time,struct _header_chunk * header_chunk,int out_type)414 int midi_command(FILE *in, FILE *out, int n, struct note_t *note, struct _meta_events *meta_events, int v_time, struct _header_chunk *header_chunk, int out_type)
415 {
416 int command,channel;
417 int ch,tone;
418 float duration;
419
420 if (n<0x80)
421 {
422 ungetc(n,in);
423 n=running_status;
424 }
425
426 command=n&0xf0;
427 channel=n&0x0f;
428
429 /* if (command==0x90 && v_time==0) command=0x80; */
430
431 if (command==0x80)
432 {
433 /* Sound Off */
434 tone=getc(in);
435 ch=getc(in);
436
437 if (v_time!=0)
438 {
439 duration=(float)v_time/((float)meta_events->quarter_note);
440 #ifdef DEBUG
441 printf("Sound Off [ %f %d %d ] ",duration,meta_events->quarter_note,v_time);
442 #endif
443 }
444 else
445 { duration=0; }
446
447 if (tone!=current_note)
448 {
449 #ifdef DEBUG
450 printf("Warning: Note to stop and previous note don't match.\n");
451 #endif
452 }
453 else
454 {
455 if (default_channel==-1 || channel==default_channel)
456 { add_note(out, tone, v_time, note, header_chunk,out_type); }
457 }
458 #ifdef DEBUG
459 printf("tone: %d %f\n",tone,duration);
460 #endif
461 }
462 else
463 if (command==0x90)
464 {
465 /* Sound On */
466 tone=getc(in);
467 ch=getc(in);
468
469 if (v_time!=0)
470 {
471 duration=(float)v_time/((float)meta_events->quarter_note);
472 #ifdef DEBUG
473 printf("Sound On [ %f %d %d ] ",duration,meta_events->quarter_note,v_time);
474 #endif
475 }
476 else
477 { duration=0; }
478
479 current_note=tone;
480
481 if (default_channel==-1 || channel==default_channel)
482 { if (v_time!=0) add_note(out, tone, v_time, note, header_chunk, out_type); }
483
484 #ifdef DEBUG
485 printf("tone: %d %f\n",tone,duration);
486 #endif
487 }
488 else
489 if (command==0xa0)
490 {
491 /* Aftertouch */
492 ch=getc(in);
493 ch=getc(in);
494 }
495 else
496 if (command==0xb0)
497 {
498 /* Controller */
499 ch=getc(in);
500 ch=getc(in);
501 }
502 else
503 if (command==0xc0)
504 {
505 /* Program Change */
506 ch=getc(in);
507 }
508 else
509 if (command==0xd0)
510 {
511 /* Channel Pressure */
512 ch=getc(in);
513 }
514 else
515 if (command==0xe0)
516 {
517 /* Pitch Wheel */
518 ch=getc(in);
519 ch=getc(in);
520 }
521 else
522 if (command==0xf0)
523 {
524 parse_extras(in,channel);
525 }
526 /*
527 else
528 {
529 printf("Unknown MIDI code. Please email Michael Kohn (mike@mikekohn.net)\n");
530 printf("Code: ");
531 print_hex(n);
532 printf("\n");
533 }
534 */
535
536 running_status=n;
537
538 return 0;
539 }
540
MTrk_parse(FILE * in,FILE * out,struct _header_chunk * header_chunk,int n,struct _meta_events * meta_events,struct note_t * note,int out_type)541 int MTrk_parse(FILE *in, FILE *out, struct _header_chunk *header_chunk, int n, struct _meta_events *meta_events, struct note_t *note, int out_type)
542 {
543 int ch;
544 int v_time;
545 int t;
546 #ifdef DEBUG
547 int x=0;
548 #endif
549
550 #ifdef DEBUG
551 printf("***Length: %d\n",n);
552 #endif
553
554 while (1)
555 {
556 v_time=read_var(in);
557
558 ch=getc(in);
559
560 #ifdef DEBUG
561 printf("\nMTrk_parse read in: %x ",ch);
562 #endif
563
564 if (ch==EOF)
565 {
566 printf("EOF found... oops.\n");
567 return 0;
568 }
569
570 if (ch==0xff)
571 {
572 /* META Event */
573
574 #ifdef DEBUG
575 printf("META Event\n");
576 if (x!=0) { x=0; printf("\n"); }
577 #endif
578 if (parse_meta_event(in,meta_events,header_chunk)==-1) break;
579 }
580 else
581 if (ch==0xf0 || ch==0xf7)
582 {
583 /* System Exclusive Event */
584
585 #ifdef DEBUG
586 printf("System Exclusive 0x%x v_time=%d\n",ch,v_time);
587
588 if (x!=0) { x=0; printf("\n"); }
589 #endif
590 for (t=0; t<v_time; t++)
591 {
592 ch=getc(in);
593 printf("%c(0x%x)",ch,ch);
594 if (ch==0xf7) break;
595 if (ch==EOF) { printf("Premature end of file\n"); return -1; }
596 }
597 }
598 else
599 {
600 /* MIDI DATA */
601
602 if (header_flag==0)
603 {
604 note->bpm=60000000/meta_events->tempo;
605
606 header_route(out,note,5,out_type);
607
608 header_flag=1;
609 }
610
611 #ifdef DEBUG
612 printf("(%d) %02X ",v_time,ch);
613 /*
614 print_hex(ch);
615 printf(" ");
616 */
617 #endif
618
619 midi_command(in,out,ch,note,meta_events,v_time,header_chunk,out_type);
620
621 #ifdef DEBUG
622 x++;
623 if (x==15) { x=0; printf("\n"); }
624 #endif
625 }
626 }
627
628 #ifdef DEBUG
629 printf("%d\n",meta_events->tempo);
630 #endif
631 return 0;
632 }
633
parse_midi(FILE * in,FILE * out,int out_type,struct note_t * note)634 int parse_midi(FILE *in, FILE *out, int out_type, struct note_t *note)
635 {
636 char header[5];
637 int n,t,track;
638 struct _header_chunk header_chunk;
639 struct _meta_events meta_events;
640
641 default_channel=0;
642 default_track=-1;
643 header_flag=0;
644
645 default_channel=note->mcc;
646 default_track=note->mnc;
647
648 if (note->songname[0]==0)
649 {
650 t=strlen(note->outname);
651 while(t>0 && note->outname[t]!='/' && note->outname[t]!='\\') t--;
652 if (note->outname[t]=='/' || note->outname[t]=='\\') t++;
653 for (n=0; n<SONGNAME_LEN-1; n++)
654 {
655 if (note->outname[t]=='.' || note->outname[t]==0) break;
656 note->songname[n]=note->outname[t++];
657 }
658 note->songname[n]=0;
659 }
660
661 if (quiet==0)
662 {
663 printf("Song Name: %s\n",note->songname);
664 }
665
666 track=0;
667
668 meta_events.sequence_number=track;
669 meta_events.tempo=500000;
670 meta_events.time_signature[0]=4;
671 meta_events.time_signature[1]=2;
672 meta_events.time_signature[2]=0;
673 meta_events.time_signature[3]=0;
674 meta_events.key_signature[0]=0;
675 meta_events.key_signature[1]=0;
676 meta_events.quarter_note=5208;
677
678 current_note=-1;
679
680 while(1)
681 {
682 if (read_string(in,header,4)==-1)
683 { break; }
684
685 n=read_long_b(in);
686
687 if (strcasecmp(header,"MThd")==0)
688 {
689 MThd_parse(in,&header_chunk,n);
690 if (quiet==0)
691 {
692 printf("\n--------------------------------------------\n");
693 printf(" Header length: %d\n",header_chunk.header_length);
694 printf(" Format: %d\n",header_chunk.format);
695 printf("Number of Tracks: %d\n",header_chunk.tracks);
696 printf(" Division: %d\n",header_chunk.division);
697 printf("--------------------------------------------\n");
698 }
699 meta_events.quarter_note=meta_events.tempo/header_chunk.division;
700 }
701 else
702 if (strcasecmp(header,"MTrk")==0)
703 {
704 if (default_track>-1)
705 {
706 if (track>default_track) break;
707 if (track!=default_track)
708 {
709 track++;
710 fseek(in,n,SEEK_CUR);
711 continue;
712 }
713 }
714
715 if (quiet==0)
716 {
717 printf("\n--------------------------------------------\n");
718 printf("Track: %d",track++);
719 printf("\n--------------------------------------------\n");
720 }
721
722 MTrk_parse(in, out, &header_chunk, n, &meta_events, note, out_type);
723 }
724 }
725
726 footer_route(out,note,5,out_type);
727
728 return 0;
729 }
730
731
732
733