1 /*(LGPL)
2 ---------------------------------------------------------------------------
3 a_agw.c - "Algorithmically Generated Waveform" file support
4 ---------------------------------------------------------------------------
5 * Copyright (C) 2002, 2003, David Olofson
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #define DBG(x)
23
24 #include <stdio.h>
25
26 #include "kobolog.h"
27 #include "config.h"
28 #include "eel.h"
29 #include "a_types.h"
30 #include "a_wca.h"
31 #include "a_control.h"
32
33
34 /* Enum class handles */
35
36 static int enum_aformat, enum_amodtarget, enum_awaveform, enum_afiltertype;
37 static int enum_amixmode, enum_aresample;
38
39 static int enum_pparam, enum_pdriver;
40
41
42 /*----------------------------------------------------------
43 AGW Command Callbacks
44 ----------------------------------------------------------*/
45
op_w_reset(int argc,struct eel_data_t * argv)46 static int op_w_reset(int argc, struct eel_data_t *argv)
47 {
48 DBG(log_printf(D2LOG, "w_reset;\n");)
49 wca_reset();
50 return 1;
51 }
52
53
op_w_format(int argc,struct eel_data_t * argv)54 static int op_w_format(int argc, struct eel_data_t *argv)
55 {
56 int target;
57 double fs;
58 int format = enum_aformat;
59 #if 0
60 /* Alternative, more verbose method. */
61 eel_symbol_t *fmt;
62 if(eel_get_args("iEr", &target, &fmt, &fs) != 3)
63 return -1;
64 if(fmt->token != enum_aformat)
65 {
66 eel_error("Wrong enum class!");
67 return -1;
68 }
69 DBG(log_printf(D2LOG, "w_format %d, %s, %f;\n", target, eel_s_stringrep(fmt), fs);)
70 format = fmt->data.value.i;
71 #else
72 if(eel_get_args("ier", &target, &format, &fs) != 3)
73 return -1;
74 #endif
75 DBG(log_printf(D2LOG, "w_format %d, %d, %f;\n", target, format, fs);)
76 audio_wave_format(target, format, (int)fs);
77 return 1;
78 }
79
80
op_w_gain(int argc,struct eel_data_t * argv)81 static int op_w_gain(int argc, struct eel_data_t *argv)
82 {
83 int target;
84 if(eel_get_args("i", &target) != 1)
85 return -1;
86 DBG(log_printf(D2LOG, "w_gain %d;\n", target);)
87 wca_gain(target);
88 return 1;
89 }
90
91
op_w_convert(int argc,struct eel_data_t * argv)92 static int op_w_convert(int argc, struct eel_data_t *argv)
93 {
94 int source, target;
95 double fs;
96 int format = enum_aformat;
97 int interpol = enum_aresample;
98 argc = eel_get_args("iie[re]",
99 &source, &target, &format,
100 &fs, &interpol);
101 if(argc < 3)
102 return -1;
103 if(argc < 4)
104 fs = 0;
105 if(argc < 5)
106 interpol = AR_BEST;
107 DBG(log_printf(D2LOG, "w_convert %d, %d, %d, %d, %d;\n", source, target,
108 format, (int)fs, interpol);)
109 audio_wave_convert(source, target, format, (int)fs, interpol);
110 return 1;
111 }
112
113
op_w_enhance(int argc,struct eel_data_t * argv)114 static int op_w_enhance(int argc, struct eel_data_t *argv)
115 {
116 int target;
117 double f, level;
118 if(eel_get_args("irr", &target, &f, &level) != 3)
119 return -1;
120 DBG(log_printf(D2LOG, "w_enhance %d, %d, %f;\n", target, (int)f, level);)
121 wca_enhance(target, (int)f, level);
122 return 1;
123 }
124
125
op_w_gate(int argc,struct eel_data_t * argv)126 static int op_w_gate(int argc, struct eel_data_t *argv)
127 {
128 int target;
129 double f, min, thres, att;
130 if(eel_get_args("irrrr",
131 &target, &f, &min, &thres, &att) != 5)
132 return -1;
133 DBG(log_printf(D2LOG, "w_gate %d, %d, %f, %f, %f;\n",
134 target, (int)f, min, thres, att);)
135 wca_gate(target, (int)f, min, thres, att);
136 return 1;
137 }
138
139
op_w_blank(int argc,struct eel_data_t * argv)140 static int op_w_blank(int argc, struct eel_data_t *argv)
141 {
142 int target, loop;
143 unsigned samples;
144 argc = eel_get_args("ii[i]", &target, &samples, &loop);
145 if(argc < 2)
146 return -1;
147 if(argc < 3)
148 loop = 0;
149 DBG(log_printf(D2LOG, "w_blank %d, %d, %d;\n", target, samples, loop);)
150 audio_wave_blank(target, samples, loop);
151 return 1;
152 }
153
154
op_w_load(int argc,struct eel_data_t * argv)155 static int op_w_load(int argc, struct eel_data_t *argv)
156 {
157 int target, loop;
158 const char *fn;
159 argc = eel_get_args("is[i]", &target, &fn, &loop);
160 if(argc < 2)
161 return -1;
162 if(argc < 3)
163 loop = 0;
164 DBG(log_printf(D2LOG, "w_load %d, \"%s\", %d;\n", target, fn, loop);)
165 if(audio_wave_load(target, fn, loop) < 0)
166 return -1;
167 return 1;
168 }
169
170
op_w_save(int argc,struct eel_data_t * argv)171 static int op_w_save(int argc, struct eel_data_t *argv)
172 {
173 int target;
174 const char *fn;
175 if(eel_get_args("is", &target, &fn) != 2)
176 return -1;
177 DBG(log_printf(D2LOG, "w_save %d, \"%s\";\n", target, fn);)
178 if(audio_wave_save(target, fn) < 0)
179 return -1;
180 return 1;
181 }
182
183
op_w_prepare(int argc,struct eel_data_t * argv)184 static int op_w_prepare(int argc, struct eel_data_t *argv)
185 {
186 int target;
187 if(eel_get_args("i", &target) < 1)
188 return -1;
189 DBG(log_printf(D2LOG, "w_prepare %d;\n", target);)
190 audio_wave_prepare(target);
191 return 1;
192 }
193
194
op_w_env(int argc,struct eel_data_t * argv)195 static int op_w_env(int argc, struct eel_data_t *argv)
196 {
197 int i;
198 int modtarget = enum_amodtarget;
199 double dur[WCA_MAX_ENV_STEPS];
200 double val[WCA_MAX_ENV_STEPS];
201
202 if(argc > 1 + 2*WCA_MAX_ENV_STEPS)
203 {
204 eel_error("Too many envelope steps!");
205 return -1;
206 }
207
208 if(eel_get_args("e[<rr>]", &modtarget, &dur, &val) != argc)
209 return -1;
210
211 DBG(log_printf(D2LOG, "w_env %d", modtarget);)
212 wca_mod_reset(modtarget);
213 if(2 == argc)
214 {
215 /*
216 * Note that dur[0] actually becomes a *value*
217 * rather than a time in this case!
218 */
219 DBG(log_printf(D2LOG, ", %f;\n", dur[0]);)
220 wca_val(modtarget, dur[0]);
221 return 1;
222 }
223 for(i = 1; i < argc; i += 2)
224 {
225 int sec = (i-1)/2;
226 DBG(log_printf(D2LOG, ", <%f", dur[sec]);)
227 if(i+1 >= argc)
228 {
229 eel_error("<duration, value> argruments must"
230 " come in pairs!");
231 return -1;
232 }
233 DBG(else
234 log_printf(D2LOG, ", %f", val[sec]);)
235 DBG(log_printf(D2LOG, ">");)
236 wca_env(modtarget, dur[sec], val[sec]);
237 }
238 DBG(log_printf(D2LOG, ";\n");)
239
240 return 1;
241 }
242
243
op_w_mod(int argc,struct eel_data_t * argv)244 static int op_w_mod(int argc, struct eel_data_t *argv)
245 {
246 int mt;
247 double f, a, d;
248 mt = enum_amodtarget;
249 if(eel_get_args("errr", &mt, &f, &a, &d) != 4)
250 return -1;
251 DBG(log_printf(D2LOG, "w_mod %d, %f, %f, %f;\n", mt, f, a, d);)
252 wca_mod(mt, f, a, d);
253 return 1;
254 }
255
256
op_w_osc(int argc,struct eel_data_t * argv)257 static int op_w_osc(int argc, struct eel_data_t *argv)
258 {
259 int target, wf, mm;
260 wf = enum_awaveform;
261 mm = enum_amixmode;
262 switch(eel_get_args("ie[e]", &target, &wf, &mm))
263 {
264 case 2:
265 mm = WCA_ADD;
266 case 3:
267 break;
268 default:
269 return -1;
270 }
271 DBG(log_printf(D2LOG, "w_osc %d, %d, %d;\n", target, wf, mm);)
272 wca_osc(target, wf, mm);
273 return 1;
274 }
275
276
op_w_filter(int argc,struct eel_data_t * argv)277 static int op_w_filter(int argc, struct eel_data_t *argv)
278 {
279 int target, ft;
280 ft = enum_afiltertype;
281 if(eel_get_args("ie", &target, &ft) != 2)
282 return -1;
283 DBG(log_printf(D2LOG, "w_filter %d, %d;\n", target, ft);)
284 wca_filter(target, ft);
285 return 1;
286 }
287
288
289
290 /*----------------------------------------------------------
291 Patch Command Callbacks
292 ----------------------------------------------------------*/
293
op_p_param(int argc,struct eel_data_t * argv)294 static int op_p_param(int argc, struct eel_data_t *argv)
295 {
296 int patch, param;
297 double value;
298 param = enum_pparam;
299 if(eel_get_args("ier", &patch, ¶m, &value) != 3)
300 return -1;
301 switch(param)
302 {
303 case APP_DRIVER:
304 case APP_WAVE:
305 case APP_ENV_SKIP:
306 case APP_LFO_SHAPE:
307 audio_patch_param(patch, param, (int)value);
308 break;
309 default:
310 audio_patch_param(patch, param, (int)(value * 65536.0));
311 break;
312 }
313 DBG(log_printf(D2LOG, "p_param %d, %d, %f;\n", patch, param, value);)
314 return 1;
315 }
316
317
op_p_driver(int argc,struct eel_data_t * argv)318 static int op_p_driver(int argc, struct eel_data_t *argv)
319 {
320 int patch;
321 eel_symbol_t *callback;
322 if(eel_get_args("if", &patch, &callback) != 2)
323 return -1;
324 DBG(log_printf(D2LOG, "p_driver %d, %s;\n", patch, eel_s_stringrep(callback));)
325 return 1;
326 }
327
328
329 /*----------------------------------------------------------
330 Init code
331 ----------------------------------------------------------*/
332
load_keywords(void)333 static void load_keywords(void)
334 {
335 /* WCA calls */
336 eel_register_operator("w_reset", op_w_reset, 100, 0 ,0);
337 eel_register_operator("w_format", op_w_format, 100, 0 ,0);
338 eel_register_operator("w_blank", op_w_blank, 100, 0 ,0);
339 eel_register_operator("w_load", op_w_load, 100, 0 ,0);
340 eel_register_operator("w_save", op_w_save, 100, 0 ,0);
341 eel_register_operator("w_prepare", op_w_prepare, 100, 0 ,0);
342 eel_register_operator("w_env", op_w_env, 100, 0 ,0);
343 eel_register_operator("w_mod", op_w_mod, 100, 0 ,0);
344 eel_register_operator("w_osc", op_w_osc, 100, 0 ,0);
345 eel_register_operator("w_filter", op_w_filter, 100, 0 ,0);
346 eel_register_operator("w_gain", op_w_gain, 100, 0 ,0);
347 eel_register_operator("w_convert", op_w_convert, 100, 0 ,0);
348 eel_register_operator("w_enhance", op_w_enhance, 100, 0 ,0);
349 eel_register_operator("w_gate", op_w_gate, 100, 0 ,0);
350
351 /* w_convert resampling modes */
352 enum_aresample = eel_register_enum_class();
353 eel_register_enum(enum_aresample, "NEAREST", AR_NEAREST);
354 eel_register_enum(enum_aresample, "NEAREST4X", AR_NEAREST_4X);
355 eel_register_enum(enum_aresample, "LINEAR", AR_LINEAR);
356 eel_register_enum(enum_aresample, "LINEAR2X", AR_LINEAR_2X_R);
357 eel_register_enum(enum_aresample, "LINEAR4X", AR_LINEAR_4X_R);
358 eel_register_enum(enum_aresample, "LINEAR8X", AR_LINEAR_8X_R);
359 eel_register_enum(enum_aresample, "LINEAR16X", AR_LINEAR_16X_R);
360 eel_register_enum(enum_aresample, "CUBIC", AR_CUBIC_R);
361
362 eel_register_enum(enum_aresample, "WORST", AR_WORST);
363 eel_register_enum(enum_aresample, "MEDIUM", AR_MEDIUM);
364 eel_register_enum(enum_aresample, "BEST", AR_BEST);
365
366 /* Sample formats */
367 enum_aformat = eel_register_enum_class();
368 eel_register_enum(enum_aformat, "MONO8", AF_MONO8);
369 eel_register_enum(enum_aformat, "STEREO8", AF_STEREO8);
370 eel_register_enum(enum_aformat, "MONO16", AF_MONO16);
371 eel_register_enum(enum_aformat, "STEREO16", AF_STEREO16);
372 eel_register_enum(enum_aformat, "MONO32", AF_MONO32);
373 eel_register_enum(enum_aformat, "STEREO32", AF_STEREO32);
374
375 /* Modulation targets */
376 enum_amodtarget = eel_register_enum_class();
377 eel_register_enum(enum_amodtarget, "AMPLITUDE", WCA_AMPLITUDE);
378 eel_register_enum(enum_amodtarget, "BALANCE", WCA_BALANCE);
379 eel_register_enum(enum_amodtarget, "FREQUENCY", WCA_FREQUENCY);
380 eel_register_enum(enum_amodtarget, "LIMIT", WCA_LIMIT);
381 eel_register_enum(enum_amodtarget, "MOD1", WCA_MOD1);
382 eel_register_enum(enum_amodtarget, "MOD2", WCA_MOD2);
383 eel_register_enum(enum_amodtarget, "MOD3", WCA_MOD3);
384
385 /* Oscillator output modes */
386 enum_amixmode = eel_register_enum_class();
387 eel_register_enum(enum_amixmode, "ADD", WCA_ADD);
388 eel_register_enum(enum_amixmode, "MUL", WCA_MUL);
389 eel_register_enum(enum_amixmode, "FM", WCA_FM);
390 eel_register_enum(enum_amixmode, "FM_ADD", WCA_FM_ADD);
391 eel_register_enum(enum_amixmode, "SYNC", WCA_SYNC);
392 eel_register_enum(enum_amixmode, "SYNC_ADD", WCA_SYNC_ADD);
393
394 /* Oscillator waveforms */
395 enum_awaveform = eel_register_enum_class();
396 eel_register_enum(enum_awaveform, "DC", WCA_DC);
397 eel_register_enum(enum_awaveform, "SINE", WCA_SINE);
398 eel_register_enum(enum_awaveform, "HALFSINE", WCA_HALFSINE);
399 eel_register_enum(enum_awaveform, "RECTSINE", WCA_RECTSINE);
400 eel_register_enum(enum_awaveform, "SINEMORPH", WCA_SINEMORPH);
401 eel_register_enum(enum_awaveform, "BLMORPH", WCA_BLMORPH);
402 eel_register_enum(enum_awaveform, "BLCROSS", WCA_BLCROSS);
403 eel_register_enum(enum_awaveform, "PULSE", WCA_PULSE);
404 eel_register_enum(enum_awaveform, "TRIANGLE", WCA_TRIANGLE);
405 eel_register_enum(enum_awaveform, "NOISE", WCA_NOISE);
406 eel_register_enum(enum_awaveform, "SPECTRUM", WCA_SPECTRUM);
407 eel_register_enum(enum_awaveform, "ASPECTRUM", WCA_ASPECTRUM);
408 eel_register_enum(enum_awaveform, "HSPECTRUM", WCA_HSPECTRUM);
409 eel_register_enum(enum_awaveform, "AHSPECTRUM", WCA_AHSPECTRUM);
410
411 /* Filter types */
412 enum_afiltertype = eel_register_enum_class();
413 eel_register_enum(enum_afiltertype, "ALLPASS", WCA_ALLPASS);
414 eel_register_enum(enum_afiltertype, "LOWPASS_6", WCA_LOWPASS_6DB);
415 eel_register_enum(enum_afiltertype, "HIGHPASS_6", WCA_HIGHPASS_6DB);
416 eel_register_enum(enum_afiltertype, "LOWPASS_12", WCA_LOWPASS_12DB);
417 eel_register_enum(enum_afiltertype, "HIGHPASS_12", WCA_HIGHPASS_12DB);
418 eel_register_enum(enum_afiltertype, "BANDPASS_12", WCA_BANDPASS_12DB);
419 eel_register_enum(enum_afiltertype, "NOTCH_12", WCA_NOTCH_12DB);
420 eel_register_enum(enum_afiltertype, "PEAK_12", WCA_PEAK_12DB);
421
422 /* Patch calls */
423 eel_register_operator("p_param", op_p_param, 100, 0 ,0);
424 eel_register_operator("p_driver", op_p_driver, 100, 0 ,0);
425
426 /* Patch Parameters */
427 enum_pparam = eel_register_enum_class();
428 eel_register_enum(enum_pparam, "DRIVER", APP_DRIVER);
429 eel_register_enum(enum_pparam, "WAVE", APP_WAVE);
430 eel_register_enum(enum_pparam, "RANDPITCH", APP_RANDPITCH);
431 eel_register_enum(enum_pparam, "RANDVOL", APP_RANDVOL);
432
433 eel_register_enum(enum_pparam, "ENV_SKIP", APP_ENV_SKIP);
434 eel_register_enum(enum_pparam, "ENV_L0", APP_ENV_L0);
435 eel_register_enum(enum_pparam, "ENV_DELAY", APP_ENV_DELAY);
436 eel_register_enum(enum_pparam, "ENV_T1", APP_ENV_T1);
437 eel_register_enum(enum_pparam, "ENV_L1", APP_ENV_L1);
438 eel_register_enum(enum_pparam, "ENV_HOLD", APP_ENV_HOLD);
439 eel_register_enum(enum_pparam, "ENV_T2", APP_ENV_T2);
440 eel_register_enum(enum_pparam, "ENV_L2", APP_ENV_L2);
441 eel_register_enum(enum_pparam, "ENV_T3", APP_ENV_T3);
442 eel_register_enum(enum_pparam, "ENV_T4", APP_ENV_T4);
443
444 /* Patch Drivers */
445 enum_pdriver = eel_register_enum_class();
446 eel_register_enum(enum_pdriver, "MONO", PD_MONO);
447 eel_register_enum(enum_pdriver, "POLY", PD_POLY);
448 eel_register_enum(enum_pdriver, "MIDI", PD_MIDI);
449 eel_register_enum(enum_pdriver, "EEL", PD_EEL);
450 }
451
452
453 /*----------------------------------------------------------
454 API code
455 ----------------------------------------------------------*/
456
457 static int _agw_initialized = 0;
458
459
agw_open(void)460 int agw_open(void)
461 {
462 if(_agw_initialized)
463 return 0;
464
465 eel_open();
466
467 eel_push_scope(); /* begin AGW extensions scope */
468
469 load_keywords();
470
471 /* Built-in variables */
472 (void)eel_set_integer("target", -1);
473
474 _agw_initialized = 1;
475 return 0;
476 }
477
agw_close(void)478 void agw_close(void)
479 {
480 if(!_agw_initialized)
481 return;
482
483 eel_pop_scope(); /* end AGW extensions scope */
484
485 eel_close();
486
487 _agw_initialized = 0;
488 }
489
490 #define CHECKINIT if(!_agw_initialized) agw_open();
491
agw_load(int wid,const char * name)492 int agw_load(int wid, const char *name)
493 {
494 int script, res;
495
496 CHECKINIT
497
498 if(wid < 0)
499 {
500 wid = audio_wave_alloc(wid);
501 if(wid < 0)
502 return wid;
503 }
504
505 script = eel_load(name);
506 if(script < 0)
507 return -1;
508
509 eel_push_scope(); /* begin script scope */
510
511 /* Initialize "argument" variables */
512 (void)eel_set_integer("target", wid);
513
514 /* Reset the waveform construction engine */
515 wca_reset();
516
517 res = eel_run(script);
518 eel_free(script);
519
520 eel_pop_scope(); /* end script scope */
521
522 if(res < 0)
523 return -1;
524
525 audio_wave_prepare(wid);
526
527 return wid;
528 }
529