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, &param, &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