timidity.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 #include "pent_include.h"
00022 
00023 #ifdef USE_TIMIDITY_MIDI
00024 
00025 #include <cstdio>
00026 #include <cstdlib>
00027 #include <cstring>
00028 
00029 #include "SDL.h"
00030 #include "timidity.h"
00031 #include "timidity_common.h"
00032 #include "timidity_instrum.h"
00033 #include "timidity_playmidi.h"
00034 #include "timidity_readmidi.h"
00035 #include "timidity_output.h"
00036 #include "timidity_controls.h"
00037 #include "timidity_tables.h"
00038 
00039 // we want to use Pentagram's config
00040 #ifndef PENTAGRAM_IN_EXULT
00041 #include "SettingManager.h"
00042 #else
00043 #include "Configuration.h"
00044 #endif
00045 
00046 
00047 #ifdef NS_TIMIDITY
00048 namespace NS_TIMIDITY {
00049 #endif
00050 
00051 void (*s32tobuf)(void *dp, sint32 *lp, sint32 c);
00052 int free_instruments_afterwards=0;
00053 static char def_instr_name[256]="";
00054 
00055 int AUDIO_BUFFER_SIZE;
00056 sample_t *resample_buffer=0;
00057 sint32 *common_buffer=0;
00058 
00059 #define MAXWORDS 10
00060 
00061 static int read_config_file(const char *name)
00062 {
00063   FILE *fp;
00064   char tmp[1024], *w[MAXWORDS], *cp;
00065   ToneBank *bank=0;
00066   int i, j, k, line=0, words;
00067   static int rcf_count=0;
00068 
00069   if (rcf_count>50)
00070    {
00071     ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00072       "Probable source loop in configuration files");
00073     return (-1);
00074    }
00075 
00076   if (!(fp=open_file(name, 1, OF_VERBOSE)))
00077    return -1;
00078 
00079   while (fgets(tmp, sizeof(tmp), fp))
00080    {
00081       line++;
00082     w[words=0]=strtok(tmp, " \t\r\n\240");
00083     if (!w[0] || (*w[0]=='#')) continue;
00084       while (w[words] && (words < MAXWORDS))
00085   w[++words]=strtok(0," \t\r\n\240");
00086       if (!strcmp(w[0], "dir"))
00087   {
00088     if (words < 2)
00089      {
00090         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00091           "%s: line %d: No directory given\n", name, line);
00092         return -2;
00093      }
00094     for (i=1; i<words; i++)
00095       add_to_pathlist(w[i]);
00096   }
00097     else if (!strcmp(w[0], "source"))
00098   {
00099     if (words < 2)
00100       {
00101         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00102           "%s: line %d: No file name given\n", name, line);
00103         return -2;
00104      }
00105     for (i=1; i<words; i++)
00106       {
00107         rcf_count++;
00108       read_config_file(w[i]);
00109         rcf_count--;
00110       }
00111   }
00112       else if (!strcmp(w[0], "default"))
00113   {
00114     if (words != 2)
00115       {
00116         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00117         "%s: line %d: Must specify exactly one patch name\n",
00118           name, line);
00119         return -2;
00120       }
00121     strncpy(def_instr_name, w[1], 255);
00122     def_instr_name[255]='\0';
00123   }
00124     else if (!strcmp(w[0], "drumset"))
00125   {
00126     if (words < 2)
00127       {
00128         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00129           "%s: line %d: No drum set number given\n", 
00130           name, line);
00131       return -2;
00132       }
00133     i=atoi(w[1]);
00134     if (i<0 || i>127)
00135      {
00136         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00137           "%s: line %d: Drum set must be between 0 and 127\n",
00138         name, line);
00139         return -2;
00140      }
00141     if (!drumset[i])
00142       {
00143         drumset[i]=safe_Malloc<ToneBank>();
00144                 memset(drumset[i], 0, sizeof(ToneBank));
00145      }
00146     bank=drumset[i];
00147   }
00148     else if (!strcmp(w[0], "bank"))
00149   {
00150     if (words < 2)
00151      {
00152         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00153           "%s: line %d: No bank number given\n", 
00154         name, line);
00155         return -2;
00156      }
00157     i=atoi(w[1]);
00158     if (i<0 || i>127)
00159       {
00160         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00161           "%s: line %d: Tone bank must be between 0 and 127\n",
00162         name, line);
00163         return -2;
00164       }
00165     if (!tonebank[i])
00166      {
00167                 tonebank[i]=safe_Malloc<ToneBank>();
00168         memset(tonebank[i], 0, sizeof(ToneBank));
00169       }
00170     bank=tonebank[i];
00171   }
00172       else {
00173   if ((words < 2) || (*w[0] < '0' || *w[0] > '9'))
00174     {
00175      ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00176         "%s: line %d: syntax error\n", name, line);
00177      return -2;
00178     }
00179   i=atoi(w[0]);
00180   if (i<0 || i>127)
00181     {
00182       ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00183         "%s: line %d: Program must be between 0 and 127\n",
00184         name, line);
00185       return -2;
00186     }
00187   if (!bank)
00188     {
00189       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00190        "%s: line %d: Must specify tone bank or drum set "
00191         "before assignment\n",
00192         name, line);
00193      return -2;
00194     }
00195   if (bank->tone[i].name)
00196     free(bank->tone[i].name);
00197   strcpy((bank->tone[i].name=safe_Malloc<char>(strlen(w[1])+1)),w[1]);
00198   bank->tone[i].note=bank->tone[i].amp=bank->tone[i].pan=
00199     bank->tone[i].strip_loop=bank->tone[i].strip_envelope=
00200       bank->tone[i].strip_tail=-1;
00201 
00202   for (j=2; j<words; j++)
00203     {
00204       if (!(cp=strchr(w[j], '=')))
00205         {
00206     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
00207       name, line, w[j]);
00208     return -2;
00209         }
00210       *cp++=0;
00211       if (!strcmp(w[j], "amp"))
00212       {
00213     k=atoi(cp);
00214     if ((k<0 || k>MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
00215       {
00216        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00217           "%s: line %d: amplification must be between "
00218          "0 and %d\n", name, line, MAX_AMPLIFICATION);
00219        return -2;
00220       }
00221     bank->tone[i].amp=k;
00222         }
00223       else if (!strcmp(w[j], "note"))
00224         {
00225     k=atoi(cp);
00226     if ((k<0 || k>127) || (*cp < '0' || *cp > '9'))
00227       {
00228        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00229          "%s: line %d: note must be between 0 and 127\n",
00230           name, line);
00231         return -2;
00232       }
00233     bank->tone[i].note=k;
00234       }
00235      else if (!strcmp(w[j], "pan"))
00236       {
00237     if (!strcmp(cp, "center"))
00238       k=64;
00239     else if (!strcmp(cp, "left"))
00240       k=0;
00241     else if (!strcmp(cp, "right"))
00242       k=127;
00243     else
00244       k=((atoi(cp)+100) * 100) / 157;
00245     if ((k<0 || k>127) ||
00246        (k==0 && *cp!='-' && (*cp < '0' || *cp > '9')))
00247       {
00248        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
00249          "%s: line %d: panning must be left, right, "
00250          "center, or between -100 and 100\n",
00251          name, line);
00252        return -2;
00253       }
00254     bank->tone[i].pan=k;
00255       }
00256      else if (!strcmp(w[j], "keep"))
00257       {
00258     if (!strcmp(cp, "env"))
00259       bank->tone[i].strip_envelope=0;
00260     else if (!strcmp(cp, "loop"))
00261       bank->tone[i].strip_loop=0;
00262     else
00263       {
00264         ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00265           "%s: line %d: keep must be env or loop\n", name, line);
00266        return -2;
00267       }
00268       }
00269      else if (!strcmp(w[j], "strip"))
00270       {
00271     if (!strcmp(cp, "env"))
00272       bank->tone[i].strip_envelope=1;
00273     else if (!strcmp(cp, "loop"))
00274       bank->tone[i].strip_loop=1;
00275     else if (!strcmp(cp, "tail"))
00276       bank->tone[i].strip_tail=1;
00277     else
00278       {
00279        ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00280          "%s: line %d: strip must be env, loop, or tail\n",
00281          name, line);
00282        return -2;
00283       }
00284       }
00285      else
00286       {
00287     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
00288       name, line, w[j]);
00289     return -2;
00290       }
00291     }
00292     }
00293    }
00294   if (ferror(fp))
00295    {
00296     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't read from %s\n", name);
00297     close_file(fp);
00298     return -2;
00299    }
00300   close_file(fp);
00301   return 0;
00302 }
00303 
00304 #if 0
00305 // not used
00306 int Timidity_Init(int rate, int format, int channels, int samples)
00307 {
00308   if (read_config_file(CONFIG_FILE)<0) {
00309     return(-1);
00310   }
00311 
00312   /* Set play mode parameters */
00313   play_mode->rate = rate;
00314   play_mode->encoding = 0;
00315   if ( (format&0xFF) == 16 ) {
00316     play_mode->encoding |= PE_16BIT;
00317   }
00318   if ( (format&0x8000) ) {
00319     play_mode->encoding |= PE_SIGNED;
00320   }
00321   if ( channels == 1 ) {
00322     play_mode->encoding |= PE_MONO;
00323   } 
00324   switch (format) {
00325     case AUDIO_S8:
00326       s32tobuf = s32tos8;
00327       break;
00328     case AUDIO_U8:
00329       s32tobuf = s32tou8;
00330       break;
00331     case AUDIO_S16LSB:
00332       s32tobuf = s32tos16l;
00333       break;
00334     case AUDIO_S16MSB:
00335       s32tobuf = s32tos16b;
00336       break;
00337     case AUDIO_U16LSB:
00338       s32tobuf = s32tou16l;
00339       break;
00340     case AUDIO_U16MSB:
00341       s32tobuf = s32tou16b;
00342       break;
00343     default:
00344       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Unsupported audio format");
00345       return(-1);
00346   }
00347   AUDIO_BUFFER_SIZE = samples;
00348 
00349   /* Allocate memory for mixing (WARNING:  Memory leak!) */
00350   resample_buffer = safe_Malloc<sample_t>(AUDIO_BUFFER_SIZE);
00351   common_buffer = safe_Malloc<sint32>(AUDIO_BUFFER_SIZE*2);
00352 
00353   init_tables();
00354 
00355   if (ctl->open(0, 0)) {
00356     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Couldn't open %s\n", ctl->id_name);
00357     return(-1);
00358   }
00359 
00360   if (!control_ratio) {
00361     control_ratio = play_mode->rate / CONTROLS_PER_SECOND;
00362     if(control_ratio<1)
00363       control_ratio=1;
00364     else if (control_ratio > MAX_CONTROL_RATIO)
00365       control_ratio=MAX_CONTROL_RATIO;
00366   }
00367   if (*def_instr_name)
00368     set_default_instrument(def_instr_name);
00369   return(0);
00370 }
00371 #endif
00372 
00373 int Timidity_Init_Simple(int rate, int samples, sint32 encoding)
00374 {
00375   std::string configfile;
00376   /* see if the pentagram config file specifies an alternate timidity.cfg */
00377 #ifndef PENTAGRAM_IN_EXULT
00378   SettingManager* settings = SettingManager::get_instance();
00379   if (!settings->get("timiditycfg", configfile))
00380           configfile = CONFIG_FILE;
00381 #else
00382         config->value("config/audio/midi/timiditycfg", configfile, CONFIG_FILE);
00383 #endif
00384 
00385   if (read_config_file(configfile.c_str())<0) {
00386     return(-1);
00387   }
00388 
00389   /* Check to see if the encoding is 'valid' */
00390 
00391   // Only 16 bit can be byte swapped
00392   if ((encoding & PE_BYTESWAP) && !(encoding & PE_16BIT))
00393           return(-1);
00394 
00395   // u-Law can only be mono or stereo 
00396   if ((encoding & PE_ULAW) && (encoding & ~(PE_ULAW|PE_MONO)))
00397           return(-1);
00398 
00399   /* Set play mode parameters */
00400   play_mode->rate = rate;
00401   play_mode->encoding = encoding;
00402   switch (play_mode->encoding) {
00403     case 0:
00404         case PE_MONO:
00405       s32tobuf = s32tou8;
00406       break;
00407 
00408     case PE_SIGNED:
00409         case PE_SIGNED|PE_MONO:
00410       s32tobuf = s32tos8;
00411       break;
00412 
00413     case PE_ULAW:
00414         case PE_ULAW|PE_MONO:
00415       s32tobuf = s32toulaw;
00416       break;
00417 
00418     case PE_16BIT:
00419         case PE_16BIT|PE_MONO:
00420       s32tobuf = s32tou16;
00421       break;
00422 
00423     case PE_16BIT|PE_SIGNED:
00424         case PE_16BIT|PE_SIGNED|PE_MONO:
00425       s32tobuf = s32tos16;
00426       break;
00427 
00428     case PE_BYTESWAP|PE_16BIT:
00429         case PE_BYTESWAP|PE_16BIT|PE_MONO:
00430       s32tobuf = s32tou16x;
00431       break;
00432 
00433     case PE_BYTESWAP|PE_16BIT|PE_SIGNED:
00434         case PE_BYTESWAP|PE_16BIT|PE_SIGNED|PE_MONO:
00435       s32tobuf = s32tos16x;
00436       break;
00437 
00438     default:
00439       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Unsupported audio format");
00440       return(-1);
00441   }
00442 
00443   AUDIO_BUFFER_SIZE = samples;
00444 
00445   /* Allocate memory for mixing (WARNING:  Memory leak!) */
00446   resample_buffer = safe_Malloc<sample_t>(AUDIO_BUFFER_SIZE);
00447   common_buffer = safe_Malloc<sint32>(AUDIO_BUFFER_SIZE*2);
00448 
00449   init_tables();
00450 
00451   if (ctl->open(0, 0)) {
00452     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Couldn't open %s\n", ctl->id_name);
00453     return(-1);
00454   }
00455 
00456   if (!control_ratio) {
00457     control_ratio = play_mode->rate / CONTROLS_PER_SECOND;
00458     if(control_ratio<1)
00459       control_ratio=1;
00460     else if (control_ratio > MAX_CONTROL_RATIO)
00461       control_ratio=MAX_CONTROL_RATIO;
00462   }
00463   if (*def_instr_name)
00464     set_default_instrument(def_instr_name);
00465   return(0);
00466 }
00467 
00468 void Timidity_DeInit()
00469 {
00470         free_instruments();
00471 
00472         if (resample_buffer) free(resample_buffer);
00473         resample_buffer = 0;
00474 
00475         if (common_buffer) free(common_buffer);
00476         common_buffer = 0;
00477 }
00478 
00479 
00480 char timidity_error[1024] = "";
00481 char *Timidity_Error(void)
00482 {
00483   return(timidity_error);
00484 }
00485 
00486 #ifdef NS_TIMIDITY
00487 };
00488 #endif
00489 
00490 #endif //USE_TIMIDITY_MIDI
00491 
00492 

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