timidity_readmidi.cpp

Go to the documentation of this file.
00001 /*
00002 
00003     TiMidity -- Experimental MIDI to WAVE converter
00004     Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 
00020 */
00021 
00022 #include "pent_include.h"
00023 
00024 #ifdef USE_TIMIDITY_MIDI
00025 
00026 #include <cstdio>
00027 #include <cstdlib>
00028 #include <cstring>
00029 
00030 #ifndef _WIN32_WCE
00031 #include <cerrno>
00032 #else
00033 static int errno = 0;
00034 static char *strerror(int _errno) {
00035         return "";
00036 }
00037 #endif
00038 
00039 #include "timidity.h"
00040 #include "timidity_common.h"
00041 #include "timidity_instrum.h"
00042 #include "timidity_playmidi.h"
00043 #include "timidity_readmidi.h"
00044 #include "timidity_output.h"
00045 #include "timidity_controls.h"
00046 
00047 #ifdef NS_TIMIDITY
00048 namespace NS_TIMIDITY {
00049 #endif
00050 
00051 sint32 quietchannels=0;
00052 
00053 /* to avoid some unnecessary parameter passing */
00054 static MidiEventList *evlist;
00055 static sint32 event_count;
00056 static FILE *fp;
00057 static sint32 at;
00058 
00059 /* These would both fit into 32 bits, but they are often added in
00060    large multiples, so it's simpler to have two roomy ints */
00061 static sint32 sample_increment, sample_correction; /*samples per MIDI delta-t*/
00062 
00063 /* Computes how many (fractional) samples one MIDI delta-time unit contains */
00064 static void compute_sample_increment(sint32 tempo, sint32 divisions)
00065 {
00066   double a;
00067   a = (double) (tempo) * (double) (play_mode->rate) * (65536.0/1000000.0) /
00068     (double)(divisions);
00069 
00070   sample_correction = (sint32)(a) & 0xFFFF;
00071   sample_increment = (sint32)(a) >> 16;
00072 
00073   ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Samples per delta-t: %d (correction %d)",
00074        sample_increment, sample_correction);
00075 }
00076 
00077 /* Read variable-length number (7 bits per byte, MSB first) */
00078 static sint32 getvl(void)
00079 {
00080   sint32 l=0;
00081   uint8 c;
00082   for (;;)
00083     {
00084       fread(&c,1,1,fp);
00085       l += (c & 0x7f);
00086       if (!(c & 0x80)) return l;
00087       l<<=7;
00088     }
00089 }
00090 
00091 /* Print a string from the file, followed by a newline. Any non-ASCII
00092    or unprintable characters will be converted to periods. */
00093 static int dumpstring(sint32 len, char *label)
00094 {
00095   signed char *s=safe_Malloc<signed char>(len+1);
00096   if (len != (sint32)fread(s, 1, len, fp))
00097     {
00098       free(s);
00099       return -1;
00100     }
00101   s[len]='\0';
00102   while (len--)
00103     {
00104       if (s[len]<32)
00105         s[len]='.';
00106     }
00107   ctl->cmsg(CMSG_TEXT, VERB_VERBOSE, "%s%s", label, s);
00108   free(s);
00109   return 0;
00110 }
00111 
00112 #define MIDIEVENT(at,t,ch,pa,pb) \
00113   event=safe_Malloc<MidiEventList>(); \
00114   event->event.time=at; event->event.type=t; event->event.channel=ch; \
00115   event->event.a=pa; event->event.b=pb; event->next=0;\
00116   return event;
00117 
00118 #define MAGIC_EOT ((MidiEventList *)(-1))
00119 
00120 /* Read a MIDI event, returning a freshly allocated element that can
00121    be linked to the event list */
00122 static MidiEventList *read_midi_event(void)
00123 {
00124   static uint8 laststatus, lastchan;
00125   static uint8 nrpn=0, rpn_msb[16], rpn_lsb[16]; /* one per channel */
00126   uint8 me, type, a,b,c;
00127   sint32 len;
00128   MidiEventList *event;
00129 
00130   for (;;)
00131     {
00132       at+=getvl();
00133       if (fread(&me,1,1,fp)!=1)
00134         {
00135           ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: read_midi_event: %s", 
00136                current_filename, strerror(errno));
00137           return 0;
00138         }
00139       
00140       if(me==0xF0 || me == 0xF7) /* SysEx event */
00141         {
00142           len=getvl();
00143           skip(fp, len);
00144         }
00145       else if(me==0xFF) /* Meta event */
00146         {
00147           fread(&type,1,1,fp);
00148           len=getvl();
00149           if (type>0 && type<16)
00150             {
00151               static char *label[]={
00152                 "Text event: ", "Text: ", "Copyright: ", "Track name: ",
00153                 "Instrument: ", "Lyric: ", "Marker: ", "Cue point: "};
00154               dumpstring(len, label[(type>7) ? 0 : type]);
00155             }
00156           else
00157             switch(type)
00158               {
00159               case 0x2F: /* End of Track */
00160                 return MAGIC_EOT;
00161 
00162               case 0x51: /* Tempo */
00163                 fread(&a,1,1,fp); fread(&b,1,1,fp); fread(&c,1,1,fp);
00164                 MIDIEVENT(at, ME_TEMPO, c, a, b);
00165                 
00166               default:
00167                 ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
00168                      "(Meta event type 0x%02x, length %ld)", type, len);
00169                 skip(fp, len);
00170                 break;
00171               }
00172         }
00173       else
00174         {
00175           a=me;
00176           if (a & 0x80) /* status byte */
00177             {
00178               lastchan=a & 0x0F;
00179               laststatus=(a>>4) & 0x07;
00180               fread(&a, 1,1, fp);
00181               a &= 0x7F;
00182             }
00183           switch(laststatus)
00184             {
00185             case 0: /* Note off */
00186               fread(&b, 1,1, fp);
00187               b &= 0x7F;
00188               MIDIEVENT(at, ME_NOTEOFF, lastchan, a,b);
00189 
00190             case 1: /* Note on */
00191               fread(&b, 1,1, fp);
00192               b &= 0x7F;
00193               MIDIEVENT(at, ME_NOTEON, lastchan, a,b);
00194 
00195             case 2: /* Key Pressure */
00196               fread(&b, 1,1, fp);
00197               b &= 0x7F;
00198               MIDIEVENT(at, ME_KEYPRESSURE, lastchan, a, b);
00199 
00200             case 3: /* Control change */
00201               fread(&b, 1,1, fp);
00202               b &= 0x7F;
00203               {
00204                 int control=255;
00205                 switch(a)
00206                   {
00207                   case 7: control=ME_MAINVOLUME; break;
00208                   case 10: control=ME_PAN; break;
00209                   case 11: control=ME_EXPRESSION; break;
00210                   case 64: control=ME_SUSTAIN; break;
00211                   case 120: control=ME_ALL_SOUNDS_OFF; break;
00212                   case 121: control=ME_RESET_CONTROLLERS; break;
00213                   case 123: control=ME_ALL_NOTES_OFF; break;
00214 
00215                     /* These should be the SCC-1 tone bank switch
00216                        commands. I don't know why there are two, or
00217                        why the latter only allows switching to bank 0.
00218                        Also, some MIDI files use 0 as some sort of
00219                        continuous controller. This will cause lots of
00220                        warnings about undefined tone banks. */
00221                   case 0: control=ME_TONE_BANK; break;
00222                   case 32: 
00223                     if (b!=0)
00224                       ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
00225                                 "(Strange: tone bank change 0x20%02x)", b);
00226                     else
00227                       control=ME_TONE_BANK;
00228                     break;
00229 
00230                   case 100: nrpn=0; rpn_msb[lastchan]=b; break;
00231                   case 101: nrpn=0; rpn_lsb[lastchan]=b; break;
00232                   case 99: nrpn=1; rpn_msb[lastchan]=b; break;
00233                   case 98: nrpn=1; rpn_lsb[lastchan]=b; break;
00234                     
00235                   case 6:
00236                     if (nrpn)
00237                       {
00238                         ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
00239                                   "(Data entry (MSB) for NRPN %02x,%02x: %ld)",
00240                                   rpn_msb[lastchan], rpn_lsb[lastchan],
00241                                   b);
00242                         break;
00243                       }
00244                     
00245                     switch((rpn_msb[lastchan]<<8) | rpn_lsb[lastchan])
00246                       {
00247                       case 0x0000: /* Pitch bend sensitivity */
00248                         control=ME_PITCH_SENS;
00249                         break;
00250 
00251                       case 0x7F7F: /* RPN reset */
00252                         /* reset pitch bend sensitivity to 2 */
00253                         MIDIEVENT(at, ME_PITCH_SENS, lastchan, 2, 0);
00254 
00255                       default:
00256                         ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
00257                                   "(Data entry (MSB) for RPN %02x,%02x: %ld)",
00258                                   rpn_msb[lastchan], rpn_lsb[lastchan],
00259                                   b);
00260                         break;
00261                       }
00262                     break;
00263                     
00264                   default:
00265                     ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
00266                               "(Control %d: %d)", a, b);
00267                     break;
00268                   }
00269                 if (control != 255)
00270                   { 
00271                     MIDIEVENT(at, control, lastchan, b, 0); 
00272                   }
00273               }
00274               break;
00275 
00276             case 4: /* Program change */
00277               a &= 0x7f;
00278               MIDIEVENT(at, ME_PROGRAM, lastchan, a, 0);
00279 
00280             case 5: /* Channel pressure - NOT IMPLEMENTED */
00281               break;
00282 
00283             case 6: /* Pitch wheel */
00284               fread(&b, 1,1, fp);
00285               b &= 0x7F;
00286               MIDIEVENT(at, ME_PITCHWHEEL, lastchan, a, b);
00287 
00288             default: 
00289               ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00290                    "*** Can't happen: status 0x%02X, channel 0x%02X",
00291                    laststatus, lastchan);
00292               break;
00293             }
00294         }
00295     }
00296   
00297   return event;
00298 }
00299 
00300 #undef MIDIEVENT
00301 
00302 /* Read a midi track into the linked list, either merging with any previous
00303    tracks or appending to them. */
00304 static int read_track(int append)
00305 {
00306   MidiEventList *meep;
00307   MidiEventList *next, *new_event;
00308   sint32 len;
00309   char tmp[4];
00310 
00311   meep=evlist;
00312   if (append && meep)
00313     {
00314       /* find the last event in the list */
00315       for (; meep->next; meep=meep->next)
00316         ;
00317       at=meep->event.time;
00318     }
00319   else
00320     at=0;
00321 
00322   /* Check the formalities */
00323   
00324   if ((fread(tmp,1,4,fp) != 4) || (fread(&len,4,1,fp) != 1))
00325     {
00326       ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00327            "%s: Can't read track header.", current_filename);
00328       return -1;
00329     }
00330   len=BE_LONG(len);
00331   if (memcmp(tmp, "MTrk", 4))
00332     {
00333       ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00334            "%s: Corrupt MIDI file.", current_filename);
00335       return -2;
00336     }
00337 
00338   for (;;)
00339     {
00340       if (!(new_event=read_midi_event())) /* Some kind of error  */
00341         return -2;
00342 
00343       if (new_event==MAGIC_EOT) /* End-of-track Hack. */
00344         {
00345           return 0;
00346         }
00347 
00348       next=meep->next;
00349       while (next && (next->event.time < new_event->event.time))
00350         {
00351           meep=next;
00352           next=meep->next;
00353         }
00354           
00355       new_event->next=next;
00356       meep->next=new_event;
00357 
00358       event_count++; /* Count the event. (About one?) */
00359       meep=new_event;
00360     }
00361 }
00362 
00363 /* Free the linked event list from memory. */
00364 static void free_midi_list(void)
00365 {
00366   MidiEventList *meep, *next;
00367   if (!(meep=evlist)) return;
00368   while (meep)
00369     {
00370       next=meep->next;
00371       free(meep);
00372       meep=next;
00373     }
00374   evlist=0;
00375 }
00376 
00377 /* Allocate an array of MidiEvents and fill it from the linked list of
00378    events, marking used instruments for loading. Convert event times to
00379    samples: handle tempo changes. Strip unnecessary events from the list.
00380    Free the linked list. */
00381 static MidiEvent *groom_list(sint32 divisions,sint32 *eventsp,sint32 *samplesp)
00382 {
00383   MidiEvent *groomed_list, *lp;
00384   MidiEventList *meep;
00385   sint32 i, our_event_count, tempo, skip_this_event, new_value;
00386   sint32 sample_cum, samples_to_do, at, st, dt, counting_time;
00387 
00388   int current_bank[16], current_set[16], current_program[16]; 
00389   /* Or should each bank have its own current program? */
00390 
00391   for (i=0; i<16; i++)
00392     {
00393       current_bank[i]=0;
00394       current_set[i]=0;
00395       current_program[i]=default_program;
00396     }
00397 
00398   tempo=500000;
00399   compute_sample_increment(tempo, divisions);
00400 
00401   /* This may allocate a bit more than we need */
00402   groomed_list=lp=safe_Malloc<MidiEvent>(event_count+1);
00403   meep=evlist;
00404 
00405   our_event_count=0;
00406   st=at=sample_cum=0;
00407   counting_time=2; /* We strip any silence before the first NOTE ON. */
00408 
00409   for (i=0; i<event_count; i++)
00410     {
00411       skip_this_event=0;
00412       ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY,
00413                 "%6d: ch %2d: event %d (%d,%d)",
00414                 meep->event.time, meep->event.channel + 1,
00415                 meep->event.type, meep->event.a, meep->event.b);
00416 
00417       if (meep->event.type==ME_TEMPO)
00418         {
00419           tempo=
00420             meep->event.channel + meep->event.b * 256 + meep->event.a * 65536;
00421           compute_sample_increment(tempo, divisions);
00422           skip_this_event=1;
00423         }
00424       else if ((quietchannels & (1<<meep->event.channel)))
00425         skip_this_event=1;
00426       else switch (meep->event.type)
00427         {
00428         case ME_PROGRAM:
00429           if (ISDRUMCHANNEL(meep->event.channel))
00430             {
00431               if (drumset[meep->event.a]) /* Is this a defined drumset? */
00432                 new_value=meep->event.a;
00433               else
00434                 {
00435                   ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
00436                        "Drum set %d is undefined", meep->event.a);
00437                   new_value=meep->event.a=0;
00438                 }
00439               if (current_set[meep->event.channel] != new_value)
00440                 current_set[meep->event.channel]=new_value;
00441               else 
00442                 skip_this_event=1;
00443             }
00444           else
00445             {
00446               new_value=meep->event.a;
00447               if ((current_program[meep->event.channel] != SPECIAL_PROGRAM)
00448                   && (current_program[meep->event.channel] != new_value))
00449                 current_program[meep->event.channel] = new_value;
00450               else
00451                 skip_this_event=1;
00452             }
00453           break;
00454 
00455         case ME_NOTEON:
00456           if (counting_time)
00457             counting_time=1;
00458           if (ISDRUMCHANNEL(meep->event.channel))
00459             {
00460               /* Mark this instrument to be loaded */
00461               if (!(drumset[current_set[meep->event.channel]]
00462                     ->tone[meep->event.a].instrument))
00463                 drumset[current_set[meep->event.channel]]
00464                   ->tone[meep->event.a].instrument=
00465                     MAGIC_LOAD_INSTRUMENT;
00466             }
00467           else
00468             {
00469               if (current_program[meep->event.channel]==SPECIAL_PROGRAM)
00470                 break;
00471               /* Mark this instrument to be loaded */
00472               if (!(tonebank[current_bank[meep->event.channel]]
00473                     ->tone[current_program[meep->event.channel]].instrument))
00474                 tonebank[current_bank[meep->event.channel]]
00475                   ->tone[current_program[meep->event.channel]].instrument=
00476                     MAGIC_LOAD_INSTRUMENT;
00477             }
00478           break;
00479 
00480         case ME_TONE_BANK:
00481           if (ISDRUMCHANNEL(meep->event.channel))
00482             {
00483               skip_this_event=1;
00484               break;
00485             }
00486           if (tonebank[meep->event.a]) /* Is this a defined tone bank? */
00487             new_value=meep->event.a;
00488           else 
00489             {
00490               ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
00491                    "Tone bank %d is undefined", meep->event.a);
00492               new_value=meep->event.a=0;
00493             }
00494           if (current_bank[meep->event.channel]!=new_value)
00495             current_bank[meep->event.channel]=new_value;
00496           else
00497             skip_this_event=1;
00498           break;
00499         }
00500 
00501       /* Recompute time in samples*/
00502       if ((dt=meep->event.time - at) && !counting_time)
00503         {
00504           samples_to_do=sample_increment * dt;
00505           sample_cum += sample_correction * dt;
00506           if (sample_cum & 0xFFFF0000)
00507             {
00508               samples_to_do += ((sample_cum >> 16) & 0xFFFF);
00509               sample_cum &= 0x0000FFFF;
00510             }
00511           st += samples_to_do;
00512         }
00513       else if (counting_time==1) counting_time=0;
00514       if (!skip_this_event)
00515         {
00516           /* Add the event to the list */
00517           *lp=meep->event;
00518           lp->time=st;
00519           lp++;
00520           our_event_count++;
00521         }
00522       at=meep->event.time;
00523       meep=meep->next;
00524     }
00525   /* Add an End-of-Track event */
00526   lp->time=st;
00527   lp->type=ME_EOT;
00528   our_event_count++;
00529   free_midi_list();
00530   
00531   *eventsp=our_event_count;
00532   *samplesp=st;
00533   return groomed_list;
00534 }
00535 
00536 MidiEvent *read_midi_file(FILE *mfp, sint32 *count, sint32 *sp)
00537 {
00538   sint32 len, divisions;
00539   sint16 format, tracks, divisions_tmp;
00540   int i;
00541   char tmp[4];
00542 
00543   fp=mfp;
00544   event_count=0;
00545   at=0;
00546   evlist=0;
00547 
00548   if ((fread(tmp,1,4,fp) != 4) || (fread(&len,4,1,fp) != 1))
00549     {
00550       if (ferror(fp))
00551         {
00552           ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", current_filename, 
00553                strerror(errno));
00554         }
00555       else
00556         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00557              "%s: Not a MIDI file!", current_filename);
00558       return 0;
00559     }
00560   len=BE_LONG(len);
00561   if (memcmp(tmp, "MThd", 4) || len < 6)
00562     {
00563       ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00564            "%s: Not a MIDI file!", current_filename);
00565       return 0;
00566     }
00567 
00568   fread(&format, 2, 1, fp);
00569   fread(&tracks, 2, 1, fp);
00570   fread(&divisions_tmp, 2, 1, fp);
00571   format=BE_SHORT(format);
00572   tracks=BE_SHORT(tracks);
00573   divisions_tmp=BE_SHORT(divisions_tmp);
00574 
00575   if (divisions_tmp<0)
00576     {
00577       /* SMPTE time -- totally untested. Got a MIDI file that uses this? */
00578       divisions=
00579         (sint32)(-(divisions_tmp/256)) * (sint32)(divisions_tmp & 0xFF);
00580     }
00581   else divisions=(sint32)(divisions_tmp);
00582 
00583   if (len > 6)
00584     {
00585       ctl->cmsg(CMSG_WARNING, VERB_NORMAL, 
00586            "%s: MIDI file header size %ld bytes", 
00587            current_filename, len);
00588       skip(fp, len-6); /* skip the excess */
00589     }
00590   if (format<0 || format >2)
00591     {
00592       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00593            "%s: Unknown MIDI file format %d", current_filename, format);
00594       return 0;
00595     }
00596   ctl->cmsg(CMSG_INFO, VERB_VERBOSE, 
00597        "Format: %d  Tracks: %d  Divisions: %d", format, tracks, divisions);
00598 
00599   /* Put a do-nothing event first in the list for easier processing */
00600   evlist=safe_Malloc<MidiEventList>();
00601   evlist->event.time=0;
00602   evlist->event.type=ME_NONE;
00603   evlist->next=0;
00604   event_count++;
00605 
00606   switch(format)
00607     {
00608     case 0:
00609       if (read_track(0))
00610         {
00611           free_midi_list();
00612           return 0;
00613         }
00614       break;
00615 
00616     case 1:
00617       for (i=0; i<tracks; i++)
00618         if (read_track(0))
00619           {
00620             free_midi_list();
00621             return 0;
00622           }
00623       break;
00624 
00625     case 2: /* We simply play the tracks sequentially */
00626       for (i=0; i<tracks; i++)
00627         if (read_track(1))
00628           {
00629             free_midi_list();
00630             return 0;
00631           }
00632       break;
00633     }
00634   return groom_list(divisions, count, sp);
00635 }
00636 
00637 #ifdef NS_TIMIDITY
00638 };
00639 #endif
00640 
00641 #endif //USE_TIMIDITY_MIDI

Generated on Fri Jul 27 22:27:44 2007 for pentagram by  doxygen 1.4.7