This commit was manufactured by cvs2svn to create branch 'decode'.
[gnokii.git] / common / files / midifile.c
diff --git a/common/files/midifile.c b/common/files/midifile.c
deleted file mode 100644 (file)
index 9e55249..0000000
+++ /dev/null
@@ -1,1321 +0,0 @@
-/* a little modified code from http://iki.fi/too/sw/xring/ */
-
-/* embedding modified midifile.h and midifile.c into this file */
-
-/***** midifile.h ******/
-
-struct MF {
-/* definitions for MIDI file parsing code */
-  int (*Mf_getc)(struct MF *);
-  void (*Mf_header)(struct MF *, int, int, int);
-  void (*Mf_trackstart)(struct MF *);
-  void (*Mf_trackend)(struct MF *);
-  void (*Mf_noteon)(struct MF *, int, int, int);
-  void (*Mf_noteoff)(struct MF *, int, int, int);
-  void (*Mf_pressure)(struct MF *, int, int, int);
-  void (*Mf_parameter)(struct MF *, int, int, int);
-  void (*Mf_pitchbend)(struct MF *, int, int, int);
-  void (*Mf_program)(struct MF *, int, int);
-  void (*Mf_chanpressure)(struct MF *, int, int);
-  void (*Mf_sysex)(struct MF *, int, char *);
-  void (*Mf_metamisc)(struct MF *, int, int, char * );
-  void (*Mf_seqspecific)(struct MF *, int, int, char *);
-  void (*Mf_seqnum)(struct MF *, int);
-  void (*Mf_text)(struct MF *, int, int, char *);
-  void (*Mf_eot)(struct MF *);
-  void (*Mf_timesig)(struct MF *, int, int, int, int);
-  void (*Mf_smpte)(struct MF *, int, int, int, int, int);
-  void (*Mf_tempo)(struct MF *, long);
-  void (*Mf_keysig)(struct MF *, int, int);
-  void (*Mf_arbitrary)(struct MF *, int, char *);
-  void (*Mf_error)(struct MF *, char * );
-#if 0
-/* definitions for MIDI file writing code */
-  void (*Mf_putc)(struct MF *);
-  void (*Mf_writetrack)(struct MF *);
-  void (*Mf_writetempotrack)(struct MF *);
-#endif
-  /* variables */
-  int Mf_nomerge;             /* 1 => continue'ed system exclusives are */
-                                       /* not collapsed. */
-  long Mf_currtime;          /* current time in delta-time units */
-
-/* private stuff */
-  long Mf_toberead;
-  long Mf_numbyteswritten;
-
-  char *Msgbuff;       /* message buffer */
-  int Msgsize;         /* Size of currently allocated Msg */
-  int Msgindex;                /* index of next available location in Msg */
-
-};
-
-float mf_ticks2sec(unsigned long ticks,int division,unsigned int tempo);
-unsigned long mf_sec2ticks(float secs,int division, unsigned int tempo);
-
-void mferror(struct MF * mf, char * s);
-
-/*void mfwrite(); */
-
-
-/* MIDI status commands most significant bit is 1 */
-#define note_off               0x80
-#define note_on                0x90
-#define poly_aftertouch        0xa0
-#define control_change         0xb0
-#define program_chng           0xc0
-#define channel_aftertouch      0xd0
-#define pitch_wheel            0xe0
-#define system_exclusive       0xf0
-#define delay_packet           (1111)
-
-/* 7 bit controllers */
-#define damper_pedal            0x40
-#define portamento             0x41    
-#define sostenuto              0x42
-#define soft_pedal             0x43
-#define general_4               0x44
-#define        hold_2                  0x45
-#define        general_5               0x50
-#define        general_6               0x51
-#define general_7              0x52
-#define general_8              0x53
-#define tremolo_depth          0x5c
-#define chorus_depth           0x5d
-#define        detune                  0x5e
-#define phaser_depth           0x5f
-
-/* parameter values */
-#define data_inc               0x60
-#define data_dec               0x61
-
-/* parameter selection */
-#define non_reg_lsb            0x62
-#define non_reg_msb            0x63
-#define reg_lsb                        0x64
-#define reg_msb                        0x65
-
-/* Standard MIDI Files meta event definitions */
-#define        meta_event              0xFF
-#define        sequence_number         0x00
-#define        text_event              0x01
-#define copyright_notice       0x02
-#define sequence_name          0x03
-#define instrument_name        0x04
-#define lyric                  0x05
-#define marker                 0x06
-#define        cue_point               0x07
-#define channel_prefix         0x20
-#define        end_of_track            0x2f
-#define        set_tempo               0x51
-#define        smpte_offset            0x54
-#define        time_signature          0x58
-#define        key_signature           0x59
-#define        sequencer_specific      0x74
-
-/* Manufacturer's ID number */
-#define Seq_Circuits (0x01) /* Sequential Circuits Inc. */
-#define Big_Briar    (0x02) /* Big Briar Inc.           */
-#define Octave       (0x03) /* Octave/Plateau           */
-#define Moog         (0x04) /* Moog Music               */
-#define Passport     (0x05) /* Passport Designs         */
-#define Lexicon      (0x06) /* Lexicon                         */
-#define Tempi        (0x20) /* Bon Tempi                */
-#define Siel         (0x21) /* S.I.E.L.                 */
-#define Kawai        (0x41) 
-#define Roland       (0x42)
-#define Korg         (0x42)
-#define Yamaha       (0x43)
-
-/* miscellaneous definitions */
-#define MThd 0x4d546864
-#define MTrk 0x4d54726b
-#define lowerbyte(x) ((unsigned char)(x & 0xff))
-#define upperbyte(x) ((unsigned char)((x & 0xff00)>>8))
-
-/* the midifile interface */
-void midifile(struct MF * mf);
-
-/***** midifile.c ******/
-
-/*
- * midifile 1.11
- * 
- * Read and write a MIDI file.  Externally-assigned function pointers are 
- * called upon recognizing things in the file.
- *
- * Original release ?
- * June 1989 - Added writing capability, M. Czeiszperger.
- *
- *          The file format implemented here is called
- *          Standard MIDI Files, and is part of the Musical
- *          instrument Digital Interface specification.
- *          The spec is avaiable from:
- *
- *               International MIDI Association
- *               5316 West 57th Street
- *               Los Angeles, CA 90056
- *
- *          An in-depth description of the spec can also be found
- *          in the article "Introducing Standard MIDI Files", published
- *          in Electronic Musician magazine, April, 1989.
- * 
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-
-#ifdef WIN32\r
-\r
-  #include <windows.h>\r
-\r
-#else\r
-\r
-  #include <unistd.h>\r
-#endif\r
-
-#include "gsm-common.h"
-#include "gsm-ringtones.h"
-
-#define NULLFUNC NULL
-
-static void readheader(struct MF * mf);
-static int readtrack(struct MF * mf);
-static void chanmessage(struct MF * mf,int status,int c1,int c2);
-static void msginit(struct MF * mf);
-static void msgadd(struct MF * mf,int c);
-static void metaevent(struct MF * mf, int type);
-static void sysex(struct MF * mf);
-static int msgleng(struct MF * mf);
-static void badbyte(struct MF * mf,int c);
-static void biggermsg(struct MF * mf);
-
-
-static long readvarinum(struct MF * mf);
-static long read32bit(struct MF * mf);
-static long to32bit(int, int, int, int);
-static int read16bit(struct MF * mf);
-static int to16bit(int, int);
-static char * msg(struct MF * mf);
-
-/* The only non-static function in this file. */
-void mfread(struct MF * mf)
-{
-       if ( mf->Mf_getc == NULLFUNC )
-               mferror(mf, "mfread() called without setting Mf_getc"); 
-
-       readheader(mf);
-       while ( readtrack(mf) )
-               ;
-}
-
-/* for backward compatibility with the original lib */
-void midifile(struct MF * mf)
-{
-    mfread(mf);
-}
-
-/* read through the "MThd" or "MTrk" header string */
-static int readmt(struct MF * mf, char * s)
-{
-       int n = 0;
-       char *p = s;
-       int c=0;
-
-       while ( n++<4 && (c=mf->Mf_getc(mf)) != EOF ) {
-               if ( c != *p++ ) {
-                       char buff[32];
-                       (void) strcpy(buff, "expecting ");
-                       (void) strcat(buff, s);
-                       mferror(mf, buff);
-               }
-       }
-       return c;
-}
-
-/* read a single character and abort on EOF */
-static int egetc(struct MF * mf)
-{
-       int c = mf->Mf_getc(mf);
-
-       if ( c == EOF )
-               mferror(mf, "premature EOF");
-       mf->Mf_toberead--;
-       return c;
-}
-
-/* read a header chunk */
-static void readheader(struct MF * mf)
-{
-       int format, ntrks, division;
-
-       if ( readmt(mf, "MThd") == EOF )
-               return;
-
-       mf->Mf_toberead = read32bit(mf);
-       format = read16bit(mf);
-       ntrks = read16bit(mf);
-       division = read16bit(mf);
-
-       if ( mf->Mf_header )
-               (*mf->Mf_header)(mf, format,ntrks,division);
-
-       /* flush any extra stuff, in case the length of header is not 6 */
-       while ( mf->Mf_toberead > 0 )
-               (void) egetc(mf);
-}
-
-static int readtrack(struct MF * mf)            /* read a track chunk */
-{
-       /* This array is indexed by the high half of a status byte.  It's */
-       /* value is either the number of bytes needed (1 or 2) for a channel */
-       /* message, or 0 (meaning it's not  a channel message). */
-       static int chantype[] = {
-               0, 0, 0, 0, 0, 0, 0, 0,         /* 0x00 through 0x70 */
-               2, 2, 2, 2, 1, 1, 2, 0          /* 0x80 through 0xf0 */
-       };
-       long lookfor;
-       int c, c1, type;
-       int sysexcontinue = 0;  /* 1 if last message was an unfinished sysex */
-       int running = 0;        /* 1 when running status used */
-       int status = 0;         /* status value (e.g. 0x90==note-on) */
-       int needed;
-
-       if ( readmt(mf, "MTrk") == EOF )
-               return(0);
-
-       mf->Mf_toberead = read32bit(mf);
-       mf->Mf_currtime = 0;
-
-       if ( mf->Mf_trackstart )
-               (*mf->Mf_trackstart)(mf);
-
-       while ( mf->Mf_toberead > 0 ) {
-
-               mf->Mf_currtime += readvarinum(mf);     /* delta time */
-
-               c = egetc(mf);
-
-               if ( sysexcontinue && c != 0xf7 )
-                       mferror(mf, "didn't find expected continuation of a sysex");
-
-               if ( (c & 0x80) == 0 ) {         /* running status? */
-                       if ( status == 0 )
-                               mferror(mf, "unexpected running status");
-                       running = 1;
-               }
-               else {
-                       status = c;
-                       running = 0;
-               }
-
-               needed = chantype[ (status>>4) & 0xf ];
-
-               if ( needed ) {         /* ie. is it a channel message? */
-
-                       if ( running )
-                               c1 = c;
-                       else
-                               c1 = egetc(mf);
-                       chanmessage(mf, status, c1, (needed>1)? egetc(mf): 0);
-                       continue;;
-               }
-
-               switch ( c ) {
-
-               case 0xff:                      /* meta event */
-
-                       type = egetc(mf);
-                       lookfor = mf->Mf_toberead - readvarinum(mf);
-                       msginit(mf);
-
-                       while ( mf->Mf_toberead > lookfor )
-                               msgadd(mf, egetc(mf));
-
-                       metaevent(mf, type);
-                       break;
-
-               case 0xf0:              /* start of system exclusive */
-
-                       lookfor = mf->Mf_toberead - readvarinum(mf);
-                       msginit(mf);
-                       msgadd(mf, 0xf0);
-
-                       while ( mf->Mf_toberead > lookfor )
-                               msgadd(mf, c=egetc(mf));
-
-                       if ( c==0xf7 || mf->Mf_nomerge==0 )
-                               sysex(mf);
-                       else
-                               sysexcontinue = 1;  /* merge into next msg */
-                       break;
-
-               case 0xf7:      /* sysex continuation or arbitrary stuff */
-
-                       lookfor = mf->Mf_toberead - readvarinum(mf);
-
-                       if ( ! sysexcontinue )
-                               msginit(mf);
-
-                       while ( mf->Mf_toberead > lookfor )
-                               msgadd(mf, c=egetc(mf));
-
-                       if ( ! sysexcontinue ) {
-                               if ( mf->Mf_arbitrary )
-                                       (*mf->Mf_arbitrary)(mf, msgleng(mf),msg(mf));
-                       }
-                       else if ( c == 0xf7 ) {
-                               sysex(mf);
-                               sysexcontinue = 0;
-                       }
-                       break;
-               default:
-                       badbyte(mf, c);
-                       break;
-               }
-       }
-       if ( mf->Mf_trackend )
-               (*mf->Mf_trackend)(mf);
-       return(1);
-}
-
-static void badbyte(struct MF * mf,int c)
-{
-       char buff[32];
-
-       (void) sprintf(buff,"unexpected byte: 0x%02x",c);
-       mferror(mf, buff);
-}
-
-static void metaevent(struct MF * mf, int type)
-{
-       int leng = msgleng(mf);
-       char *m = msg(mf);
-
-       switch  ( type ) {
-       case 0x00:
-               if ( mf->Mf_seqnum )
-                       (*mf->Mf_seqnum)(mf, to16bit(m[0],m[1]));
-               break;
-       case 0x01:      /* Text event */
-       case 0x02:      /* Copyright notice */
-       case 0x03:      /* Sequence/Track name */
-       case 0x04:      /* Instrument name */
-       case 0x05:      /* Lyric */
-       case 0x06:      /* Marker */
-       case 0x07:      /* Cue point */
-       case 0x08:
-       case 0x09:
-       case 0x0a:
-       case 0x0b:
-       case 0x0c:
-       case 0x0d:
-       case 0x0e:
-       case 0x0f:
-               /* These are all text events */
-               if ( mf->Mf_text )
-                       (*mf->Mf_text)(mf, type,leng,m);
-               break;
-       case 0x2f:      /* End of Track */
-               if ( mf->Mf_eot )
-                       (*mf->Mf_eot)(mf);
-               break;
-       case 0x51:      /* Set tempo */
-               if ( mf->Mf_tempo )
-                       (*mf->Mf_tempo)(mf, to32bit(0,m[0],m[1],m[2]));
-               break;
-       case 0x54:
-               if ( mf->Mf_smpte )
-                       (*mf->Mf_smpte)(mf, m[0],m[1],m[2],m[3],m[4]);
-               break;
-       case 0x58:
-               if ( mf->Mf_timesig )
-                       (*mf->Mf_timesig)(mf, m[0],m[1],m[2],m[3]);
-               break;
-       case 0x59:
-               if ( mf->Mf_keysig )
-                       (*mf->Mf_keysig)(mf, m[0],m[1]);
-               break;
-       case 0x7f:
-               if ( mf->Mf_seqspecific )
-                       (*mf->Mf_seqspecific)(mf, type, leng, m);
-               break;
-       default:
-               if ( mf->Mf_metamisc )
-                       (*mf->Mf_metamisc)(mf, type,leng,m);
-       }
-}
-
-static void sysex(struct MF * mf)
-{
-       if ( mf->Mf_sysex )
-               (*mf->Mf_sysex)(mf, msgleng(mf),msg(mf));
-}
-
-static void chanmessage(struct MF * mf,int status,int c1,int c2)
-{
-       int chan = status & 0xf;
-
-       switch ( status & 0xf0 ) {
-       case 0x80:
-               if ( mf->Mf_noteoff )
-                       (*mf->Mf_noteoff)(mf, chan,c1,c2);
-               break;
-       case 0x90:
-               if ( mf->Mf_noteon )
-                       (*mf->Mf_noteon)(mf, chan,c1,c2);
-               break;
-       case 0xa0:
-               if ( mf->Mf_pressure )
-                       (*mf->Mf_pressure)(mf, chan,c1,c2);
-               break;
-       case 0xb0:
-               if ( mf->Mf_parameter )
-                       (*mf->Mf_parameter)(mf, chan,c1,c2);
-               break;
-       case 0xe0:
-               if ( mf->Mf_pitchbend )
-                       (*mf->Mf_pitchbend)(mf, chan,c1,c2);
-               break;
-       case 0xc0:
-               if ( mf->Mf_program )
-                       (*mf->Mf_program)(mf, chan,c1);
-               break;
-       case 0xd0:
-               if ( mf->Mf_chanpressure )
-                       (*mf->Mf_chanpressure)(mf, chan,c1);
-               break;
-       }
-}
-
-/* readvarinum - read a varying-length number, and return the */
-/* number of characters it took. */
-
-static long readvarinum(struct MF * mf)
-{
-       long value;
-       int c;
-
-       c = egetc(mf);
-       value = c;
-       if ( c & 0x80 ) {
-               value &= 0x7f;
-               do {
-                       c = egetc(mf);
-                       value = (value << 7) + (c & 0x7f);
-               } while (c & 0x80);
-       }
-       return (value);
-}
-
-static long to32bit(int c1,int c2,int c3,int c4)
-{
-       long value = 0L;
-
-       value = (c1 & 0xff);
-       value = (value<<8) + (c2 & 0xff);
-       value = (value<<8) + (c3 & 0xff);
-       value = (value<<8) + (c4 & 0xff);
-       return (value);
-}
-
-static int to16bit(int c1,int c2)
-{
-       return ((c1 & 0xff ) << 8) + (c2 & 0xff);
-}
-
-static long read32bit(struct MF * mf)
-{
-       int c1, c2, c3, c4;
-
-       c1 = egetc(mf);
-       c2 = egetc(mf);
-       c3 = egetc(mf);
-       c4 = egetc(mf);
-       return to32bit(c1,c2,c3,c4);
-}
-
-static int read16bit(struct MF * mf)
-{
-       int c1, c2;
-       c1 = egetc(mf);
-       c2 = egetc(mf);
-       return to16bit(c1,c2);
-}
-
-/* static */
-void mferror(struct MF * mf, char * s)
-{
-       if ( mf->Mf_error )
-               (*mf->Mf_error)(mf, s);
-       exit(1);
-}
-
-/* The code below allows collection of a system exclusive message of */
-/* arbitrary length.  The Msgbuff is expanded as necessary.  The only */
-/* visible data/routines are msginit(), msgadd(), msg(), msgleng(). */
-
-#define MSGINCREMENT 128
-
-static void msginit(struct MF * mf)
-{
-       mf->Msgindex = 0;
-}
-
-static char * msg(struct MF * mf)
-{
-       return(mf->Msgbuff);
-}
-
-static int msgleng(struct MF * mf)
-{
-       return(mf->Msgindex);
-}
-
-static void msgadd(struct MF * mf,int c)
-{
-       /* If necessary, allocate larger message buffer. */
-       if ( mf->Msgindex >= mf->Msgsize )
-               biggermsg(mf);
-       mf->Msgbuff[mf->Msgindex++] = c;
-}
-
-static void biggermsg(struct MF * mf)
-{
-       char *newmess;
-       char *oldmess = mf->Msgbuff;
-       int oldleng = mf->Msgsize;
-
-       mf->Msgsize += MSGINCREMENT;
-       newmess = (char *) malloc( (unsigned)(sizeof(char) * mf->Msgsize) );
-
-       if(newmess == NULL)
-               mferror(mf, "malloc error!");
-               
-       /* copy old message into larger new one */
-       if ( oldmess != NULL ) {
-               register char *p = newmess;
-               register char *q = oldmess;
-               register char *endq = &oldmess[oldleng];
-
-               for ( ; q!=endq ; p++,q++ )
-                       *p = *q;
-               free(oldmess);
-       }
-       mf->Msgbuff = newmess;
-}
-
-#if 0 /* saving time not converting write function at this time
-       */
-/*
- * mfwrite() - The only fuction you'll need to call to write out
- *             a midi file.
- *
- * format      0 - Single multi-channel track
- *             1 - Multiple simultaneous tracks
- *             2 - One or more sequentially independent
- *                 single track patterns                
- * ntracks     The number of tracks in the file.
- * division    This is kind of tricky, it can represent two
- *             things, depending on whether it is positive or negative
- *             (bit 15 set or not).  If  bit  15  of division  is zero,
- *             bits 14 through 0 represent the number of delta-time
- *             "ticks" which make up a quarter note.  If bit  15 of
- *             division  is  a one, delta-times in a file correspond to
- *             subdivisions of a second similiar to  SMPTE  and  MIDI
- *             time code.  In  this format bits 14 through 8 contain
- *             one of four values - 24, -25, -29, or -30,
- *             corresponding  to  the  four standard  SMPTE and MIDI
- *             time code frame per second formats, where  -29
- *             represents  30  drop  frame.   The  second  byte
- *             consisting  of  bits 7 through 0 corresponds the the
- *             resolution within a frame.  Refer the Standard MIDI
- *             Files 1.0 spec for more details.
- * fp          This should be the open file pointer to the file you
- *             want to write.  It will have be a global in order
- *             to work with Mf_putc.  
- */ 
-void 
-mfwrite(format,ntracks,division,fp) 
-int format,ntracks,division; 
-FILE *fp; 
-{
-    int i; void mf_write_track_chunk(), mf_write_header_chunk();
-
-    if ( mf->Mf_putc == NULLFUNC )
-           mferror(mf, "mfmf_write() called without setting Mf_putc");
-
-    if ( mf->Mf_writetrack == NULLFUNC )
-           mferror(mf, "mfmf_write() called without setting Mf_mf_writetrack"); 
-
-    /* every MIDI file starts with a header */
-    mf_write_header_chunk(format,ntracks,division);
-
-    /* In format 1 files, the first track is a tempo map */
-    if(format == 1 && ( mf->Mf_writetempotrack ))
-    {
-       (*mf->Mf_writetempotrack)();
-    }
-
-    /* The rest of the file is a series of tracks */
-    for(i = 0; i < ntracks; i++)
-        mf_write_track_chunk(i,fp);
-}
-
-void 
-mf_write_track_chunk(which_track,fp)
-int which_track;
-FILE *fp;
-{
-       unsigned long trkhdr,trklength;
-       long offset, place_marker;
-       void write16bit(),write32bit();
-       
-       
-       trkhdr = MTrk;
-       trklength = 0;
-
-       /* Remember where the length was written, because we don't
-          know how long it will be until we've finished writing */
-       offset = ftell(fp); 
-
-#ifdef DEBUG
-        printf("offset = %d\n",(int) offset);
-#endif
-
-       /* Write the track chunk header */
-       write32bit(trkhdr);
-       write32bit(trklength);
-
-       mf->Mf_numbyteswritten = 0L; /* the header's length doesn't count */
-
-       if( mf->Mf_writetrack )
-       {
-           (*mf->Mf_writetrack)(which_track);
-       }
-
-       /* mf_write End of track meta event */
-       eputc(mf, 0);
-       eputc(mf, meta_event);
-       eputc(mf, end_of_track);
-
-       eputc(mf, 0);
-        
-       /* It's impossible to know how long the track chunk will be beforehand,
-           so the position of the track length data is kept so that it can
-           be written after the chunk has been generated */
-       place_marker = ftell(fp);
-       
-       /* This method turned out not to be portable because the
-           parameter returned from ftell is not guaranteed to be
-           in bytes on every machine */
-       /* track.length = place_marker - offset - (long) sizeof(track); */
-
-#ifdef DEBUG
-printf("length = %d\n",(int) trklength);
-#endif
-
-       if(fseek(fp,offset,0) < 0)
-           mferror(mf, "error seeking during final stage of write");
-
-       trklength = mf->Mf_numbyteswritten;
-
-       /* Re-mf_write the track chunk header with right length */
-       write32bit(trkhdr);
-       write32bit(trklength);
-
-       fseek(fp,place_marker,0);
-} /* End gen_track_chunk() */
-
-
-void 
-mf_write_header_chunk(format,ntracks,division)
-int format,ntracks,division;
-{
-    unsigned long ident,length;
-    void write16bit(),write32bit();
-    
-    ident = MThd;           /* Head chunk identifier                    */
-    length = 6;             /* Chunk length                             */
-
-    /* individual bytes of the header must be written separately
-       to preserve byte order across cpu types :-( */
-    write32bit(ident);
-    write32bit(length);
-    write16bit(format);
-    write16bit(ntracks);
-    write16bit(division);
-} /* end gen_header_chunk() */
-
-
-#ifdef WHENISTHISNEEDED
-/*
- * mf_write_midi_event()
- * 
- * Library routine to mf_write a single MIDI track event in the standard MIDI
- * file format. The format is:
- *
- *                    <delta-time><event>
- *
- * In this case, event can be any multi-byte midi message, such as
- * "note on", "note off", etc.      
- *
- * delta_time - the time in ticks since the last event.
- * type - the type of meta event.
- * chan - The midi channel.
- * data - A pointer to a block of chars containing the META EVENT,
- *        data.
- * size - The length of the meta-event data.
- */
-int 
-mf_write_midi_event(delta_time, type, chan, data, size)
-unsigned long delta_time;
-unsigned int chan,type;
-unsigned long size;
-unsigned char *data;
-{
-    int i;
-    void WriteVarLen();
-    unsigned char c;
-
-    WriteVarLen(delta_time);
-
-    /* all MIDI events start with the type in the first four bits,
-       and the channel in the lower four bits */
-    c = type | chan;
-
-    if(chan > 15)
-        perror("error: MIDI channel greater than 16\n");
-
-    eputc(mf, c);
-
-    /* write out the data bytes */
-    for(i = 0; i < size; i++)
-       eputc(mf, data[i]);
-
-    return(size);
-} /* end mf_write MIDI event */
-
-/*
- * mf_write_meta_event()
- *
- * Library routine to mf_write a single meta event in the standard MIDI
- * file format. The format of a meta event is:
- *
- *          <delta-time><FF><type><length><bytes>
- *
- * delta_time - the time in ticks since the last event.
- * type - the type of meta event.
- * data - A pointer to a block of chars containing the META EVENT,
- *        data.
- * size - The length of the meta-event data.
- */
-int
-mf_write_meta_event(delta_time, type, data, size)
-unsigned long delta_time;
-unsigned char *data,type;
-unsigned long size;
-{
-    int i;
-
-    WriteVarLen(delta_time);
-    
-    /* This marks the fact we're writing a meta-event */
-    eputc(mf, meta_event);
-
-    /* The type of meta event */
-    eputc(mf, type);
-
-    /* The length of the data bytes to follow */
-    WriteVarLen(size); 
-
-    for(i = 0; i < size; i++)
-    {
-       if(eputc(mf, data[i]) != data[i])
-           return(-1); 
-    }
-    return(size);
-} /* end mf_write_meta_event */
-
-void 
-mf_write_tempo(tempo)
-unsigned long tempo;
-{
-    /* Write tempo */
-    /* all tempos are written as 120 beats/minute, */
-    /* expressed in microseconds/quarter note     */
-    eputc(mf, 0);
-    eputc(mf, meta_event);
-    eputc(mf, set_tempo);
-
-    eputc(mf, 3);
-    eputc(mf, (unsigned)(0xff & (tempo >> 16)));
-    eputc(mf, (unsigned)(0xff & (tempo >> 8)));
-    eputc(mf, (unsigned)(0xff & tempo));
-}
-
-#endif
-/*
- * Write multi-length bytes to MIDI format files
- */
-void 
-WriteVarLen(value)
-unsigned long value;
-{
-  unsigned long buffer;
-
-  buffer = value & 0x7f;
-  while((value >>= 7) > 0)
-  {
-       buffer <<= 8;
-       buffer |= 0x80;
-       buffer += (value & 0x7f);
-  }
-  while(1){
-       eputc(mf, (unsigned)(buffer & 0xff));
-       
-       if(buffer & 0x80)
-               buffer >>= 8;
-       else
-               return;
-       }
-}/* end of WriteVarLen */
-
-
-/*
- * write32bit()
- * write16bit()
- *
- * These routines are used to make sure that the byte order of
- * the various data types remains constant between machines. This
- * helps make sure that the code will be portable from one system
- * to the next.  It is slightly dangerous that it assumes that longs
- * have at least 32 bits and ints have at least 16 bits, but this
- * has been true at least on PCs, UNIX machines, and Macintosh's.
- *
- */
-void 
-write32bit(data)
-unsigned long data;
-{
-    eputc(mf, x(unsigned)((data >> 24) & 0xff));
-    eputc(mf, (unsigned)((data >> 16) & 0xff));
-    eputc(mf, (unsigned)((data >> 8 ) & 0xff));
-    eputc(mf, (unsigned)(data & 0xff));
-}
-
-void 
-write16bit(data)
-int data;
-{
-    eputc(mf, (unsigned)((data & 0xff00) >> 8));
-    eputc(mf, (unsigned)(data & 0xff));
-}
-
-/* write a single character and abort on error */
-eputc(mf, c)                   
-unsigned char c;
-{
-       int return_val;
-       
-       if((mf->Mf_putc) == NULLFUNC)
-       {
-               mferror(mf, "Mf_putc undefined");
-               return(-1);
-       }
-       
-       return_val = (mf->Mf_putc)(mf, c);
-
-       if ( return_val == EOF )
-               mferror(mf, "error writing");
-               
-       mf->Mf_numbyteswritten++;
-       return(return_val);
-}
-
-#endif
-
-unsigned long mf_sec2ticks(float secs,int division, unsigned int tempo)
-{    
-     return (long)(((secs * 1000.0) / 4.0 * division) / tempo);
-}
-
-
-/* 
- * This routine converts delta times in ticks into seconds. The
- * else statement is needed because the formula is different for tracks
- * based on notes and tracks based on SMPTE times.
- *
- */
-float mf_ticks2sec(unsigned long ticks,int division,unsigned int tempo)
-{
-    float smpte_format, smpte_resolution;
-
-    if(division > 0)
-        return ((float) (((float)(ticks) * (float)(tempo)) / ((float)(division) * 1000000.0)));
-    else
-    {
-       smpte_format = upperbyte(division);
-       smpte_resolution = lowerbyte(division);
-       return (float) ((float) ticks / (smpte_format * smpte_resolution * 1000000.0));
-    }
-} /* end of ticks2sec() */
-
-/* code to utilize the interface */
-
-#define TRACE(x, y) do { if (x) printf y; } while (0)
-
-
-typedef unsigned long ulg;
-typedef unsigned char uch;
-typedef unsigned int  ui;
-
-struct NoteInfo
-{
-  int beats;
-  int nrnotes;
-  struct Notes {
-    ui note : 4;
-    ui scale : 4;
-    ui length : 4;
-    ui lextra : 4;
-  } note[1];
-};
-
-#define IBUFSIZE 1024
-struct MFX
-{
-  struct MF mfi;
-  struct NoteInfo * ni;
-  int allocated;
-
-  int division;
-  int trackstate;
-
-  int prevnoteonpitch; /* -1, nothing, 0 pause, 1-x note. */
-  ulg prevnoteontime;
-
-  struct {
-    int fd;
-    uch buf[IBUFSIZE];
-    int len;
-    int p;
-  } istrm;
-};
-
-enum { TRK_NONE, TRK_READING, TRK_FINISHED };
-
-#define ALLOCSIZE 256
-
-#define NIALLOC(size) (struct NoteInfo *)malloc(sizeof (struct NoteInfo) + ((size) - 1) * sizeof (struct Notes))
-
-#define NIREALLOC(ni, size) (struct NoteInfo *)realloc((ni), sizeof (struct NoteInfo) + ((size) - 1) * sizeof (struct Notes))
-
-
-static void lm_error(struct MF * mf, char * s);
-
-static int  lm_getc(struct MF * mf);
-static void lm_header(struct MF * mf, int, int, int);
-static void lm_trackstart(struct MF * mf);
-static void lm_trackend(struct MF * mf);
-static void lm_tempo(struct MF *, long);
-static void lm_noteon(struct MF *, int, int, int);
-static void lm_noteoff(struct MF *, int, int, int);
-
-
-struct NoteInfo * readmidi(int fd)
-{
-  struct MFX mfxi = { { 0 } };
-  struct MF * mf = (struct MF *)&mfxi;
-  
-  mfxi.ni = NIALLOC(ALLOCSIZE);
-  mfxi.allocated = ALLOCSIZE;
-
-  /* set variables to their initial values */
-  mfxi.division = 0;
-  mfxi.trackstate = TRK_NONE;
-  mfxi.prevnoteonpitch = -1;
-  mfxi.ni->nrnotes = 0;
-  mfxi.ni->beats = 120; 
-
-  mfxi.istrm.fd = fd;
-  mfxi.istrm.p = mfxi.istrm.len = 0;
-  mf->Mf_getc = lm_getc;
-  
-  mf->Mf_header = lm_header;
-  mf->Mf_tempo = lm_tempo;
-  mf->Mf_trackstart = lm_trackstart;
-  mf->Mf_trackend = lm_trackend;
-  mf->Mf_noteon = lm_noteon;
-  mf->Mf_noteoff = lm_noteoff;
-
-  mf->Mf_error = lm_error;
-
-  midifile(mf);
-
-  return mfxi.ni;
-}
-
-static void lm_error(struct MF * mf, char * s)
-{
-  fprintf(stderr, "%s\n", s);
-}
-
-static int lm_getc(struct MF * mf)
-{
-  struct MFX * mfx = (struct MFX *)mf;
-
-  /* printf("p %d, len %d\n", mfx->istrm.p, mfx->istrm.len); */
-  if (mfx->istrm.p == mfx->istrm.len)
-  {
-    mfx->istrm.len = read(mfx->istrm.fd, mfx->istrm.buf, IBUFSIZE);
-    /* printf("readlen %d\n", mfx->istrm.len); */
-    if (mfx->istrm.len <= 0)
-      return -1;
-
-    mfx->istrm.p = 1;
-    return mfx->istrm.buf[0];
-  }
-  /* else */
-  return mfx->istrm.buf[mfx->istrm.p++];
-}
-
-static void lm_header(struct MF * mf, int format, int ntrks, int division)
-{
-  struct MFX * mfx = (struct MFX *)mf;
-
-  TRACE(0, ("lm_header(%p, %d, %d, %d)\n", mf, format, ntrks, division));
-
-  mfx->division = division;
-}
-
-/* this is just a quess */
-static void lm_tempo(struct MF * mf, long tempo)
-{
-  struct MFX * mfx = (struct MFX *)mf;
-
-  TRACE(0, ("lm_tempo(%p, %ld)\n", mf, tempo));
-
-  if (mfx->trackstate != TRK_FINISHED)
-    mfx->ni->beats = 60000000 / tempo;
-}
-
-
-static void addnote(struct MFX * mfx, int pitch, int duration, int special)
-{
-  int nr, p, s;
-  struct NoteInfo * ni;
-  
-  if (mfx->ni->nrnotes == mfx->allocated)
-  {
-    mfx->allocated += ALLOCSIZE;
-    mfx->ni = NIREALLOC(mfx->ni, mfx->allocated);
-    if (mfx->ni == NULL)
-      exit(1);
-  }
-  ni = mfx->ni; /* mfx->ni pointer value may have changed above */
-  nr = ni->nrnotes++;
-
-  
-  if (pitch == 0)  { p = 0; s = 0; }
-  else  { pitch--; p = (pitch % 12) + 1; s = pitch / 12; }
-  
-  ni->note[nr].note = p;
-  ni->note[nr].scale = s;
-
-  ni->note[nr].length = duration;
-  ni->note[nr].lextra = special;
-}
-  
-/* currently supported */
-static /*     N  32  32.  16  16.   8    8.   4    4.   2    2.   1     1.  */
-int vals[] = { 15, 38,  54, 78,  109, 156, 218, 312, 437, 625, 875, 1250 };
-
-static void writenote(struct MFX * mfx, int delta)
-{
-  ulg millinotetime = delta * 250 / mfx->division;
-  int i;
-  int duration;
-  int special;
-  
-  for(i = 0; i < sizeof vals / sizeof vals[0]; i++)
-  {
-    if (millinotetime < vals[i])
-      break;
-  }
-
-  if (i == 0)
-    return;
-
-  i--;
-  duration = i / 2;
-  special = i & 1;
-
-  addnote(mfx, mfx->prevnoteonpitch, duration, special); /* XXX think this */
-}
-  
-
-static void lm_trackstart(struct MF * mf)
-{
-  struct MFX * mfx = (struct MFX *)mf;
-
-  TRACE(0, ("lm_trackstart(%p)\n", mf));
-
-  if (mfx->trackstate == TRK_NONE)
-    mfx->trackstate = TRK_READING;
-
-  mfx->prevnoteonpitch = -1;
-}
-
-static void lm_trackend(struct MF * mf)
-{
-  struct MFX * mfx = (struct MFX *)mf;
-  long time = mf->Mf_currtime;
-
-  TRACE(0, ("lm_trackend(%p)\n", mf));
-
-  if (mfx->trackstate == TRK_READING && mfx->ni->nrnotes > 0)
-    mfx->trackstate = TRK_FINISHED;
-
-  if (mfx->prevnoteonpitch >= 0)
-    writenote(mfx, time - mfx->prevnoteontime);
-  
-  mfx->prevnoteonpitch = -1;
-}
-
-static void lm_noteon(struct MF * mf, int chan, int pitch, int vol)
-{
-  struct MFX * mfx = (struct MFX *)mf;
-  long time = mf->Mf_currtime;
-
-  TRACE(0, ("lm_noteon(%p, %d, %d, %d)\n", mf, chan, pitch, vol));
-
-  if (vol == 0) /* kludge? to handle some (format 1? midi files) */
-    return; 
-  
-  if (mfx->trackstate != TRK_READING)
-    return;
-  
-  if (mfx->prevnoteonpitch >= 0)
-    writenote(mfx, time - mfx->prevnoteontime);
-
-  if (vol == 0)
-    mfx->prevnoteonpitch = 0;
-  else
-    mfx->prevnoteonpitch = pitch + 1;
-  
-  mfx->prevnoteontime = time;
-}
-
-static void lm_noteoff(struct MF * mf, int chan, int pitch, int vol)
-{
-  struct MFX * mfx = (struct MFX *)mf;
-  long time = mf->Mf_currtime;
-  
-  TRACE(0, ("lm_noteoff(%p, %d, %d, %d)\n", mf, chan, pitch, vol));
-
-  if (mfx->prevnoteonpitch >= 0)
-  {
-    writenote(mfx, time - mfx->prevnoteontime);
-    mfx->prevnoteonpitch = -1;
-  }
-  mfx->prevnoteonpitch = 0;
-  mfx->prevnoteontime = time;
-}
-
-//{ "p", "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "h" };
-char notes[] =
-  { 255,  0,   1,   2,    3,   4,    6,   7,    8,   9,   10,  11 ,   12 };
-
-u8 lengths[] =  { 4, 8, 16, 32, 64, 128 };
-
-static void countdefaults(struct NoteInfo * ni, int * length_p, int * scale_p)
-{
-  int lengths[15] = { 0 };
-  int scales[15] = { 0 };
-  int maxlenval = 0; /* (*) */
-  int maxscaleval = 0;
-  int i;
-
-  for (i = 0; i < ni->nrnotes; i++)
-  {
-    struct Notes * note = &ni->note[i];
-
-    lengths[note->length]++;
-    scales[note->scale]++;
-  }
-
-  maxlenval = lengths[0]; /* (*) smart compiler eliminates dead code */
-  *length_p = 0;
-  
-  for (i = 1; i < 15; i++) /* `p' incremented scales[0], therefore ignored */
-  {
-    TRACE(0, ("%d - len: %d, scale: %d\n", i, lengths[i], scales[i]));
-    
-    if (lengths[i] > maxlenval) {
-      *length_p = i;
-      maxlenval = lengths[i];
-    }
-    if (scales[i] > maxscaleval) {
-      *scale_p = i;
-      maxscaleval = scales[i];
-    }
-  }
-}
-
-GSM_Error loadmid(char *filename, GSM_Ringtone *ringtone)
-{
-  int fd;
-  struct NoteInfo * ni;
-  int i;
-  int deflen, defscale;
-
-#ifdef WIN32
-  if ((fd = open(filename, O_RDONLY | O_BINARY)) < 0)
-  {
-    perror("open");
-    return GE_CANTOPENFILE;
-  }
-#else
-  if ((fd = open(filename, O_RDONLY)) < 0)
-  {
-    perror("open");
-    return GE_CANTOPENFILE;
-  }
-#endif
-  
-  ni = readmidi(fd);
-
-  if (ni == NULL)
-    return 0;
-
-  countdefaults(ni, &deflen, &defscale);
-
-  strcpy(ringtone->name,"GNOKII");
-
-  if (ni->nrnotes<MAX_RINGTONE_NOTES)
-    ringtone->NrNotes=ni->nrnotes;
-  else
-    ringtone->NrNotes=MAX_RINGTONE_NOTES;
-    
-  for (i = 0; i < ringtone->NrNotes; i++)
-  {
-    struct Notes * note = &ni->note[i];
-
-    ringtone->notes[i].note=notes[note->note];
-    ringtone->notes[i].note=notes[note->note]+(note->scale%4)*14;    
-    
-    ringtone->notes[i].duration=lengths[note->length];
-    if (note->lextra)
-      ringtone->notes[i].duration=ringtone->notes[i].duration*1.5;
-
-    ringtone->notes[i].tempo=ni->beats;
-
-  }
-
-  ringtone->Loop=15;
-  
-  return 0;
-}