1 /* a little modified code from http://iki.fi/too/sw/xring/ */
3 /* embedding modified midifile.h and midifile.c into this file */
7 /***** midifile.h ******/
10 /* definitions for MIDI file parsing code */
11 int (*Mf_getc)(struct MF *);
12 void (*Mf_header)(struct MF *, int, int, int);
13 void (*Mf_trackstart)(struct MF *);
14 void (*Mf_trackend)(struct MF *);
15 void (*Mf_noteon)(struct MF *, int, int, int);
16 void (*Mf_noteoff)(struct MF *, int, int, int);
17 void (*Mf_pressure)(struct MF *, int, int, int);
18 void (*Mf_parameter)(struct MF *, int, int, int);
19 void (*Mf_pitchbend)(struct MF *, int, int, int);
20 void (*Mf_program)(struct MF *, int, int);
21 void (*Mf_chanpressure)(struct MF *, int, int);
22 void (*Mf_sysex)(struct MF *, int, char *);
23 void (*Mf_metamisc)(struct MF *, int, int, char * );
24 void (*Mf_seqspecific)(struct MF *, int, int, char *);
25 void (*Mf_seqnum)(struct MF *, int);
26 void (*Mf_text)(struct MF *, int, int, char *);
27 void (*Mf_eot)(struct MF *);
28 void (*Mf_timesig)(struct MF *, int, int, int, int);
29 void (*Mf_smpte)(struct MF *, int, int, int, int, int);
30 void (*Mf_tempo)(struct MF *, long);
31 void (*Mf_keysig)(struct MF *, int, int);
32 void (*Mf_arbitrary)(struct MF *, int, char *);
33 void (*Mf_error)(struct MF *, char * );
35 /* definitions for MIDI file writing code */
36 void (*Mf_putc)(struct MF *);
37 void (*Mf_writetrack)(struct MF *);
38 void (*Mf_writetempotrack)(struct MF *);
41 int Mf_nomerge; /* 1 => continue'ed system exclusives are */
43 long Mf_currtime; /* current time in delta-time units */
47 long Mf_numbyteswritten;
49 char *Msgbuff; /* message buffer */
50 int Msgsize; /* Size of currently allocated Msg */
51 int Msgindex; /* index of next available location in Msg */
55 float mf_ticks2sec(unsigned long ticks,int division,unsigned int tempo);
56 unsigned long mf_sec2ticks(float secs,int division, unsigned int tempo);
58 void mferror(struct MF * mf, char * s);
63 /* MIDI status commands most significant bit is 1 */
66 #define poly_aftertouch 0xa0
67 #define control_change 0xb0
68 #define program_chng 0xc0
69 #define channel_aftertouch 0xd0
70 #define pitch_wheel 0xe0
71 #define system_exclusive 0xf0
72 #define delay_packet (1111)
74 /* 7 bit controllers */
75 #define damper_pedal 0x40
76 #define portamento 0x41
77 #define sostenuto 0x42
78 #define soft_pedal 0x43
79 #define general_4 0x44
81 #define general_5 0x50
82 #define general_6 0x51
83 #define general_7 0x52
84 #define general_8 0x53
85 #define tremolo_depth 0x5c
86 #define chorus_depth 0x5d
88 #define phaser_depth 0x5f
90 /* parameter values */
94 /* parameter selection */
95 #define non_reg_lsb 0x62
96 #define non_reg_msb 0x63
100 /* Standard MIDI Files meta event definitions */
101 #define meta_event 0xFF
102 #define sequence_number 0x00
103 #define text_event 0x01
104 #define copyright_notice 0x02
105 #define sequence_name 0x03
106 #define instrument_name 0x04
109 #define cue_point 0x07
110 #define channel_prefix 0x20
111 #define end_of_track 0x2f
112 #define set_tempo 0x51
113 #define smpte_offset 0x54
114 #define time_signature 0x58
115 #define key_signature 0x59
116 #define sequencer_specific 0x74
118 /* Manufacturer's ID number */
119 #define Seq_Circuits (0x01) /* Sequential Circuits Inc. */
120 #define Big_Briar (0x02) /* Big Briar Inc. */
121 #define Octave (0x03) /* Octave/Plateau */
122 #define Moog (0x04) /* Moog Music */
123 #define Passport (0x05) /* Passport Designs */
124 #define Lexicon (0x06) /* Lexicon */
125 #define Tempi (0x20) /* Bon Tempi */
126 #define Siel (0x21) /* S.I.E.L. */
128 #define Roland (0x42)
130 #define Yamaha (0x43)
132 /* miscellaneous definitions */
133 #define MThd 0x4d546864
134 #define MTrk 0x4d54726b
135 #define lowerbyte(x) ((unsigned char)(x & 0xff))
136 #define upperbyte(x) ((unsigned char)((x & 0xff00)>>8))
138 /* the midifile interface */
139 void midifile(struct MF * mf);
141 /***** midifile.c ******/
146 * Read and write a MIDI file. Externally-assigned function pointers are
147 * called upon recognizing things in the file.
150 * June 1989 - Added writing capability, M. Czeiszperger.
152 * The file format implemented here is called
153 * Standard MIDI Files, and is part of the Musical
154 * instrument Digital Interface specification.
155 * The spec is avaiable from:
157 * International MIDI Association
158 * 5316 West 57th Street
159 * Los Angeles, CA 90056
161 * An in-depth description of the spec can also be found
162 * in the article "Introducing Standard MIDI Files", published
163 * in Electronic Musician magazine, April, 1989.
181 #include "gsm-common.h"
182 #include "gsm-ringtones.h"
184 #define NULLFUNC NULL
186 static void readheader(struct MF * mf);
187 static int readtrack(struct MF * mf);
188 static void chanmessage(struct MF * mf,int status,int c1,int c2);
189 static void msginit(struct MF * mf);
190 static void msgadd(struct MF * mf,int c);
191 static void metaevent(struct MF * mf, int type);
192 static void sysex(struct MF * mf);
193 static int msgleng(struct MF * mf);
194 static void badbyte(struct MF * mf,int c);
195 static void biggermsg(struct MF * mf);
198 static long readvarinum(struct MF * mf);
199 static long read32bit(struct MF * mf);
200 static long to32bit(int, int, int, int);
201 static int read16bit(struct MF * mf);
202 static int to16bit(int, int);
203 static char * msg(struct MF * mf);
205 /* The only non-static function in this file. */
206 void mfread(struct MF * mf)
208 if ( mf->Mf_getc == NULLFUNC )
209 mferror(mf, "mfread() called without setting Mf_getc");
212 while ( readtrack(mf) )
216 /* for backward compatibility with the original lib */
217 void midifile(struct MF * mf)
222 /* read through the "MThd" or "MTrk" header string */
223 static int readmt(struct MF * mf, char * s)
229 while ( n++<4 && (c=mf->Mf_getc(mf)) != EOF ) {
232 (void) strcpy(buff, "expecting ");
233 (void) strcat(buff, s);
240 /* read a single character and abort on EOF */
241 static int egetc(struct MF * mf)
243 int c = mf->Mf_getc(mf);
246 mferror(mf, "premature EOF");
251 /* read a header chunk */
252 static void readheader(struct MF * mf)
254 int format, ntrks, division;
256 if ( readmt(mf, "MThd") == EOF )
259 mf->Mf_toberead = read32bit(mf);
260 format = read16bit(mf);
261 ntrks = read16bit(mf);
262 division = read16bit(mf);
265 (*mf->Mf_header)(mf, format,ntrks,division);
267 /* flush any extra stuff, in case the length of header is not 6 */
268 while ( mf->Mf_toberead > 0 )
272 static int readtrack(struct MF * mf) /* read a track chunk */
274 /* This array is indexed by the high half of a status byte. It's */
275 /* value is either the number of bytes needed (1 or 2) for a channel */
276 /* message, or 0 (meaning it's not a channel message). */
277 static int chantype[] = {
278 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 through 0x70 */
279 2, 2, 2, 2, 1, 1, 2, 0 /* 0x80 through 0xf0 */
283 int sysexcontinue = 0; /* 1 if last message was an unfinished sysex */
284 int running = 0; /* 1 when running status used */
285 int status = 0; /* status value (e.g. 0x90==note-on) */
288 if ( readmt(mf, "MTrk") == EOF )
291 mf->Mf_toberead = read32bit(mf);
294 if ( mf->Mf_trackstart )
295 (*mf->Mf_trackstart)(mf);
297 while ( mf->Mf_toberead > 0 ) {
299 mf->Mf_currtime += readvarinum(mf); /* delta time */
303 if ( sysexcontinue && c != 0xf7 )
304 mferror(mf, "didn't find expected continuation of a sysex");
306 if ( (c & 0x80) == 0 ) { /* running status? */
308 mferror(mf, "unexpected running status");
316 needed = chantype[ (status>>4) & 0xf ];
318 if ( needed ) { /* ie. is it a channel message? */
324 chanmessage(mf, status, c1, (needed>1)? egetc(mf): 0);
330 case 0xff: /* meta event */
333 lookfor = mf->Mf_toberead - readvarinum(mf);
336 while ( mf->Mf_toberead > lookfor )
337 msgadd(mf, egetc(mf));
342 case 0xf0: /* start of system exclusive */
344 lookfor = mf->Mf_toberead - readvarinum(mf);
348 while ( mf->Mf_toberead > lookfor )
349 msgadd(mf, c=egetc(mf));
351 if ( c==0xf7 || mf->Mf_nomerge==0 )
354 sysexcontinue = 1; /* merge into next msg */
357 case 0xf7: /* sysex continuation or arbitrary stuff */
359 lookfor = mf->Mf_toberead - readvarinum(mf);
361 if ( ! sysexcontinue )
364 while ( mf->Mf_toberead > lookfor )
365 msgadd(mf, c=egetc(mf));
367 if ( ! sysexcontinue ) {
368 if ( mf->Mf_arbitrary )
369 (*mf->Mf_arbitrary)(mf, msgleng(mf),msg(mf));
371 else if ( c == 0xf7 ) {
381 if ( mf->Mf_trackend )
382 (*mf->Mf_trackend)(mf);
386 static void badbyte(struct MF * mf,int c)
390 (void) sprintf(buff,"unexpected byte: 0x%02x",c);
394 static void metaevent(struct MF * mf, int type)
396 int leng = msgleng(mf);
402 (*mf->Mf_seqnum)(mf, to16bit(m[0],m[1]));
404 case 0x01: /* Text event */
405 case 0x02: /* Copyright notice */
406 case 0x03: /* Sequence/Track name */
407 case 0x04: /* Instrument name */
408 case 0x05: /* Lyric */
409 case 0x06: /* Marker */
410 case 0x07: /* Cue point */
419 /* These are all text events */
421 (*mf->Mf_text)(mf, type,leng,m);
423 case 0x2f: /* End of Track */
427 case 0x51: /* Set tempo */
429 (*mf->Mf_tempo)(mf, to32bit(0,m[0],m[1],m[2]));
433 (*mf->Mf_smpte)(mf, m[0],m[1],m[2],m[3],m[4]);
436 if ( mf->Mf_timesig )
437 (*mf->Mf_timesig)(mf, m[0],m[1],m[2],m[3]);
441 (*mf->Mf_keysig)(mf, m[0],m[1]);
444 if ( mf->Mf_seqspecific )
445 (*mf->Mf_seqspecific)(mf, type, leng, m);
448 if ( mf->Mf_metamisc )
449 (*mf->Mf_metamisc)(mf, type,leng,m);
453 static void sysex(struct MF * mf)
456 (*mf->Mf_sysex)(mf, msgleng(mf),msg(mf));
459 static void chanmessage(struct MF * mf,int status,int c1,int c2)
461 int chan = status & 0xf;
463 switch ( status & 0xf0 ) {
465 if ( mf->Mf_noteoff )
466 (*mf->Mf_noteoff)(mf, chan,c1,c2);
470 (*mf->Mf_noteon)(mf, chan,c1,c2);
473 if ( mf->Mf_pressure )
474 (*mf->Mf_pressure)(mf, chan,c1,c2);
477 if ( mf->Mf_parameter )
478 (*mf->Mf_parameter)(mf, chan,c1,c2);
481 if ( mf->Mf_pitchbend )
482 (*mf->Mf_pitchbend)(mf, chan,c1,c2);
485 if ( mf->Mf_program )
486 (*mf->Mf_program)(mf, chan,c1);
489 if ( mf->Mf_chanpressure )
490 (*mf->Mf_chanpressure)(mf, chan,c1);
495 /* readvarinum - read a varying-length number, and return the */
496 /* number of characters it took. */
498 static long readvarinum(struct MF * mf)
509 value = (value << 7) + (c & 0x7f);
515 static long to32bit(int c1,int c2,int c3,int c4)
520 value = (value<<8) + (c2 & 0xff);
521 value = (value<<8) + (c3 & 0xff);
522 value = (value<<8) + (c4 & 0xff);
526 static int to16bit(int c1,int c2)
528 return ((c1 & 0xff ) << 8) + (c2 & 0xff);
531 static long read32bit(struct MF * mf)
539 return to32bit(c1,c2,c3,c4);
542 static int read16bit(struct MF * mf)
547 return to16bit(c1,c2);
551 void mferror(struct MF * mf, char * s)
554 (*mf->Mf_error)(mf, s);
558 /* The code below allows collection of a system exclusive message of */
559 /* arbitrary length. The Msgbuff is expanded as necessary. The only */
560 /* visible data/routines are msginit(), msgadd(), msg(), msgleng(). */
562 #define MSGINCREMENT 128
564 static void msginit(struct MF * mf)
569 static char * msg(struct MF * mf)
574 static int msgleng(struct MF * mf)
576 return(mf->Msgindex);
579 static void msgadd(struct MF * mf,int c)
581 /* If necessary, allocate larger message buffer. */
582 if ( mf->Msgindex >= mf->Msgsize )
584 mf->Msgbuff[mf->Msgindex++] = c;
587 static void biggermsg(struct MF * mf)
590 char *oldmess = mf->Msgbuff;
591 int oldleng = mf->Msgsize;
593 mf->Msgsize += MSGINCREMENT;
594 newmess = (char *) malloc( (unsigned)(sizeof(char) * mf->Msgsize) );
597 mferror(mf, "malloc error!");
599 /* copy old message into larger new one */
600 if ( oldmess != NULL ) {
601 register char *p = newmess;
602 register char *q = oldmess;
603 register char *endq = &oldmess[oldleng];
605 for ( ; q!=endq ; p++,q++ )
609 mf->Msgbuff = newmess;
612 #if 0 /* saving time not converting write function at this time
615 * mfwrite() - The only fuction you'll need to call to write out
618 * format 0 - Single multi-channel track
619 * 1 - Multiple simultaneous tracks
620 * 2 - One or more sequentially independent
621 * single track patterns
622 * ntracks The number of tracks in the file.
623 * division This is kind of tricky, it can represent two
624 * things, depending on whether it is positive or negative
625 * (bit 15 set or not). If bit 15 of division is zero,
626 * bits 14 through 0 represent the number of delta-time
627 * "ticks" which make up a quarter note. If bit 15 of
628 * division is a one, delta-times in a file correspond to
629 * subdivisions of a second similiar to SMPTE and MIDI
630 * time code. In this format bits 14 through 8 contain
631 * one of four values - 24, -25, -29, or -30,
632 * corresponding to the four standard SMPTE and MIDI
633 * time code frame per second formats, where -29
634 * represents 30 drop frame. The second byte
635 * consisting of bits 7 through 0 corresponds the the
636 * resolution within a frame. Refer the Standard MIDI
637 * Files 1.0 spec for more details.
638 * fp This should be the open file pointer to the file you
639 * want to write. It will have be a global in order
640 * to work with Mf_putc.
643 mfwrite(format,ntracks,division,fp)
644 int format,ntracks,division;
647 int i; void mf_write_track_chunk(), mf_write_header_chunk();
649 if ( mf->Mf_putc == NULLFUNC )
650 mferror(mf, "mfmf_write() called without setting Mf_putc");
652 if ( mf->Mf_writetrack == NULLFUNC )
653 mferror(mf, "mfmf_write() called without setting Mf_mf_writetrack");
655 /* every MIDI file starts with a header */
656 mf_write_header_chunk(format,ntracks,division);
658 /* In format 1 files, the first track is a tempo map */
659 if(format == 1 && ( mf->Mf_writetempotrack ))
661 (*mf->Mf_writetempotrack)();
664 /* The rest of the file is a series of tracks */
665 for(i = 0; i < ntracks; i++)
666 mf_write_track_chunk(i,fp);
670 mf_write_track_chunk(which_track,fp)
674 unsigned long trkhdr,trklength;
675 long offset, place_marker;
676 void write16bit(),write32bit();
682 /* Remember where the length was written, because we don't
683 know how long it will be until we've finished writing */
687 printf("offset = %d\n",(int) offset);
690 /* Write the track chunk header */
692 write32bit(trklength);
694 mf->Mf_numbyteswritten = 0L; /* the header's length doesn't count */
696 if( mf->Mf_writetrack )
698 (*mf->Mf_writetrack)(which_track);
701 /* mf_write End of track meta event */
703 eputc(mf, meta_event);
704 eputc(mf, end_of_track);
708 /* It's impossible to know how long the track chunk will be beforehand,
709 so the position of the track length data is kept so that it can
710 be written after the chunk has been generated */
711 place_marker = ftell(fp);
713 /* This method turned out not to be portable because the
714 parameter returned from ftell is not guaranteed to be
715 in bytes on every machine */
716 /* track.length = place_marker - offset - (long) sizeof(track); */
719 printf("length = %d\n",(int) trklength);
722 if(fseek(fp,offset,0) < 0)
723 mferror(mf, "error seeking during final stage of write");
725 trklength = mf->Mf_numbyteswritten;
727 /* Re-mf_write the track chunk header with right length */
729 write32bit(trklength);
731 fseek(fp,place_marker,0);
732 } /* End gen_track_chunk() */
736 mf_write_header_chunk(format,ntracks,division)
737 int format,ntracks,division;
739 unsigned long ident,length;
740 void write16bit(),write32bit();
742 ident = MThd; /* Head chunk identifier */
743 length = 6; /* Chunk length */
745 /* individual bytes of the header must be written separately
746 to preserve byte order across cpu types :-( */
751 write16bit(division);
752 } /* end gen_header_chunk() */
755 #ifdef WHENISTHISNEEDED
757 * mf_write_midi_event()
759 * Library routine to mf_write a single MIDI track event in the standard MIDI
760 * file format. The format is:
762 * <delta-time><event>
764 * In this case, event can be any multi-byte midi message, such as
765 * "note on", "note off", etc.
767 * delta_time - the time in ticks since the last event.
768 * type - the type of meta event.
769 * chan - The midi channel.
770 * data - A pointer to a block of chars containing the META EVENT,
772 * size - The length of the meta-event data.
775 mf_write_midi_event(delta_time, type, chan, data, size)
776 unsigned long delta_time;
777 unsigned int chan,type;
785 WriteVarLen(delta_time);
787 /* all MIDI events start with the type in the first four bits,
788 and the channel in the lower four bits */
792 perror("error: MIDI channel greater than 16\n");
796 /* write out the data bytes */
797 for(i = 0; i < size; i++)
801 } /* end mf_write MIDI event */
804 * mf_write_meta_event()
806 * Library routine to mf_write a single meta event in the standard MIDI
807 * file format. The format of a meta event is:
809 * <delta-time><FF><type><length><bytes>
811 * delta_time - the time in ticks since the last event.
812 * type - the type of meta event.
813 * data - A pointer to a block of chars containing the META EVENT,
815 * size - The length of the meta-event data.
818 mf_write_meta_event(delta_time, type, data, size)
819 unsigned long delta_time;
820 unsigned char *data,type;
825 WriteVarLen(delta_time);
827 /* This marks the fact we're writing a meta-event */
828 eputc(mf, meta_event);
830 /* The type of meta event */
833 /* The length of the data bytes to follow */
836 for(i = 0; i < size; i++)
838 if(eputc(mf, data[i]) != data[i])
842 } /* end mf_write_meta_event */
845 mf_write_tempo(tempo)
849 /* all tempos are written as 120 beats/minute, */
850 /* expressed in microseconds/quarter note */
852 eputc(mf, meta_event);
853 eputc(mf, set_tempo);
856 eputc(mf, (unsigned)(0xff & (tempo >> 16)));
857 eputc(mf, (unsigned)(0xff & (tempo >> 8)));
858 eputc(mf, (unsigned)(0xff & tempo));
863 * Write multi-length bytes to MIDI format files
869 unsigned long buffer;
871 buffer = value & 0x7f;
872 while((value >>= 7) > 0)
876 buffer += (value & 0x7f);
879 eputc(mf, (unsigned)(buffer & 0xff));
886 }/* end of WriteVarLen */
893 * These routines are used to make sure that the byte order of
894 * the various data types remains constant between machines. This
895 * helps make sure that the code will be portable from one system
896 * to the next. It is slightly dangerous that it assumes that longs
897 * have at least 32 bits and ints have at least 16 bits, but this
898 * has been true at least on PCs, UNIX machines, and Macintosh's.
905 eputc(mf, x(unsigned)((data >> 24) & 0xff));
906 eputc(mf, (unsigned)((data >> 16) & 0xff));
907 eputc(mf, (unsigned)((data >> 8 ) & 0xff));
908 eputc(mf, (unsigned)(data & 0xff));
915 eputc(mf, (unsigned)((data & 0xff00) >> 8));
916 eputc(mf, (unsigned)(data & 0xff));
919 /* write a single character and abort on error */
925 if((mf->Mf_putc) == NULLFUNC)
927 mferror(mf, "Mf_putc undefined");
931 return_val = (mf->Mf_putc)(mf, c);
933 if ( return_val == EOF )
934 mferror(mf, "error writing");
936 mf->Mf_numbyteswritten++;
942 unsigned long mf_sec2ticks(float secs,int division, unsigned int tempo)
944 return (long)(((secs * 1000.0) / 4.0 * division) / tempo);
949 * This routine converts delta times in ticks into seconds. The
950 * else statement is needed because the formula is different for tracks
951 * based on notes and tracks based on SMPTE times.
954 float mf_ticks2sec(unsigned long ticks,int division,unsigned int tempo)
956 float smpte_format, smpte_resolution;
959 return ((float) (((float)(ticks) * (float)(tempo)) / ((float)(division) * 1000000.0)));
962 smpte_format = upperbyte(division);
963 smpte_resolution = lowerbyte(division);
964 return (float) ((float) ticks / (smpte_format * smpte_resolution * 1000000.0));
966 } /* end of ticks2sec() */
968 /* code to utilize the interface */
970 #define TRACE(x, y) do { if (x) printf y; } while (0)
973 typedef unsigned long ulg;
974 typedef unsigned char uch;
975 typedef unsigned int ui;
989 #define IBUFSIZE 1024
993 struct NoteInfo * ni;
999 int prevnoteonpitch; /* -1, nothing, 0 pause, 1-x note. */
1010 enum { TRK_NONE, TRK_READING, TRK_FINISHED };
1012 #define ALLOCSIZE 256
1014 #define NIALLOC(size) (struct NoteInfo *)malloc(sizeof (struct NoteInfo) + ((size) - 1) * sizeof (struct Notes))
1016 #define NIREALLOC(ni, size) (struct NoteInfo *)realloc((ni), sizeof (struct NoteInfo) + ((size) - 1) * sizeof (struct Notes))
1019 static void lm_error(struct MF * mf, char * s);
1021 static int lm_getc(struct MF * mf);
1022 static void lm_header(struct MF * mf, int, int, int);
1023 static void lm_trackstart(struct MF * mf);
1024 static void lm_trackend(struct MF * mf);
1025 static void lm_tempo(struct MF *, long);
1026 static void lm_noteon(struct MF *, int, int, int);
1027 static void lm_noteoff(struct MF *, int, int, int);
1030 struct NoteInfo * readmidi(int fd)
1032 struct MFX mfxi = { { 0 } };
1033 struct MF * mf = (struct MF *)&mfxi;
1035 mfxi.ni = NIALLOC(ALLOCSIZE);
1036 mfxi.allocated = ALLOCSIZE;
1038 /* set variables to their initial values */
1040 mfxi.trackstate = TRK_NONE;
1041 mfxi.prevnoteonpitch = -1;
1042 mfxi.ni->nrnotes = 0;
1043 mfxi.ni->beats = 120;
1046 mfxi.istrm.p = mfxi.istrm.len = 0;
1047 mf->Mf_getc = lm_getc;
1049 mf->Mf_header = lm_header;
1050 mf->Mf_tempo = lm_tempo;
1051 mf->Mf_trackstart = lm_trackstart;
1052 mf->Mf_trackend = lm_trackend;
1053 mf->Mf_noteon = lm_noteon;
1054 mf->Mf_noteoff = lm_noteoff;
1056 mf->Mf_error = lm_error;
1063 static void lm_error(struct MF * mf, char * s)
1065 fprintf(stderr, "%s\n", s);
1068 static int lm_getc(struct MF * mf)
1070 struct MFX * mfx = (struct MFX *)mf;
1072 /* printf("p %d, len %d\n", mfx->istrm.p, mfx->istrm.len); */
1073 if (mfx->istrm.p == mfx->istrm.len)
1075 mfx->istrm.len = read(mfx->istrm.fd, mfx->istrm.buf, IBUFSIZE);
1076 /* printf("readlen %d\n", mfx->istrm.len); */
1077 if (mfx->istrm.len <= 0)
1081 return mfx->istrm.buf[0];
1084 return mfx->istrm.buf[mfx->istrm.p++];
1087 static void lm_header(struct MF * mf, int format, int ntrks, int division)
1089 struct MFX * mfx = (struct MFX *)mf;
1091 TRACE(0, ("lm_header(%p, %d, %d, %d)\n", mf, format, ntrks, division));
1093 mfx->division = division;
1096 /* this is just a quess */
1097 static void lm_tempo(struct MF * mf, long tempo)
1099 struct MFX * mfx = (struct MFX *)mf;
1101 TRACE(0, ("lm_tempo(%p, %ld)\n", mf, tempo));
1103 if (mfx->trackstate != TRK_FINISHED)
1104 mfx->ni->beats = 60000000 / tempo;
1108 static void addnote(struct MFX * mfx, int pitch, int duration, int special)
1111 struct NoteInfo * ni;
1113 if (mfx->ni->nrnotes == mfx->allocated)
1115 mfx->allocated += ALLOCSIZE;
1116 mfx->ni = NIREALLOC(mfx->ni, mfx->allocated);
1117 if (mfx->ni == NULL)
1120 ni = mfx->ni; /* mfx->ni pointer value may have changed above */
1124 if (pitch == 0) { p = 0; s = 0; }
1125 else { pitch--; p = (pitch % 12) + 1; s = pitch / 12; }
1127 ni->note[nr].note = p;
1128 ni->note[nr].scale = s;
1130 ni->note[nr].length = duration;
1131 ni->note[nr].lextra = special;
1134 /* currently supported */
1135 static /* N 32 32. 16 16. 8 8. 4 4. 2 2. 1 1. */
1136 int vals[] = { 15, 38, 54, 78, 109, 156, 218, 312, 437, 625, 875, 1250 };
1138 static void writenote(struct MFX * mfx, int delta)
1140 ulg millinotetime = delta * 250 / mfx->division;
1145 for(i = 0; i < sizeof vals / sizeof vals[0]; i++)
1147 if (millinotetime < vals[i])
1158 addnote(mfx, mfx->prevnoteonpitch, duration, special); /* XXX think this */
1162 static void lm_trackstart(struct MF * mf)
1164 struct MFX * mfx = (struct MFX *)mf;
1166 TRACE(0, ("lm_trackstart(%p)\n", mf));
1168 if (mfx->trackstate == TRK_NONE)
1169 mfx->trackstate = TRK_READING;
1171 mfx->prevnoteonpitch = -1;
1174 static void lm_trackend(struct MF * mf)
1176 struct MFX * mfx = (struct MFX *)mf;
1177 long time = mf->Mf_currtime;
1179 TRACE(0, ("lm_trackend(%p)\n", mf));
1181 if (mfx->trackstate == TRK_READING && mfx->ni->nrnotes > 0)
1182 mfx->trackstate = TRK_FINISHED;
1184 if (mfx->prevnoteonpitch >= 0)
1185 writenote(mfx, time - mfx->prevnoteontime);
1187 mfx->prevnoteonpitch = -1;
1190 static void lm_noteon(struct MF * mf, int chan, int pitch, int vol)
1192 struct MFX * mfx = (struct MFX *)mf;
1193 long time = mf->Mf_currtime;
1195 TRACE(0, ("lm_noteon(%p, %d, %d, %d)\n", mf, chan, pitch, vol));
1197 if (vol == 0) /* kludge? to handle some (format 1? midi files) */
1200 if (mfx->trackstate != TRK_READING)
1203 if (mfx->prevnoteonpitch >= 0)
1204 writenote(mfx, time - mfx->prevnoteontime);
1207 mfx->prevnoteonpitch = 0;
1209 mfx->prevnoteonpitch = pitch + 1;
1211 mfx->prevnoteontime = time;
1214 static void lm_noteoff(struct MF * mf, int chan, int pitch, int vol)
1216 struct MFX * mfx = (struct MFX *)mf;
1217 long time = mf->Mf_currtime;
1219 TRACE(0, ("lm_noteoff(%p, %d, %d, %d)\n", mf, chan, pitch, vol));
1221 if (mfx->prevnoteonpitch >= 0)
1223 writenote(mfx, time - mfx->prevnoteontime);
1224 mfx->prevnoteonpitch = -1;
1226 mfx->prevnoteonpitch = 0;
1227 mfx->prevnoteontime = time;
1230 //{ "p", "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "h" };
1232 { 255, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11 , 12 };
1234 u8 lengths[] = { 4, 8, 16, 32, 64, 128 };
1236 static void countdefaults(struct NoteInfo * ni, int * length_p, int * scale_p)
1238 int lengths[15] = { 0 };
1239 int scales[15] = { 0 };
1240 int maxlenval = 0; /* (*) */
1241 int maxscaleval = 0;
1244 for (i = 0; i < ni->nrnotes; i++)
1246 struct Notes * note = &ni->note[i];
1248 lengths[note->length]++;
1249 scales[note->scale]++;
1252 maxlenval = lengths[0]; /* (*) smart compiler eliminates dead code */
1255 for (i = 1; i < 15; i++) /* `p' incremented scales[0], therefore ignored */
1257 TRACE(0, ("%d - len: %d, scale: %d\n", i, lengths[i], scales[i]));
1259 if (lengths[i] > maxlenval) {
1261 maxlenval = lengths[i];
1263 if (scales[i] > maxscaleval) {
1265 maxscaleval = scales[i];
1270 GSM_Error loadmid(char *filename, GSM_Ringtone *ringtone)
1273 struct NoteInfo * ni;
1275 int deflen, defscale;
1278 if ((fd = open(filename, O_RDONLY | O_BINARY)) < 0)
1281 return GE_CANTOPENFILE;
1284 if ((fd = open(filename, O_RDONLY)) < 0)
1287 return GE_CANTOPENFILE;
1296 countdefaults(ni, &deflen, &defscale);
1298 strcpy(ringtone->name,"GNOKII");
1300 if (ni->nrnotes<MAX_RINGTONE_NOTES)
1301 ringtone->NrNotes=ni->nrnotes;
1303 ringtone->NrNotes=MAX_RINGTONE_NOTES;
1305 for (i = 0; i < ringtone->NrNotes; i++)
1307 struct Notes * note = &ni->note[i];
1309 ringtone->notes[i].note=notes[note->note];
1310 ringtone->notes[i].note=notes[note->note]+(note->scale%4)*14;
1312 ringtone->notes[i].duration=lengths[note->length];
1314 ringtone->notes[i].duration=ringtone->notes[i].duration*1.5;
1316 ringtone->notes[i].tempo=ni->beats;