timidity/timidity.c
author Sam Lantinga <slouken@lokigames.com>
Tue, 21 Dec 1999 17:13:05 +0000
changeset 24 a25bb2d59ce8
parent 0 4ce2db4db959
child 245 63b3650714de
permissions -rw-r--r--
Updated for SDL 1.0.1
     1 /*
     2 
     3     TiMidity -- Experimental MIDI to WAVE converter
     4     Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
     5 
     6 	 This program is free software; you can redistribute it and/or modify
     7 	 it under the terms of the GNU General Public License as published by
     8     the Free Software Foundation; either version 2 of the License, or
     9 	 (at your option) any later version.
    10 
    11     This program is distributed in the hope that it will be useful,
    12     but WITHOUT ANY WARRANTY; without even the implied warranty of
    13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 	 GNU General Public License for more details.
    15 
    16     You should have received a copy of the GNU General Public License
    17     along with this program; if not, write to the Free Software
    18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    19 
    20 */
    21 #include <stdio.h>
    22 #include <stdlib.h>
    23 #include <string.h>
    24 
    25 #include "SDL.h"
    26 #include "config.h"
    27 #include "common.h"
    28 #include "instrum.h"
    29 #include "playmidi.h"
    30 #include "readmidi.h"
    31 #include "output.h"
    32 #include "controls.h"
    33 #include "timidity.h"
    34 
    35 #include "tables.h"
    36 
    37 void (*s32tobuf)(void *dp, int32 *lp, int32 c);
    38 int free_instruments_afterwards=0;
    39 static char def_instr_name[256]="";
    40 
    41 int AUDIO_BUFFER_SIZE;
    42 sample_t *resample_buffer;
    43 int32 *common_buffer;
    44 
    45 #define MAXWORDS 10
    46 
    47 static int read_config_file(char *name)
    48 {
    49   FILE *fp;
    50   char tmp[1024], *w[MAXWORDS], *cp;
    51   ToneBank *bank=0;
    52   int i, j, k, line=0, words;
    53   static int rcf_count=0;
    54 
    55   if (rcf_count>50)
    56    {
    57     ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
    58       "Probable source loop in configuration files");
    59     return (-1);
    60    }
    61 
    62   if (!(fp=open_file(name, 1, OF_VERBOSE)))
    63    return -1;
    64 
    65   while (fgets(tmp, sizeof(tmp), fp))
    66    {
    67       line++;
    68     w[words=0]=strtok(tmp, " \t\r\n\240");
    69     if (!w[0] || (*w[0]=='#')) continue;
    70       while (w[words] && (words < MAXWORDS))
    71   w[++words]=strtok(0," \t\r\n\240");
    72       if (!strcmp(w[0], "dir"))
    73   {
    74     if (words < 2)
    75      {
    76         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
    77           "%s: line %d: No directory given\n", name, line);
    78         return -2;
    79      }
    80     for (i=1; i<words; i++)
    81       add_to_pathlist(w[i]);
    82   }
    83     else if (!strcmp(w[0], "source"))
    84   {
    85     if (words < 2)
    86       {
    87         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
    88           "%s: line %d: No file name given\n", name, line);
    89         return -2;
    90      }
    91     for (i=1; i<words; i++)
    92       {
    93         rcf_count++;
    94       read_config_file(w[i]);
    95         rcf_count--;
    96       }
    97   }
    98       else if (!strcmp(w[0], "default"))
    99   {
   100     if (words != 2)
   101       {
   102         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   103         "%s: line %d: Must specify exactly one patch name\n",
   104           name, line);
   105         return -2;
   106       }
   107     strncpy(def_instr_name, w[1], 255);
   108     def_instr_name[255]='\0';
   109   }
   110     else if (!strcmp(w[0], "drumset"))
   111   {
   112     if (words < 2)
   113       {
   114         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   115           "%s: line %d: No drum set number given\n", 
   116           name, line);
   117       return -2;
   118       }
   119     i=atoi(w[1]);
   120     if (i<0 || i>127)
   121      {
   122         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   123           "%s: line %d: Drum set must be between 0 and 127\n",
   124         name, line);
   125         return -2;
   126      }
   127     if (!drumset[i])
   128       {
   129         drumset[i]=safe_malloc(sizeof(ToneBank));
   130       memset(drumset[i], 0, sizeof(ToneBank));
   131      }
   132     bank=drumset[i];
   133   }
   134     else if (!strcmp(w[0], "bank"))
   135   {
   136     if (words < 2)
   137      {
   138         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   139           "%s: line %d: No bank number given\n", 
   140         name, line);
   141         return -2;
   142      }
   143     i=atoi(w[1]);
   144     if (i<0 || i>127)
   145       {
   146         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   147           "%s: line %d: Tone bank must be between 0 and 127\n",
   148         name, line);
   149         return -2;
   150       }
   151     if (!tonebank[i])
   152      {
   153       tonebank[i]=safe_malloc(sizeof(ToneBank));
   154         memset(tonebank[i], 0, sizeof(ToneBank));
   155       }
   156     bank=tonebank[i];
   157   }
   158       else {
   159   if ((words < 2) || (*w[0] < '0' || *w[0] > '9'))
   160     {
   161      ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   162         "%s: line %d: syntax error\n", name, line);
   163      return -2;
   164     }
   165   i=atoi(w[0]);
   166   if (i<0 || i>127)
   167     {
   168       ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   169         "%s: line %d: Program must be between 0 and 127\n",
   170         name, line);
   171       return -2;
   172     }
   173   if (!bank)
   174     {
   175       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   176        "%s: line %d: Must specify tone bank or drum set "
   177         "before assignment\n",
   178         name, line);
   179      return -2;
   180     }
   181   if (bank->tone[i].name)
   182     free(bank->tone[i].name);
   183   strcpy((bank->tone[i].name=safe_malloc(strlen(w[1])+1)),w[1]);
   184   bank->tone[i].note=bank->tone[i].amp=bank->tone[i].pan=
   185     bank->tone[i].strip_loop=bank->tone[i].strip_envelope=
   186       bank->tone[i].strip_tail=-1;
   187 
   188   for (j=2; j<words; j++)
   189     {
   190       if (!(cp=strchr(w[j], '=')))
   191         {
   192     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
   193       name, line, w[j]);
   194     return -2;
   195         }
   196       *cp++=0;
   197       if (!strcmp(w[j], "amp"))
   198       {
   199     k=atoi(cp);
   200     if ((k<0 || k>MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
   201       {
   202        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   203           "%s: line %d: amplification must be between "
   204          "0 and %d\n", name, line, MAX_AMPLIFICATION);
   205        return -2;
   206       }
   207     bank->tone[i].amp=k;
   208         }
   209       else if (!strcmp(w[j], "note"))
   210         {
   211     k=atoi(cp);
   212     if ((k<0 || k>127) || (*cp < '0' || *cp > '9'))
   213       {
   214        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   215          "%s: line %d: note must be between 0 and 127\n",
   216           name, line);
   217         return -2;
   218       }
   219     bank->tone[i].note=k;
   220       }
   221      else if (!strcmp(w[j], "pan"))
   222       {
   223     if (!strcmp(cp, "center"))
   224       k=64;
   225     else if (!strcmp(cp, "left"))
   226       k=0;
   227     else if (!strcmp(cp, "right"))
   228       k=127;
   229     else
   230       k=((atoi(cp)+100) * 100) / 157;
   231     if ((k<0 || k>127) ||
   232        (k==0 && *cp!='-' && (*cp < '0' || *cp > '9')))
   233       {
   234        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   235          "%s: line %d: panning must be left, right, "
   236          "center, or between -100 and 100\n",
   237          name, line);
   238        return -2;
   239       }
   240     bank->tone[i].pan=k;
   241       }
   242      else if (!strcmp(w[j], "keep"))
   243       {
   244     if (!strcmp(cp, "env"))
   245       bank->tone[i].strip_envelope=0;
   246     else if (!strcmp(cp, "loop"))
   247       bank->tone[i].strip_loop=0;
   248     else
   249       {
   250         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   251           "%s: line %d: keep must be env or loop\n", name, line);
   252        return -2;
   253       }
   254       }
   255      else if (!strcmp(w[j], "strip"))
   256       {
   257     if (!strcmp(cp, "env"))
   258       bank->tone[i].strip_envelope=1;
   259     else if (!strcmp(cp, "loop"))
   260       bank->tone[i].strip_loop=1;
   261     else if (!strcmp(cp, "tail"))
   262       bank->tone[i].strip_tail=1;
   263     else
   264       {
   265        ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   266          "%s: line %d: strip must be env, loop, or tail\n",
   267          name, line);
   268        return -2;
   269       }
   270       }
   271      else
   272       {
   273     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
   274       name, line, w[j]);
   275     return -2;
   276       }
   277     }
   278     }
   279    }
   280   if (ferror(fp))
   281    {
   282     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't read from %s\n", name);
   283     close_file(fp);
   284     return -2;
   285    }
   286   close_file(fp);
   287   return 0;
   288 }
   289 
   290 int Timidity_Init(int rate, int format, int channels, int samples)
   291 {
   292   if (read_config_file(CONFIG_FILE)<0) {
   293     return(-1);
   294   }
   295 
   296   /* Set play mode parameters */
   297   play_mode->rate = rate;
   298   play_mode->encoding = 0;
   299   if ( (format&0xFF) == 16 ) {
   300     play_mode->encoding |= PE_16BIT;
   301   }
   302   if ( (format&0x8000) ) {
   303     play_mode->encoding |= PE_SIGNED;
   304   }
   305   if ( channels == 1 ) {
   306     play_mode->encoding |= PE_MONO;
   307   } 
   308   switch (format) {
   309     case AUDIO_S8:
   310       s32tobuf = s32tos8;
   311       break;
   312     case AUDIO_U8:
   313       s32tobuf = s32tou8;
   314       break;
   315     case AUDIO_S16LSB:
   316       s32tobuf = s32tos16l;
   317       break;
   318     case AUDIO_S16MSB:
   319       s32tobuf = s32tos16b;
   320       break;
   321     case AUDIO_U16LSB:
   322       s32tobuf = s32tou16l;
   323       break;
   324     case AUDIO_U16MSB:
   325       s32tobuf = s32tou16b;
   326       break;
   327     default:
   328       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Unsupported audio format");
   329       return(-1);
   330   }
   331   AUDIO_BUFFER_SIZE = samples;
   332 
   333   /* Allocate memory for mixing (WARNING:  Memory leak!) */
   334   resample_buffer = safe_malloc(AUDIO_BUFFER_SIZE*sizeof(sample_t));
   335   common_buffer = safe_malloc(AUDIO_BUFFER_SIZE*2*sizeof(int32));
   336 
   337   init_tables();
   338 
   339   if (ctl->open(0, 0)) {
   340     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Couldn't open %s\n", ctl->id_name);
   341     return(-1);
   342   }
   343 
   344   if (!control_ratio) {
   345     control_ratio = play_mode->rate / CONTROLS_PER_SECOND;
   346     if(control_ratio<1)
   347       control_ratio=1;
   348     else if (control_ratio > MAX_CONTROL_RATIO)
   349       control_ratio=MAX_CONTROL_RATIO;
   350   }
   351   if (*def_instr_name)
   352     set_default_instrument(def_instr_name);
   353   return(0);
   354 }
   355 
   356 char timidity_error[1024] = "";
   357 char *Timidity_Error(void)
   358 {
   359   return(timidity_error);
   360 }