timidity/timidity.c
changeset 0 4ce2db4db959
child 24 a25bb2d59ce8
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/timidity/timidity.c	Thu Oct 21 18:02:08 1999 +0000
     1.3 @@ -0,0 +1,360 @@
     1.4 +/*
     1.5 +
     1.6 +    TiMidity -- Experimental MIDI to WAVE converter
     1.7 +    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
     1.8 +
     1.9 +	 This program is free software; you can redistribute it and/or modify
    1.10 +	 it under the terms of the GNU General Public License as published by
    1.11 +    the Free Software Foundation; either version 2 of the License, or
    1.12 +	 (at your option) any later version.
    1.13 +
    1.14 +    This program is distributed in the hope that it will be useful,
    1.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.17 +	 GNU General Public License for more details.
    1.18 +
    1.19 +    You should have received a copy of the GNU General Public License
    1.20 +    along with this program; if not, write to the Free Software
    1.21 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    1.22 +
    1.23 +*/
    1.24 +#include <stdio.h>
    1.25 +#include <stdlib.h>
    1.26 +#include <string.h>
    1.27 +
    1.28 +#include <SDL/SDL.h>
    1.29 +#include "config.h"
    1.30 +#include "common.h"
    1.31 +#include "instrum.h"
    1.32 +#include "playmidi.h"
    1.33 +#include "readmidi.h"
    1.34 +#include "output.h"
    1.35 +#include "controls.h"
    1.36 +#include "timidity.h"
    1.37 +
    1.38 +#include "tables.h"
    1.39 +
    1.40 +void (*s32tobuf)(void *dp, int32 *lp, int32 c);
    1.41 +int free_instruments_afterwards=0;
    1.42 +static char def_instr_name[256]="";
    1.43 +
    1.44 +int AUDIO_BUFFER_SIZE;
    1.45 +sample_t *resample_buffer;
    1.46 +int32 *common_buffer;
    1.47 +
    1.48 +#define MAXWORDS 10
    1.49 +
    1.50 +static int read_config_file(char *name)
    1.51 +{
    1.52 +  FILE *fp;
    1.53 +  char tmp[1024], *w[MAXWORDS], *cp;
    1.54 +  ToneBank *bank=0;
    1.55 +  int i, j, k, line=0, words;
    1.56 +  static int rcf_count=0;
    1.57 +
    1.58 +  if (rcf_count>50)
    1.59 +   {
    1.60 +    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
    1.61 +      "Probable source loop in configuration files");
    1.62 +    return (-1);
    1.63 +   }
    1.64 +
    1.65 +  if (!(fp=open_file(name, 1, OF_VERBOSE)))
    1.66 +   return -1;
    1.67 +
    1.68 +  while (fgets(tmp, sizeof(tmp), fp))
    1.69 +   {
    1.70 +      line++;
    1.71 +    w[words=0]=strtok(tmp, " \t\r\n\240");
    1.72 +    if (!w[0] || (*w[0]=='#')) continue;
    1.73 +      while (w[words] && (words < MAXWORDS))
    1.74 +  w[++words]=strtok(0," \t\r\n\240");
    1.75 +      if (!strcmp(w[0], "dir"))
    1.76 +  {
    1.77 +    if (words < 2)
    1.78 +     {
    1.79 +        ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
    1.80 +          "%s: line %d: No directory given\n", name, line);
    1.81 +        return -2;
    1.82 +     }
    1.83 +    for (i=1; i<words; i++)
    1.84 +      add_to_pathlist(w[i]);
    1.85 +  }
    1.86 +    else if (!strcmp(w[0], "source"))
    1.87 +  {
    1.88 +    if (words < 2)
    1.89 +      {
    1.90 +        ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
    1.91 +          "%s: line %d: No file name given\n", name, line);
    1.92 +        return -2;
    1.93 +     }
    1.94 +    for (i=1; i<words; i++)
    1.95 +      {
    1.96 +        rcf_count++;
    1.97 +      read_config_file(w[i]);
    1.98 +        rcf_count--;
    1.99 +      }
   1.100 +  }
   1.101 +      else if (!strcmp(w[0], "default"))
   1.102 +  {
   1.103 +    if (words != 2)
   1.104 +      {
   1.105 +        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   1.106 +        "%s: line %d: Must specify exactly one patch name\n",
   1.107 +          name, line);
   1.108 +        return -2;
   1.109 +      }
   1.110 +    strncpy(def_instr_name, w[1], 255);
   1.111 +    def_instr_name[255]='\0';
   1.112 +  }
   1.113 +    else if (!strcmp(w[0], "drumset"))
   1.114 +  {
   1.115 +    if (words < 2)
   1.116 +      {
   1.117 +        ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   1.118 +          "%s: line %d: No drum set number given\n", 
   1.119 +          name, line);
   1.120 +      return -2;
   1.121 +      }
   1.122 +    i=atoi(w[1]);
   1.123 +    if (i<0 || i>127)
   1.124 +     {
   1.125 +        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   1.126 +          "%s: line %d: Drum set must be between 0 and 127\n",
   1.127 +        name, line);
   1.128 +        return -2;
   1.129 +     }
   1.130 +    if (!drumset[i])
   1.131 +      {
   1.132 +        drumset[i]=safe_malloc(sizeof(ToneBank));
   1.133 +      memset(drumset[i], 0, sizeof(ToneBank));
   1.134 +     }
   1.135 +    bank=drumset[i];
   1.136 +  }
   1.137 +    else if (!strcmp(w[0], "bank"))
   1.138 +  {
   1.139 +    if (words < 2)
   1.140 +     {
   1.141 +        ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   1.142 +          "%s: line %d: No bank number given\n", 
   1.143 +        name, line);
   1.144 +        return -2;
   1.145 +     }
   1.146 +    i=atoi(w[1]);
   1.147 +    if (i<0 || i>127)
   1.148 +      {
   1.149 +        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   1.150 +          "%s: line %d: Tone bank must be between 0 and 127\n",
   1.151 +        name, line);
   1.152 +        return -2;
   1.153 +      }
   1.154 +    if (!tonebank[i])
   1.155 +     {
   1.156 +      tonebank[i]=safe_malloc(sizeof(ToneBank));
   1.157 +        memset(tonebank[i], 0, sizeof(ToneBank));
   1.158 +      }
   1.159 +    bank=tonebank[i];
   1.160 +  }
   1.161 +      else {
   1.162 +  if ((words < 2) || (*w[0] < '0' || *w[0] > '9'))
   1.163 +    {
   1.164 +     ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   1.165 +        "%s: line %d: syntax error\n", name, line);
   1.166 +     return -2;
   1.167 +    }
   1.168 +  i=atoi(w[0]);
   1.169 +  if (i<0 || i>127)
   1.170 +    {
   1.171 +      ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   1.172 +        "%s: line %d: Program must be between 0 and 127\n",
   1.173 +        name, line);
   1.174 +      return -2;
   1.175 +    }
   1.176 +  if (!bank)
   1.177 +    {
   1.178 +      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   1.179 +       "%s: line %d: Must specify tone bank or drum set "
   1.180 +        "before assignment\n",
   1.181 +        name, line);
   1.182 +     return -2;
   1.183 +    }
   1.184 +  if (bank->tone[i].name)
   1.185 +    free(bank->tone[i].name);
   1.186 +  strcpy((bank->tone[i].name=safe_malloc(strlen(w[1])+1)),w[1]);
   1.187 +  bank->tone[i].note=bank->tone[i].amp=bank->tone[i].pan=
   1.188 +    bank->tone[i].strip_loop=bank->tone[i].strip_envelope=
   1.189 +      bank->tone[i].strip_tail=-1;
   1.190 +
   1.191 +  for (j=2; j<words; j++)
   1.192 +    {
   1.193 +      if (!(cp=strchr(w[j], '=')))
   1.194 +        {
   1.195 +    ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
   1.196 +      name, line, w[j]);
   1.197 +    return -2;
   1.198 +        }
   1.199 +      *cp++=0;
   1.200 +      if (!strcmp(w[j], "amp"))
   1.201 +      {
   1.202 +    k=atoi(cp);
   1.203 +    if ((k<0 || k>MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
   1.204 +      {
   1.205 +       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   1.206 +          "%s: line %d: amplification must be between "
   1.207 +         "0 and %d\n", name, line, MAX_AMPLIFICATION);
   1.208 +       return -2;
   1.209 +      }
   1.210 +    bank->tone[i].amp=k;
   1.211 +        }
   1.212 +      else if (!strcmp(w[j], "note"))
   1.213 +        {
   1.214 +    k=atoi(cp);
   1.215 +    if ((k<0 || k>127) || (*cp < '0' || *cp > '9'))
   1.216 +      {
   1.217 +       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   1.218 +         "%s: line %d: note must be between 0 and 127\n",
   1.219 +          name, line);
   1.220 +        return -2;
   1.221 +      }
   1.222 +    bank->tone[i].note=k;
   1.223 +      }
   1.224 +     else if (!strcmp(w[j], "pan"))
   1.225 +      {
   1.226 +    if (!strcmp(cp, "center"))
   1.227 +      k=64;
   1.228 +    else if (!strcmp(cp, "left"))
   1.229 +      k=0;
   1.230 +    else if (!strcmp(cp, "right"))
   1.231 +      k=127;
   1.232 +    else
   1.233 +      k=((atoi(cp)+100) * 100) / 157;
   1.234 +    if ((k<0 || k>127) ||
   1.235 +       (k==0 && *cp!='-' && (*cp < '0' || *cp > '9')))
   1.236 +      {
   1.237 +       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
   1.238 +         "%s: line %d: panning must be left, right, "
   1.239 +         "center, or between -100 and 100\n",
   1.240 +         name, line);
   1.241 +       return -2;
   1.242 +      }
   1.243 +    bank->tone[i].pan=k;
   1.244 +      }
   1.245 +     else if (!strcmp(w[j], "keep"))
   1.246 +      {
   1.247 +    if (!strcmp(cp, "env"))
   1.248 +      bank->tone[i].strip_envelope=0;
   1.249 +    else if (!strcmp(cp, "loop"))
   1.250 +      bank->tone[i].strip_loop=0;
   1.251 +    else
   1.252 +      {
   1.253 +        ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   1.254 +          "%s: line %d: keep must be env or loop\n", name, line);
   1.255 +       return -2;
   1.256 +      }
   1.257 +      }
   1.258 +     else if (!strcmp(w[j], "strip"))
   1.259 +      {
   1.260 +    if (!strcmp(cp, "env"))
   1.261 +      bank->tone[i].strip_envelope=1;
   1.262 +    else if (!strcmp(cp, "loop"))
   1.263 +      bank->tone[i].strip_loop=1;
   1.264 +    else if (!strcmp(cp, "tail"))
   1.265 +      bank->tone[i].strip_tail=1;
   1.266 +    else
   1.267 +      {
   1.268 +       ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
   1.269 +         "%s: line %d: strip must be env, loop, or tail\n",
   1.270 +         name, line);
   1.271 +       return -2;
   1.272 +      }
   1.273 +      }
   1.274 +     else
   1.275 +      {
   1.276 +    ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
   1.277 +      name, line, w[j]);
   1.278 +    return -2;
   1.279 +      }
   1.280 +    }
   1.281 +    }
   1.282 +   }
   1.283 +  if (ferror(fp))
   1.284 +   {
   1.285 +    ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't read from %s\n", name);
   1.286 +    close_file(fp);
   1.287 +    return -2;
   1.288 +   }
   1.289 +  close_file(fp);
   1.290 +  return 0;
   1.291 +}
   1.292 +
   1.293 +int Timidity_Init(int rate, int format, int channels, int samples)
   1.294 +{
   1.295 +  if (read_config_file(CONFIG_FILE)<0) {
   1.296 +    return(-1);
   1.297 +  }
   1.298 +
   1.299 +  /* Set play mode parameters */
   1.300 +  play_mode->rate = rate;
   1.301 +  play_mode->encoding = 0;
   1.302 +  if ( (format&0xFF) == 16 ) {
   1.303 +    play_mode->encoding |= PE_16BIT;
   1.304 +  }
   1.305 +  if ( (format&0x8000) ) {
   1.306 +    play_mode->encoding |= PE_SIGNED;
   1.307 +  }
   1.308 +  if ( channels == 1 ) {
   1.309 +    play_mode->encoding |= PE_MONO;
   1.310 +  } 
   1.311 +  switch (format) {
   1.312 +    case AUDIO_S8:
   1.313 +      s32tobuf = s32tos8;
   1.314 +      break;
   1.315 +    case AUDIO_U8:
   1.316 +      s32tobuf = s32tou8;
   1.317 +      break;
   1.318 +    case AUDIO_S16LSB:
   1.319 +      s32tobuf = s32tos16l;
   1.320 +      break;
   1.321 +    case AUDIO_S16MSB:
   1.322 +      s32tobuf = s32tos16b;
   1.323 +      break;
   1.324 +    case AUDIO_U16LSB:
   1.325 +      s32tobuf = s32tou16l;
   1.326 +      break;
   1.327 +    case AUDIO_U16MSB:
   1.328 +      s32tobuf = s32tou16b;
   1.329 +      break;
   1.330 +    default:
   1.331 +      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Unsupported audio format");
   1.332 +      return(-1);
   1.333 +  }
   1.334 +  AUDIO_BUFFER_SIZE = samples;
   1.335 +
   1.336 +  /* Allocate memory for mixing (WARNING:  Memory leak!) */
   1.337 +  resample_buffer = safe_malloc(AUDIO_BUFFER_SIZE*sizeof(sample_t));
   1.338 +  common_buffer = safe_malloc(AUDIO_BUFFER_SIZE*2*sizeof(int32));
   1.339 +
   1.340 +  init_tables();
   1.341 +
   1.342 +  if (ctl->open(0, 0)) {
   1.343 +    ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Couldn't open %s\n", ctl->id_name);
   1.344 +    return(-1);
   1.345 +  }
   1.346 +
   1.347 +  if (!control_ratio) {
   1.348 +    control_ratio = play_mode->rate / CONTROLS_PER_SECOND;
   1.349 +    if(control_ratio<1)
   1.350 +      control_ratio=1;
   1.351 +    else if (control_ratio > MAX_CONTROL_RATIO)
   1.352 +      control_ratio=MAX_CONTROL_RATIO;
   1.353 +  }
   1.354 +  if (*def_instr_name)
   1.355 +    set_default_instrument(def_instr_name);
   1.356 +  return(0);
   1.357 +}
   1.358 +
   1.359 +char timidity_error[1024] = "";
   1.360 +char *Timidity_Error(void)
   1.361 +{
   1.362 +  return(timidity_error);
   1.363 +}