00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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
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
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
00390
00391
00392 if ((encoding & PE_BYTESWAP) && !(encoding & PE_16BIT))
00393 return(-1);
00394
00395
00396 if ((encoding & PE_ULAW) && (encoding & ~(PE_ULAW|PE_MONO)))
00397 return(-1);
00398
00399
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
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