timidity/timidity.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 12 Oct 2009 05:39:13 +0000
changeset 449 3f60c121d643
parent 437 cd21b80e524f
child 450 9d5e6ab8ddfc
permissions -rw-r--r--
Use PATH_MAX if possible, instead of arbitrarily-sized buffers.

Fixes Bugzilla #840.
     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 "ctrlmode.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 resample_t *resample_buffer=NULL;
    43 int32 *common_buffer=NULL;
    44 int num_ochannels;
    45 
    46 #define MAXWORDS 10
    47 
    48 static int read_config_file(const char *name)
    49 {
    50   FILE *fp;
    51   char tmp[PATH_MAX], *w[MAXWORDS], *cp;
    52   ToneBank *bank=0;
    53   int i, j, k, line=0, words;
    54   static int rcf_count=0;
    55 
    56   if (rcf_count>50)
    57    {
    58     ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
    59       "Probable source loop in configuration files");
    60     return (-1);
    61    }
    62 
    63   if (!(fp=open_file(name, 1, OF_VERBOSE)))
    64    return -1;
    65 
    66   while (fgets(tmp, sizeof(tmp), fp))
    67   {
    68     line++;
    69     w[words=0]=strtok(tmp, " \t\r\n\240");
    70     if (!w[0] || (*w[0]=='#')) continue;
    71     while (w[words] && (words < MAXWORDS))
    72       {
    73         w[++words]=strtok(0," \t\r\n\240");
    74         if (w[words] && w[words][0]=='#') break;
    75       }
    76     if (!strcmp(w[0], "map")) continue;
    77     if (!strcmp(w[0], "dir"))
    78     {
    79       if (words < 2)
    80        {
    81         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
    82           "%s: line %d: No directory given\n", name, line);
    83         return -2;
    84        }
    85       for (i=1; i<words; i++)
    86         add_to_pathlist(w[i]);
    87     }
    88   else if (!strcmp(w[0], "source"))
    89   {
    90     if (words < 2)
    91       {
    92         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
    93           "%s: line %d: No file name given\n", name, line);
    94         return -2;
    95      }
    96     for (i=1; i<words; i++)
    97       {
    98         rcf_count++;
    99       read_config_file(w[i]);
   100         rcf_count--;
   101       }
   102   }
   103       else if (!strcmp(w[0], "default"))
   104   {
   105     if (words != 2)
   106       {
   107         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   108         "%s: line %d: Must specify exactly one patch name\n",
   109           name, line);
   110         return -2;
   111       }
   112     strncpy(def_instr_name, w[1], 255);
   113     def_instr_name[255]='\0';
   114   }
   115     else if (!strcmp(w[0], "drumset"))
   116   {
   117     if (words < 2)
   118       {
   119         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   120           "%s: line %d: No drum set number given\n", 
   121           name, line);
   122       return -2;
   123       }
   124     i=atoi(w[1]);
   125     if (i<0 || i>127)
   126      {
   127         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   128           "%s: line %d: Drum set must be between 0 and 127\n",
   129         name, line);
   130         return -2;
   131      }
   132     if (!drumset[i])
   133       {
   134         drumset[i]=safe_malloc(sizeof(ToneBank));
   135       memset(drumset[i], 0, sizeof(ToneBank));
   136      }
   137     bank=drumset[i];
   138   }
   139     else if (!strcmp(w[0], "bank"))
   140   {
   141     if (words < 2)
   142      {
   143         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   144           "%s: line %d: No bank number given\n", 
   145         name, line);
   146         return -2;
   147      }
   148     i=atoi(w[1]);
   149     if (i<0 || i>127)
   150       {
   151         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   152           "%s: line %d: Tone bank must be between 0 and 127\n",
   153         name, line);
   154         return -2;
   155       }
   156     if (!tonebank[i])
   157      {
   158       tonebank[i]=safe_malloc(sizeof(ToneBank));
   159         memset(tonebank[i], 0, sizeof(ToneBank));
   160       }
   161     bank=tonebank[i];
   162   }
   163       else {
   164   if ((words < 2) || (*w[0] < '0' || *w[0] > '9'))
   165     {
   166      ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   167         "%s: line %d: syntax error\n", name, line);
   168      return -2;
   169     }
   170   i=atoi(w[0]);
   171   if (i<0 || i>127)
   172     {
   173       ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   174         "%s: line %d: Program must be between 0 and 127\n",
   175         name, line);
   176       return -2;
   177     }
   178   if (!bank)
   179     {
   180       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   181        "%s: line %d: Must specify tone bank or drum set "
   182         "before assignment\n",
   183         name, line);
   184      return -2;
   185     }
   186   if (bank->tone[i].name)
   187     free(bank->tone[i].name);
   188   strcpy((bank->tone[i].name=safe_malloc(strlen(w[1])+1)),w[1]);
   189   bank->tone[i].note=bank->tone[i].amp=bank->tone[i].pan=
   190     bank->tone[i].strip_loop=bank->tone[i].strip_envelope=
   191       bank->tone[i].strip_tail=-1;
   192 
   193   for (j=2; j<words; j++)
   194     {
   195       if (!(cp=strchr(w[j], '=')))
   196         {
   197     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
   198       name, line, w[j]);
   199     return -2;
   200         }
   201       *cp++=0;
   202       if (!strcmp(w[j], "amp"))
   203       {
   204     k=atoi(cp);
   205     if ((k<0 || k>MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
   206       {
   207        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   208           "%s: line %d: amplification must be between "
   209          "0 and %d\n", name, line, MAX_AMPLIFICATION);
   210        return -2;
   211       }
   212     bank->tone[i].amp=k;
   213         }
   214       else if (!strcmp(w[j], "note"))
   215         {
   216     k=atoi(cp);
   217     if ((k<0 || k>127) || (*cp < '0' || *cp > '9'))
   218       {
   219        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   220          "%s: line %d: note must be between 0 and 127\n",
   221           name, line);
   222         return -2;
   223       }
   224     bank->tone[i].note=k;
   225       }
   226      else if (!strcmp(w[j], "pan"))
   227       {
   228     if (!strcmp(cp, "center"))
   229       k=64;
   230     else if (!strcmp(cp, "left"))
   231       k=0;
   232     else if (!strcmp(cp, "right"))
   233       k=127;
   234     else
   235       k=((atoi(cp)+100) * 100) / 157;
   236     if ((k<0 || k>127) ||
   237        (k==0 && *cp!='-' && (*cp < '0' || *cp > '9')))
   238       {
   239        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   240          "%s: line %d: panning must be left, right, "
   241          "center, or between -100 and 100\n",
   242          name, line);
   243        return -2;
   244       }
   245     bank->tone[i].pan=k;
   246       }
   247      else if (!strcmp(w[j], "keep"))
   248       {
   249     if (!strcmp(cp, "env"))
   250       bank->tone[i].strip_envelope=0;
   251     else if (!strcmp(cp, "loop"))
   252       bank->tone[i].strip_loop=0;
   253     else
   254       {
   255         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   256           "%s: line %d: keep must be env or loop\n", name, line);
   257        return -2;
   258       }
   259       }
   260      else if (!strcmp(w[j], "strip"))
   261       {
   262     if (!strcmp(cp, "env"))
   263       bank->tone[i].strip_envelope=1;
   264     else if (!strcmp(cp, "loop"))
   265       bank->tone[i].strip_loop=1;
   266     else if (!strcmp(cp, "tail"))
   267       bank->tone[i].strip_tail=1;
   268     else
   269       {
   270        ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   271          "%s: line %d: strip must be env, loop, or tail\n",
   272          name, line);
   273        return -2;
   274       }
   275       }
   276      else
   277       {
   278     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
   279       name, line, w[j]);
   280     return -2;
   281       }
   282     }
   283     }
   284    }
   285   if (ferror(fp))
   286    {
   287     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't read from %s\n", name);
   288     close_file(fp);
   289     return -2;
   290    }
   291   close_file(fp);
   292   return 0;
   293 }
   294 
   295 int Timidity_Init(int rate, int format, int channels, int samples)
   296 {
   297   const char *env = getenv("TIMIDITY_CFG");
   298   if (!env || read_config_file(env)<0) {
   299     if (read_config_file(CONFIG_FILE)<0) {
   300       if (read_config_file(CONFIG_FILE_ETC)<0) {
   301         return(-1);
   302       }
   303     }
   304   }
   305 
   306   if (channels < 1 || channels == 3 || channels == 5 || channels > 6) return(-1);
   307 
   308   num_ochannels = channels;
   309 
   310   /* Set play mode parameters */
   311   play_mode->rate = rate;
   312   play_mode->encoding = 0;
   313   if ( (format&0xFF) == 16 ) {
   314     play_mode->encoding |= PE_16BIT;
   315   }
   316   if ( (format&0x8000) ) {
   317     play_mode->encoding |= PE_SIGNED;
   318   }
   319   if ( channels == 1 ) {
   320     play_mode->encoding |= PE_MONO;
   321   } 
   322   switch (format) {
   323     case AUDIO_S8:
   324       s32tobuf = s32tos8;
   325       break;
   326     case AUDIO_U8:
   327       s32tobuf = s32tou8;
   328       break;
   329     case AUDIO_S16LSB:
   330       s32tobuf = s32tos16l;
   331       break;
   332     case AUDIO_S16MSB:
   333       s32tobuf = s32tos16b;
   334       break;
   335     case AUDIO_U16LSB:
   336       s32tobuf = s32tou16l;
   337       break;
   338     case AUDIO_U16MSB:
   339       s32tobuf = s32tou16b;
   340       break;
   341     default:
   342       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Unsupported audio format");
   343       return(-1);
   344   }
   345   AUDIO_BUFFER_SIZE = samples;
   346 
   347   /* Allocate memory for mixing (WARNING:  Memory leak!) */
   348   resample_buffer = safe_malloc(AUDIO_BUFFER_SIZE*sizeof(resample_t)+100);
   349   common_buffer = safe_malloc(AUDIO_BUFFER_SIZE*num_ochannels*sizeof(int32));
   350 
   351   init_tables();
   352 
   353   if (ctl->open(0, 0)) {
   354     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Couldn't open %s\n", ctl->id_name);
   355     return(-1);
   356   }
   357 
   358   if (!control_ratio) {
   359     control_ratio = play_mode->rate / CONTROLS_PER_SECOND;
   360     if(control_ratio<1)
   361       control_ratio=1;
   362     else if (control_ratio > MAX_CONTROL_RATIO)
   363       control_ratio=MAX_CONTROL_RATIO;
   364   }
   365   if (*def_instr_name)
   366     set_default_instrument(def_instr_name);
   367   return(0);
   368 }
   369 
   370 char timidity_error[1024] = "";
   371 const char *Timidity_Error(void)
   372 {
   373   return(timidity_error);
   374 }