timidity.c
上传用户:nini_0081
上传日期:2022-07-21
资源大小:2628k
文件大小:9k
源码类别:

多媒体编程

开发平台:

DOS

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