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 "pent_include.h"
22
23 #ifdef USE_TIMIDITY_MIDI
24
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstring>
28 #include <vector>
29
30 using std::vector;
31
32 #include "SDL.h"
33 #include "timidity.h"
34 #include "timidity_common.h"
35 #include "timidity_instrum.h"
36 #include "timidity_playmidi.h"
37 #include "timidity_readmidi.h"
38 #include "timidity_output.h"
39 #include "timidity_controls.h"
40 #include "timidity_tables.h"
41
42 // we want to use Pentagram's config
43 #include "Configuration.h"
44
45 #ifdef NS_TIMIDITY
46 namespace NS_TIMIDITY {
47 #endif
48
49 void (*s32tobuf)(void *dp, sint32 *lp, sint32 c);
50 int free_instruments_afterwards=0;
51 static char def_instr_name[256]="";
52
53 int AUDIO_BUFFER_SIZE;
54 sample_t *resample_buffer=nullptr;
55 sint32 *common_buffer=nullptr;
56
57 #define MAXWORDS 10u
58
read_config_file(const char * name)59 static int read_config_file(const char *name)
60 {
61 FILE *fp;
62 char tmp[1024];
63 vector<char*> w;
64 w.reserve(MAXWORDS);
65 ToneBank *bank=nullptr;
66 int line=0;
67 static int rcf_count=0;
68
69 if (rcf_count>50)
70 {
71 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
72 "Probable source loop in configuration files");
73 return -1;
74 }
75
76 if (!(fp=open_file(name, 1, OF_VERBOSE)))
77 return -1;
78
79 while (fgets(tmp, sizeof(tmp), fp))
80 {
81 line++;
82 w.clear();
83 w.push_back(strtok(tmp, " \t\r\n\240"));
84 if (!w[0] || (*w[0]=='#')) continue;
85 while (w.back() && w.size() < MAXWORDS)
86 w.push_back(strtok(nullptr," \t\r\n\240"));
87 if (!strcmp(w[0], "dir"))
88 {
89 if (w.size() < 2)
90 {
91 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
92 "%s: line %d: No directory given\n", name, line);
93 close_file(fp);
94 return -2;
95 }
96 for (unsigned i=1; i<w.size(); i++)
97 add_to_pathlist(w[i]);
98 }
99 else if (!strcmp(w[0], "source"))
100 {
101 if (w.size() < 2)
102 {
103 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
104 "%s: line %d: No file name given\n", name, line);
105 close_file(fp);
106 return -2;
107 }
108 for (unsigned i=1; i<w.size(); i++)
109 {
110 rcf_count++;
111 read_config_file(w[i]);
112 rcf_count--;
113 }
114 }
115 else if (!strcmp(w[0], "default"))
116 {
117 if (w.size() != 2)
118 {
119 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
120 "%s: line %d: Must specify exactly one patch name\n",
121 name, line);
122 close_file(fp);
123 return -2;
124 }
125 strncpy(def_instr_name, w[1], 255);
126 def_instr_name[255]='\0';
127 }
128 else if (!strcmp(w[0], "drumset"))
129 {
130 if (w.size() < 2)
131 {
132 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
133 "%s: line %d: No drum set number given\n",
134 name, line);
135 close_file(fp);
136 return -2;
137 }
138 int i=atoi(w[1]);
139 if (i<0 || i>127)
140 {
141 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
142 "%s: line %d: Drum set must be between 0 and 127\n",
143 name, line);
144 close_file(fp);
145 return -2;
146 }
147 if (!drumset[i])
148 {
149 drumset[i]=safe_Malloc<ToneBank>();
150 memset(drumset[i], 0, sizeof(ToneBank));
151 }
152 bank=drumset[i];
153 }
154 else if (!strcmp(w[0], "bank"))
155 {
156 if (w.size() < 2)
157 {
158 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
159 "%s: line %d: No bank number given\n",
160 name, line);
161 close_file(fp);
162 return -2;
163 }
164 int i=atoi(w[1]);
165 if (i<0 || i>127)
166 {
167 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
168 "%s: line %d: Tone bank must be between 0 and 127\n",
169 name, line);
170 close_file(fp);
171 return -2;
172 }
173 if (!tonebank[i])
174 {
175 tonebank[i]=safe_Malloc<ToneBank>();
176 memset(tonebank[i], 0, sizeof(ToneBank));
177 }
178 bank=tonebank[i];
179 }
180 else {
181 if ((w.size() < 2) || !std::isdigit(static_cast<unsigned char>(*w[0])))
182 {
183 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
184 "%s: line %d: syntax error\n", name, line);
185 close_file(fp);
186 return -2;
187 }
188 int i=atoi(w[0]);
189 if (i<0 || i>127)
190 {
191 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
192 "%s: line %d: Program must be between 0 and 127\n",
193 name, line);
194 close_file(fp);
195 return -2;
196 }
197 if (!bank)
198 {
199 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
200 "%s: line %d: Must specify tone bank or drum set "
201 "before assignment\n",
202 name, line);
203 close_file(fp);
204 return -2;
205 }
206 if (bank->tone[i].name)
207 free(bank->tone[i].name);
208 strcpy((bank->tone[i].name=safe_Malloc<char>(strlen(w[1])+1)),w[1]);
209 bank->tone[i].note=bank->tone[i].amp=bank->tone[i].pan=
210 bank->tone[i].strip_loop=bank->tone[i].strip_envelope=
211 bank->tone[i].strip_tail=-1;
212
213 for (unsigned j=2; j<w.size(); j++)
214 {
215 char *cp = strchr(w[j], '=');
216 if (!cp)
217 {
218 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
219 name, line, w[j]);
220 close_file(fp);
221 return -2;
222 }
223 *cp++=0;
224 if (!strcmp(w[j], "amp"))
225 {
226 int k=atoi(cp);
227 if ((k<0 || k>MAX_AMPLIFICATION) || !std::isdigit(static_cast<unsigned char>(*cp)))
228 {
229 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
230 "%s: line %d: amplification must be between "
231 "0 and %d\n", name, line, MAX_AMPLIFICATION);
232 close_file(fp);
233 return -2;
234 }
235 bank->tone[i].amp=k;
236 }
237 else if (!strcmp(w[j], "note"))
238 {
239 int k=atoi(cp);
240 if ((k<0 || k>127) || !std::isdigit(static_cast<unsigned char>(*cp)))
241 {
242 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
243 "%s: line %d: note must be between 0 and 127\n",
244 name, line);
245 close_file(fp);
246 return -2;
247 }
248 bank->tone[i].note=k;
249 }
250 else if (!strcmp(w[j], "pan"))
251 {
252 int k;
253 if (!strcmp(cp, "center"))
254 k=64;
255 else if (!strcmp(cp, "left"))
256 k=0;
257 else if (!strcmp(cp, "right"))
258 k=127;
259 else
260 k=((atoi(cp)+100) * 100) / 157;
261 if ((k<0 || k>127) ||
262 (k==0 && *cp!='-' && !std::isdigit(static_cast<unsigned char>(*cp))))
263 {
264 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
265 "%s: line %d: panning must be left, right, "
266 "center, or between -100 and 100\n",
267 name, line);
268 close_file(fp);
269 return -2;
270 }
271 bank->tone[i].pan=k;
272 }
273 else if (!strcmp(w[j], "keep"))
274 {
275 if (!strcmp(cp, "env"))
276 bank->tone[i].strip_envelope=0;
277 else if (!strcmp(cp, "loop"))
278 bank->tone[i].strip_loop=0;
279 else
280 {
281 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
282 "%s: line %d: keep must be env or loop\n", name, line);
283 close_file(fp);
284 return -2;
285 }
286 }
287 else if (!strcmp(w[j], "strip"))
288 {
289 if (!strcmp(cp, "env"))
290 bank->tone[i].strip_envelope=1;
291 else if (!strcmp(cp, "loop"))
292 bank->tone[i].strip_loop=1;
293 else if (!strcmp(cp, "tail"))
294 bank->tone[i].strip_tail=1;
295 else
296 {
297 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
298 "%s: line %d: strip must be env, loop, or tail\n",
299 name, line);
300 close_file(fp);
301 return -2;
302 }
303 }
304 else
305 {
306 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: bad patch option %s\n",
307 name, line, w[j]);
308 close_file(fp);
309 return -2;
310 }
311 }
312 }
313 }
314 if (ferror(fp))
315 {
316 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't read from %s\n", name);
317 close_file(fp);
318 return -2;
319 }
320 close_file(fp);
321 return 0;
322 }
323
Timidity_Init_Simple(int rate,int samples,sint32 encoding)324 int Timidity_Init_Simple(int rate, int samples, sint32 encoding)
325 {
326 std::string configfile;
327 /* see if the pentagram config file specifies an alternate timidity.cfg */
328 config->value("config/audio/midi/timiditycfg", configfile, CONFIG_FILE);
329
330 if (read_config_file(configfile.c_str())<0) {
331 return -1;
332 }
333
334 /* Check to see if the encoding is 'valid' */
335
336 // Only 16 bit can be byte swapped
337 if ((encoding & PE_BYTESWAP) && !(encoding & PE_16BIT))
338 return -1;
339
340 // u-Law can only be mono or stereo
341 if ((encoding & PE_ULAW) && (encoding & ~(PE_ULAW|PE_MONO)))
342 return -1;
343
344 /* Set play mode parameters */
345 play_mode->rate = rate;
346 play_mode->encoding = encoding;
347 switch (play_mode->encoding) {
348 case 0:
349 case PE_MONO:
350 s32tobuf = s32tou8;
351 break;
352
353 case PE_SIGNED:
354 case PE_SIGNED|PE_MONO:
355 s32tobuf = s32tos8;
356 break;
357
358 case PE_ULAW:
359 case PE_ULAW|PE_MONO:
360 s32tobuf = s32toulaw;
361 break;
362
363 case PE_16BIT:
364 case PE_16BIT|PE_MONO:
365 s32tobuf = s32tou16;
366 break;
367
368 case PE_16BIT|PE_SIGNED:
369 case PE_16BIT|PE_SIGNED|PE_MONO:
370 s32tobuf = s32tos16;
371 break;
372
373 case PE_BYTESWAP|PE_16BIT:
374 case PE_BYTESWAP|PE_16BIT|PE_MONO:
375 s32tobuf = s32tou16x;
376 break;
377
378 case PE_BYTESWAP|PE_16BIT|PE_SIGNED:
379 case PE_BYTESWAP|PE_16BIT|PE_SIGNED|PE_MONO:
380 s32tobuf = s32tos16x;
381 break;
382
383 default:
384 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Unsupported audio format");
385 return -1;
386 }
387
388 AUDIO_BUFFER_SIZE = samples;
389
390 /* Allocate memory for mixing (WARNING: Memory leak!) */
391 resample_buffer = safe_Malloc<sample_t>(AUDIO_BUFFER_SIZE);
392 common_buffer = safe_Malloc<sint32>(AUDIO_BUFFER_SIZE*2);
393
394 init_tables();
395
396 if (ctl->open(0, 0)) {
397 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Couldn't open %s\n", ctl->id_name);
398 return -1;
399 }
400
401 if (!control_ratio) {
402 control_ratio = play_mode->rate / CONTROLS_PER_SECOND;
403 if(control_ratio<1)
404 control_ratio=1;
405 else if (control_ratio > MAX_CONTROL_RATIO)
406 control_ratio=MAX_CONTROL_RATIO;
407 }
408 if (*def_instr_name)
409 set_default_instrument(def_instr_name);
410 return 0;
411 }
412
Timidity_DeInit()413 void Timidity_DeInit()
414 {
415 free_instruments();
416
417 free(resample_buffer);
418 resample_buffer = nullptr;
419
420 free(common_buffer);
421 common_buffer = nullptr;
422 }
423
424
425 char timidity_error[1024] = "";
Timidity_Error()426 char *Timidity_Error()
427 {
428 return timidity_error;
429 }
430
431 #ifdef NS_TIMIDITY
432 }
433 #endif
434
435 #endif //USE_TIMIDITY_MIDI
436
437
438