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