1 /* CLM (Music V) implementation */
2
3 #include "mus-config.h"
4
5 #if USE_SND
6 #include "snd.h"
7 #endif
8
9 #include <stddef.h>
10 #include <math.h>
11 #include <stdio.h>
12 #include <errno.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdarg.h>
16
17 #ifndef _MSC_VER
18 #include <unistd.h>
19 #else
20 #include <io.h>
21 #pragma warning(disable: 4244)
22 #endif
23
24 #include "_sndlib.h"
25 #include "clm.h"
26 #include "clm-strings.h"
27
28 #if HAVE_GSL
29 #include <gsl/gsl_complex.h>
30 #include <gsl/gsl_complex_math.h>
31 #endif
32
33 #if HAVE_FFTW3
34 #include <fftw3.h>
35 #endif
36
37 #if HAVE_COMPLEX_TRIG
38 #include <complex.h>
39 #endif
40
41 #if (!DISABLE_SINCOS) && defined(__GNUC__) && defined(__linux__)
42 #define HAVE_SINCOS 1
43 void sincos(double x, double *sin, double *cos);
44 #else
45 #define HAVE_SINCOS 0
46 #endif
47
48 #ifndef TWO_PI
49 #define TWO_PI (2.0 * M_PI)
50 #endif
51
52 #if (!USE_SND)
53 #define mus_clear_floats(Arr, Len) \
54 do { \
55 mus_long_t K; \
56 mus_float_t *dst; \
57 dst = Arr; \
58 for (K = Len; K > 0; K--) \
59 *dst++ = 0.0; \
60 } while (0)
61 #define mus_copy_floats(Dst, Src, Len) \
62 do { \
63 mus_long_t K; \
64 mus_float_t *dst, *src; \
65 dst = Dst; \
66 src = Src; \
67 for (K = Len; K > 0; K--) \
68 *dst++ = *src++; \
69 } while (0)
70 #define mus_add_floats(Dst, Src, Len) \
71 do { \
72 mus_long_t K; \
73 mus_float_t *dst, *src; \
74 dst = Dst; \
75 src = Src; \
76 for (K = Len; K > 0; K--) \
77 *dst++ += *src++; \
78 } while (0)
79 #endif
80
81 struct mus_any_class {
82 int type;
83 char *name;
84 void (*release)(mus_any *ptr);
85 char *(*describe)(mus_any *ptr); /* caller should free the string */
86 bool (*equalp)(mus_any *gen1, mus_any *gen2);
87 mus_float_t *(*data)(mus_any *ptr);
88 mus_float_t *(*set_data)(mus_any *ptr, mus_float_t *new_data);
89 mus_long_t (*length)(mus_any *ptr);
90 mus_long_t (*set_length)(mus_any *ptr, mus_long_t new_length);
91 mus_float_t (*frequency)(mus_any *ptr);
92 mus_float_t (*set_frequency)(mus_any *ptr, mus_float_t new_freq);
93 mus_float_t (*phase)(mus_any *ptr);
94 mus_float_t (*set_phase)(mus_any *ptr, mus_float_t new_phase);
95 mus_float_t (*scaler)(mus_any *ptr);
96 mus_float_t (*set_scaler)(mus_any *ptr, mus_float_t val);
97 mus_float_t (*increment)(mus_any *ptr);
98 mus_float_t (*set_increment)(mus_any *ptr, mus_float_t val);
99 mus_float_t (*run)(mus_any *gen, mus_float_t arg1, mus_float_t arg2);
100 mus_clm_extended_t extended_type;
101 void *(*closure)(mus_any *gen);
102 int (*channels)(mus_any *ptr);
103 mus_float_t (*offset)(mus_any *ptr);
104 mus_float_t (*set_offset)(mus_any *ptr, mus_float_t val);
105 mus_float_t (*width)(mus_any *ptr);
106 mus_float_t (*set_width)(mus_any *ptr, mus_float_t val);
107 mus_float_t (*xcoeff)(mus_any *ptr, int index);
108 mus_float_t (*set_xcoeff)(mus_any *ptr, int index, mus_float_t val);
109 mus_long_t (*hop)(mus_any *ptr);
110 mus_long_t (*set_hop)(mus_any *ptr, mus_long_t new_length);
111 mus_long_t (*ramp)(mus_any *ptr);
112 mus_long_t (*set_ramp)(mus_any *ptr, mus_long_t new_length);
113 mus_float_t (*read_sample)(mus_any *ptr, mus_long_t samp, int chan);
114 mus_float_t (*write_sample)(mus_any *ptr, mus_long_t samp, int chan, mus_float_t data);
115 char *(*file_name)(mus_any *ptr);
116 int (*end)(mus_any *ptr);
117 mus_long_t (*location)(mus_any *ptr);
118 mus_long_t (*set_location)(mus_any *ptr, mus_long_t loc);
119 int (*channel)(mus_any *ptr);
120 mus_float_t (*ycoeff)(mus_any *ptr, int index);
121 mus_float_t (*set_ycoeff)(mus_any *ptr, int index, mus_float_t val);
122 mus_float_t *(*xcoeffs)(mus_any *ptr);
123 mus_float_t *(*ycoeffs)(mus_any *ptr);
124 void (*reset)(mus_any *ptr);
125 void *(*set_closure)(mus_any *gen, void *e);
126 mus_any *(*copy)(mus_any *ptr);
127 };
128
129
130 enum {MUS_OSCIL, MUS_NCOS, MUS_DELAY, MUS_COMB, MUS_NOTCH, MUS_ALL_PASS,
131 MUS_TABLE_LOOKUP, MUS_SQUARE_WAVE, MUS_SAWTOOTH_WAVE, MUS_TRIANGLE_WAVE, MUS_PULSE_TRAIN,
132 MUS_RAND, MUS_RAND_INTERP, MUS_ASYMMETRIC_FM, MUS_ONE_ZERO, MUS_ONE_POLE, MUS_TWO_ZERO, MUS_TWO_POLE, MUS_FORMANT,
133 MUS_SRC, MUS_GRANULATE, MUS_WAVE_TRAIN,
134 MUS_FILTER, MUS_FIR_FILTER, MUS_IIR_FILTER, MUS_CONVOLVE, MUS_ENV, MUS_LOCSIG,
135 MUS_READIN, MUS_FILE_TO_SAMPLE, MUS_FILE_TO_FRAMPLE,
136 MUS_SAMPLE_TO_FILE, MUS_FRAMPLE_TO_FILE, MUS_PHASE_VOCODER,
137 MUS_MOVING_AVERAGE, MUS_MOVING_MAX, MUS_MOVING_NORM, MUS_NSIN, MUS_SSB_AM, MUS_POLYSHAPE, MUS_FILTERED_COMB,
138 MUS_MOVE_SOUND, MUS_NRXYSIN, MUS_NRXYCOS, MUS_POLYWAVE, MUS_FIRMANT, MUS_FORMANT_BANK,
139 MUS_ONE_POLE_ALL_PASS, MUS_COMB_BANK, MUS_ALL_PASS_BANK, MUS_FILTERED_COMB_BANK, MUS_OSCIL_BANK,
140 MUS_PULSED_ENV, MUS_RXYKSIN, MUS_RXYKCOS,
141 MUS_INITIAL_GEN_TAG};
142
mus_generator_class(mus_any * ptr)143 mus_any_class *mus_generator_class(mus_any *ptr) {return(ptr->core);}
144
mus_generator_set_extended_type(mus_any_class * p,mus_clm_extended_t extended_type)145 void mus_generator_set_extended_type(mus_any_class *p, mus_clm_extended_t extended_type) {p->extended_type = extended_type;}
mus_generator_set_length(mus_any_class * p,mus_long_t (* length)(mus_any * ptr))146 void mus_generator_set_length(mus_any_class *p, mus_long_t (*length)(mus_any *ptr)) {p->length = length;}
mus_generator_set_scaler(mus_any_class * p,mus_float_t (* scaler)(mus_any * ptr))147 void mus_generator_set_scaler(mus_any_class *p, mus_float_t (*scaler)(mus_any *ptr)) {p->scaler = scaler;}
mus_generator_set_channels(mus_any_class * p,int (* channels)(mus_any * ptr))148 void mus_generator_set_channels(mus_any_class *p, int (*channels)(mus_any *ptr)) {p->channels = channels;}
mus_generator_set_location(mus_any_class * p,mus_long_t (* location)(mus_any * ptr))149 void mus_generator_set_location(mus_any_class *p, mus_long_t (*location)(mus_any *ptr)) {p->location = location;}
mus_generator_set_set_location(mus_any_class * p,mus_long_t (* set_location)(mus_any * ptr,mus_long_t loc))150 void mus_generator_set_set_location(mus_any_class *p, mus_long_t (*set_location)(mus_any *ptr, mus_long_t loc)) {p->set_location = set_location;}
mus_generator_set_read_sample(mus_any_class * p,mus_float_t (* read_sample)(mus_any * ptr,mus_long_t samp,int chan))151 void mus_generator_set_read_sample(mus_any_class *p, mus_float_t (*read_sample)(mus_any *ptr, mus_long_t samp, int chan)) {p->read_sample = read_sample;}
mus_generator_set_channel(mus_any_class * p,int (* channel)(mus_any * ptr))152 void mus_generator_set_channel(mus_any_class *p, int (*channel)(mus_any *ptr)) {p->channel = channel;}
mus_generator_set_file_name(mus_any_class * p,char * (* file_name)(mus_any * ptr))153 void mus_generator_set_file_name(mus_any_class *p, char *(*file_name)(mus_any *ptr)) {p->file_name = file_name;}
154
mus_make_generator(int type,char * name,void (* release)(mus_any * ptr),char * (* describe)(mus_any * ptr),bool (* equalp)(mus_any * gen1,mus_any * gen2))155 mus_any_class *mus_make_generator(int type, char *name,
156 void (*release)(mus_any *ptr),
157 char *(*describe)(mus_any *ptr),
158 bool (*equalp)(mus_any *gen1, mus_any *gen2))
159 {
160 mus_any_class *p;
161 p = (mus_any_class *)calloc(1, sizeof(mus_any_class));
162 p->type = type;
163 p->name = name;
164 p->release = release;
165 p->describe = describe;
166 p->equalp = equalp;
167 return(p);
168 }
169
170
171 static int mus_generator_type = MUS_INITIAL_GEN_TAG;
172
mus_make_generator_type(void)173 int mus_make_generator_type(void) {return(mus_generator_type++);}
174
175
176 static const char *interp_name[] = {"step", "linear", "sinusoidal", "all-pass", "lagrange", "bezier", "hermite"};
177
mus_interp_type_to_string(int type)178 const char *mus_interp_type_to_string(int type)
179 {
180 if (mus_is_interp_type(type))
181 return(interp_name[type]);
182 return("unknown");
183 }
184
185
186 static mus_float_t sampling_rate = MUS_DEFAULT_SAMPLING_RATE;
187
188 static mus_float_t w_rate = (TWO_PI / MUS_DEFAULT_SAMPLING_RATE);
189
190
191 static mus_float_t float_equal_fudge_factor = 0.0000001;
192
mus_float_equal_fudge_factor(void)193 mus_float_t mus_float_equal_fudge_factor(void) {return(float_equal_fudge_factor);}
194
mus_set_float_equal_fudge_factor(mus_float_t val)195 mus_float_t mus_set_float_equal_fudge_factor(mus_float_t val)
196 {
197 mus_float_t prev;
198 prev = float_equal_fudge_factor;
199 float_equal_fudge_factor = val;
200 return(prev);
201 }
202
203
204 static int array_print_length = MUS_DEFAULT_ARRAY_PRINT_LENGTH;
205
mus_array_print_length(void)206 int mus_array_print_length(void) {return(array_print_length);}
207
mus_set_array_print_length(int val)208 int mus_set_array_print_length(int val)
209 {
210 int prev;
211 prev = array_print_length;
212 if (val >= 0) array_print_length = val;
213 return(prev);
214 }
215
216
217 static mus_long_t clm_file_buffer_size = MUS_DEFAULT_FILE_BUFFER_SIZE;
218
mus_file_buffer_size(void)219 mus_long_t mus_file_buffer_size(void) {return(clm_file_buffer_size);}
220
mus_set_file_buffer_size(mus_long_t size)221 mus_long_t mus_set_file_buffer_size(mus_long_t size)
222 {
223 /* this is set in with-sound, among other places */
224 mus_long_t prev;
225 prev = clm_file_buffer_size;
226 clm_file_buffer_size = size;
227 return(prev);
228 }
229
230
mus_radians_to_hz(mus_float_t rads)231 mus_float_t mus_radians_to_hz(mus_float_t rads) {return(rads / w_rate);}
mus_hz_to_radians(mus_float_t hz)232 mus_float_t mus_hz_to_radians(mus_float_t hz) {return(hz * w_rate);}
233
234
mus_degrees_to_radians(mus_float_t degree)235 mus_float_t mus_degrees_to_radians(mus_float_t degree) {return(degree * TWO_PI / 360.0);}
mus_radians_to_degrees(mus_float_t rads)236 mus_float_t mus_radians_to_degrees(mus_float_t rads) {return(rads * 360.0 / TWO_PI);}
237
238
mus_db_to_linear(mus_float_t x)239 mus_float_t mus_db_to_linear(mus_float_t x) {return(pow(10.0, x / 20.0));}
mus_linear_to_db(mus_float_t x)240 mus_float_t mus_linear_to_db(mus_float_t x) {if (x > 0.0) return(20.0 * log10(x)); return(-100.0);}
241
242
mus_odd_multiple(mus_float_t x,mus_float_t y)243 mus_float_t mus_odd_multiple(mus_float_t x, mus_float_t y) {mus_long_t f; f = (mus_long_t)floor(x); return(y * ((f & 1) ? f : (f + 1)));}
mus_even_multiple(mus_float_t x,mus_float_t y)244 mus_float_t mus_even_multiple(mus_float_t x, mus_float_t y) {mus_long_t f; f = (mus_long_t)floor(x); return(y * ((f & 1) ? (f + 1) : f));}
mus_odd_weight(mus_float_t x)245 mus_float_t mus_odd_weight(mus_float_t x) {mus_long_t f; f = (mus_long_t)floor(x); return(1.0 - fabs(x - ((f & 1) ? f : (f + 1))));}
mus_even_weight(mus_float_t x)246 mus_float_t mus_even_weight(mus_float_t x) {mus_long_t f; f = (mus_long_t)floor(x); return(1.0 - fabs(x - ((f & 1) ? (f + 1) : f)));}
247
mus_srate(void)248 mus_float_t mus_srate(void) {return(sampling_rate);}
249
mus_set_srate(mus_float_t val)250 mus_float_t mus_set_srate(mus_float_t val)
251 {
252 mus_float_t prev;
253 prev = sampling_rate;
254 if (val > 0.0)
255 {
256 sampling_rate = val;
257 w_rate = (TWO_PI / sampling_rate);
258 }
259 return(prev);
260 }
261
262
mus_seconds_to_samples(mus_float_t secs)263 mus_long_t mus_seconds_to_samples(mus_float_t secs) {return((mus_long_t)(secs * sampling_rate));}
mus_samples_to_seconds(mus_long_t samps)264 mus_float_t mus_samples_to_seconds(mus_long_t samps) {return((mus_float_t)((mus_float_t)samps / (mus_float_t)sampling_rate));}
265
266
267 #define DESCRIBE_BUFFER_SIZE 2048
268 #define STR_SIZE 128
269
float_array_to_string(mus_float_t * arr,int len,int loc)270 static char *float_array_to_string(mus_float_t *arr, int len, int loc)
271 {
272 /* %g is needed here rather than %f -- otherwise the number strings can be any size */
273 #define MAX_NUM_SIZE 64
274 char *base, *str;
275 int i, lim, size = 512;
276 if (!arr)
277 {
278 str = (char *)malloc(4 * sizeof(char));
279 snprintf(str, 4, "nil");
280 return(str);
281 }
282 lim = (array_print_length + 4) * MAX_NUM_SIZE; /* 4 for possible bounds below */
283 if (lim > size) size = lim;
284 if (loc < 0) loc = 0;
285
286 base = (char *)calloc(size, sizeof(char));
287 str = (char *)malloc(STR_SIZE * sizeof(char));
288
289 if (len > 0)
290 {
291 int k;
292 snprintf(base, size, "[");
293 lim = len;
294 if (lim > array_print_length) lim = array_print_length;
295 k = loc;
296 if (k >= len) k = 0;
297 for (i = 0; i < lim - 1; i++)
298 {
299 snprintf(str, STR_SIZE, "%.3g ", arr[k]);
300 strcat(base, str);
301 if ((int)(strlen(base) + MAX_NUM_SIZE) > size)
302 {
303 base = (char *)realloc(base, size * 2 * sizeof(char));
304 base[size] = 0;
305 size *= 2;
306 }
307 k++;
308 if (k >= len) k = 0;
309 }
310 snprintf(str, STR_SIZE, "%.3g%s", arr[k], (len > lim) ? "..." : "]");
311 strcat(base, str);
312 }
313 else snprintf(base, size, "[]");
314 if (len > lim)
315 {
316 /* print ranges */
317 int min_loc = 0, max_loc = 0;
318 mus_float_t min_val, max_val;
319 min_val = arr[0];
320 max_val = arr[0];
321 for (i = 1; i < len; i++)
322 {
323 if (arr[i] < min_val) {min_val = arr[i]; min_loc = i;}
324 if (arr[i] > max_val) {max_val = arr[i]; max_loc = i;}
325 }
326 snprintf(str, STR_SIZE, "(%d: %.3g, %d: %.3g)]", min_loc, min_val, max_loc, max_val);
327 strcat(base, str);
328 }
329 free(str);
330 return(base);
331 }
332
333
clm_array_to_string(mus_any ** gens,int num_gens,const char * name,const char * indent)334 static char *clm_array_to_string(mus_any **gens, int num_gens, const char *name, const char *indent)
335 {
336 char *descr = NULL;
337 if ((gens) && (num_gens > 0))
338 {
339 int i, len = 0;
340 char **descrs;
341 descrs = (char **)calloc(num_gens, sizeof(char *));
342 for (i = 0; i < num_gens; i++)
343 {
344 if (gens[i])
345 {
346 char *str;
347 str = mus_describe(gens[i]);
348 if (str)
349 {
350 descrs[i] = mus_format("\n%s[%d]: %s", indent, i, str);
351 free(str);
352 }
353 else descrs[i] = mus_format("\n%s[%d]:", indent, i);
354 }
355 else descrs[i] = mus_format("\n%s[%d]: nil", indent, i);
356 len += strlen(descrs[i]);
357 }
358 len += (64 + strlen(name));
359 descr = (char *)malloc(len * sizeof(char));
360 snprintf(descr, len, "%s[%d]:", name, num_gens);
361 for (i = 0; i < num_gens; i++)
362 {
363 strcat(descr, descrs[i]);
364 free(descrs[i]);
365 }
366 free(descrs);
367 }
368 else
369 {
370 descr = (char *)malloc(128 * sizeof(char));
371 snprintf(descr, 128, "%s: nil", name);
372 }
373 return(descr);
374 }
375
376
int_array_to_string(int * arr,int num_ints,const char * name)377 static char *int_array_to_string(int *arr, int num_ints, const char *name)
378 {
379 #define MAX_INT_SIZE 32
380 char *descr = NULL;
381 if ((arr) && (num_ints > 0))
382 {
383 int i, len;
384 char *intstr;
385 len = num_ints * MAX_INT_SIZE + 64;
386 descr = (char *)calloc(len, sizeof(char));
387 intstr = (char *)malloc(MAX_INT_SIZE * sizeof(char));
388 snprintf(descr, len, "%s[%d]: (", name, num_ints);
389 for (i = 0; i < num_ints - 1; i++)
390 {
391 snprintf(intstr, MAX_INT_SIZE, "%d ", arr[i]);
392 strcat(descr, intstr);
393 }
394 snprintf(intstr, MAX_INT_SIZE, "%d)", arr[num_ints - 1]);
395 strcat(descr, intstr);
396 free(intstr);
397 }
398 else
399 {
400 descr = (char *)malloc(128 * sizeof(char));
401 snprintf(descr, 128, "%s: nil", name);
402 }
403 return(descr);
404 }
405
406
407
408 /* ---------------- generic functions ---------------- */
409
410 #define check_gen(Ptr, Name) ((Ptr) ? true : (!mus_error(MUS_NO_GEN, "null generator passed to %s", Name)))
411
mus_type(mus_any * ptr)412 int mus_type(mus_any *ptr)
413 {
414 return(((check_gen(ptr, S_mus_type)) && (ptr->core)) ? ptr->core->type : -1);
415 }
416
417
mus_name(mus_any * ptr)418 const char *mus_name(mus_any *ptr)
419 {
420 return((!ptr) ? "null" : ptr->core->name);
421 }
422
423
mus_free(mus_any * gen)424 void mus_free(mus_any *gen)
425 {
426 if (gen)
427 (*(gen->core->release))(gen);
428 }
429
430
mus_describe(mus_any * gen)431 char *mus_describe(mus_any *gen)
432 {
433 if (!gen)
434 return(mus_strdup((char *)"null"));
435 if ((gen->core) && (gen->core->describe))
436 return((*(gen->core->describe))(gen));
437 else mus_error(MUS_NO_DESCRIBE, "can't describe %s", mus_name(gen));
438 return(NULL);
439 }
440
441
mus_equalp(mus_any * p1,mus_any * p2)442 bool mus_equalp(mus_any *p1, mus_any *p2)
443 {
444 if ((p1) && (p2))
445 {
446 if ((p1->core)->equalp)
447 return((*((p1->core)->equalp))(p1, p2));
448 else return(p1 == p2);
449 }
450 return(true); /* (eq nil nil) */
451 }
452
453
mus_reset(mus_any * gen)454 void mus_reset(mus_any *gen)
455 {
456 if ((check_gen(gen, S_mus_reset)) &&
457 (gen->core->reset))
458 (*(gen->core->reset))(gen);
459 else mus_error(MUS_NO_RESET, "can't reset %s", mus_name(gen));
460 }
461
462
mus_copy(mus_any * gen)463 mus_any *mus_copy(mus_any *gen)
464 {
465 if ((check_gen(gen, S_mus_copy)) &&
466 (gen->core->copy))
467 return((*(gen->core->copy))(gen));
468 else mus_error(MUS_NO_COPY, "can't copy %s", mus_name(gen));
469 return(NULL);
470 }
471
472
mus_frequency(mus_any * gen)473 mus_float_t mus_frequency(mus_any *gen)
474 {
475 if ((check_gen(gen, S_mus_frequency)) &&
476 (gen->core->frequency))
477 return((*(gen->core->frequency))(gen));
478 return((mus_float_t)mus_error(MUS_NO_FREQUENCY, "can't get %s's frequency", mus_name(gen)));
479 }
480
481
mus_set_frequency(mus_any * gen,mus_float_t val)482 mus_float_t mus_set_frequency(mus_any *gen, mus_float_t val)
483 {
484 if ((check_gen(gen, S_set S_mus_frequency)) &&
485 (gen->core->set_frequency))
486 return((*(gen->core->set_frequency))(gen, val));
487 return((mus_float_t)mus_error(MUS_NO_FREQUENCY, "can't set %s's frequency", mus_name(gen)));
488 }
489
490
mus_phase(mus_any * gen)491 mus_float_t mus_phase(mus_any *gen)
492 {
493 if ((check_gen(gen, S_mus_phase)) &&
494 (gen->core->phase))
495 return((*(gen->core->phase))(gen));
496 return((mus_float_t)mus_error(MUS_NO_PHASE, "can't get %s's phase", mus_name(gen)));
497 }
498
499
mus_set_phase(mus_any * gen,mus_float_t val)500 mus_float_t mus_set_phase(mus_any *gen, mus_float_t val)
501 {
502 if ((check_gen(gen, S_set S_mus_phase)) &&
503 (gen->core->set_phase))
504 return((*(gen->core->set_phase))(gen, val));
505 return((mus_float_t)mus_error(MUS_NO_PHASE, "can't set %s's phase", mus_name(gen)));
506 }
507
508
509
mus_scaler(mus_any * gen)510 mus_float_t mus_scaler(mus_any *gen)
511 {
512 if ((check_gen(gen, S_mus_scaler)) &&
513 (gen->core->scaler))
514 return((*(gen->core->scaler))(gen));
515 return((mus_float_t)mus_error(MUS_NO_SCALER, "can't get %s's scaler", mus_name(gen)));
516 }
517
518
mus_set_scaler(mus_any * gen,mus_float_t val)519 mus_float_t mus_set_scaler(mus_any *gen, mus_float_t val)
520 {
521 if ((check_gen(gen, S_set S_mus_scaler)) &&
522 (gen->core->set_scaler))
523 return((*(gen->core->set_scaler))(gen, val));
524 return((mus_float_t)mus_error(MUS_NO_SCALER, "can't set %s's scaler", mus_name(gen)));
525 }
526
527
mus_feedforward(mus_any * gen)528 mus_float_t mus_feedforward(mus_any *gen) /* shares "scaler" */
529 {
530 if ((check_gen(gen, S_mus_feedforward)) &&
531 (gen->core->scaler))
532 return((*(gen->core->scaler))(gen));
533 return((mus_float_t)mus_error(MUS_NO_FEEDFORWARD, "can't get %s's feedforward", mus_name(gen)));
534 }
535
536
mus_set_feedforward(mus_any * gen,mus_float_t val)537 mus_float_t mus_set_feedforward(mus_any *gen, mus_float_t val)
538 {
539 if ((check_gen(gen, S_set S_mus_feedforward)) &&
540 (gen->core->set_scaler))
541 return((*(gen->core->set_scaler))(gen, val));
542 return((mus_float_t)mus_error(MUS_NO_FEEDFORWARD, "can't set %s's feedforward", mus_name(gen)));
543 }
544
545
mus_offset(mus_any * gen)546 mus_float_t mus_offset(mus_any *gen)
547 {
548 if ((check_gen(gen, S_mus_offset)) &&
549 (gen->core->offset))
550 return((*(gen->core->offset))(gen));
551 return((mus_float_t)mus_error(MUS_NO_OFFSET, "can't get %s's offset", mus_name(gen)));
552 }
553
554
mus_set_offset(mus_any * gen,mus_float_t val)555 mus_float_t mus_set_offset(mus_any *gen, mus_float_t val)
556 {
557 if ((check_gen(gen, S_set S_mus_offset)) &&
558 (gen->core->set_offset))
559 return((*(gen->core->set_offset))(gen, val));
560 return((mus_float_t)mus_error(MUS_NO_OFFSET, "can't set %s's offset", mus_name(gen)));
561 }
562
563
mus_width(mus_any * gen)564 mus_float_t mus_width(mus_any *gen)
565 {
566 if ((check_gen(gen, S_mus_width)) &&
567 (gen->core->width))
568 return((*(gen->core->width))(gen));
569 return((mus_float_t)mus_error(MUS_NO_WIDTH, "can't get %s's width", mus_name(gen)));
570 }
571
572
mus_set_width(mus_any * gen,mus_float_t val)573 mus_float_t mus_set_width(mus_any *gen, mus_float_t val)
574 {
575 if ((check_gen(gen, S_set S_mus_width)) &&
576 (gen->core->set_width))
577 return((*(gen->core->set_width))(gen, val));
578 return((mus_float_t)mus_error(MUS_NO_WIDTH, "can't set %s's width", mus_name(gen)));
579 }
580
581
mus_increment(mus_any * gen)582 mus_float_t mus_increment(mus_any *gen)
583 {
584 if ((check_gen(gen, S_mus_increment)) &&
585 (gen->core->increment))
586 return((*(gen->core->increment))(gen));
587 return((mus_float_t)mus_error(MUS_NO_INCREMENT, "can't get %s's increment", mus_name(gen)));
588 }
589
590
mus_set_increment(mus_any * gen,mus_float_t val)591 mus_float_t mus_set_increment(mus_any *gen, mus_float_t val)
592 {
593 if ((check_gen(gen, S_set S_mus_increment)) &&
594 (gen->core->set_increment))
595 return((*(gen->core->set_increment))(gen, val));
596 return((mus_float_t)mus_error(MUS_NO_INCREMENT, "can't set %s's increment", mus_name(gen)));
597 }
598
599
mus_feedback(mus_any * gen)600 mus_float_t mus_feedback(mus_any *gen) /* shares "increment" */
601 {
602 if ((check_gen(gen, S_mus_feedback)) &&
603 (gen->core->increment))
604 return((*(gen->core->increment))(gen));
605 return((mus_float_t)mus_error(MUS_NO_FEEDBACK, "can't get %s's feedback", mus_name(gen)));
606 }
607
608
mus_set_feedback(mus_any * gen,mus_float_t val)609 mus_float_t mus_set_feedback(mus_any *gen, mus_float_t val)
610 {
611 if ((check_gen(gen, S_set S_mus_feedback)) &&
612 (gen->core->set_increment))
613 return((*(gen->core->set_increment))(gen, val));
614 return((mus_float_t)mus_error(MUS_NO_FEEDBACK, "can't set %s's feedback", mus_name(gen)));
615 }
616
617
mus_environ(mus_any * gen)618 void *mus_environ(mus_any *gen)
619 {
620 if (check_gen(gen, "mus-environ"))
621 return((*(gen->core->closure))(gen));
622 return(NULL);
623 }
624
625
mus_set_environ(mus_any * gen,void * e)626 void *mus_set_environ(mus_any *gen, void *e)
627 {
628 if (check_gen(gen, S_set "mus-environ"))
629 return((*(gen->core->set_closure))(gen, e));
630 return(NULL);
631 }
632
633
mus_run(mus_any * gen,mus_float_t arg1,mus_float_t arg2)634 mus_float_t mus_run(mus_any *gen, mus_float_t arg1, mus_float_t arg2)
635 {
636 if ((check_gen(gen, "mus-run")) &&
637 (gen->core->run))
638 return((*(gen->core->run))(gen, arg1, arg2));
639 return((mus_float_t)mus_error(MUS_NO_RUN, "can't run %s", mus_name(gen)));
640 }
641
642
mus_length(mus_any * gen)643 mus_long_t mus_length(mus_any *gen)
644 {
645 if ((check_gen(gen, S_mus_length)) &&
646 (gen->core->length))
647 return((*(gen->core->length))(gen));
648 return(mus_error(MUS_NO_LENGTH, "can't get %s's length", mus_name(gen)));
649 }
650
651
mus_set_length(mus_any * gen,mus_long_t len)652 mus_long_t mus_set_length(mus_any *gen, mus_long_t len)
653 {
654 if ((check_gen(gen, S_set S_mus_length)) &&
655 (gen->core->set_length))
656 return((*(gen->core->set_length))(gen, len));
657 return(mus_error(MUS_NO_LENGTH, "can't set %s's length", mus_name(gen)));
658 }
659
660
mus_order(mus_any * gen)661 mus_long_t mus_order(mus_any *gen) /* shares "length", no set */
662 {
663 if ((check_gen(gen, S_mus_order)) &&
664 (gen->core->length))
665 return((*(gen->core->length))(gen));
666 return(mus_error(MUS_NO_ORDER, "can't get %s's order", mus_name(gen)));
667 }
668
669
mus_channels(mus_any * gen)670 int mus_channels(mus_any *gen)
671 {
672 if ((check_gen(gen, S_mus_channels)) &&
673 (gen->core->channels))
674 return((*(gen->core->channels))(gen));
675 return(mus_error(MUS_NO_CHANNELS, "can't get %s's channels", mus_name(gen)));
676 }
677
678
mus_interp_type(mus_any * gen)679 int mus_interp_type(mus_any *gen) /* shares "channels", no set */
680 {
681 if ((check_gen(gen, S_mus_interp_type)) &&
682 (gen->core->channels))
683 return((*(gen->core->channels))(gen));
684 return(mus_error(MUS_NO_INTERP_TYPE, "can't get %s's interp type", mus_name(gen)));
685 }
686
687
mus_position(mus_any * gen)688 int mus_position(mus_any *gen) /* shares "channels", no set, only used in C (snd-env.c) */
689 {
690 if ((check_gen(gen, "mus-position")) &&
691 (gen->core->channels))
692 return((*(gen->core->channels))(gen));
693 return(mus_error(MUS_NO_POSITION, "can't get %s's position", mus_name(gen)));
694 }
695
696
mus_channel(mus_any * gen)697 int mus_channel(mus_any *gen)
698 {
699 if ((check_gen(gen, S_mus_channel)) &&
700 (gen->core->channel))
701 return(((*gen->core->channel))(gen));
702 return(mus_error(MUS_NO_CHANNEL, "can't get %s's channel", mus_name(gen)));
703 }
704
705
mus_hop(mus_any * gen)706 mus_long_t mus_hop(mus_any *gen)
707 {
708 if ((check_gen(gen, S_mus_hop)) &&
709 (gen->core->hop))
710 return((*(gen->core->hop))(gen));
711 return(mus_error(MUS_NO_HOP, "can't get %s's hop value", mus_name(gen)));
712 }
713
714
mus_set_hop(mus_any * gen,mus_long_t len)715 mus_long_t mus_set_hop(mus_any *gen, mus_long_t len)
716 {
717 if ((check_gen(gen, S_set S_mus_hop)) &&
718 (gen->core->set_hop))
719 return((*(gen->core->set_hop))(gen, len));
720 return(mus_error(MUS_NO_HOP, "can't set %s's hop value", mus_name(gen)));
721 }
722
723
mus_ramp(mus_any * gen)724 mus_long_t mus_ramp(mus_any *gen)
725 {
726 if ((check_gen(gen, S_mus_ramp)) &&
727 (gen->core->ramp))
728 return((*(gen->core->ramp))(gen));
729 return(mus_error(MUS_NO_RAMP, "can't get %s's ramp value", mus_name(gen)));
730 }
731
732
mus_set_ramp(mus_any * gen,mus_long_t len)733 mus_long_t mus_set_ramp(mus_any *gen, mus_long_t len)
734 {
735 if ((check_gen(gen, S_set S_mus_ramp)) &&
736 (gen->core->set_ramp))
737 return((*(gen->core->set_ramp))(gen, len));
738 return(mus_error(MUS_NO_RAMP, "can't set %s's ramp value", mus_name(gen)));
739 }
740
741
mus_data(mus_any * gen)742 mus_float_t *mus_data(mus_any *gen)
743 {
744 if ((check_gen(gen, S_mus_data)) &&
745 (gen->core->data))
746 return((*(gen->core->data))(gen));
747 mus_error(MUS_NO_DATA, "can't get %s's data", mus_name(gen));
748 return(NULL);
749 }
750
751
752 /* every case that implements the data or set data functions needs to include
753 * a var-allocated flag, since all such memory has to be handled via vcts
754 */
755
mus_set_data(mus_any * gen,mus_float_t * new_data)756 mus_float_t *mus_set_data(mus_any *gen, mus_float_t *new_data)
757 {
758 if (check_gen(gen, S_set S_mus_data))
759 {
760 if (gen->core->set_data)
761 {
762 (*(gen->core->set_data))(gen, new_data);
763 return(new_data);
764 }
765 else mus_error(MUS_NO_DATA, "can't set %s's data", mus_name(gen));
766 }
767 return(new_data);
768 }
769
770
mus_xcoeffs(mus_any * gen)771 mus_float_t *mus_xcoeffs(mus_any *gen)
772 {
773 if ((check_gen(gen, S_mus_xcoeffs)) &&
774 (gen->core->xcoeffs))
775 return((*(gen->core->xcoeffs))(gen));
776 mus_error(MUS_NO_XCOEFFS, "can't get %s's xcoeffs", mus_name(gen));
777 return(NULL);
778 }
779
780
mus_ycoeffs(mus_any * gen)781 mus_float_t *mus_ycoeffs(mus_any *gen)
782 {
783 if ((check_gen(gen, S_mus_ycoeffs)) &&
784 (gen->core->ycoeffs))
785 return((*(gen->core->ycoeffs))(gen));
786 mus_error(MUS_NO_YCOEFFS, "can't get %s's ycoeffs", mus_name(gen));
787 return(NULL);
788 }
789
790
mus_xcoeff(mus_any * gen,int index)791 mus_float_t mus_xcoeff(mus_any *gen, int index)
792 {
793 if ((check_gen(gen, S_mus_xcoeff)) &&
794 (gen->core->xcoeff))
795 return((*(gen->core->xcoeff))(gen, index));
796 return(mus_error(MUS_NO_XCOEFF, "can't get %s's xcoeff[%d] value", mus_name(gen), index));
797 }
798
799
mus_set_xcoeff(mus_any * gen,int index,mus_float_t val)800 mus_float_t mus_set_xcoeff(mus_any *gen, int index, mus_float_t val)
801 {
802 if ((check_gen(gen, S_set S_mus_xcoeff)) &&
803 (gen->core->set_xcoeff))
804 return((*(gen->core->set_xcoeff))(gen, index, val));
805 return(mus_error(MUS_NO_XCOEFF, "can't set %s's xcoeff[%d] value", mus_name(gen), index));
806 }
807
808
mus_ycoeff(mus_any * gen,int index)809 mus_float_t mus_ycoeff(mus_any *gen, int index)
810 {
811 if ((check_gen(gen, S_mus_ycoeff)) &&
812 (gen->core->ycoeff))
813 return((*(gen->core->ycoeff))(gen, index));
814 return(mus_error(MUS_NO_YCOEFF, "can't get %s's ycoeff[%d] value", mus_name(gen), index));
815 }
816
817
mus_set_ycoeff(mus_any * gen,int index,mus_float_t val)818 mus_float_t mus_set_ycoeff(mus_any *gen, int index, mus_float_t val)
819 {
820 if ((check_gen(gen, S_set S_mus_ycoeff)) &&
821 (gen->core->set_ycoeff))
822 return((*(gen->core->set_ycoeff))(gen, index, val));
823 return(mus_error(MUS_NO_YCOEFF, "can't set %s's ycoeff[%d] value", mus_name(gen), index));
824 }
825
826
mus_location(mus_any * gen)827 mus_long_t mus_location(mus_any *gen)
828 {
829 if ((check_gen(gen, S_mus_location)) &&
830 (gen->core->location))
831 return(((*gen->core->location))(gen));
832 return((mus_long_t)mus_error(MUS_NO_LOCATION, "can't get %s's location", mus_name(gen)));
833 }
834
mus_set_location(mus_any * gen,mus_long_t loc)835 mus_long_t mus_set_location(mus_any *gen, mus_long_t loc)
836 {
837 if ((check_gen(gen, S_set S_mus_location)) &&
838 (gen->core->set_location))
839 return((*(gen->core->set_location))(gen, loc));
840 return((mus_long_t)mus_error(MUS_NO_LOCATION, "can't set %s's location", mus_name(gen)));
841 }
842
mus_file_name(mus_any * gen)843 char *mus_file_name(mus_any *gen)
844 {
845 if ((check_gen(gen, S_mus_file_name)) &&
846 (gen->core->file_name))
847 return((*(gen->core->file_name))(gen));
848 else mus_error(MUS_NO_FILE_NAME, "can't get %s's file name", mus_name(gen));
849 return(NULL);
850 }
851
852
mus_phase_exists(mus_any * gen)853 bool mus_phase_exists(mus_any *gen) {return(gen->core->phase);}
mus_frequency_exists(mus_any * gen)854 bool mus_frequency_exists(mus_any *gen) {return(gen->core->frequency);}
mus_length_exists(mus_any * gen)855 bool mus_length_exists(mus_any *gen) {return(gen->core->length);}
mus_order_exists(mus_any * gen)856 bool mus_order_exists(mus_any *gen) {return(gen->core->length);}
mus_data_exists(mus_any * gen)857 bool mus_data_exists(mus_any *gen) {return(gen->core->data);}
mus_name_exists(mus_any * gen)858 bool mus_name_exists(mus_any *gen) {return(gen->core->name);}
mus_scaler_exists(mus_any * gen)859 bool mus_scaler_exists(mus_any *gen) {return(gen->core->scaler);}
mus_offset_exists(mus_any * gen)860 bool mus_offset_exists(mus_any *gen) {return(gen->core->offset);}
mus_width_exists(mus_any * gen)861 bool mus_width_exists(mus_any *gen) {return(gen->core->width);}
mus_file_name_exists(mus_any * gen)862 bool mus_file_name_exists(mus_any *gen) {return(gen->core->file_name);}
mus_xcoeffs_exists(mus_any * gen)863 bool mus_xcoeffs_exists(mus_any *gen) {return(gen->core->xcoeffs);}
mus_ycoeffs_exists(mus_any * gen)864 bool mus_ycoeffs_exists(mus_any *gen) {return(gen->core->ycoeffs);}
mus_increment_exists(mus_any * gen)865 bool mus_increment_exists(mus_any *gen) {return(gen->core->increment);}
mus_location_exists(mus_any * gen)866 bool mus_location_exists(mus_any *gen) {return(gen->core->location);}
mus_channel_exists(mus_any * gen)867 bool mus_channel_exists(mus_any *gen) {return(gen->core->channel);}
mus_channels_exists(mus_any * gen)868 bool mus_channels_exists(mus_any *gen) {return(gen->core->channels);}
mus_interp_type_exists(mus_any * gen)869 bool mus_interp_type_exists(mus_any *gen) {return(gen->core->channels);}
mus_ramp_exists(mus_any * gen)870 bool mus_ramp_exists(mus_any *gen) {return(gen->core->ramp);}
mus_hop_exists(mus_any * gen)871 bool mus_hop_exists(mus_any *gen) {return(gen->core->hop);}
mus_feedforward_exists(mus_any * gen)872 bool mus_feedforward_exists(mus_any *gen) {return(gen->core->scaler);}
mus_feedback_exists(mus_any * gen)873 bool mus_feedback_exists(mus_any *gen) {return(gen->core->increment);}
874
875
876 /* ---------------- AM etc ---------------- */
877
mus_ring_modulate(mus_float_t sig1,mus_float_t sig2)878 mus_float_t mus_ring_modulate(mus_float_t sig1, mus_float_t sig2)
879 {
880 return(sig1 * sig2);
881 }
882
883
mus_amplitude_modulate(mus_float_t carrier,mus_float_t sig1,mus_float_t sig2)884 mus_float_t mus_amplitude_modulate(mus_float_t carrier, mus_float_t sig1, mus_float_t sig2)
885 {
886 return(sig1 * (carrier + sig2));
887 }
888
889
mus_contrast_enhancement(mus_float_t sig,mus_float_t index)890 mus_float_t mus_contrast_enhancement(mus_float_t sig, mus_float_t index)
891 {
892 return(sin((sig * M_PI_2) + (index * sin(sig * TWO_PI))));
893 }
894
895
mus_arrays_are_equal(mus_float_t * arr1,mus_float_t * arr2,mus_float_t fudge,mus_long_t len)896 bool mus_arrays_are_equal(mus_float_t *arr1, mus_float_t *arr2, mus_float_t fudge, mus_long_t len)
897 {
898 mus_long_t i;
899 if (fudge == 0.0)
900 {
901 for (i = 0; i < len; i++)
902 if (arr1[i] != arr2[i])
903 return(false);
904 }
905 else
906 {
907 mus_long_t len4;
908 len4 = len - 4;
909 i = 0;
910 while (i <= len4)
911 {
912 if (fabs(arr1[i] - arr2[i]) > fudge)
913 return(false);
914 i++;
915 if (fabs(arr1[i] - arr2[i]) > fudge)
916 return(false);
917 i++;
918 if (fabs(arr1[i] - arr2[i]) > fudge)
919 return(false);
920 i++;
921 if (fabs(arr1[i] - arr2[i]) > fudge)
922 return(false);
923 i++;
924 }
925 for (; i < len; i++)
926 if (fabs(arr1[i] - arr2[i]) > fudge)
927 return(false);
928 }
929 return(true);
930 }
931
932
clm_arrays_are_equal(mus_float_t * arr1,mus_float_t * arr2,mus_long_t len)933 static bool clm_arrays_are_equal(mus_float_t *arr1, mus_float_t *arr2, mus_long_t len)
934 {
935 return(mus_arrays_are_equal(arr1, arr2, float_equal_fudge_factor, len));
936 }
937
mus_dot_product(mus_float_t * data1,mus_float_t * data2,mus_long_t size)938 mus_float_t mus_dot_product(mus_float_t *data1, mus_float_t *data2, mus_long_t size)
939 {
940 mus_long_t i, size4;
941 mus_float_t sum = 0.0;
942 size4 = size - 4;
943 i = 0;
944 while (i <= size4)
945 {
946 sum += (data1[i] * data2[i]);
947 i++;
948 sum += (data1[i] * data2[i]);
949 i++;
950 sum += (data1[i] * data2[i]);
951 i++;
952 sum += (data1[i] * data2[i]);
953 i++;
954 }
955 for (; i < size; i++)
956 sum += (data1[i] * data2[i]);
957 return(sum);
958 }
959
960
961 #if HAVE_COMPLEX_TRIG
962 #if HAVE_FORTH
963 #include "xen.h"
964 #endif
965
mus_edot_product(complex double freq,complex double * data,mus_long_t size)966 complex double mus_edot_product(complex double freq, complex double *data, mus_long_t size)
967 {
968 int i;
969 complex double sum = 0.0;
970 for (i = 0; i < size; i++)
971 sum += (cexp(i * freq) * data[i]);
972 return(sum);
973 }
974 #endif
975
976
mus_polynomial(mus_float_t * coeffs,mus_float_t x,int ncoeffs)977 mus_float_t mus_polynomial(mus_float_t *coeffs, mus_float_t x, int ncoeffs)
978 {
979 mus_float_t sum;
980 int i;
981 if (ncoeffs <= 0) return(0.0);
982 if (ncoeffs == 1) return(coeffs[0]); /* just a constant term */
983 sum = coeffs[ncoeffs - 1];
984 /* unrolled is slower */
985 for (i = ncoeffs - 2; i >= 0; i--)
986 sum = (sum * x) + coeffs[i];
987 return((mus_float_t)sum);
988 }
989
mus_rectangular_to_polar(mus_float_t * rl,mus_float_t * im,mus_long_t size)990 void mus_rectangular_to_polar(mus_float_t *rl, mus_float_t *im, mus_long_t size)
991 {
992 mus_long_t i;
993 for (i = 0; i < size; i++)
994 {
995 mus_float_t temp; /* apparently floating underflows (denormals?) in sqrt are bringing us to a halt */
996 temp = rl[i] * rl[i] + im[i] * im[i];
997 if (temp < .00000001)
998 {
999 rl[i] = 0.0;
1000 im[i] = 0.0;
1001 }
1002 else
1003 {
1004 im[i] = -atan2(im[i], rl[i]); /* "-" here so that clockwise is positive? is this backwards? */
1005 rl[i] = sqrt(temp);
1006 }
1007 }
1008 }
1009
1010
mus_rectangular_to_magnitudes(mus_float_t * rl,mus_float_t * im,mus_long_t size)1011 void mus_rectangular_to_magnitudes(mus_float_t *rl, mus_float_t *im, mus_long_t size)
1012 {
1013 mus_long_t i;
1014 for (i = 0; i < size; i++)
1015 {
1016 mus_float_t temp; /* apparently floating underflows in sqrt are bringing us to a halt */
1017 temp = rl[i] * rl[i] + im[i] * im[i];
1018 if (temp < .00000001)
1019 rl[i] = 0.0;
1020 else rl[i] = sqrt(temp);
1021 }
1022 }
1023
1024
mus_polar_to_rectangular(mus_float_t * rl,mus_float_t * im,mus_long_t size)1025 void mus_polar_to_rectangular(mus_float_t *rl, mus_float_t *im, mus_long_t size)
1026 {
1027 mus_long_t i;
1028 for (i = 0; i < size; i++)
1029 {
1030 #if HAVE_SINCOS
1031 double sx, cx;
1032 sincos(-im[i], &sx, &cx);
1033 im[i] = sx * rl[i];
1034 rl[i] *= cx;
1035 #else
1036 mus_float_t temp;
1037 temp = rl[i] * sin(-im[i]); /* minus to match sense of rectangular->polar above */
1038 rl[i] *= cos(-im[i]);
1039 im[i] = temp;
1040 #endif
1041 }
1042 }
1043
1044
array_normalize(mus_float_t * table,mus_long_t table_size)1045 static mus_float_t *array_normalize(mus_float_t *table, mus_long_t table_size)
1046 {
1047 mus_float_t amp = 0.0;
1048 mus_long_t i;
1049
1050 for (i = 0; i < table_size; i++)
1051 if (amp < (fabs(table[i])))
1052 amp = fabs(table[i]);
1053
1054 if ((amp > 0.0) &&
1055 (amp != 1.0))
1056 for (i = 0; i < table_size; i++)
1057 table[i] /= amp;
1058
1059 return(table);
1060 }
1061
1062
1063 /* ---------------- interpolation ---------------- */
1064
mus_array_interp(mus_float_t * wave,mus_float_t phase,mus_long_t size)1065 mus_float_t mus_array_interp(mus_float_t *wave, mus_float_t phase, mus_long_t size)
1066 {
1067 /* changed 26-Sep-00 to be closer to mus.lisp */
1068 mus_long_t int_part;
1069 mus_float_t frac_part;
1070 if ((phase < 0.0) || (phase > size))
1071 {
1072 /* 28-Mar-01 changed to fmod; I was hoping to avoid this... */
1073 phase = fmod((mus_float_t)phase, (mus_float_t)size);
1074 if (phase < 0.0) phase += size;
1075 }
1076
1077 int_part = (mus_long_t)phase; /* (mus_long_t)floor(phase); */
1078 frac_part = phase - int_part;
1079 if (int_part == size) int_part = 0;
1080
1081 if (frac_part == 0.0)
1082 return(wave[int_part]);
1083 else
1084 {
1085 mus_long_t inx;
1086 inx = int_part + 1;
1087 if (inx >= size) inx = 0;
1088 return(wave[int_part] + (frac_part * (wave[inx] - wave[int_part])));
1089 }
1090 }
1091
1092
mus_array_all_pass_interp(mus_float_t * wave,mus_float_t phase,mus_long_t size,mus_float_t yn1)1093 static mus_float_t mus_array_all_pass_interp(mus_float_t *wave, mus_float_t phase, mus_long_t size, mus_float_t yn1)
1094 {
1095 /* this is intended for delay lines where you have a stream of values; in table-lookup it can be a mess */
1096 mus_long_t int_part, inx;
1097 mus_float_t frac_part;
1098 if ((phase < 0.0) || (phase > size))
1099 {
1100 phase = fmod((mus_float_t)phase, (mus_float_t)size);
1101 if (phase < 0.0) phase += size;
1102 }
1103 int_part = (mus_long_t)floor(phase);
1104 frac_part = phase - int_part;
1105 if (int_part == size) int_part = 0;
1106 inx = int_part + 1;
1107 if (inx >= size) inx -= size;
1108 #if 1
1109 /* from DAFX */
1110 if (frac_part == 0.0)
1111 return(wave[inx] - yn1);
1112 return(wave[int_part] * frac_part + (1.0 - frac_part) * (wave[inx] - yn1));
1113 #else
1114 /* from Perry Cook */
1115 if (frac_part == 0.0)
1116 return(wave[int_part] + wave[inx] - yn1);
1117 else return(wave[int_part] + ((1.0 - frac_part) / (1 + frac_part)) * (wave[inx] - yn1));
1118 #endif
1119 }
1120
1121
mus_array_lagrange_interp(mus_float_t * wave,mus_float_t x,mus_long_t size)1122 static mus_float_t mus_array_lagrange_interp(mus_float_t *wave, mus_float_t x, mus_long_t size)
1123 {
1124 /* Abramovitz and Stegun 25.2.11 -- everyone badmouths this poor formula */
1125 /* x assumed to be in the middle, between second and third vals */
1126 mus_long_t x0, xp1, xm1;
1127 mus_float_t p, pp;
1128 if ((x < 0.0) || (x > size))
1129 {
1130 x = fmod((mus_float_t)x, (mus_float_t)size);
1131 if (x < 0.0) x += size;
1132 }
1133 x0 = (mus_long_t)floor(x);
1134 p = x - x0;
1135 if (x0 >= size) x0 -= size;
1136 if (p == 0.0) return(wave[x0]);
1137 xp1 = x0 + 1;
1138 if (xp1 >= size) xp1 -= size;
1139 xm1 = x0 - 1;
1140 if (xm1 < 0) xm1 += size;
1141 pp = p * p;
1142 return((wave[xm1] * 0.5 * (pp - p)) +
1143 (wave[x0] * (1.0 - pp)) +
1144 (wave[xp1] * 0.5 * (p + pp)));
1145 }
1146
1147
mus_array_hermite_interp(mus_float_t * wave,mus_float_t x,mus_long_t size)1148 static mus_float_t mus_array_hermite_interp(mus_float_t *wave, mus_float_t x, mus_long_t size)
1149 {
1150 /* from James McCartney */
1151 mus_long_t x0, x1, x2, x3;
1152 mus_float_t p, c0, c1, c2, c3, y0, y1, y2, y3;
1153 if ((x < 0.0) || (x > size))
1154 {
1155 x = fmod((mus_float_t)x, (mus_float_t)size);
1156 if (x < 0.0) x += size;
1157 }
1158 x1 = (mus_long_t)floor(x);
1159 p = x - x1;
1160 if (x1 == size) x1 = 0;
1161 if (p == 0.0) return(wave[x1]);
1162 x2 = x1 + 1;
1163 if (x2 == size) x2 = 0;
1164 x3 = x2 + 1;
1165 if (x3 == size) x3 = 0;
1166 x0 = x1 - 1;
1167 if (x0 < 0) x0 = size - 1;
1168 y0 = wave[x0];
1169 y1 = wave[x1];
1170 y2 = wave[x2];
1171 y3 = wave[x3];
1172 c0 = y1;
1173 c1 = 0.5 * (y2 - y0);
1174 c3 = 1.5 * (y1 - y2) + 0.5 * (y3 - y0);
1175 c2 = y0 - y1 + c1 - c3;
1176 return(((c3 * p + c2) * p + c1) * p + c0);
1177 }
1178
1179
mus_array_bezier_interp(mus_float_t * wave,mus_float_t x,mus_long_t size)1180 static mus_float_t mus_array_bezier_interp(mus_float_t *wave, mus_float_t x, mus_long_t size)
1181 {
1182 mus_long_t x0, x1, x2, x3;
1183 mus_float_t p, y0, y1, y2, y3, ay, by, cy;
1184 if ((x < 0.0) || (x > size))
1185 {
1186 x = fmod((mus_float_t)x, (mus_float_t)size);
1187 if (x < 0.0) x += size;
1188 }
1189 x1 = (mus_long_t)floor(x);
1190 p = ((x - x1) + 1.0) / 3.0;
1191 if (x1 == size) x1 = 0;
1192 x2 = x1 + 1;
1193 if (x2 == size) x2 = 0;
1194 x3 = x2 + 1;
1195 if (x3 == size) x3 = 0;
1196 x0 = x1 - 1;
1197 if (x0 < 0) x0 = size - 1;
1198 y0 = wave[x0];
1199 y1 = wave[x1];
1200 y2 = wave[x2];
1201 y3 = wave[x3];
1202 cy = 3 * (y1 - y0);
1203 by = 3 * (y2 - y1) - cy;
1204 ay = y3 - y0 - cy - by;
1205 return(y0 + p * (cy + (p * (by + (p * ay)))));
1206 }
1207
1208
mus_is_interp_type(int val)1209 bool mus_is_interp_type(int val)
1210 {
1211 /* this is C++'s fault. */
1212 switch (val)
1213 {
1214 case MUS_INTERP_NONE:
1215 case MUS_INTERP_LINEAR:
1216 case MUS_INTERP_SINUSOIDAL:
1217 case MUS_INTERP_LAGRANGE:
1218 case MUS_INTERP_HERMITE:
1219 case MUS_INTERP_ALL_PASS:
1220 case MUS_INTERP_BEZIER:
1221 return(true);
1222 }
1223 return(false);
1224 }
1225
1226
mus_interpolate(mus_interp_t type,mus_float_t x,mus_float_t * table,mus_long_t table_size,mus_float_t y)1227 mus_float_t mus_interpolate(mus_interp_t type, mus_float_t x, mus_float_t *table, mus_long_t table_size, mus_float_t y)
1228 {
1229 switch (type)
1230 {
1231 case MUS_INTERP_NONE:
1232 {
1233 mus_long_t x0;
1234 x0 = ((mus_long_t)x) % table_size;
1235 if (x0 < 0) x0 += table_size;
1236 return(table[x0]);
1237 }
1238
1239 case MUS_INTERP_LAGRANGE:
1240 return(mus_array_lagrange_interp(table, x, table_size));
1241
1242 case MUS_INTERP_HERMITE:
1243 return(mus_array_hermite_interp(table, x, table_size));
1244
1245 case MUS_INTERP_LINEAR:
1246 return(mus_array_interp(table, x, table_size));
1247
1248 case MUS_INTERP_ALL_PASS:
1249 return(mus_array_all_pass_interp(table, x, table_size, y));
1250
1251 case MUS_INTERP_BEZIER:
1252 return(mus_array_bezier_interp(table, x, table_size));
1253
1254 default:
1255 mus_error(MUS_ARG_OUT_OF_RANGE, "unknown interpolation type: %d", type);
1256 break;
1257 }
1258 return(0.0);
1259 }
1260
1261
1262
1263 /* ---------------- oscil ---------------- */
1264
1265 typedef struct {
1266 mus_any_class *core;
1267 mus_float_t phase, freq;
1268 } osc;
1269
1270
mus_oscil(mus_any * ptr,mus_float_t fm,mus_float_t pm)1271 mus_float_t mus_oscil(mus_any *ptr, mus_float_t fm, mus_float_t pm)
1272 {
1273 osc *gen = (osc *)ptr;
1274 mus_float_t result;
1275 result = gen->phase + pm;
1276 gen->phase += (gen->freq + fm);
1277 return(sin(result));
1278 }
1279
1280
mus_oscil_unmodulated(mus_any * ptr)1281 mus_float_t mus_oscil_unmodulated(mus_any *ptr)
1282 {
1283 osc *gen = (osc *)ptr;
1284 mus_float_t result;
1285 result = gen->phase;
1286 gen->phase += gen->freq;
1287 return(sin(result));
1288 }
1289
1290
mus_oscil_fm(mus_any * ptr,mus_float_t fm)1291 mus_float_t mus_oscil_fm(mus_any *ptr, mus_float_t fm)
1292 {
1293 osc *gen = (osc *)ptr;
1294 mus_float_t result;
1295 result = gen->phase;
1296 gen->phase += (gen->freq + fm);
1297 return(sin(result));
1298 }
1299
1300
mus_oscil_pm(mus_any * ptr,mus_float_t pm)1301 mus_float_t mus_oscil_pm(mus_any *ptr, mus_float_t pm)
1302 {
1303 mus_float_t result;
1304 osc *gen = (osc *)ptr;
1305 result = gen->phase + pm;
1306 gen->phase += gen->freq;
1307 return(sin(result));
1308 }
1309
1310
mus_is_oscil(mus_any * ptr)1311 bool mus_is_oscil(mus_any *ptr)
1312 {
1313 return((ptr) &&
1314 (ptr->core->type == MUS_OSCIL));
1315 }
1316 /* this could be: bool mus_is_oscil(mus_any *ptr) {return((ptr) && (ptr->core == &OSCIL_CLASS));}
1317 */
1318
1319
free_oscil(mus_any * ptr)1320 static void free_oscil(mus_any *ptr) {free(ptr);}
1321
oscil_freq(mus_any * ptr)1322 static mus_float_t oscil_freq(mus_any *ptr) {return(mus_radians_to_hz(((osc *)ptr)->freq));}
oscil_set_freq(mus_any * ptr,mus_float_t val)1323 static mus_float_t oscil_set_freq(mus_any *ptr, mus_float_t val) {((osc *)ptr)->freq = mus_hz_to_radians(val); return(val);}
1324
oscil_increment(mus_any * ptr)1325 static mus_float_t oscil_increment(mus_any *ptr) {return(((osc *)ptr)->freq);}
oscil_set_increment(mus_any * ptr,mus_float_t val)1326 static mus_float_t oscil_set_increment(mus_any *ptr, mus_float_t val) {((osc *)ptr)->freq = val; return(val);}
1327
oscil_phase(mus_any * ptr)1328 static mus_float_t oscil_phase(mus_any *ptr) {return(fmod(((osc *)ptr)->phase, TWO_PI));}
oscil_set_phase(mus_any * ptr,mus_float_t val)1329 static mus_float_t oscil_set_phase(mus_any *ptr, mus_float_t val) {((osc *)ptr)->phase = val; return(val);}
1330
oscil_cosines(mus_any * ptr)1331 static mus_long_t oscil_cosines(mus_any *ptr) {return(1);}
oscil_reset(mus_any * ptr)1332 static void oscil_reset(mus_any *ptr) {((osc *)ptr)->phase = 0.0;}
1333
oscil_copy(mus_any * ptr)1334 static mus_any *oscil_copy(mus_any *ptr)
1335 {
1336 osc *g;
1337 g = (osc *)malloc(sizeof(osc));
1338 memcpy((void *)g, (void *)ptr, sizeof(osc));
1339 return((mus_any *)g);
1340 }
1341
fallback_scaler(mus_any * ptr)1342 static mus_float_t fallback_scaler(mus_any *ptr) {return(1.0);}
1343
1344
oscil_equalp(mus_any * p1,mus_any * p2)1345 static bool oscil_equalp(mus_any *p1, mus_any *p2)
1346 {
1347 return((p1 == p2) ||
1348 ((mus_is_oscil((mus_any *)p1)) &&
1349 (mus_is_oscil((mus_any *)p2)) &&
1350 ((((osc *)p1)->freq) == (((osc *)p2)->freq)) &&
1351 ((((osc *)p1)->phase) == (((osc *)p2)->phase))));
1352 }
1353
1354
describe_oscil(mus_any * ptr)1355 static char *describe_oscil(mus_any *ptr)
1356 {
1357 char *describe_buffer;
1358 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
1359 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f",
1360 mus_name(ptr),
1361 mus_frequency(ptr),
1362 mus_phase(ptr));
1363 return(describe_buffer);
1364 }
1365
1366
1367 static mus_any_class OSCIL_CLASS = {
1368 MUS_OSCIL,
1369 (char *)S_oscil, /* the "(char *)" business is for g++'s benefit */
1370 &free_oscil,
1371 &describe_oscil,
1372 &oscil_equalp,
1373 0, 0,
1374 &oscil_cosines, 0,
1375 &oscil_freq,
1376 &oscil_set_freq,
1377 &oscil_phase,
1378 &oscil_set_phase,
1379 &fallback_scaler, 0,
1380 &oscil_increment,
1381 &oscil_set_increment,
1382 &mus_oscil,
1383 MUS_NOT_SPECIAL,
1384 NULL,
1385 0,
1386 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1387 0, 0, 0, 0, 0, 0, 0,
1388 0, 0, 0, 0,
1389 &oscil_reset,
1390 0,
1391 &oscil_copy
1392 };
1393
1394
1395
mus_make_oscil(mus_float_t freq,mus_float_t phase)1396 mus_any *mus_make_oscil(mus_float_t freq, mus_float_t phase)
1397 {
1398 osc *gen;
1399 gen = (osc *)malloc(sizeof(osc));
1400 gen->core = &OSCIL_CLASS;
1401 gen->freq = mus_hz_to_radians(freq);
1402 gen->phase = phase;
1403 return((mus_any *)gen);
1404 }
1405
1406 /* decided against feedback-oscil (as in cellon) because it's not clear how to handle the index,
1407 * and there are many options for the filtering -- since this part of the signal path
1408 * is not hidden, there's no reason to bring it out explicitly (as in filtered-comb)
1409 */
1410
1411
1412 /* ---------------- oscil-bank ---------------- */
1413
1414 typedef struct {
1415 mus_any_class *core;
1416 int size, orig_size;
1417 mus_float_t *amps, *phases, *freqs; /* these can change, so sincos is not always safe */
1418 bool free_phases;
1419 mus_float_t (*ob_func)(mus_any *ptr);
1420 #if HAVE_SINCOS
1421 double *sn1, *cs1, *sn2, *cs2, *phs;
1422 bool use_sc;
1423 #endif
1424 } ob;
1425
1426
free_oscil_bank(mus_any * ptr)1427 static void free_oscil_bank(mus_any *ptr)
1428 {
1429 ob *g = (ob *)ptr;
1430 #if HAVE_SINCOS
1431 if (g->sn1) {free(g->sn1); g->sn1 = NULL;}
1432 if (g->sn2) {free(g->sn2); g->sn2 = NULL;}
1433 if (g->cs1) {free(g->cs1); g->cs1 = NULL;}
1434 if (g->cs2) {free(g->cs2); g->cs2 = NULL;}
1435 if (g->phs) {free(g->phs); g->phs = NULL;}
1436 #endif
1437 if ((g->phases) && (g->free_phases)) {free(g->phases); g->phases = NULL;}
1438 free(ptr);
1439 }
1440
ob_copy(mus_any * ptr)1441 static mus_any *ob_copy(mus_any *ptr)
1442 {
1443 ob *g, *p;
1444
1445 p = (ob *)ptr;
1446 g = (ob *)malloc(sizeof(ob));
1447 memcpy((void *)g, (void *)ptr, sizeof(ob));
1448
1449 g->ob_func = p->ob_func;
1450
1451 #if HAVE_SINCOS
1452 if (g->sn1)
1453 {
1454 int bytes;
1455 bytes = g->size * sizeof(double);
1456 g->sn1 = (double *)malloc(bytes);
1457 memcpy((void *)(g->sn1), (void *)(p->sn1), bytes);
1458 g->sn2 = (double *)malloc(bytes);
1459 memcpy((void *)(g->sn2), (void *)(p->sn2), bytes);
1460 g->cs1 = (double *)malloc(bytes);
1461 memcpy((void *)(g->cs1), (void *)(p->cs1), bytes);
1462 g->cs2 = (double *)malloc(bytes);
1463 memcpy((void *)(g->cs2), (void *)(p->cs2), bytes);
1464 g->phs = (double *)malloc(bytes);
1465 memcpy((void *)(g->phs), (void *)(p->phs), bytes);
1466 g->use_sc = p->use_sc;
1467 }
1468 #endif
1469
1470 /* we have to make a new phases array -- otherwise the original and copy step on each other */
1471 g->free_phases = true;
1472 g->phases = (mus_float_t *)malloc(g->size * sizeof(mus_float_t));
1473 mus_copy_floats(g->phases, p->phases, g->size);
1474 return((mus_any *)g);
1475 }
1476
ob_data(mus_any * ptr)1477 static mus_float_t *ob_data(mus_any *ptr) {return(((ob *)ptr)->phases);}
1478
run_oscil_bank(mus_any * ptr,mus_float_t input,mus_float_t unused)1479 static mus_float_t run_oscil_bank(mus_any *ptr, mus_float_t input, mus_float_t unused)
1480 {
1481 return(mus_oscil_bank(ptr));
1482 }
1483
1484
oscil_bank_length(mus_any * ptr)1485 static mus_long_t oscil_bank_length(mus_any *ptr)
1486 {
1487 return(((ob *)ptr)->size);
1488 }
1489
1490
oscil_bank_set_length(mus_any * ptr,mus_long_t len)1491 static mus_long_t oscil_bank_set_length(mus_any *ptr, mus_long_t len)
1492 {
1493 ob *g = (ob *)ptr;
1494 if (len < 0)
1495 g->size = 0;
1496 else
1497 {
1498 if (len > g->orig_size)
1499 g->size = g->orig_size;
1500 else g->size = len;
1501 }
1502 return(len);
1503 }
1504
1505
oscil_bank_reset(mus_any * ptr)1506 static void oscil_bank_reset(mus_any *ptr)
1507 {
1508 ob *p = (ob *)ptr;
1509 p->size = p->orig_size;
1510 mus_clear_floats(p->phases, p->orig_size);
1511 }
1512
1513
oscil_bank_equalp(mus_any * p1,mus_any * p2)1514 static bool oscil_bank_equalp(mus_any *p1, mus_any *p2)
1515 {
1516 ob *o1 = (ob *)p1;
1517 ob *o2 = (ob *)p2;
1518 if (p1 == p2) return(true);
1519 return((o1->size == o2->size) &&
1520 (o1->orig_size == o2->orig_size) &&
1521 (o1->amps == o2->amps) &&
1522 (o1->freqs == o2->freqs) &&
1523 ((o1->phases == o2->phases) ||
1524 (clm_arrays_are_equal(o1->phases, o2->phases, o2->size))));
1525 }
1526
1527
describe_oscil_bank(mus_any * ptr)1528 static char *describe_oscil_bank(mus_any *ptr)
1529 {
1530 ob *gen = (ob *)ptr;
1531 char *describe_buffer;
1532 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
1533 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s size: %d",
1534 mus_name(ptr),
1535 gen->size);
1536 return(describe_buffer);
1537 }
1538
1539 static mus_any_class OSCIL_BANK_CLASS = {
1540 MUS_OSCIL_BANK,
1541 (char *)S_oscil_bank,
1542 &free_oscil_bank,
1543 &describe_oscil_bank,
1544 &oscil_bank_equalp,
1545 &ob_data, 0,
1546 &oscil_bank_length, &oscil_bank_set_length,
1547 0, 0,
1548 0, 0,
1549 0, 0,
1550 0, 0,
1551 &run_oscil_bank,
1552 MUS_NOT_SPECIAL,
1553 NULL, 0,
1554 0, 0, 0, 0,
1555 0, 0,
1556 0, 0, 0, 0,
1557 0, 0, 0, 0, 0, 0, 0,
1558 0, 0, 0, 0,
1559 &oscil_bank_reset,
1560 0, &ob_copy
1561 };
1562
1563
mus_is_oscil_bank(mus_any * ptr)1564 bool mus_is_oscil_bank(mus_any *ptr)
1565 {
1566 return((ptr) &&
1567 (ptr->core->type == MUS_OSCIL_BANK));
1568 }
1569
1570
oscil_bank(mus_any * ptr)1571 static mus_float_t oscil_bank(mus_any *ptr)
1572 {
1573 ob *p = (ob *)ptr;
1574 int i;
1575 mus_float_t sum = 0.0;
1576 if (!p->amps)
1577 {
1578 for (i = 0; i < p->size; i++)
1579 {
1580 sum += sin(p->phases[i]);
1581 p->phases[i] += p->freqs[i];
1582 }
1583 }
1584 else
1585 {
1586 for (i = 0; i < p->size; i++)
1587 {
1588 sum += (p->amps[i] * sin(p->phases[i]));
1589 p->phases[i] += p->freqs[i];
1590 }
1591 }
1592 return(sum);
1593 }
1594
1595
1596 #if HAVE_SINCOS
stable_oscil_bank(mus_any * ptr)1597 static mus_float_t stable_oscil_bank(mus_any *ptr)
1598 {
1599 ob *p = (ob *)ptr;
1600 int i;
1601 mus_float_t sum = 0.0;
1602 if (p->use_sc)
1603 {
1604 for (i = 0; i < p->size; i++)
1605 sum += (p->sn1[i] * p->cs2[i] + p->cs1[i] * p->sn2[i]);
1606 p->use_sc = false;
1607 }
1608 else
1609 {
1610 double s, c;
1611 if (!p->amps)
1612 {
1613 for (i = 0; i < p->size; i++)
1614 {
1615 sincos(p->phases[i], &s, &c);
1616 p->sn2[i] = s;
1617 p->cs2[i] = c;
1618 sum += s;
1619 p->phases[i] += p->phs[i];
1620 }
1621 }
1622 else
1623 {
1624 for (i = 0; i < p->size; i++)
1625 {
1626 sincos(p->phases[i], &s, &c);
1627 p->sn2[i] = s;
1628 p->cs2[i] = c;
1629 sum += p->amps[i] * s;
1630 p->phases[i] += p->phs[i];
1631 }
1632 }
1633 p->use_sc = true;
1634 }
1635 return(sum);
1636 }
1637 #endif
1638
1639
mus_oscil_bank(mus_any * ptr)1640 mus_float_t mus_oscil_bank(mus_any *ptr)
1641 {
1642 ob *p = (ob *)ptr;
1643 return(p->ob_func(ptr));
1644 }
1645
1646
mus_make_oscil_bank(int size,mus_float_t * freqs,mus_float_t * phases,mus_float_t * amps,bool stable)1647 mus_any *mus_make_oscil_bank(int size, mus_float_t *freqs, mus_float_t *phases, mus_float_t *amps, bool stable)
1648 {
1649 ob *gen;
1650
1651 gen = (ob *)malloc(sizeof(ob));
1652 gen->core = &OSCIL_BANK_CLASS;
1653 gen->orig_size = size;
1654 gen->size = size;
1655 gen->amps = amps;
1656 gen->freqs = freqs;
1657 gen->phases = phases;
1658 gen->free_phases = false;
1659 gen->ob_func = oscil_bank;
1660
1661 #if HAVE_SINCOS
1662 if (stable)
1663 {
1664 int i;
1665 double s, c;
1666
1667 gen->ob_func = stable_oscil_bank;
1668 gen->use_sc = false;
1669 gen->sn1 = (double *)malloc(size * sizeof(double));
1670 gen->sn2 = (double *)malloc(size * sizeof(double));
1671 gen->cs1 = (double *)malloc(size * sizeof(double));
1672 gen->cs2 = (double *)malloc(size * sizeof(double));
1673 gen->phs = (double *)malloc(size * sizeof(double));
1674
1675 for (i = 0; i < size; i++)
1676 {
1677 sincos(freqs[i], &s, &c);
1678 if (amps)
1679 {
1680 s *= amps[i];
1681 c *= amps[i];
1682 }
1683 gen->sn1[i] = s;
1684 gen->cs1[i] = c;
1685 gen->phs[i] = freqs[i] * 2.0;
1686 }
1687 }
1688 else
1689 {
1690 gen->sn1 = NULL;
1691 gen->sn2 = NULL;
1692 gen->cs1 = NULL;
1693 gen->cs2 = NULL;
1694 gen->phs = NULL;
1695 }
1696 #endif
1697
1698 return((mus_any *)gen);
1699 }
1700
1701
1702
1703 /* ---------------- ncos ---------------- */
1704
1705 typedef struct {
1706 mus_any_class *core;
1707 int n;
1708 mus_float_t scaler, cos5, phase, freq;
1709 } cosp;
1710
1711 #define DIVISOR_NEAR_ZERO(Den) (fabs(Den) < 1.0e-14)
1712
mus_ncos(mus_any * ptr,mus_float_t fm)1713 mus_float_t mus_ncos(mus_any *ptr, mus_float_t fm)
1714 {
1715 /* changed 25-Apr-04: use less stupid formula */
1716 /* (/ (- (/ (sin (* (+ n 0.5) angle)) (* 2 (sin (* 0.5 angle)))) 0.5) n) */
1717 mus_float_t val, den;
1718 cosp *gen = (cosp *)ptr;
1719 den = sin(gen->phase * 0.5);
1720 if (DIVISOR_NEAR_ZERO(den)) /* see note -- this was den == 0.0 1-Aug-07 */
1721 /* perhaps use DBL_EPSILON (1.0e-9 I think) */
1722 val = 1.0;
1723 else
1724 {
1725 val = (gen->scaler * (((sin(gen->phase * gen->cos5)) / (2.0 * den)) - 0.5));
1726 if (val > 1.0) val = 1.0;
1727 /* I think this can't happen now that we check den above, but just in case... */
1728 /* this check is actually incomplete, since we can be much below the correct value also, but the den check should fix those cases too */
1729 }
1730 gen->phase += (gen->freq + fm);
1731 return((mus_float_t)val);
1732 }
1733
1734
1735 /* I think we could add ncos_pm via:
1736 *
1737 * mus_float_t mus_ncos_pm(mus_any *ptr, mus_float_t fm, mus_float_t pm)
1738 * {
1739 * cosp *gen = (cosp *)ptr;
1740 * mus_float_t result;
1741 * gen->phase += pm;
1742 * result = mus_ncos(ptr, fm);
1743 * gen->phase -= pm;
1744 * return(result);
1745 * }
1746 *
1747 * and the same trick could add pm to anything:
1748 *
1749 * mus_float_t mus_run_with_pm(mus_any *ptr, mus_float_t fm, mus_float_t pm)
1750 * {
1751 * mus_float_t result;
1752 * mus_set_phase(ptr, mus_phase(ptr) + pm);
1753 * result = mus_run(ptr, fm, 0.0);
1754 * mus_set_phase (ptr, mus_phase(ptr) - pm);
1755 * return(result);
1756 * }
1757 *
1758 * fm could also be handled here so the 4 cases become gen, mus_run_with_fm|pm|fm_and_pm(gen)
1759 * but... this could just as well happen at the extension language level, except that run doesn't expand macros?
1760 * The problem with differentiating the pm and using the fm arg is that we'd need a closure.
1761 */
1762
1763 #if 0
1764 /* if the current phase is close to 0.0, there were numerical troubles here:
1765 :(/ (cos (* 1.5 pi 1.0000000000000007)) (cos (* 0.5 pi 1.0000000000000007)))
1766 -3.21167411694788
1767 :(/ (cos (* 1.5 pi 1.0000000000000004)) (cos (* 0.5 pi 1.0000000000000004)))
1768 -2.63292557243357
1769 :(/ (cos (* 1.5 pi 1.0000000000000002)) (cos (* 0.5 pi 1.0000000000000002)))
1770 -1.84007079646018
1771 :(/ (cos (* 1.5 pi 1.0000000000000001)) (cos (* 0.5 pi 1.0000000000000001)))
1772 -3.0
1773 :(/ (cos (* 1.5 pi 1.0000000000000008)) (cos (* 0.5 pi 1.0000000000000008)))
1774 -3.34939116712516
1775 ;; 16 bits in is probably too much for mus_float_ts
1776 ;; these numbers can be hit in normal cases:
1777
1778 (define (ncos-with-inversions n x)
1779 ;; Andrews Askey Roy 261
1780 (let* ((num (cos (* x (+ 0.5 n))))
1781 (den (cos (* x 0.5)))
1782 (val (/ num den))) ; Chebyshev polynomial of the third kind! (4th uses sin = our current formula)
1783 (/ (- (if (even? n) val (- val))
1784 0.5)
1785 (+ 1 (* n 2)))))
1786
1787 (with-sound (:scaled-to 1.0)
1788 (do ((i 0 (+ i 1))
1789 (x 0.0 (+ x .01)))
1790 ((= i 200)) ; glitch at 100 (= 1)
1791 (outa i (ncos-with-inversions 1 (* pi x)) *output*)))
1792 */
1793 #endif
1794
1795
mus_is_ncos(mus_any * ptr)1796 bool mus_is_ncos(mus_any *ptr)
1797 {
1798 return((ptr) &&
1799 (ptr->core->type == MUS_NCOS));
1800 }
1801
1802
free_ncos(mus_any * ptr)1803 static void free_ncos(mus_any *ptr) {free(ptr);}
ncos_reset(mus_any * ptr)1804 static void ncos_reset(mus_any *ptr) {((cosp *)ptr)->phase = 0.0;}
1805
ncos_freq(mus_any * ptr)1806 static mus_float_t ncos_freq(mus_any *ptr) {return(mus_radians_to_hz(((cosp *)ptr)->freq));}
ncos_set_freq(mus_any * ptr,mus_float_t val)1807 static mus_float_t ncos_set_freq(mus_any *ptr, mus_float_t val) {((cosp *)ptr)->freq = mus_hz_to_radians(val); return(val);}
1808
ncos_increment(mus_any * ptr)1809 static mus_float_t ncos_increment(mus_any *ptr) {return(((cosp *)ptr)->freq);}
ncos_set_increment(mus_any * ptr,mus_float_t val)1810 static mus_float_t ncos_set_increment(mus_any *ptr, mus_float_t val) {((cosp *)ptr)->freq = val; return(val);}
1811
ncos_phase(mus_any * ptr)1812 static mus_float_t ncos_phase(mus_any *ptr) {return(fmod(((cosp *)ptr)->phase, TWO_PI));}
ncos_set_phase(mus_any * ptr,mus_float_t val)1813 static mus_float_t ncos_set_phase(mus_any *ptr, mus_float_t val) {((cosp *)ptr)->phase = val; return(val);}
1814
ncos_scaler(mus_any * ptr)1815 static mus_float_t ncos_scaler(mus_any *ptr) {return(((cosp *)ptr)->scaler);}
ncos_set_scaler(mus_any * ptr,mus_float_t val)1816 static mus_float_t ncos_set_scaler(mus_any *ptr, mus_float_t val) {((cosp *)ptr)->scaler = val; return(val);}
1817
ncos_n(mus_any * ptr)1818 static mus_long_t ncos_n(mus_any *ptr) {return(((cosp *)ptr)->n);}
1819
cosp_copy(mus_any * ptr)1820 static mus_any *cosp_copy(mus_any *ptr)
1821 {
1822 cosp *g;
1823 g = (cosp *)malloc(sizeof(cosp));
1824 memcpy((void *)g, (void *)ptr, sizeof(cosp));
1825 return((mus_any *)g);
1826 }
1827
ncos_set_n(mus_any * ptr,mus_long_t val)1828 static mus_long_t ncos_set_n(mus_any *ptr, mus_long_t val)
1829 {
1830 cosp *gen = (cosp *)ptr;
1831 if (val > 0)
1832 {
1833 gen->n = (int)val;
1834 gen->cos5 = val + 0.5;
1835 gen->scaler = 1.0 / (mus_float_t)val;
1836 }
1837 return(val);
1838 }
1839
run_ncos(mus_any * ptr,mus_float_t fm,mus_float_t unused)1840 static mus_float_t run_ncos(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_ncos(ptr, fm));}
1841
1842
ncos_equalp(mus_any * p1,mus_any * p2)1843 static bool ncos_equalp(mus_any *p1, mus_any *p2)
1844 {
1845 return((p1 == p2) ||
1846 ((mus_is_ncos((mus_any *)p1)) && (mus_is_ncos((mus_any *)p2)) &&
1847 ((((cosp *)p1)->freq) == (((cosp *)p2)->freq)) &&
1848 ((((cosp *)p1)->phase) == (((cosp *)p2)->phase)) &&
1849 ((((cosp *)p1)->n) == (((cosp *)p2)->n)) &&
1850 ((((cosp *)p1)->scaler) == (((cosp *)p2)->scaler))));
1851 }
1852
1853
describe_ncos(mus_any * ptr)1854 static char *describe_ncos(mus_any *ptr)
1855 {
1856 char *describe_buffer;
1857 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
1858 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, n: %d",
1859 mus_name(ptr),
1860 mus_frequency(ptr),
1861 mus_phase(ptr),
1862 (int)mus_order(ptr));
1863 return(describe_buffer);
1864 }
1865
1866
1867 static mus_any_class NCOS_CLASS = {
1868 MUS_NCOS,
1869 (char *)S_ncos,
1870 &free_ncos,
1871 &describe_ncos,
1872 &ncos_equalp,
1873 0, 0, /* data */
1874 &ncos_n,
1875 &ncos_set_n,
1876 &ncos_freq,
1877 &ncos_set_freq,
1878 &ncos_phase,
1879 &ncos_set_phase,
1880 &ncos_scaler,
1881 &ncos_set_scaler,
1882 &ncos_increment,
1883 &ncos_set_increment,
1884 &run_ncos,
1885 MUS_NOT_SPECIAL,
1886 NULL,
1887 0,
1888 0, 0, 0, 0, 0, 0,
1889 0, 0, 0, 0,
1890 0, 0, 0, 0, 0, 0, 0,
1891 0, 0, 0, 0,
1892 &ncos_reset,
1893 0,
1894 &cosp_copy
1895 };
1896
1897
mus_make_ncos(mus_float_t freq,int n)1898 mus_any *mus_make_ncos(mus_float_t freq, int n)
1899 {
1900 cosp *gen;
1901 gen = (cosp *)malloc(sizeof(cosp));
1902 gen->core = &NCOS_CLASS;
1903 if (n == 0) n = 1;
1904 gen->scaler = 1.0 / (mus_float_t)n;
1905 gen->n = n;
1906 gen->cos5 = n + 0.5;
1907 gen->freq = mus_hz_to_radians(freq);
1908 gen->phase = 0.0;
1909 return((mus_any *)gen);
1910 }
1911
1912
1913 /* ---------------- nsin ---------------- */
1914
nsin_equalp(mus_any * p1,mus_any * p2)1915 static bool nsin_equalp(mus_any *p1, mus_any *p2)
1916 {
1917 return((p1 == p2) ||
1918 ((mus_is_nsin((mus_any *)p1)) && (mus_is_nsin((mus_any *)p2)) &&
1919 ((((cosp *)p1)->freq) == (((cosp *)p2)->freq)) &&
1920 ((((cosp *)p1)->phase) == (((cosp *)p2)->phase)) &&
1921 ((((cosp *)p1)->n) == (((cosp *)p2)->n)) &&
1922 ((((cosp *)p1)->scaler) == (((cosp *)p2)->scaler))));
1923 }
1924
1925
describe_nsin(mus_any * ptr)1926 static char *describe_nsin(mus_any *ptr)
1927 {
1928 char *describe_buffer;
1929 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
1930 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, n: %d",
1931 mus_name(ptr),
1932 mus_frequency(ptr),
1933 mus_phase(ptr),
1934 (int)mus_order(ptr));
1935 return(describe_buffer);
1936 }
1937
1938
mus_is_nsin(mus_any * ptr)1939 bool mus_is_nsin(mus_any *ptr)
1940 {
1941 return((ptr) &&
1942 (ptr->core->type == MUS_NSIN));
1943 }
1944
1945
1946 #if 0
1947 /* its simplest to get the maxes by running an example and recording the maxamp, but it also
1948 * works for small "n" to use the derivative of the sum-of-sines as a Chebyshev polynomial in cos x,
1949 * find its roots, and plug acos(root) into the original, recording the max:
1950 *
1951 (define (smax coeffs)
1952 (let* ((n (vct-length coeffs))
1953 (dcos (make-vct n 1.0)))
1954 (do ((i 0 (+ i 1)))
1955 ((= i n))
1956 (vct-set! dcos i (* (+ i 1) (vct-ref coeffs i))))
1957 (let ((partials ()))
1958 (do ((i 0 (+ i 1)))
1959 ((= i n))
1960 (set! partials (append (list (vct-ref dcos i) (+ i 1)) partials)))
1961 (let ((Tn (partials->polynomial (reverse partials))))
1962 (let ((roots (poly-roots Tn)))
1963 (let ((mx (* -2 n)))
1964 (for-each
1965 (lambda (root)
1966 (let ((acr (acos root))
1967 (sum 0.0))
1968 (do ((i 0 (+ i 1)))
1969 ((= i n))
1970 (set! sum (+ sum (* (vct-ref coeffs i) (sin (* (+ i 1) acr))))))
1971 (if (> (abs sum) mx)
1972 (set! mx (abs sum)))))
1973 roots)
1974 mx))))))
1975
1976 (smax (make-vct n 1.0))
1977
1978 * but that's too much effort for an initialization function.
1979 * much faster is this search (it usually hits an answer in 2 or 3 tries):
1980 *
1981 (define (find-nsin-max n)
1982
1983 (define (ns x n)
1984 (let* ((a2 (/ x 2))
1985 (den (sin a2)))
1986 (if (= den 0.0)
1987 0.0
1988 (/ (* (sin (* n a2)) (sin (* (+ n 1) a2))) den))))
1989
1990 (define (find-mid-max n lo hi)
1991 (let ((mid (/ (+ lo hi) 2)))
1992 (let ((ylo (ns lo n))
1993 (yhi (ns hi n)))
1994 (if (< (abs (- ylo yhi)) 1e-100)
1995 (list (ns mid n)
1996 (rationalize (/ mid pi) 0.0))
1997 (if (> ylo yhi)
1998 (find-mid-max n lo mid)
1999 (find-mid-max n mid hi))))))
2000
2001 (find-mid-max n 0.0 (/ pi (+ n .5))))
2002 *
2003 * the 'mid' point has a surprisingly simple relation to pi:
2004 *
2005 * (find-max 100000000000000)
2006 * 7.24518620297426541161857919764185053934850053037407235e13
2007 *
2008 * (find-max 1000000000000000000000000)
2009 * 7.24518620297422918568756794921595308358209723004380140e23 1/1333333333333333333333334 = .75e-24 -> (3*pi)/(4*n)
2010 *
2011 * (find-max 10000000000000000000000000000000000)
2012 * 7.24518620297422918568756432662285195872681453497436666955413707681801083640192066844820049586929551886747925783e33
2013 *
2014 * which is approximately (/ (* 8 (expt (sin (* pi 3/8)) 2)) (* 3 pi)):
2015 * 7.245186202974229185687564326622851596467504
2016 *
2017 * (to get that expression, plug in 3pi/4n, treat (n+1)/n as essentially 1 as n gets very large,
2018 * treat (sin x) as about x when x is very small, and simplify)
2019 * so if n>10, we could use (ns (/ (* 3 pi) (* 4 n)) n) without major error
2020 * It's possible to differentiate the nsin formula:
2021 *
2022 * -(cos(x/2)sin(nx/2)sin((n+1)x/2))/(2sin^2(x/2)) + ncos(nx/2)sin((n+1)x/2)/(2sin(x/2)) + (n+1)sin(nx/2)cos((n+1)x/2)/(2sin(x/2))
2023 *
2024 * and find the first 0 when n is very large -- it is very close to 3pi/(4*n)
2025 */
2026 #endif
2027
2028
nsin_ns(mus_float_t x,int n)2029 static mus_float_t nsin_ns(mus_float_t x, int n)
2030 {
2031 mus_float_t a2, den;
2032 a2 = x / 2;
2033 den = sin(a2);
2034 if (den == 0.0)
2035 return(0.0);
2036 return(sin(n * a2) * sin((n + 1) * a2) / den);
2037 }
2038
2039
find_nsin_scaler(int n,mus_float_t lo,mus_float_t hi)2040 static mus_float_t find_nsin_scaler(int n, mus_float_t lo, mus_float_t hi)
2041 {
2042 mus_float_t mid, ylo, yhi;
2043 mid = (lo + hi) / 2;
2044 ylo = nsin_ns(lo, n);
2045 yhi = nsin_ns(hi, n);
2046 if (fabs(ylo - yhi) < 1e-12)
2047 return(nsin_ns(mid, n));
2048 if (ylo > yhi)
2049 return(find_nsin_scaler(n, lo, mid));
2050 return(find_nsin_scaler(n, mid, hi));
2051 }
2052
2053
nsin_scaler(int n)2054 static mus_float_t nsin_scaler(int n)
2055 {
2056 return(1.0 / find_nsin_scaler(n, 0.0, M_PI / (n + 0.5)));
2057 }
2058
2059
nsin_set_n(mus_any * ptr,mus_long_t val)2060 static mus_long_t nsin_set_n(mus_any *ptr, mus_long_t val)
2061 {
2062 cosp *gen = (cosp *)ptr;
2063 gen->n = (int)val;
2064 gen->cos5 = val + 1.0;
2065 gen->scaler = nsin_scaler((int)val);
2066 return(val);
2067 }
2068
2069
mus_nsin(mus_any * ptr,mus_float_t fm)2070 mus_float_t mus_nsin(mus_any *ptr, mus_float_t fm)
2071 {
2072 /* (let* ((a2 (* angle 0.5))
2073 (den (sin a2)))
2074 (if (= den 0.0)
2075 0.0
2076 (/ (* (sin (* n a2)) (sin (* (+ n 1) a2))) den)))
2077 */
2078 #if HAVE_SINCOS
2079 double val, a2, ns, nc, s, c;
2080 cosp *gen = (cosp *)ptr;
2081 a2 = gen->phase * 0.5;
2082 sincos(a2, &s, &c);
2083 if (DIVISOR_NEAR_ZERO(s)) /* see note under ncos */
2084 val = 0.0;
2085 else
2086 {
2087 sincos(gen->n * a2, &ns, &nc);
2088 val = gen->scaler * ns * (ns * c + nc * s) / s;
2089 }
2090 #else
2091 mus_float_t val, den, a2;
2092 cosp *gen = (cosp *)ptr;
2093 a2 = gen->phase * 0.5;
2094 den = sin(a2);
2095 if (DIVISOR_NEAR_ZERO(den)) /* see note under ncos */
2096 val = 0.0;
2097 else val = gen->scaler * sin(gen->n * a2) * sin(a2 * gen->cos5) / den;
2098 #endif
2099 gen->phase += (gen->freq + fm);
2100 return((mus_float_t)val);
2101 }
2102
2103
run_nsin(mus_any * ptr,mus_float_t fm,mus_float_t unused)2104 static mus_float_t run_nsin(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_nsin(ptr, fm));}
2105
2106 static mus_any_class NSIN_CLASS = {
2107 MUS_NSIN,
2108 (char *)S_nsin,
2109 &free_ncos,
2110 &describe_nsin,
2111 &nsin_equalp,
2112 0, 0, /* data */
2113 &ncos_n,
2114 &nsin_set_n,
2115 &ncos_freq,
2116 &ncos_set_freq,
2117 &ncos_phase,
2118 &ncos_set_phase,
2119 &ncos_scaler,
2120 &ncos_set_scaler,
2121 &ncos_increment,
2122 &ncos_set_increment,
2123 &run_nsin,
2124 MUS_NOT_SPECIAL,
2125 NULL,
2126 0,
2127 0, 0, 0, 0, 0, 0,
2128 0, 0, 0, 0,
2129 0, 0, 0, 0, 0, 0, 0,
2130 0, 0, 0, 0,
2131 &ncos_reset,
2132 0,
2133 &cosp_copy
2134 };
2135
2136
mus_make_nsin(mus_float_t freq,int n)2137 mus_any *mus_make_nsin(mus_float_t freq, int n)
2138 {
2139 cosp *gen;
2140 gen = (cosp *)mus_make_ncos(freq, n);
2141 gen->core = &NSIN_CLASS;
2142 gen->scaler = nsin_scaler(n);
2143 gen->cos5 = gen->n + 1.0;
2144 return((mus_any *)gen);
2145 }
2146
2147
2148 /* ---------------- asymmetric-fm ---------------- */
2149
2150 /* changed from sin(sin) to cos(sin) and added amplitude normalization 6-Sep-07 */
2151
2152 typedef struct {
2153 mus_any_class *core;
2154 mus_float_t r;
2155 mus_float_t freq, phase;
2156 mus_float_t ratio;
2157 mus_float_t cosr, sinr;
2158 mus_float_t one;
2159 } asyfm;
2160
2161
free_asymmetric_fm(mus_any * ptr)2162 static void free_asymmetric_fm(mus_any *ptr) {free(ptr);}
asyfm_reset(mus_any * ptr)2163 static void asyfm_reset(mus_any *ptr) {((asyfm *)ptr)->phase = 0.0;}
2164
asyfm_copy(mus_any * ptr)2165 static mus_any *asyfm_copy(mus_any *ptr)
2166 {
2167 asyfm *g;
2168 g = (asyfm *)malloc(sizeof(asyfm));
2169 memcpy((void *)g, (void *)ptr, sizeof(asyfm));
2170 return((mus_any *)g);
2171 }
2172
asyfm_freq(mus_any * ptr)2173 static mus_float_t asyfm_freq(mus_any *ptr) {return(mus_radians_to_hz(((asyfm *)ptr)->freq));}
asyfm_set_freq(mus_any * ptr,mus_float_t val)2174 static mus_float_t asyfm_set_freq(mus_any *ptr, mus_float_t val) {((asyfm *)ptr)->freq = mus_hz_to_radians(val); return(val);}
2175
asyfm_increment(mus_any * ptr)2176 static mus_float_t asyfm_increment(mus_any *ptr) {return(((asyfm *)ptr)->freq);}
asyfm_set_increment(mus_any * ptr,mus_float_t val)2177 static mus_float_t asyfm_set_increment(mus_any *ptr, mus_float_t val) {((asyfm *)ptr)->freq = val; return(val);}
2178
asyfm_phase(mus_any * ptr)2179 static mus_float_t asyfm_phase(mus_any *ptr) {return(fmod(((asyfm *)ptr)->phase, TWO_PI));}
asyfm_set_phase(mus_any * ptr,mus_float_t val)2180 static mus_float_t asyfm_set_phase(mus_any *ptr, mus_float_t val) {((asyfm *)ptr)->phase = val; return(val);}
2181
asyfm_ratio(mus_any * ptr)2182 static mus_float_t asyfm_ratio(mus_any *ptr) {return(((asyfm *)ptr)->ratio);}
2183
asyfm_r(mus_any * ptr)2184 static mus_float_t asyfm_r(mus_any *ptr) {return(((asyfm *)ptr)->r);}
2185
asyfm_set_r(mus_any * ptr,mus_float_t val)2186 static mus_float_t asyfm_set_r(mus_any *ptr, mus_float_t val)
2187 {
2188 asyfm *gen = (asyfm *)ptr;
2189 if (val != 0.0)
2190 {
2191 gen->r = val;
2192 gen->cosr = 0.5 * (val - (1.0 / val));
2193 gen->sinr = 0.5 * (val + (1.0 / val));
2194 if ((val > 1.0) ||
2195 ((val < 0.0) && (val > -1.0)))
2196 gen->one = -1.0;
2197 else gen->one = 1.0;
2198 }
2199 return(val);
2200 }
2201
2202
asyfm_equalp(mus_any * p1,mus_any * p2)2203 static bool asyfm_equalp(mus_any *p1, mus_any *p2)
2204 {
2205 return((p1 == p2) ||
2206 (((p1->core)->type == (p2->core)->type) &&
2207 ((((asyfm *)p1)->freq) == (((asyfm *)p2)->freq)) &&
2208 ((((asyfm *)p1)->phase) == (((asyfm *)p2)->phase)) &&
2209 ((((asyfm *)p1)->ratio) == (((asyfm *)p2)->ratio)) &&
2210 ((((asyfm *)p1)->r) == (((asyfm *)p2)->r))));
2211 }
2212
2213
describe_asyfm(mus_any * ptr)2214 static char *describe_asyfm(mus_any *ptr)
2215 {
2216 char *describe_buffer;
2217 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
2218 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, ratio: %.3f, r: %.3f",
2219 mus_name(ptr),
2220 mus_frequency(ptr),
2221 mus_phase(ptr),
2222 ((asyfm *)ptr)->ratio,
2223 asyfm_r(ptr));
2224 return(describe_buffer);
2225 }
2226
2227
mus_is_asymmetric_fm(mus_any * ptr)2228 bool mus_is_asymmetric_fm(mus_any *ptr)
2229 {
2230 return((ptr) &&
2231 (ptr->core->type == MUS_ASYMMETRIC_FM));
2232 }
2233
2234
mus_asymmetric_fm(mus_any * ptr,mus_float_t index,mus_float_t fm)2235 mus_float_t mus_asymmetric_fm(mus_any *ptr, mus_float_t index, mus_float_t fm)
2236 {
2237 asyfm *gen = (asyfm *)ptr;
2238 mus_float_t result;
2239 mus_float_t mth;
2240 mth = gen->ratio * gen->phase;
2241 result = exp(index * gen->cosr * (gen->one + cos(mth))) * cos(gen->phase + index * gen->sinr * sin(mth));
2242 /* second index factor added 4-Mar-02 and (+/-)1.0 + cos to normalize amps 6-Sep-07 */
2243 gen->phase += (gen->freq + fm);
2244 return(result);
2245 }
2246
2247
mus_asymmetric_fm_unmodulated(mus_any * ptr,mus_float_t index)2248 mus_float_t mus_asymmetric_fm_unmodulated(mus_any *ptr, mus_float_t index)
2249 {
2250 asyfm *gen = (asyfm *)ptr;
2251 mus_float_t result, mth;
2252 mth = gen->ratio * gen->phase;
2253 result = exp(index * gen->cosr * (gen->one + cos(mth))) * cos(gen->phase + index * gen->sinr * sin(mth));
2254 /* second index factor added 4-Mar-02 */
2255 gen->phase += gen->freq;
2256 return(result);
2257 }
2258
2259 static mus_any_class ASYMMETRIC_FM_CLASS = {
2260 MUS_ASYMMETRIC_FM,
2261 (char *)S_asymmetric_fm,
2262 &free_asymmetric_fm,
2263 &describe_asyfm,
2264 &asyfm_equalp,
2265 0, 0, 0, 0,
2266 &asyfm_freq,
2267 &asyfm_set_freq,
2268 &asyfm_phase,
2269 &asyfm_set_phase,
2270 &asyfm_r,
2271 &asyfm_set_r,
2272 &asyfm_increment,
2273 &asyfm_set_increment,
2274 &mus_asymmetric_fm,
2275 MUS_NOT_SPECIAL,
2276 NULL, 0,
2277 &asyfm_ratio,
2278 0, 0, 0, 0, 0, 0, 0, 0, 0,
2279 0, 0, 0, 0, 0, 0, 0,
2280 0, 0, 0, 0,
2281 &asyfm_reset,
2282 0,
2283 &asyfm_copy
2284 };
2285
2286
mus_make_asymmetric_fm(mus_float_t freq,mus_float_t phase,mus_float_t r,mus_float_t ratio)2287 mus_any *mus_make_asymmetric_fm(mus_float_t freq, mus_float_t phase, mus_float_t r, mus_float_t ratio) /* r default 1.0, ratio 1.0 */
2288 {
2289 asyfm *gen = NULL;
2290 if (r == 0.0)
2291 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_asymmetric_fm ": r can't be 0.0");
2292 else
2293 {
2294 gen = (asyfm *)malloc(sizeof(asyfm));
2295 gen->core = &ASYMMETRIC_FM_CLASS;
2296 gen->freq = mus_hz_to_radians(freq);
2297 gen->phase = phase;
2298 gen->r = r;
2299 gen->ratio = ratio;
2300 gen->cosr = 0.5 * (r - (1.0 / r)); /* 0.5 factor for I/2 */
2301 gen->sinr = 0.5 * (r + (1.0 / r));
2302 if ((r > 1.0) ||
2303 ((r < 0.0) && (r > -1.0)))
2304 gen->one = -1.0;
2305 else gen->one = 1.0;
2306 }
2307 return((mus_any *)gen);
2308 }
2309
2310
2311
2312
2313 /*---------------- nrxysin (sine-summation) and nrxycos ---------------- */
2314
2315 /* the generator uses x and y (frequencies), but it's very common to start up with 0 freqs
2316 * and let the fm arg set the frequency, so it seems like we want to give the ratio between
2317 * the frequencies at make time, rather than two (possibly dummy) frequencies).
2318 * xy-ratio negative to build (via r) backwards.
2319 */
2320
2321 #define MAX_R 0.999999
2322 #define MIN_R -0.999999
2323
2324 typedef struct {
2325 mus_any_class *core;
2326 mus_float_t freq, phase;
2327 int n;
2328 mus_float_t norm, r, r_to_n_plus_1, r_squared_plus_1, y_over_x;
2329 } nrxy;
2330
2331
free_nrxy(mus_any * ptr)2332 static void free_nrxy(mus_any *ptr) {free(ptr);}
nrxy_reset(mus_any * ptr)2333 static void nrxy_reset(mus_any *ptr) {((nrxy *)ptr)->phase = 0.0;}
2334
nrxy_copy(mus_any * ptr)2335 static mus_any *nrxy_copy(mus_any *ptr)
2336 {
2337 nrxy *g;
2338 g = (nrxy *)malloc(sizeof(nrxy));
2339 memcpy((void *)g, (void *)ptr, sizeof(nrxy));
2340 return((mus_any *)g);
2341 }
2342
nrxy_freq(mus_any * ptr)2343 static mus_float_t nrxy_freq(mus_any *ptr) {return(mus_radians_to_hz(((nrxy *)ptr)->freq));}
nrxy_set_freq(mus_any * ptr,mus_float_t val)2344 static mus_float_t nrxy_set_freq(mus_any *ptr, mus_float_t val) {((nrxy *)ptr)->freq = mus_hz_to_radians(val); return(val);}
2345
nrxy_increment(mus_any * ptr)2346 static mus_float_t nrxy_increment(mus_any *ptr) {return(((nrxy *)ptr)->freq);}
nrxy_set_increment(mus_any * ptr,mus_float_t val)2347 static mus_float_t nrxy_set_increment(mus_any *ptr, mus_float_t val) {((nrxy *)ptr)->freq = val; return(val);}
2348
nrxy_phase(mus_any * ptr)2349 static mus_float_t nrxy_phase(mus_any *ptr) {return(fmod(((nrxy *)ptr)->phase, TWO_PI));}
nrxy_set_phase(mus_any * ptr,mus_float_t val)2350 static mus_float_t nrxy_set_phase(mus_any *ptr, mus_float_t val) {((nrxy *)ptr)->phase = val; return(val);}
2351
nrxy_n(mus_any * ptr)2352 static mus_long_t nrxy_n(mus_any *ptr) {return((mus_long_t)(((nrxy *)ptr)->n));}
2353
nrxy_y_over_x(mus_any * ptr)2354 static mus_float_t nrxy_y_over_x(mus_any *ptr) {return(((nrxy *)ptr)->y_over_x);}
nrxy_set_y_over_x(mus_any * ptr,mus_float_t val)2355 static mus_float_t nrxy_set_y_over_x(mus_any *ptr, mus_float_t val) {((nrxy *)ptr)->y_over_x = val; return(val);}
2356
nrxy_r(mus_any * ptr)2357 static mus_float_t nrxy_r(mus_any *ptr) {return(((nrxy *)ptr)->r);}
2358
nrxy_set_r(mus_any * ptr,mus_float_t r)2359 static mus_float_t nrxy_set_r(mus_any *ptr, mus_float_t r)
2360 {
2361 nrxy *gen = (nrxy *)ptr;
2362 int n;
2363 n = gen->n;
2364 if (r > MAX_R) r = MAX_R;
2365 if (r < MIN_R) r = MIN_R;
2366 gen->r = r;
2367 gen->r_to_n_plus_1 = pow(r, n + 1);
2368 gen->r_squared_plus_1 = 1.0 + r * r;
2369 if (n == 0)
2370 gen->norm = 1.0;
2371 else gen->norm = (pow(fabs(r), n + 1) - 1.0) / (fabs(r) - 1.0);
2372 /* fabs here because if r<0.0, we line up at (2k-1)*pi rather than 2k*pi, but
2373 * otherwise the waveform is identical
2374 */
2375 return(r);
2376 }
2377
nrxy_equalp(mus_any * p1,mus_any * p2)2378 static bool nrxy_equalp(mus_any *p1, mus_any *p2)
2379 {
2380 nrxy *g1 = (nrxy *)p1;
2381 nrxy *g2 = (nrxy *)p2;
2382 return((p1 == p2) ||
2383 (((g1->core)->type == (g2->core)->type) &&
2384 (g1->freq == g2->freq) &&
2385 (g1->phase == g2->phase) &&
2386 (g1->n == g2->n) &&
2387 (g1->r == g2->r) &&
2388 (g1->y_over_x == g2->y_over_x)));
2389 }
2390
2391
mus_is_nrxysin(mus_any * ptr)2392 bool mus_is_nrxysin(mus_any *ptr)
2393 {
2394 return((ptr) &&
2395 (ptr->core->type == MUS_NRXYSIN));
2396 }
2397
2398
describe_nrxysin(mus_any * ptr)2399 static char *describe_nrxysin(mus_any *ptr)
2400 {
2401 nrxy *gen = (nrxy *)ptr;
2402 char *describe_buffer;
2403 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
2404 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s frequency: %.3f, ratio: %.3f, phase: %.3f, n: %d, r: %.3f",
2405 mus_name(ptr),
2406 mus_frequency(ptr),
2407 gen->y_over_x,
2408 mus_phase(ptr),
2409 gen->n,
2410 nrxy_r(ptr));
2411 return(describe_buffer);
2412 }
2413
2414
mus_nrxysin(mus_any * ptr,mus_float_t fm)2415 mus_float_t mus_nrxysin(mus_any *ptr, mus_float_t fm)
2416 {
2417 /* Jolley 475 but 0..n rather than 0..n-1 */
2418 /* see also Durell and Robson "Advanced Trigonometry" p 175 */
2419
2420 nrxy *gen = (nrxy *)ptr;
2421 mus_float_t x, y, r, divisor;
2422 int n;
2423
2424 x = gen->phase;
2425 n = gen->n;
2426 r = gen->r;
2427 gen->phase += (gen->freq + fm);
2428
2429
2430 if (gen->y_over_x == 1.0)
2431 {
2432 #if (!HAVE_SINCOS)
2433 divisor = gen->norm * (gen->r_squared_plus_1 - (2 * r * cos(x)));
2434 if (DIVISOR_NEAR_ZERO(divisor))
2435 return(0.0);
2436 return((sin(x) - gen->r_to_n_plus_1 * (sin(x * (n + 2)) - r * sin(x * (n + 1)))) / divisor);
2437 #else
2438 double sx, cx, snx, cnx;
2439 sincos(x, &sx, &cx);
2440 divisor = gen->norm * (gen->r_squared_plus_1 - (2 * r * cx));
2441 if (DIVISOR_NEAR_ZERO(divisor))
2442 return(0.0);
2443 sincos((n + 1) * x, &snx, &cnx);
2444 return((sx - gen->r_to_n_plus_1 * (sx * cnx + (cx - r) * snx)) / divisor);
2445 #endif
2446 }
2447
2448 #if HAVE_SINCOS
2449 {
2450 double xs, xc, ys, yc, nys, nyc, sin_x_y, sin_x_ny, sin_x_n1y, cos_x_ny;
2451
2452 y = x * gen->y_over_x;
2453 sincos(y, &ys, &yc);
2454 divisor = gen->norm * (gen->r_squared_plus_1 - (2 * r * yc));
2455 if (DIVISOR_NEAR_ZERO(divisor))
2456 return(0.0);
2457
2458 sincos(x, &xs, &xc);
2459 sincos(n * y, &nys, &nyc);
2460 sin_x_y = (xs * yc - ys * xc);
2461 sin_x_ny = (xs * nyc + nys * xc);
2462 cos_x_ny = (xc * nyc - xs * nys);
2463 sin_x_n1y = (sin_x_ny * yc + cos_x_ny * ys);
2464
2465 return((xs -
2466 r * sin_x_y -
2467 gen->r_to_n_plus_1 * (sin_x_n1y - r * sin_x_ny)) / divisor);
2468 }
2469 #else
2470 y = x * gen->y_over_x;
2471 divisor = gen->norm * (gen->r_squared_plus_1 - (2 * r * cos(y)));
2472 if (DIVISOR_NEAR_ZERO(divisor))
2473 return(0.0);
2474
2475 return((sin(x) -
2476 r * sin(x - y) -
2477 gen->r_to_n_plus_1 * (sin(x + (n + 1) * y) -
2478 r * sin(x + n * y))) /
2479 divisor);
2480 #endif
2481 }
2482
2483
run_nrxysin(mus_any * ptr,mus_float_t fm,mus_float_t unused)2484 static mus_float_t run_nrxysin(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_nrxysin(ptr, fm));}
2485
2486
2487 static mus_any_class NRXYSIN_CLASS = {
2488 MUS_NRXYSIN,
2489 (char *)S_nrxysin,
2490 &free_nrxy,
2491 &describe_nrxysin,
2492 &nrxy_equalp,
2493 0, 0,
2494 &nrxy_n, 0,
2495 &nrxy_freq,
2496 &nrxy_set_freq,
2497 &nrxy_phase,
2498 &nrxy_set_phase,
2499 &nrxy_r,
2500 &nrxy_set_r,
2501 &nrxy_increment,
2502 &nrxy_set_increment,
2503 &run_nrxysin,
2504 MUS_NOT_SPECIAL,
2505 NULL, 0,
2506 &nrxy_y_over_x,
2507 &nrxy_set_y_over_x,
2508 0, 0, 0, 0,
2509 0, 0, 0, 0,
2510 0, 0, 0, 0, 0, 0, 0,
2511 0, 0, 0, 0,
2512 &nrxy_reset,
2513 0,
2514 &nrxy_copy
2515 };
2516
2517
mus_make_nrxysin(mus_float_t frequency,mus_float_t y_over_x,int n,mus_float_t r)2518 mus_any *mus_make_nrxysin(mus_float_t frequency, mus_float_t y_over_x, int n, mus_float_t r)
2519 {
2520 nrxy *gen;
2521 gen = (nrxy *)malloc(sizeof(nrxy));
2522 gen->core = &NRXYSIN_CLASS;
2523 gen->freq = mus_hz_to_radians(frequency);
2524 gen->y_over_x = y_over_x;
2525 gen->phase = 0.0;
2526 gen->n = n;
2527 nrxy_set_r((mus_any *)gen, r);
2528 return((mus_any *)gen);
2529 }
2530
2531
mus_is_nrxycos(mus_any * ptr)2532 bool mus_is_nrxycos(mus_any *ptr)
2533 {
2534 return((ptr) &&
2535 (ptr->core->type == MUS_NRXYCOS));
2536 }
2537
2538
describe_nrxycos(mus_any * ptr)2539 static char *describe_nrxycos(mus_any *ptr)
2540 {
2541 nrxy *gen = (nrxy *)ptr;
2542 char *describe_buffer;
2543 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
2544 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s frequency: %.3f, ratio: %.3f, phase: %.3f, n: %d, r: %.3f",
2545 mus_name(ptr),
2546 mus_frequency(ptr),
2547 gen->y_over_x,
2548 mus_phase(ptr),
2549 gen->n,
2550 nrxy_r(ptr));
2551 return(describe_buffer);
2552 }
2553
2554
mus_nrxycos(mus_any * ptr,mus_float_t fm)2555 mus_float_t mus_nrxycos(mus_any *ptr, mus_float_t fm)
2556 {
2557 nrxy *gen = (nrxy *)ptr;
2558 mus_float_t x, y, r, divisor;
2559 int n;
2560
2561 x = gen->phase;
2562 y = x * gen->y_over_x;
2563 n = gen->n;
2564 r = gen->r;
2565
2566 gen->phase += (gen->freq + fm);
2567
2568 #if HAVE_SINCOS
2569 {
2570 double xs, xc, ys, yc, nys, nyc, cos_x_y, cos_x_ny, cos_x_n1y, sin_x_ny;
2571
2572 sincos(y, &ys, &yc);
2573 divisor = gen->norm * (gen->r_squared_plus_1 - (2 * r * yc));
2574 if (DIVISOR_NEAR_ZERO(divisor))
2575 return(1.0);
2576
2577 sincos(x, &xs, &xc);
2578 sincos(n * y, &nys, &nyc);
2579 cos_x_y = (xc * yc + ys * xs);
2580 sin_x_ny = (xs * nyc + nys * xc);
2581 cos_x_ny = (xc * nyc - xs * nys);
2582 cos_x_n1y = (cos_x_ny * yc - sin_x_ny * ys);
2583 return((xc -
2584 r * cos_x_y -
2585 gen->r_to_n_plus_1 * (cos_x_n1y - r * cos_x_ny)) / divisor);
2586 }
2587 #else
2588 divisor = gen->norm * (gen->r_squared_plus_1 - (2 * r * cos(y)));
2589 if (DIVISOR_NEAR_ZERO(divisor))
2590 return(1.0);
2591 /* this can happen if r>0.9999999 or thereabouts;
2592 */
2593
2594 return((cos(x) -
2595 r * cos(x - y) -
2596 gen->r_to_n_plus_1 * (cos(x + (n + 1) * y) -
2597 r * cos(x + n * y))) /
2598 divisor);
2599 #endif
2600 }
2601
2602
run_nrxycos(mus_any * ptr,mus_float_t fm,mus_float_t unused)2603 static mus_float_t run_nrxycos(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_nrxycos(ptr, fm));}
2604
2605
2606 static mus_any_class NRXYCOS_CLASS = {
2607 MUS_NRXYCOS,
2608 (char *)S_nrxycos,
2609 &free_nrxy,
2610 &describe_nrxycos,
2611 &nrxy_equalp,
2612 0, 0,
2613 &nrxy_n, 0,
2614 &nrxy_freq,
2615 &nrxy_set_freq,
2616 &nrxy_phase,
2617 &nrxy_set_phase,
2618 &nrxy_r,
2619 &nrxy_set_r,
2620 &nrxy_increment,
2621 &nrxy_set_increment,
2622 &run_nrxycos,
2623 MUS_NOT_SPECIAL,
2624 NULL, 0,
2625 &nrxy_y_over_x,
2626 &nrxy_set_y_over_x,
2627 0, 0, 0, 0,
2628 0, 0, 0, 0,
2629 0, 0, 0, 0, 0, 0, 0,
2630 0, 0, 0, 0,
2631 &nrxy_reset,
2632 0,
2633 &nrxy_copy
2634 };
2635
2636
mus_make_nrxycos(mus_float_t frequency,mus_float_t y_over_x,int n,mus_float_t r)2637 mus_any *mus_make_nrxycos(mus_float_t frequency, mus_float_t y_over_x, int n, mus_float_t r)
2638 {
2639 nrxy *gen;
2640 gen = (nrxy *)mus_make_nrxysin(frequency, y_over_x, n, r);
2641 gen->core = &NRXYCOS_CLASS;
2642 return((mus_any *)gen);
2643 }
2644
2645
2646
2647 /* ---------------- rxykcos/sin ---------------- */
2648
2649 typedef struct {
2650 mus_any_class *core;
2651 mus_float_t r, ar;
2652 mus_float_t freq, phase;
2653 mus_float_t ratio;
2654 } rxyk;
2655
2656
free_rxykcos(mus_any * ptr)2657 static void free_rxykcos(mus_any *ptr) {free(ptr);}
rxyk_reset(mus_any * ptr)2658 static void rxyk_reset(mus_any *ptr) {((rxyk *)ptr)->phase = 0.0;}
2659
rxyk_copy(mus_any * ptr)2660 static mus_any *rxyk_copy(mus_any *ptr)
2661 {
2662 rxyk *g;
2663 g = (rxyk *)malloc(sizeof(rxyk));
2664 memcpy((void *)g, (void *)ptr, sizeof(rxyk));
2665 return((mus_any *)g);
2666 }
2667
rxyk_freq(mus_any * ptr)2668 static mus_float_t rxyk_freq(mus_any *ptr) {return(mus_radians_to_hz(((rxyk *)ptr)->freq));}
rxyk_set_freq(mus_any * ptr,mus_float_t val)2669 static mus_float_t rxyk_set_freq(mus_any *ptr, mus_float_t val) {((rxyk *)ptr)->freq = mus_hz_to_radians(val); return(val);}
2670
rxyk_increment(mus_any * ptr)2671 static mus_float_t rxyk_increment(mus_any *ptr) {return(((rxyk *)ptr)->freq);}
rxyk_set_increment(mus_any * ptr,mus_float_t val)2672 static mus_float_t rxyk_set_increment(mus_any *ptr, mus_float_t val) {((rxyk *)ptr)->freq = val; return(val);}
2673
rxyk_phase(mus_any * ptr)2674 static mus_float_t rxyk_phase(mus_any *ptr) {return(fmod(((rxyk *)ptr)->phase, TWO_PI));}
rxyk_set_phase(mus_any * ptr,mus_float_t val)2675 static mus_float_t rxyk_set_phase(mus_any *ptr, mus_float_t val) {((rxyk *)ptr)->phase = val; return(val);}
2676
rxyk_ratio(mus_any * ptr)2677 static mus_float_t rxyk_ratio(mus_any *ptr) {return(((rxyk *)ptr)->ratio);}
2678
rxyk_r(mus_any * ptr)2679 static mus_float_t rxyk_r(mus_any *ptr) {return(((rxyk *)ptr)->r);}
2680
rxyk_set_r(mus_any * ptr,mus_float_t val)2681 static mus_float_t rxyk_set_r(mus_any *ptr, mus_float_t val)
2682 {
2683 rxyk *gen = (rxyk *)ptr;
2684 gen->r = val;
2685 gen->ar = 1.0 / exp(fabs(val));
2686 return(val);
2687 }
2688
run_rxykcos(mus_any * ptr,mus_float_t fm,mus_float_t unused)2689 static mus_float_t run_rxykcos(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_rxykcos(ptr, fm));}
run_rxyksin(mus_any * ptr,mus_float_t fm,mus_float_t unused)2690 static mus_float_t run_rxyksin(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_rxyksin(ptr, fm));}
2691
rxyk_equalp(mus_any * p1,mus_any * p2)2692 static bool rxyk_equalp(mus_any *p1, mus_any *p2)
2693 {
2694 return((p1 == p2) ||
2695 (((p1->core)->type == (p2->core)->type) &&
2696 ((((rxyk *)p1)->freq) == (((rxyk *)p2)->freq)) &&
2697 ((((rxyk *)p1)->phase) == (((rxyk *)p2)->phase)) &&
2698 ((((rxyk *)p1)->ratio) == (((rxyk *)p2)->ratio)) &&
2699 ((((rxyk *)p1)->r) == (((rxyk *)p2)->r))));
2700 }
2701
2702
describe_rxyk(mus_any * ptr)2703 static char *describe_rxyk(mus_any *ptr)
2704 {
2705 char *describe_buffer;
2706 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
2707 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, ratio: %.3f, r: %.3f",
2708 mus_name(ptr),
2709 mus_frequency(ptr),
2710 mus_phase(ptr),
2711 ((rxyk *)ptr)->ratio,
2712 rxyk_r(ptr));
2713 return(describe_buffer);
2714 }
2715
2716
mus_is_rxykcos(mus_any * ptr)2717 bool mus_is_rxykcos(mus_any *ptr)
2718 {
2719 return((ptr) &&
2720 (ptr->core->type == MUS_RXYKCOS));
2721 }
2722
2723
mus_rxykcos(mus_any * ptr,mus_float_t fm)2724 mus_float_t mus_rxykcos(mus_any *ptr, mus_float_t fm)
2725 {
2726 rxyk *gen = (rxyk *)ptr;
2727 mus_float_t result, rx;
2728
2729 rx = gen->ratio * gen->phase;
2730 result = gen->ar * exp(gen->r * cos(rx)) * cos(gen->phase + (gen->r * sin(rx)));
2731 gen->phase += (fm + gen->freq);
2732
2733 return(result);
2734 }
2735
2736
2737 static mus_any_class RXYKCOS_CLASS = {
2738 MUS_RXYKCOS,
2739 (char *)S_rxykcos,
2740 &free_rxykcos,
2741 &describe_rxyk,
2742 &rxyk_equalp,
2743 0, 0, 0, 0,
2744 &rxyk_freq,
2745 &rxyk_set_freq,
2746 &rxyk_phase,
2747 &rxyk_set_phase,
2748 &rxyk_r,
2749 &rxyk_set_r,
2750 &rxyk_increment,
2751 &rxyk_set_increment,
2752 &run_rxykcos,
2753 MUS_NOT_SPECIAL,
2754 NULL, 0,
2755 &rxyk_ratio,
2756 0, 0, 0, 0, 0, 0, 0, 0, 0,
2757 0, 0, 0, 0, 0, 0, 0,
2758 0, 0, 0, 0,
2759 &rxyk_reset,
2760 0,
2761 &rxyk_copy
2762 };
2763
2764
mus_make_rxykcos(mus_float_t freq,mus_float_t phase,mus_float_t r,mus_float_t ratio)2765 mus_any *mus_make_rxykcos(mus_float_t freq, mus_float_t phase, mus_float_t r, mus_float_t ratio) /* r default 0.5, ratio 1.0 */
2766 {
2767 rxyk *gen;
2768 gen = (rxyk *)malloc(sizeof(rxyk));
2769 gen->core = &RXYKCOS_CLASS;
2770 gen->freq = mus_hz_to_radians(freq);
2771 gen->phase = phase;
2772 gen->r = r;
2773 gen->ar = 1.0 / exp(fabs(r));
2774 gen->ratio = ratio;
2775 return((mus_any *)gen);
2776 }
2777
2778
2779
mus_is_rxyksin(mus_any * ptr)2780 bool mus_is_rxyksin(mus_any *ptr)
2781 {
2782 return((ptr) &&
2783 (ptr->core->type == MUS_RXYKSIN));
2784 }
2785
2786
mus_rxyksin(mus_any * ptr,mus_float_t fm)2787 mus_float_t mus_rxyksin(mus_any *ptr, mus_float_t fm)
2788 {
2789 rxyk *gen = (rxyk *)ptr;
2790 mus_float_t result, rx;
2791
2792 rx = gen->ratio * gen->phase;
2793 result = gen->ar * exp(gen->r * cos(rx)) * sin(gen->phase + (gen->r * sin(rx)));
2794 gen->phase += (fm + gen->freq);
2795
2796 return(result);
2797 }
2798
2799
2800 static mus_any_class RXYKSIN_CLASS = {
2801 MUS_RXYKSIN,
2802 (char *)S_rxyksin,
2803 &free_rxykcos,
2804 &describe_rxyk,
2805 &rxyk_equalp,
2806 0, 0, 0, 0,
2807 &rxyk_freq,
2808 &rxyk_set_freq,
2809 &rxyk_phase,
2810 &rxyk_set_phase,
2811 &rxyk_r,
2812 &rxyk_set_r,
2813 &rxyk_increment,
2814 &rxyk_set_increment,
2815 &run_rxyksin,
2816 MUS_NOT_SPECIAL,
2817 NULL, 0,
2818 &rxyk_ratio,
2819 0, 0, 0, 0, 0, 0, 0, 0, 0,
2820 0, 0, 0, 0, 0, 0, 0,
2821 0, 0, 0, 0,
2822 &rxyk_reset,
2823 0,
2824 &rxyk_copy
2825 };
2826
2827
mus_make_rxyksin(mus_float_t freq,mus_float_t phase,mus_float_t r,mus_float_t ratio)2828 mus_any *mus_make_rxyksin(mus_float_t freq, mus_float_t phase, mus_float_t r, mus_float_t ratio) /* r default 0.5, ratio 1.0 */
2829 {
2830 rxyk *gen;
2831 gen = (rxyk *)malloc(sizeof(rxyk));
2832 gen->core = &RXYKSIN_CLASS;
2833 gen->freq = mus_hz_to_radians(freq);
2834 gen->phase = phase;
2835 gen->r = r;
2836 gen->ar = 1.0 / exp(fabs(r));
2837 gen->ratio = ratio;
2838 return((mus_any *)gen);
2839 }
2840
2841
2842
2843
2844 /* ---------------- table lookup ---------------- */
2845
2846 typedef struct {
2847 mus_any_class *core;
2848 mus_float_t freq, internal_mag, phase;
2849 mus_float_t *table;
2850 mus_long_t table_size;
2851 mus_interp_t type;
2852 bool table_allocated;
2853 mus_float_t yn1;
2854 mus_float_t (*tbl_look)(mus_any *ptr, mus_float_t fm);
2855 mus_float_t (*tbl_look_unmod)(mus_any *ptr);
2856 } tbl;
2857
2858
mus_partials_to_wave(mus_float_t * partial_data,int partials,mus_float_t * table,mus_long_t table_size,bool normalize)2859 mus_float_t *mus_partials_to_wave(mus_float_t *partial_data, int partials, mus_float_t *table, mus_long_t table_size, bool normalize)
2860 {
2861 int partial, k;
2862 if (!table) return(NULL);
2863 mus_clear_floats(table, table_size);
2864 for (partial = 0, k = 1; partial < partials; partial++, k += 2)
2865 {
2866 mus_float_t amp;
2867 amp = partial_data[k];
2868 if (amp != 0.0)
2869 {
2870 mus_long_t i;
2871 mus_float_t freq, angle;
2872 freq = (partial_data[partial * 2] * TWO_PI) / (mus_float_t)table_size;
2873 for (i = 0, angle = 0.0; i < table_size; i++, angle += freq)
2874 table[i] += amp * sin(angle);
2875 }
2876 }
2877 if (normalize)
2878 return(array_normalize(table, table_size));
2879 return(table);
2880 }
2881
2882
mus_phase_partials_to_wave(mus_float_t * partial_data,int partials,mus_float_t * table,mus_long_t table_size,bool normalize)2883 mus_float_t *mus_phase_partials_to_wave(mus_float_t *partial_data, int partials, mus_float_t *table, mus_long_t table_size, bool normalize)
2884 {
2885 int partial, k, n;
2886 if (!table) return(NULL);
2887 mus_clear_floats(table, table_size);
2888 for (partial = 0, k = 1, n = 2; partial < partials; partial++, k += 3, n += 3)
2889 {
2890 mus_float_t amp;
2891 amp = partial_data[k];
2892 if (amp != 0.0)
2893 {
2894 mus_long_t i;
2895 mus_float_t freq, angle;
2896 freq = (partial_data[partial * 3] * TWO_PI) / (mus_float_t)table_size;
2897 for (i = 0, angle = partial_data[n]; i < table_size; i++, angle += freq)
2898 table[i] += amp * sin(angle);
2899 }
2900 }
2901 if (normalize)
2902 return(array_normalize(table, table_size));
2903 return(table);
2904 }
2905
2906
mus_table_lookup(mus_any * ptr,mus_float_t fm)2907 mus_float_t mus_table_lookup(mus_any *ptr, mus_float_t fm)
2908 {
2909 return(((tbl *)ptr)->tbl_look(ptr, fm));
2910 }
2911
table_look_linear(mus_any * ptr,mus_float_t fm)2912 static mus_float_t table_look_linear(mus_any *ptr, mus_float_t fm)
2913 {
2914 tbl *gen = (tbl *)ptr;
2915
2916 /* we're checking already for out-of-range indices, so mus_array_interp is more than we need */
2917 mus_long_t int_part;
2918 mus_float_t frac_part, f1;
2919
2920 int_part = (mus_long_t)(gen->phase); /* floor(gen->phase) -- slow! modf is even worse */
2921 frac_part = gen->phase - int_part;
2922 f1 = gen->table[int_part];
2923 int_part++;
2924
2925 if (int_part == gen->table_size)
2926 gen->yn1 = f1 + frac_part * (gen->table[0] - f1);
2927 else gen->yn1 = f1 + frac_part * (gen->table[int_part] - f1);
2928
2929 gen->phase += (gen->freq + (fm * gen->internal_mag));
2930 if ((gen->phase >= gen->table_size) ||
2931 (gen->phase < 0.0))
2932 {
2933 gen->phase = fmod(gen->phase, gen->table_size);
2934 if (gen->phase < 0.0)
2935 gen->phase += gen->table_size;
2936 }
2937 return(gen->yn1);
2938 }
2939
2940
table_look_any(mus_any * ptr,mus_float_t fm)2941 static mus_float_t table_look_any(mus_any *ptr, mus_float_t fm)
2942 {
2943 tbl *gen = (tbl *)ptr;
2944
2945 gen->yn1 = mus_interpolate(gen->type, gen->phase, gen->table, gen->table_size, gen->yn1);
2946 gen->phase += (gen->freq + (fm * gen->internal_mag));
2947 if ((gen->phase >= gen->table_size) ||
2948 (gen->phase < 0.0))
2949 {
2950 gen->phase = fmod(gen->phase, gen->table_size);
2951 if (gen->phase < 0.0)
2952 gen->phase += gen->table_size;
2953 }
2954 return(gen->yn1);
2955 }
2956
2957
mus_table_lookup_unmodulated(mus_any * ptr)2958 mus_float_t mus_table_lookup_unmodulated(mus_any *ptr)
2959 {
2960 return(((tbl *)ptr)->tbl_look_unmod(ptr));
2961 }
2962
table_look_unmodulated_linear(mus_any * ptr)2963 static mus_float_t table_look_unmodulated_linear(mus_any *ptr)
2964 {
2965 tbl *gen = (tbl *)ptr;
2966 mus_long_t int_part;
2967 mus_float_t frac_part, f1;
2968
2969 int_part = (mus_long_t)(gen->phase);
2970 frac_part = gen->phase - int_part;
2971 f1 = gen->table[int_part];
2972 int_part++;
2973
2974 if (int_part == gen->table_size)
2975 f1 += frac_part * (gen->table[0] - f1);
2976 else f1 += frac_part * (gen->table[int_part] - f1);
2977
2978 gen->phase += gen->freq;
2979 if ((gen->phase >= gen->table_size) ||
2980 (gen->phase < 0.0))
2981 {
2982 gen->phase = fmod(gen->phase, gen->table_size);
2983 if (gen->phase < 0.0)
2984 gen->phase += gen->table_size;
2985 }
2986 return(f1);
2987 }
2988
2989
table_look_unmodulated_any(mus_any * ptr)2990 static mus_float_t table_look_unmodulated_any(mus_any *ptr)
2991 {
2992 tbl *gen = (tbl *)ptr;
2993
2994 gen->yn1 = mus_interpolate(gen->type, gen->phase, gen->table, gen->table_size, gen->yn1);
2995 gen->phase += gen->freq;
2996 if ((gen->phase >= gen->table_size) ||
2997 (gen->phase < 0.0))
2998 {
2999 gen->phase = fmod(gen->phase, gen->table_size);
3000 if (gen->phase < 0.0)
3001 gen->phase += gen->table_size;
3002 }
3003 return(gen->yn1);
3004 }
3005
3006
run_table_lookup(mus_any * ptr,mus_float_t fm,mus_float_t unused)3007 static mus_float_t run_table_lookup(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(((tbl *)ptr)->tbl_look(ptr, fm)); }
3008
mus_is_table_lookup(mus_any * ptr)3009 bool mus_is_table_lookup(mus_any *ptr)
3010 {
3011 return((ptr) &&
3012 (ptr->core->type == MUS_TABLE_LOOKUP));
3013 }
3014
table_lookup_length(mus_any * ptr)3015 static mus_long_t table_lookup_length(mus_any *ptr) {return(((tbl *)ptr)->table_size);}
table_lookup_data(mus_any * ptr)3016 static mus_float_t *table_lookup_data(mus_any *ptr) {return(((tbl *)ptr)->table);}
3017
table_lookup_freq(mus_any * ptr)3018 static mus_float_t table_lookup_freq(mus_any *ptr) {return((((tbl *)ptr)->freq * sampling_rate) / (((tbl *)ptr)->table_size));}
table_lookup_set_freq(mus_any * ptr,mus_float_t val)3019 static mus_float_t table_lookup_set_freq(mus_any *ptr, mus_float_t val) {((tbl *)ptr)->freq = (val * ((tbl *)ptr)->table_size) / sampling_rate; return(val);}
3020
table_lookup_increment(mus_any * ptr)3021 static mus_float_t table_lookup_increment(mus_any *ptr) {return(((tbl *)ptr)->freq);}
table_lookup_set_increment(mus_any * ptr,mus_float_t val)3022 static mus_float_t table_lookup_set_increment(mus_any *ptr, mus_float_t val) {((tbl *)ptr)->freq = val; return(val);}
3023
table_lookup_phase(mus_any * ptr)3024 static mus_float_t table_lookup_phase(mus_any *ptr) {return(fmod(((TWO_PI * ((tbl *)ptr)->phase) / ((tbl *)ptr)->table_size), TWO_PI));}
table_lookup_set_phase(mus_any * ptr,mus_float_t val)3025 static mus_float_t table_lookup_set_phase(mus_any *ptr, mus_float_t val) {((tbl *)ptr)->phase = (val * ((tbl *)ptr)->table_size) / TWO_PI; return(val);}
3026
table_lookup_interp_type(mus_any * ptr)3027 static int table_lookup_interp_type(mus_any *ptr) {return((int)(((tbl *)ptr)->type));} /* ints here and elsewhere to fit mus_channels method = interp-type */
3028
table_lookup_reset(mus_any * ptr)3029 static void table_lookup_reset(mus_any *ptr) {((tbl *)ptr)->phase = 0.0;}
3030
3031
describe_table_lookup(mus_any * ptr)3032 static char *describe_table_lookup(mus_any *ptr)
3033 {
3034 char *describe_buffer;
3035 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
3036 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, length: %d, interp: %s",
3037 mus_name(ptr),
3038 mus_frequency(ptr),
3039 mus_phase(ptr),
3040 (int)mus_length(ptr),
3041 mus_interp_type_to_string(table_lookup_interp_type(ptr)));
3042 return(describe_buffer);
3043 }
3044
3045
table_lookup_equalp(mus_any * p1,mus_any * p2)3046 static bool table_lookup_equalp(mus_any *p1, mus_any *p2)
3047 {
3048 tbl *t1 = (tbl *)p1;
3049 tbl *t2 = (tbl *)p2;
3050 if (p1 == p2) return(true);
3051 return((t1) && (t2) &&
3052 (t1->core->type == t2->core->type) &&
3053 (t1->table_size == t2->table_size) &&
3054 (t1->freq == t2->freq) &&
3055 (t1->phase == t2->phase) &&
3056 (t1->type == t2->type) &&
3057 (t1->internal_mag == t2->internal_mag) &&
3058 (clm_arrays_are_equal(t1->table, t2->table, t1->table_size)));
3059 }
3060
3061
free_table_lookup(mus_any * ptr)3062 static void free_table_lookup(mus_any *ptr)
3063 {
3064 tbl *gen = (tbl *)ptr;
3065 if ((gen->table) && (gen->table_allocated)) free(gen->table);
3066 free(gen);
3067 }
3068
tbl_copy(mus_any * ptr)3069 static mus_any *tbl_copy(mus_any *ptr)
3070 {
3071 tbl *g, *p;
3072
3073 p = (tbl *)ptr;
3074 g = (tbl *)malloc(sizeof(tbl));
3075 memcpy((void *)g, (void *)ptr, sizeof(tbl));
3076
3077 g->table = (mus_float_t *)malloc(g->table_size * sizeof(mus_float_t));
3078 mus_copy_floats(g->table, p->table, g->table_size);
3079 g->table_allocated = true;
3080
3081 return((mus_any *)g);
3082 }
3083
table_set_data(mus_any * ptr,mus_float_t * val)3084 static mus_float_t *table_set_data(mus_any *ptr, mus_float_t *val)
3085 {
3086 tbl *gen = (tbl *)ptr;
3087 if (gen->table_allocated) {free(gen->table); gen->table_allocated = false;}
3088 gen->table = val;
3089 return(val);
3090 }
3091
3092
3093 static mus_any_class TABLE_LOOKUP_CLASS = {
3094 MUS_TABLE_LOOKUP,
3095 (char *)S_table_lookup,
3096 &free_table_lookup,
3097 &describe_table_lookup,
3098 &table_lookup_equalp,
3099 &table_lookup_data,
3100 &table_set_data,
3101 &table_lookup_length,
3102 0,
3103 &table_lookup_freq,
3104 &table_lookup_set_freq,
3105 &table_lookup_phase,
3106 &table_lookup_set_phase,
3107 &fallback_scaler, 0,
3108 &table_lookup_increment,
3109 &table_lookup_set_increment,
3110 &run_table_lookup,
3111 MUS_NOT_SPECIAL,
3112 NULL,
3113 &table_lookup_interp_type,
3114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3115 0, 0, 0, 0, 0, 0, 0,
3116 0, 0, 0, 0,
3117 &table_lookup_reset,
3118 0, &tbl_copy
3119 };
3120
3121
mus_make_table_lookup(mus_float_t freq,mus_float_t phase,mus_float_t * table,mus_long_t table_size,mus_interp_t type)3122 mus_any *mus_make_table_lookup(mus_float_t freq, mus_float_t phase, mus_float_t *table, mus_long_t table_size, mus_interp_t type)
3123 {
3124 tbl *gen;
3125 gen = (tbl *)malloc(sizeof(tbl));
3126 gen->core = &TABLE_LOOKUP_CLASS;
3127 gen->table_size = table_size;
3128 gen->internal_mag = table_size / TWO_PI;
3129 gen->freq = (freq * table_size) / sampling_rate;
3130 gen->phase = (fmod(phase, TWO_PI) * table_size) / TWO_PI;
3131 gen->type = type;
3132 if (type == MUS_INTERP_LINEAR)
3133 {
3134 gen->tbl_look = table_look_linear;
3135 gen->tbl_look_unmod = table_look_unmodulated_linear;
3136 }
3137 else
3138 {
3139 gen->tbl_look = table_look_any;
3140 gen->tbl_look_unmod = table_look_unmodulated_any;
3141 }
3142 gen->yn1 = 0.0;
3143 if (table)
3144 {
3145 gen->table = table;
3146 gen->table_allocated = false;
3147 }
3148 else
3149 {
3150 gen->table = (mus_float_t *)calloc(table_size, sizeof(mus_float_t));
3151 gen->table_allocated = true;
3152 }
3153 return((mus_any *)gen);
3154 }
3155
3156
3157
3158 /* ---------------- polywave ---------------- */
3159
mus_partials_to_polynomial(int npartials,mus_float_t * partials,mus_polynomial_t kind)3160 mus_float_t *mus_partials_to_polynomial(int npartials, mus_float_t *partials, mus_polynomial_t kind)
3161 {
3162 /* coeffs returned in partials */
3163 int i;
3164 mus_long_t *T0, *T1, *Tn;
3165 mus_float_t *Cc1;
3166
3167 T0 = (mus_long_t *)calloc(npartials + 1, sizeof(mus_long_t));
3168 T1 = (mus_long_t *)calloc(npartials + 1, sizeof(mus_long_t));
3169 Tn = (mus_long_t *)calloc(npartials + 1, sizeof(mus_long_t));
3170 Cc1 = (mus_float_t *)calloc(npartials + 1, sizeof(mus_float_t));
3171
3172 if (kind == MUS_CHEBYSHEV_FIRST_KIND)
3173 T0[0] = 1;
3174 else T0[0] = 0;
3175 T1[1] = 1;
3176
3177 Cc1[0] = partials[0]; /* DC requested? */
3178
3179 for (i = 1; i < npartials; i++)
3180 {
3181 int k;
3182 mus_float_t amp;
3183 amp = partials[i];
3184 if (amp != 0.0)
3185 {
3186 if (kind == MUS_CHEBYSHEV_FIRST_KIND)
3187 for (k = 0; k <= i; k++)
3188 Cc1[k] += (amp * T1[k]);
3189 else
3190 for (k = 1; k <= i; k++)
3191 Cc1[k - 1] += (amp * T1[k]);
3192 }
3193 for (k = i + 1; k > 0; k--)
3194 Tn[k] = (2 * T1[k - 1]) - T0[k];
3195 Tn[0] = -T0[0];
3196 for (k = i + 1; k >= 0; k--)
3197 {
3198 T0[k] = T1[k];
3199 T1[k] = Tn[k];
3200 }
3201 }
3202
3203 for (i = 0; i < npartials; i++)
3204 partials[i] = Cc1[i];
3205
3206 free(T0);
3207 free(T1);
3208 free(Tn);
3209 free(Cc1);
3210 return(partials);
3211 }
3212
3213
mus_normalize_partials(int num_partials,mus_float_t * partials)3214 mus_float_t *mus_normalize_partials(int num_partials, mus_float_t *partials)
3215 {
3216 int i;
3217 mus_float_t sum = 0.0;
3218 for (i = 0; i < num_partials; i++)
3219 sum += fabs(partials[2 * i + 1]);
3220 if ((sum != 0.0) &&
3221 (sum != 1.0))
3222 {
3223 sum = 1.0 / sum;
3224 for (i = 0; i < num_partials; i++)
3225 partials[2 * i + 1] *= sum;
3226 }
3227 return(partials);
3228 }
3229
3230
3231 typedef struct {
3232 mus_any_class *core;
3233 mus_float_t phase, freq;
3234 mus_float_t *coeffs, *ucoeffs;
3235 int n, cheby_choice;
3236 mus_float_t index;
3237 mus_float_t (*polyw)(mus_any *ptr, mus_float_t fm);
3238 } pw;
3239
3240
mus_polywave_function(mus_any * g)3241 mus_float_t (*mus_polywave_function(mus_any *g))(mus_any *gen, mus_float_t fm)
3242 {
3243 if (mus_is_polywave(g))
3244 return(((pw *)g)->polyw);
3245 return(NULL);
3246 }
3247
free_pw(mus_any * pt)3248 static void free_pw(mus_any *pt) {free(pt);}
3249
pw_copy(mus_any * ptr)3250 static mus_any *pw_copy(mus_any *ptr)
3251 {
3252 pw *g;
3253 g = (pw *)malloc(sizeof(pw));
3254 memcpy((void *)g, (void *)ptr, sizeof(pw));
3255 return((mus_any *)g);
3256 }
3257
pw_reset(mus_any * ptr)3258 static void pw_reset(mus_any *ptr)
3259 {
3260 pw *gen = (pw *)ptr;
3261 gen->phase = 0.0;
3262 }
3263
3264
pw_equalp(mus_any * p1,mus_any * p2)3265 static bool pw_equalp(mus_any *p1, mus_any *p2)
3266 {
3267 pw *w1 = (pw *)p1;
3268 pw *w2 = (pw *)p2;
3269 if (p1 == p2) return(true);
3270 return((w1) && (w2) &&
3271 (w1->core->type == w2->core->type) &&
3272 (w1->freq == w2->freq) &&
3273 (w1->phase == w2->phase) &&
3274 (w1->n == w2->n) &&
3275 (w1->index == w2->index) &&
3276 (w1->cheby_choice == w2->cheby_choice) &&
3277 (clm_arrays_are_equal(w1->coeffs, w2->coeffs, w1->n)));
3278 }
3279
3280
pw_freq(mus_any * ptr)3281 static mus_float_t pw_freq(mus_any *ptr) {return(mus_radians_to_hz(((pw *)ptr)->freq));}
pw_set_freq(mus_any * ptr,mus_float_t val)3282 static mus_float_t pw_set_freq(mus_any *ptr, mus_float_t val) {((pw *)ptr)->freq = mus_hz_to_radians(val); return(val);}
3283
pw_increment(mus_any * ptr)3284 static mus_float_t pw_increment(mus_any *ptr) {return(((pw *)ptr)->freq);}
pw_set_increment(mus_any * ptr,mus_float_t val)3285 static mus_float_t pw_set_increment(mus_any *ptr, mus_float_t val) {((pw *)ptr)->freq = val; return(val);}
3286
pw_phase(mus_any * ptr)3287 static mus_float_t pw_phase(mus_any *ptr) {return(fmod(((pw *)ptr)->phase, TWO_PI));}
pw_set_phase(mus_any * ptr,mus_float_t val)3288 static mus_float_t pw_set_phase(mus_any *ptr, mus_float_t val) {((pw *)ptr)->phase = val; return(val);}
3289
pw_n(mus_any * ptr)3290 static mus_long_t pw_n(mus_any *ptr) {return(((pw *)ptr)->n);}
pw_set_n(mus_any * ptr,mus_long_t val)3291 static mus_long_t pw_set_n(mus_any *ptr, mus_long_t val) {((pw *)ptr)->n = (int)val; return(val);}
3292
pw_data(mus_any * ptr)3293 static mus_float_t *pw_data(mus_any *ptr) {return(((pw *)ptr)->coeffs);}
pw_udata(mus_any * ptr)3294 static mus_float_t *pw_udata(mus_any *ptr) {return(((pw *)ptr)->ucoeffs);}
pw_set_data(mus_any * ptr,mus_float_t * val)3295 static mus_float_t *pw_set_data(mus_any *ptr, mus_float_t *val) {((pw *)ptr)->coeffs = val; return(val);}
3296
pw_xcoeff(mus_any * ptr,int index)3297 static mus_float_t pw_xcoeff(mus_any *ptr, int index) {return(((pw *)ptr)->coeffs[index]);}
pw_set_xcoeff(mus_any * ptr,int index,mus_float_t val)3298 static mus_float_t pw_set_xcoeff(mus_any *ptr, int index, mus_float_t val) {((pw *)ptr)->coeffs[index] = val; return(val);}
3299
pw_ycoeff(mus_any * ptr,int index)3300 static mus_float_t pw_ycoeff(mus_any *ptr, int index) {if (((pw *)ptr)->ucoeffs) return(((pw *)ptr)->ucoeffs[index]); return(0.0);}
pw_set_ycoeff(mus_any * ptr,int index,mus_float_t val)3301 static mus_float_t pw_set_ycoeff(mus_any *ptr, int index, mus_float_t val) {if (((pw *)ptr)->ucoeffs) ((pw *)ptr)->ucoeffs[index] = val; return(val);}
3302
pw_index(mus_any * ptr)3303 static mus_float_t pw_index(mus_any *ptr) {return(((pw *)ptr)->index);}
pw_set_index(mus_any * ptr,mus_float_t val)3304 static mus_float_t pw_set_index(mus_any *ptr, mus_float_t val) {((pw *)ptr)->index = val; return(val);}
3305
pw_choice(mus_any * ptr)3306 static int pw_choice(mus_any *ptr) {return(((pw *)ptr)->cheby_choice);}
3307
3308
mus_chebyshev_tu_sum(mus_float_t x,int n,mus_float_t * tn,mus_float_t * un)3309 mus_float_t mus_chebyshev_tu_sum(mus_float_t x, int n, mus_float_t *tn, mus_float_t *un)
3310 {
3311 /* the Clenshaw algorithm -- beware of -cos(nx) where you'd expect cos(nx) */
3312 mus_float_t x2, tb, tb1 = 0.0, tb2, cx, ub, ub1 = 0.0;
3313 mus_float_t *tp, *up;
3314
3315 if (n == 1) return(tn[0]); /* added 18-Oct-17 -- looks plausible */
3316 cx = cos(x);
3317 x2 = 2.0 * cx;
3318
3319 tp = (mus_float_t *)(tn + n - 1);
3320 up = (mus_float_t *)(un + n - 1);
3321 tb = (*tp--);
3322 ub = (*up--);
3323
3324 while (up != un)
3325 {
3326 mus_float_t ub2;
3327 tb2 = tb1;
3328 tb1 = tb;
3329 tb = x2 * tb1 - tb2 + (*tp--);
3330
3331 ub2 = ub1;
3332 ub1 = ub;
3333 ub = x2 * ub1 - ub2 + (*up--);
3334 }
3335
3336 tb2 = tb1;
3337 tb1 = tb;
3338 tb = x2 * tb1 - tb2 + tn[0];
3339
3340 return((mus_float_t)((tb - tb1 * cx) + (sin(x) * ub)));
3341 }
3342
3343
mus_chebyshev_t_sum(mus_float_t x,int n,mus_float_t * tn)3344 mus_float_t mus_chebyshev_t_sum(mus_float_t x, int n, mus_float_t *tn)
3345 {
3346 int i;
3347 mus_float_t x2, b, b1 = 0.0, cx;
3348
3349 cx = cos(x);
3350 x2 = 2.0 * cx;
3351
3352 /* Tn calc */
3353 b = tn[n - 1];
3354 for (i = n - 2; i >= 0; i--)
3355 {
3356 mus_float_t b2;
3357 b2 = b1;
3358 b1 = b;
3359 b = x2 * b1 - b2 + tn[i];
3360 }
3361 return((mus_float_t)(b - b1 * cx));
3362 }
3363
3364 #if 0
3365 /* here is the trick to do odd Tn without doing the intervening evens: */
3366 (define (mus-chebyshev-odd-t-sum x n t2n)
3367 (let* ((b1 0.0)
3368 (b2 0.0)
3369 (cx1 (cos x))
3370 (cx (- (* 2 cx1 cx1) 1))
3371 (x2 (* 2.0 cx))
3372 (b (vct-ref t2n (- n 1))))
3373 (do ((i (- n 2) (1- i)))
3374 ((< i 0))
3375 (set! b2 b1)
3376 (set! b1 b)
3377 (set! b (- (+ (* b1 x2) (vct-ref t2n i)) b2)))
3378 (* cx1 (- b b1))))
3379
3380 (with-sound ()
3381 (let ((t2n (vct 0.5 0.25 0.25))
3382 (x 0.0)
3383 (dx (hz->radians 10.0)))
3384 (do ((i 0 (+ i 1)))
3385 ((= i 22050))
3386 (outa i (mus-chebyshev-odd-t-sum x 3 t2n))
3387 (set! x (+ x dx)))))
3388 #endif
3389
3390
mus_chebyshev_u_sum(mus_float_t x,int n,mus_float_t * un)3391 mus_float_t mus_chebyshev_u_sum(mus_float_t x, int n, mus_float_t *un)
3392 {
3393 int i;
3394 mus_float_t x2, b, b1 = 0.0, cx;
3395
3396 cx = cos(x);
3397 x2 = 2.0 * cx;
3398
3399 /* Un calc */
3400 b = un[n - 1];
3401 for (i = n - 2; i > 0; i--)
3402 {
3403 mus_float_t b2;
3404 b2 = b1;
3405 b1 = b;
3406 b = x2 * b1 - b2 + un[i];
3407 }
3408
3409 return((mus_float_t)(sin(x) * b));
3410 }
3411
3412
mus_chebyshev_t_sum_with_index(mus_float_t x,mus_float_t index,int n,mus_float_t * tn)3413 static mus_float_t mus_chebyshev_t_sum_with_index(mus_float_t x, mus_float_t index, int n, mus_float_t *tn)
3414 {
3415 int i;
3416 mus_float_t x2, b, b1 = 0.0, b2, cx;
3417 cx = index * cos(x);
3418 x2 = 2.0 * cx;
3419
3420 /* Tn calc */
3421 b = tn[n - 1];
3422 i = n - 2;
3423 while (i >= 4)
3424 {
3425 b2 = b1;
3426 b1 = b;
3427 b = x2 * b1 - b2 + tn[i--];
3428
3429 b2 = b1;
3430 b1 = b;
3431 b = x2 * b1 - b2 + tn[i--];
3432
3433 b2 = b1;
3434 b1 = b;
3435 b = x2 * b1 - b2 + tn[i--];
3436
3437 b2 = b1;
3438 b1 = b;
3439 b = x2 * b1 - b2 + tn[i--];
3440 }
3441 for (; i >= 0; i--)
3442 {
3443 b2 = b1;
3444 b1 = b;
3445 b = x2 * b1 - b2 + tn[i];
3446 }
3447 return((mus_float_t)(b - b1 * cx));
3448 }
3449
3450
mus_chebyshev_t_sum_with_index_2(mus_float_t x,mus_float_t index,int n,mus_float_t * tn)3451 static mus_float_t mus_chebyshev_t_sum_with_index_2(mus_float_t x, mus_float_t index, int n, mus_float_t *tn)
3452 {
3453 int i;
3454 mus_float_t x2, b, b1 = 0.0, cx;
3455
3456 cx = index * cos(x);
3457 x2 = 2.0 * cx;
3458
3459 /* Tn calc */
3460 b = tn[n - 1];
3461 for (i = n - 2; i > 0;)
3462 {
3463 mus_float_t b2;
3464 b2 = b1;
3465 b1 = b;
3466 b = x2 * b1 - b2 + tn[i--];
3467
3468 b2 = b1;
3469 b1 = b;
3470 b = x2 * b1 - b2 + tn[i--];
3471 }
3472 return((mus_float_t)(b - b1 * cx));
3473 }
3474
3475
mus_chebyshev_t_sum_with_index_3(mus_float_t x,mus_float_t index,int n,mus_float_t * tn)3476 static mus_float_t mus_chebyshev_t_sum_with_index_3(mus_float_t x, mus_float_t index, int n, mus_float_t *tn)
3477 {
3478 int i;
3479 mus_float_t x2, b, b1 = 0.0, cx;
3480
3481 cx = index * cos(x);
3482 x2 = 2.0 * cx;
3483
3484 /* Tn calc */
3485 b = tn[n - 1];
3486 for (i = n - 2; i > 0;)
3487 {
3488 mus_float_t b2;
3489 b2 = b1;
3490 b1 = b;
3491 b = x2 * b1 - b2 + tn[i--];
3492
3493 b2 = b1;
3494 b1 = b;
3495 b = x2 * b1 - b2 + tn[i--];
3496
3497 b2 = b1;
3498 b1 = b;
3499 b = x2 * b1 - b2 + tn[i--];
3500 }
3501 return((mus_float_t)(b - b1 * cx));
3502 }
3503
3504
mus_chebyshev_t_sum_with_index_5(mus_float_t x,mus_float_t index,int n,mus_float_t * tn)3505 static mus_float_t mus_chebyshev_t_sum_with_index_5(mus_float_t x, mus_float_t index, int n, mus_float_t *tn)
3506 {
3507 int i;
3508 mus_float_t x2, b, b1 = 0.0, cx;
3509
3510 cx = index * cos(x);
3511 x2 = 2.0 * cx;
3512
3513 /* Tn calc */
3514 b = tn[n - 1];
3515 for (i = n - 2; i > 0;) /* this was >= ?? (also cases above) -- presumably a copy-and-paste typo? */
3516 {
3517 mus_float_t b2;
3518 b2 = b1;
3519 b1 = b;
3520 b = x2 * b1 - b2 + tn[i--];
3521
3522 b2 = b1;
3523 b1 = b;
3524 b = x2 * b1 - b2 + tn[i--];
3525
3526 b2 = b1;
3527 b1 = b;
3528 b = x2 * b1 - b2 + tn[i--];
3529
3530 b2 = b1;
3531 b1 = b;
3532 b = x2 * b1 - b2 + tn[i--];
3533
3534 b2 = b1;
3535 b1 = b;
3536 b = x2 * b1 - b2 + tn[i--];
3537 }
3538 return((mus_float_t)(b - b1 * cx));
3539 }
3540
3541
mus_chebyshev_u_sum_with_index(mus_float_t x,mus_float_t index,int n,mus_float_t * un)3542 static mus_float_t mus_chebyshev_u_sum_with_index(mus_float_t x, mus_float_t index, int n, mus_float_t *un)
3543 {
3544 int i;
3545 mus_float_t x2, b, b1 = 0.0, cx;
3546
3547 cx = index * cos(x);
3548 x2 = 2.0 * cx;
3549
3550 /* Un calc */
3551 b = un[n - 1];
3552 for (i = n - 2; i > 0; i--)
3553 {
3554 mus_float_t b2;
3555 b2 = b1;
3556 b1 = b;
3557 b = x2 * b1 - b2 + un[i];
3558 }
3559
3560 return((mus_float_t)(sin(x) * b + un[0])); /* don't drop the constant, 16-Jan-14 */
3561 }
3562
3563 /* (with-sound () (let ((p (make-polywave 100 (list 0 0.5 1 -.2) mus-chebyshev-second-kind))) (do ((i 0 (+ i 1))) ((= i 1000)) (outa i (polywave p)))))
3564 */
3565
polyw_second_2(mus_any * ptr,mus_float_t fm)3566 static mus_float_t polyw_second_2(mus_any *ptr, mus_float_t fm)
3567 {
3568 pw *gen = (pw *)ptr;
3569 mus_float_t x;
3570
3571 x = gen->phase; /* this order (as opposed to saving the full expr below) is much faster?! */
3572 gen->phase += (gen->freq + fm);
3573 return(gen->coeffs[1] * sin(x) + gen->coeffs[0]);
3574 }
3575
3576
polyw_first_1(mus_any * ptr,mus_float_t fm)3577 static mus_float_t polyw_first_1(mus_any *ptr, mus_float_t fm)
3578 {
3579 pw *gen = (pw *)ptr;
3580 mus_float_t x;
3581
3582 x = gen->phase;
3583 gen->phase += (gen->freq + fm);
3584 return(gen->index * cos(x));
3585 }
3586
3587
polyw_first_3(mus_any * ptr,mus_float_t fm)3588 static mus_float_t polyw_first_3(mus_any *ptr, mus_float_t fm)
3589 {
3590 pw *gen = (pw *)ptr;
3591 mus_float_t x, cx;
3592 mus_float_t *tn;
3593
3594 x = gen->phase;
3595 tn = gen->coeffs;
3596 gen->phase += (gen->freq + fm);
3597
3598 cx = cos(x);
3599 return((2.0 * cx * tn[2] + tn[1]) * cx - tn[2]);
3600
3601 /* b = x2 * b1 - b2;, then return(b - b1 * cx)
3602 * but x2 = 2 * cx, so b1*(x2 - cx) -> b1 * cx
3603 * and the final recursion unrolls. The old code
3604 * (which thought tn[0] might not be 0.0) was:
3605 * cx = cos(x);
3606 * x2 = 2.0 * cx;
3607 * b = tn[2];
3608 * b2 = b1; -- but b1 is 0
3609 * b1 = b; -- b not used so this is tn[2]
3610 * b = x2 * b1 - b2 + tn[1]; -- b2 is 0.0
3611 * b2 = b1;
3612 * b1 = b;
3613 * b = x2 * b1 - b2 + tn[0];
3614 * return(b - b1 * cx);
3615 */
3616 }
3617
3618 /* (with-sound () (let ((p (make-polywave 100 (list 1 .5 2 .25)))) (do ((i 0 (+ i 1))) ((= i 30000)) (outa i (polywave p))))) */
3619
3620
polyw_first_4(mus_any * ptr,mus_float_t fm)3621 static mus_float_t polyw_first_4(mus_any *ptr, mus_float_t fm)
3622 {
3623 pw *gen = (pw *)ptr;
3624 mus_float_t x, x2, b, cx;
3625 mus_float_t *tn;
3626
3627 x = gen->phase;
3628 tn = gen->coeffs;
3629 gen->phase += (gen->freq + fm);
3630
3631 cx = cos(x);
3632 x2 = 2.0 * cx;
3633 b = x2 * tn[3] + tn[2]; /* was -tn[2]! 19-Feb-14 */
3634 return((x2 * b - tn[3] + tn[1]) * cx - b);
3635 }
3636
3637
polyw_first_5(mus_any * ptr,mus_float_t fm)3638 static mus_float_t polyw_first_5(mus_any *ptr, mus_float_t fm)
3639 {
3640 pw *gen = (pw *)ptr;
3641 mus_float_t x;
3642 mus_float_t *tn;
3643 mus_float_t x2, b, b1, b2, cx;
3644
3645 x = gen->phase;
3646 tn = gen->coeffs;
3647 gen->phase += (gen->freq + fm);
3648
3649 cx = cos(x);
3650 x2 = 2.0 * cx;
3651 b1 = tn[4];
3652 b = x2 * b1 + tn[3];
3653 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[2];
3654
3655 return((x2 * b - b1 + tn[1]) * cx - b);
3656 }
3657
3658
polyw_first_6(mus_any * ptr,mus_float_t fm)3659 static mus_float_t polyw_first_6(mus_any *ptr, mus_float_t fm)
3660 {
3661 pw *gen = (pw *)ptr;
3662 mus_float_t x;
3663 mus_float_t *tn;
3664 mus_float_t x2, b, b1, b2, cx;
3665
3666 x = gen->phase;
3667 tn = gen->coeffs;
3668 gen->phase += (gen->freq + fm);
3669
3670 cx = cos(x);
3671 x2 = 2.0 * cx;
3672 b1 = tn[5];
3673 b = x2 * b1 + tn[4];
3674 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[3];
3675 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[2];
3676
3677 return((x2 * b - b1 + tn[1]) * cx - b);
3678 }
3679
3680
polyw_first_8(mus_any * ptr,mus_float_t fm)3681 static mus_float_t polyw_first_8(mus_any *ptr, mus_float_t fm)
3682 {
3683 pw *gen = (pw *)ptr;
3684 mus_float_t x;
3685 mus_float_t *tn;
3686 mus_float_t x2, b, b1, b2, cx;
3687
3688 x = gen->phase;
3689 tn = gen->coeffs;
3690 gen->phase += (gen->freq + fm);
3691
3692 cx = cos(x);
3693 x2 = 2.0 * cx;
3694 b1 = tn[7];
3695 b = x2 * b1 + tn[6];
3696 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[5];
3697 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[4];
3698 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[3];
3699 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[2];
3700
3701 return((x2 * b - b1 + tn[1]) * cx - b);
3702 }
3703
3704
polyw_first_11(mus_any * ptr,mus_float_t fm)3705 static mus_float_t polyw_first_11(mus_any *ptr, mus_float_t fm)
3706 {
3707 pw *gen = (pw *)ptr;
3708 mus_float_t x;
3709 mus_float_t *tn;
3710 mus_float_t x2, b, b1, b2, cx;
3711
3712 x = gen->phase;
3713 tn = gen->coeffs;
3714 gen->phase += (gen->freq + fm);
3715
3716 cx = cos(x);
3717 x2 = 2.0 * cx;
3718 b1 = tn[10];
3719 b = x2 * b1 + tn[9];
3720 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[8];
3721 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[7];
3722 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[6];
3723 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[5];
3724 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[4];
3725 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[3];
3726 b2 = b1; b1 = b; b = x2 * b1 - b2 + tn[2];
3727
3728 return((x2 * b - b1 + tn[1]) * cx - b);
3729 }
3730
3731
polyw_first(mus_any * ptr,mus_float_t fm)3732 static mus_float_t polyw_first(mus_any *ptr, mus_float_t fm)
3733 {
3734 pw *gen = (pw *)ptr;
3735 mus_float_t ph;
3736 ph = gen->phase;
3737 gen->phase += (gen->freq + fm);
3738 return(mus_chebyshev_t_sum_with_index(ph, gen->index, gen->n, gen->coeffs));
3739 }
3740
3741
polyw_f1(mus_any * ptr,mus_float_t fm)3742 static mus_float_t polyw_f1(mus_any *ptr, mus_float_t fm)
3743 {
3744 pw *gen = (pw *)ptr;
3745 mus_float_t cx;
3746 cx = gen->index * cos(gen->phase);
3747 gen->phase += (gen->freq + fm);
3748 return(cx * gen->coeffs[1] + gen->coeffs[0]);
3749 }
3750
3751
polyw_f2(mus_any * ptr,mus_float_t fm)3752 static mus_float_t polyw_f2(mus_any *ptr, mus_float_t fm)
3753 {
3754 pw *gen = (pw *)ptr;
3755 mus_float_t ph;
3756 ph = gen->phase;
3757 gen->phase += (gen->freq + fm);
3758 return(mus_chebyshev_t_sum_with_index_2(ph, gen->index, gen->n, gen->coeffs));
3759 }
3760
3761
polyw_f3(mus_any * ptr,mus_float_t fm)3762 static mus_float_t polyw_f3(mus_any *ptr, mus_float_t fm)
3763 {
3764 pw *gen = (pw *)ptr;
3765 mus_float_t ph;
3766 ph = gen->phase;
3767 gen->phase += (gen->freq + fm);
3768 return(mus_chebyshev_t_sum_with_index_3(ph, gen->index, gen->n, gen->coeffs));
3769 }
3770
3771
polyw_f5(mus_any * ptr,mus_float_t fm)3772 static mus_float_t polyw_f5(mus_any *ptr, mus_float_t fm)
3773 {
3774 pw *gen = (pw *)ptr;
3775 mus_float_t ph;
3776 ph = gen->phase;
3777 gen->phase += (gen->freq + fm);
3778 return(mus_chebyshev_t_sum_with_index_5(ph, gen->index, gen->n, gen->coeffs));
3779 }
3780
3781
polyw_second(mus_any * ptr,mus_float_t fm)3782 static mus_float_t polyw_second(mus_any *ptr, mus_float_t fm)
3783 {
3784 pw *gen = (pw *)ptr;
3785 mus_float_t ph;
3786 ph = gen->phase;
3787 gen->phase += (gen->freq + fm);
3788 return(mus_chebyshev_u_sum_with_index(ph, gen->index, gen->n, gen->coeffs));
3789 }
3790
3791
polyw_second_5(mus_any * ptr,mus_float_t fm)3792 static mus_float_t polyw_second_5(mus_any *ptr, mus_float_t fm)
3793 {
3794 pw *gen = (pw *)ptr;
3795 mus_float_t *un;
3796 mus_float_t x, b, b1, cx;
3797
3798 x = gen->phase;
3799 gen->phase += (gen->freq + fm);
3800 /* gen->n is 5 */
3801 un = gen->coeffs;
3802
3803 /* this is a candidate for sincos, but gcc is already using it here! */
3804 cx = 2.0 * cos(x);
3805 b1 = cx * un[4] + un[3];
3806 b = cx * b1 + gen->index;
3807
3808 return(sin(x) * (cx * b - b1 + un[1]));
3809 }
3810
3811
polyw_third(mus_any * ptr,mus_float_t fm)3812 static mus_float_t polyw_third(mus_any *ptr, mus_float_t fm)
3813 {
3814 pw *gen = (pw *)ptr;
3815 mus_float_t ph;
3816 ph = gen->phase;
3817 gen->phase += (gen->freq + fm);
3818 return(mus_chebyshev_tu_sum(ph, gen->n, gen->coeffs, gen->ucoeffs));
3819 }
3820
3821
mus_polywave(mus_any * ptr,mus_float_t fm)3822 mus_float_t mus_polywave(mus_any *ptr, mus_float_t fm)
3823 {
3824 /* changed to use recursion, rather than polynomial in x, 25-May-08
3825 * this algorithm taken from Mason and Handscomb, "Chebyshev Polynomials" p27
3826 */
3827 return((((pw *)ptr)->polyw)(ptr, fm));
3828 }
3829
3830
mus_polywave_unmodulated(mus_any * ptr)3831 mus_float_t mus_polywave_unmodulated(mus_any *ptr)
3832 {
3833 return(mus_polywave(ptr, 0.0));
3834 }
3835
3836
run_polywave(mus_any * ptr,mus_float_t fm,mus_float_t ignored)3837 static mus_float_t run_polywave(mus_any *ptr, mus_float_t fm, mus_float_t ignored) {return(mus_polywave(ptr, fm));}
3838
3839
describe_polywave(mus_any * ptr)3840 static char *describe_polywave(mus_any *ptr)
3841 {
3842 pw *gen = (pw *)ptr;
3843 char *str;
3844 char *describe_buffer;
3845 str = float_array_to_string(gen->coeffs, gen->n, 0);
3846 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
3847 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, coeffs[%d]: %s",
3848 mus_name(ptr),
3849 mus_frequency(ptr),
3850 mus_phase(ptr),
3851 gen->n,
3852 str);
3853 free(str);
3854 return(describe_buffer);
3855 }
3856
3857
pw_set_index_and_func(mus_any * ptr,mus_float_t val)3858 static mus_float_t pw_set_index_and_func(mus_any *ptr, mus_float_t val)
3859 {
3860 pw *gen = (pw *)ptr;
3861 gen->index = val;
3862 if (gen->cheby_choice == MUS_CHEBYSHEV_FIRST_KIND)
3863 gen->polyw = polyw_first;
3864 else gen->polyw = polyw_second;
3865 return(val);
3866 }
3867
3868
3869 static mus_any_class POLYWAVE_CLASS = {
3870 MUS_POLYWAVE,
3871 (char *)S_polywave,
3872 &free_pw,
3873 &describe_polywave,
3874 &pw_equalp,
3875 &pw_data,
3876 &pw_set_data,
3877 &pw_n,
3878 &pw_set_n,
3879 &pw_freq,
3880 &pw_set_freq,
3881 &pw_phase,
3882 &pw_set_phase,
3883 &pw_index,
3884 &pw_set_index_and_func,
3885 &pw_increment,
3886 &pw_set_increment,
3887 &run_polywave,
3888 MUS_NOT_SPECIAL,
3889 NULL, 0,
3890 0, 0, 0, 0,
3891 &pw_xcoeff, &pw_set_xcoeff,
3892 0, 0, 0, 0,
3893 0, 0, 0, 0, 0, 0,
3894 &pw_choice,
3895 &pw_ycoeff, &pw_set_ycoeff,
3896 &pw_data, &pw_udata,
3897 &pw_reset,
3898 0, &pw_copy
3899 };
3900
3901
mus_make_polywave(mus_float_t frequency,mus_float_t * coeffs,int n,int cheby_choice)3902 mus_any *mus_make_polywave(mus_float_t frequency, mus_float_t *coeffs, int n, int cheby_choice)
3903 {
3904 pw *gen;
3905 gen = (pw *)malloc(sizeof(pw));
3906 gen->core = &POLYWAVE_CLASS;
3907 gen->phase = 0.0; /* cos used in cheby funcs above */
3908 gen->freq = mus_hz_to_radians(frequency);
3909 gen->coeffs = coeffs;
3910 gen->ucoeffs = NULL;
3911 gen->n = n;
3912 gen->index = 1.0;
3913 gen->cheby_choice = cheby_choice;
3914 if (cheby_choice != MUS_CHEBYSHEV_SECOND_KIND)
3915 {
3916 if (coeffs[0] == 0.0)
3917 {
3918 /* these also ignore gen->index (assumed to be 1.0) (leaving aside the first_1 case)
3919 * pw_set_index_and_func protects against that case
3920 */
3921 if (n == 2)
3922 {
3923 gen->polyw = polyw_first_1;
3924 gen->index = coeffs[1];
3925 }
3926 else
3927 {
3928 if (n == 3)
3929 gen->polyw = polyw_first_3;
3930 else
3931 {
3932 if (n == 4)
3933 gen->polyw = polyw_first_4;
3934 else
3935 {
3936 if (n == 5)
3937 gen->polyw = polyw_first_5;
3938 else
3939 {
3940 if (n == 6)
3941 gen->polyw = polyw_first_6;
3942 else
3943 {
3944 if (n == 8)
3945 gen->polyw = polyw_first_8;
3946 else
3947 {
3948 if (n == 11) /* a common case oddly enough */
3949 gen->polyw = polyw_first_11;
3950 else
3951 {
3952 if (((n - 1) % 5) == 0)
3953 gen->polyw = polyw_f5;
3954 else
3955 {
3956 if (((n - 1) % 3) == 0)
3957 gen->polyw = polyw_f3;
3958 else
3959 {
3960 if (((n - 1) % 2) == 0)
3961 gen->polyw = polyw_f2;
3962 else
3963 {
3964 /* lots of n=8 here */
3965 gen->polyw = polyw_first;
3966 }
3967 }
3968 }
3969 }
3970 }
3971 }
3972 }
3973 }
3974 }
3975 }
3976 }
3977 else
3978 {
3979 if (n == 2)
3980 gen->polyw = polyw_f1;
3981 else
3982 {
3983 if (((n - 1) % 3) == 0)
3984 gen->polyw = polyw_f3;
3985 else
3986 {
3987 if (((n - 1) % 2) == 0)
3988 gen->polyw = polyw_f2;
3989 else gen->polyw = polyw_first;
3990 }
3991 }
3992 }
3993 }
3994 else
3995 {
3996 if ((n == 5) &&
3997 (coeffs[0] == 0.0))
3998 {
3999 gen->polyw = polyw_second_5;
4000 gen->index = coeffs[2] - coeffs[4];
4001 }
4002 else
4003 {
4004 if (n == 2)
4005 gen->polyw = polyw_second_2;
4006 else gen->polyw = polyw_second;
4007 }
4008 }
4009 return((mus_any *)gen);
4010 }
4011
4012
mus_make_polywave_tu(mus_float_t frequency,mus_float_t * tcoeffs,mus_float_t * ucoeffs,int n)4013 mus_any *mus_make_polywave_tu(mus_float_t frequency, mus_float_t *tcoeffs, mus_float_t *ucoeffs, int n)
4014 {
4015 pw *gen;
4016 gen = (pw *)malloc(sizeof(pw));
4017 gen->core = &POLYWAVE_CLASS;
4018 gen->phase = 0.0; /* cos used in cheby funcs above */
4019 gen->freq = mus_hz_to_radians(frequency);
4020 gen->coeffs = tcoeffs;
4021 gen->ucoeffs = ucoeffs;
4022 gen->n = n;
4023 gen->index = 1.0;
4024 gen->cheby_choice = MUS_CHEBYSHEV_BOTH_KINDS;
4025 gen->polyw = polyw_third;
4026 return((mus_any *)gen);
4027 }
4028
4029
mus_is_polywave(mus_any * ptr)4030 bool mus_is_polywave(mus_any *ptr)
4031 {
4032 return((ptr) &&
4033 (ptr->core->type == MUS_POLYWAVE));
4034 }
4035
4036
4037
4038 /* ---------------- polyshape ---------------- */
4039
describe_polyshape(mus_any * ptr)4040 static char *describe_polyshape(mus_any *ptr)
4041 {
4042 pw *gen = (pw *)ptr;
4043 char *str;
4044 char *describe_buffer;
4045 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
4046 str = float_array_to_string(gen->coeffs, gen->n, 0);
4047 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, coeffs[%d]: %s",
4048 mus_name(ptr),
4049 mus_frequency(ptr),
4050 mus_phase(ptr),
4051 gen->n,
4052 str);
4053 free(str);
4054 return(describe_buffer);
4055 }
4056
4057
mus_polyshape(mus_any * ptr,mus_float_t index,mus_float_t fm)4058 mus_float_t mus_polyshape(mus_any *ptr, mus_float_t index, mus_float_t fm)
4059 {
4060 pw *gen = (pw *)ptr;
4061 mus_float_t result;
4062 gen->index = index;
4063 result = mus_polynomial(gen->coeffs,
4064 index * cos(gen->phase),
4065 gen->n);
4066
4067 if (gen->cheby_choice == MUS_CHEBYSHEV_SECOND_KIND)
4068 result *= sin(gen->phase);
4069
4070 gen->phase += (gen->freq + fm);
4071 return(result);
4072 }
4073
4074
mus_polyshape_unmodulated(mus_any * ptr,mus_float_t index)4075 mus_float_t mus_polyshape_unmodulated(mus_any *ptr, mus_float_t index)
4076 {
4077 pw *gen = (pw *)ptr;
4078 mus_float_t result;
4079 gen->index = index;
4080 result = mus_polynomial(gen->coeffs,
4081 index * cos(gen->phase),
4082 gen->n);
4083
4084 if (gen->cheby_choice == MUS_CHEBYSHEV_SECOND_KIND)
4085 result *= sin(gen->phase);
4086
4087 gen->phase += gen->freq;
4088 return(result);
4089 }
4090
4091
4092 static mus_any_class POLYSHAPE_CLASS = {
4093 MUS_POLYSHAPE,
4094 (char *)S_polyshape,
4095 &free_pw,
4096 &describe_polyshape,
4097 &pw_equalp,
4098 &pw_data,
4099 &pw_set_data,
4100 &pw_n,
4101 &pw_set_n,
4102 &pw_freq,
4103 &pw_set_freq,
4104 &pw_phase,
4105 &pw_set_phase,
4106 &pw_index, &pw_set_index,
4107 &pw_increment,
4108 &pw_set_increment,
4109 &mus_polyshape,
4110 MUS_NOT_SPECIAL,
4111 NULL, 0,
4112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4113 0, 0, 0, 0, 0, 0,
4114 &pw_choice,
4115 0, 0, 0, 0,
4116 &pw_reset,
4117 0, &pw_copy
4118 };
4119
4120
mus_make_polyshape(mus_float_t frequency,mus_float_t phase,mus_float_t * coeffs,int size,int cheby_choice)4121 mus_any *mus_make_polyshape(mus_float_t frequency, mus_float_t phase, mus_float_t *coeffs, int size, int cheby_choice)
4122 {
4123 mus_any *gen;
4124 gen = mus_make_polywave(frequency, coeffs, size, cheby_choice);
4125 gen->core = &POLYSHAPE_CLASS;
4126 pw_set_phase(gen, phase);
4127 return(gen);
4128 }
4129
4130
mus_is_polyshape(mus_any * ptr)4131 bool mus_is_polyshape(mus_any *ptr)
4132 {
4133 return((ptr) &&
4134 (ptr->core->type == MUS_POLYSHAPE));
4135 }
4136
4137
4138
4139
4140
4141 /* ---------------- wave-train ---------------- */
4142
4143 typedef struct {
4144 mus_any_class *core;
4145 mus_float_t freq, phase;
4146 mus_float_t *wave; /* passed in from caller */
4147 mus_long_t wave_size;
4148 mus_float_t *out_data;
4149 mus_long_t out_data_size;
4150 mus_interp_t interp_type; /* "type" field exists in core -- avoid confusion */
4151 mus_float_t next_wave_time;
4152 mus_long_t out_pos;
4153 bool first_time;
4154 mus_float_t yn1;
4155 } wt;
4156
4157
wt_freq(mus_any * ptr)4158 static mus_float_t wt_freq(mus_any *ptr) {return(((wt *)ptr)->freq);}
wt_set_freq(mus_any * ptr,mus_float_t val)4159 static mus_float_t wt_set_freq(mus_any *ptr, mus_float_t val) {((wt *)ptr)->freq = val; return(val);}
4160
wt_phase(mus_any * ptr)4161 static mus_float_t wt_phase(mus_any *ptr) {return(fmod(((TWO_PI * ((wt *)ptr)->phase) / ((mus_float_t)((wt *)ptr)->wave_size)), TWO_PI));}
wt_set_phase(mus_any * ptr,mus_float_t val)4162 static mus_float_t wt_set_phase(mus_any *ptr, mus_float_t val) {((wt *)ptr)->phase = (fmod(val, TWO_PI) * ((wt *)ptr)->wave_size) / TWO_PI; return(val);}
4163
wt_length(mus_any * ptr)4164 static mus_long_t wt_length(mus_any *ptr) {return(((wt *)ptr)->wave_size);}
wt_set_length(mus_any * ptr,mus_long_t val)4165 static mus_long_t wt_set_length(mus_any *ptr, mus_long_t val) {if (val > 0) ((wt *)ptr)->wave_size = val; return(((wt *)ptr)->wave_size);}
4166
wt_interp_type(mus_any * ptr)4167 static int wt_interp_type(mus_any *ptr) {return((int)(((wt *)ptr)->interp_type));}
4168
wt_data(mus_any * ptr)4169 static mus_float_t *wt_data(mus_any *ptr) {return(((wt *)ptr)->wave);}
wt_set_data(mus_any * ptr,mus_float_t * data)4170 static mus_float_t *wt_set_data(mus_any *ptr, mus_float_t *data) {((wt *)ptr)->wave = data; return(data);}
4171
wt_copy(mus_any * ptr)4172 static mus_any *wt_copy(mus_any *ptr)
4173 {
4174 wt *g, *p;
4175 p = (wt *)ptr;
4176 g = (wt *)malloc(sizeof(wt));
4177 memcpy((void *)g, (void *)ptr, sizeof(wt));
4178 g->out_data = (mus_float_t *)malloc(g->out_data_size * sizeof(mus_float_t));
4179 mus_copy_floats(g->out_data, p->out_data, g->out_data_size);
4180 /* g->wave is caller's data */
4181 return((mus_any *)g);
4182 }
4183
wt_equalp(mus_any * p1,mus_any * p2)4184 static bool wt_equalp(mus_any *p1, mus_any *p2)
4185 {
4186 wt *w1 = (wt *)p1;
4187 wt *w2 = (wt *)p2;
4188 if (p1 == p2) return(true);
4189 return((w1) && (w2) &&
4190 (w1->core->type == w2->core->type) &&
4191 (w1->freq == w2->freq) &&
4192 (w1->phase == w2->phase) &&
4193 (w1->interp_type == w2->interp_type) &&
4194 (w1->wave_size == w2->wave_size) &&
4195 (w1->out_data_size == w2->out_data_size) &&
4196 (w1->out_pos == w2->out_pos) &&
4197 (clm_arrays_are_equal(w1->wave, w2->wave, w1->wave_size)) &&
4198 (clm_arrays_are_equal(w1->out_data, w2->out_data, w1->out_data_size)));
4199 }
4200
describe_wt(mus_any * ptr)4201 static char *describe_wt(mus_any *ptr)
4202 {
4203 char *describe_buffer;
4204 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
4205 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, size: %" print_mus_long ", interp: %s",
4206 mus_name(ptr),
4207 mus_frequency(ptr),
4208 mus_phase(ptr),
4209 mus_length(ptr),
4210 mus_interp_type_to_string(wt_interp_type(ptr)));
4211 return(describe_buffer);
4212 }
4213
4214
mus_wave_train_any(mus_any * ptr,mus_float_t fm)4215 static mus_float_t mus_wave_train_any(mus_any *ptr, mus_float_t fm)
4216 {
4217 wt *gen = (wt *)ptr;
4218 mus_float_t result = 0.0;
4219
4220 if (gen->out_pos < gen->out_data_size)
4221 result = gen->out_data[gen->out_pos];
4222 gen->out_pos++;
4223 if (gen->out_pos >= gen->next_wave_time)
4224 {
4225 mus_long_t i;
4226 mus_float_t *wave, *out_data;
4227 mus_long_t wave_size;
4228
4229 wave = gen->wave;
4230 wave_size = gen->wave_size;
4231 out_data = gen->out_data;
4232
4233 if (gen->out_pos < gen->out_data_size)
4234 {
4235 mus_long_t good_samps;
4236 good_samps = gen->out_data_size - gen->out_pos;
4237 memmove((void *)out_data, (void *)(out_data + gen->out_pos), good_samps * sizeof(mus_float_t));
4238 mus_clear_floats(out_data + good_samps, gen->out_pos);
4239 }
4240 else mus_clear_floats(out_data, gen->out_data_size);
4241 if (gen->interp_type == MUS_INTERP_LINEAR)
4242 {
4243 /* gen->phase doesn't change, and i is an int, so we can precalculate the fractional part, etc
4244 */
4245 mus_float_t phase, frac_part;
4246 mus_long_t int_part;
4247
4248 phase = gen->phase;
4249 if ((phase < 0.0) || (phase > wave_size))
4250 {
4251 phase = fmod((mus_float_t)phase, (mus_float_t)wave_size);
4252 if (phase < 0.0) phase += wave_size;
4253 }
4254
4255 int_part = (mus_long_t)floor(phase);
4256 frac_part = phase - int_part;
4257 if (int_part == wave_size) int_part = 0;
4258
4259 if (frac_part == 0.0)
4260 {
4261 mus_long_t p;
4262 for (i = 0, p = int_part; i < wave_size; i++, p++)
4263 {
4264 if (p == wave_size) p = 0;
4265 out_data[i] += wave[p];
4266 }
4267 }
4268 else
4269 {
4270 mus_long_t p, p1;
4271 for (i = 0, p = int_part, p1 = int_part + 1; i < wave_size; i++, p1++)
4272 {
4273 if (p1 == wave_size) p1 = 0;
4274 out_data[i] += (wave[p] + frac_part * (wave[p1] - wave[p]));
4275 p = p1;
4276 }
4277 }
4278 }
4279 else
4280 {
4281 for (i = 0; i < wave_size; i++)
4282 {
4283 gen->yn1 = mus_interpolate(gen->interp_type, gen->phase + i, wave, wave_size, gen->yn1);
4284 out_data[i] += gen->yn1;
4285 }
4286 }
4287 if (gen->first_time)
4288 {
4289 gen->first_time = false;
4290 gen->out_pos = (mus_long_t)(gen->phase); /* initial phase, but as an integer in terms of wave table size (gad...) */
4291 if (gen->out_pos >= wave_size)
4292 gen->out_pos = gen->out_pos % wave_size; /* both are mus_long_t */
4293 result = out_data[gen->out_pos++];
4294 if (gen->freq == -fm)
4295 gen->next_wave_time = (mus_float_t)sampling_rate;
4296 else gen->next_wave_time = ((mus_float_t)sampling_rate / (gen->freq + fm));
4297 }
4298 else
4299 {
4300 gen->next_wave_time += (((mus_float_t)sampling_rate / (gen->freq + fm)) - gen->out_pos);
4301 gen->out_pos = 0;
4302 }
4303 }
4304 return(result);
4305 }
4306
4307
mus_wave_train(mus_any * ptr,mus_float_t fm)4308 mus_float_t mus_wave_train(mus_any *ptr, mus_float_t fm) {return(mus_wave_train_any(ptr, fm / w_rate));}
4309
mus_wave_train_unmodulated(mus_any * ptr)4310 mus_float_t mus_wave_train_unmodulated(mus_any *ptr) {return(mus_wave_train(ptr, 0.0));}
4311
run_wave_train(mus_any * ptr,mus_float_t fm,mus_float_t unused)4312 static mus_float_t run_wave_train(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_wave_train_any(ptr, fm / w_rate));}
4313
free_wt(mus_any * p)4314 static void free_wt(mus_any *p)
4315 {
4316 wt *ptr = (wt *)p;
4317 if (ptr->out_data)
4318 {
4319 free(ptr->out_data);
4320 ptr->out_data = NULL;
4321 }
4322 free(ptr);
4323 }
4324
4325
wt_reset(mus_any * ptr)4326 static void wt_reset(mus_any *ptr)
4327 {
4328 wt *gen = (wt *)ptr;
4329 gen->phase = 0.0;
4330 mus_clear_floats(gen->out_data, gen->out_data_size);
4331 gen->out_pos = gen->out_data_size;
4332 gen->next_wave_time = 0.0;
4333 gen->first_time = true;
4334 }
4335
4336
4337 static mus_any_class WAVE_TRAIN_CLASS = {
4338 MUS_WAVE_TRAIN,
4339 (char *)S_wave_train,
4340 &free_wt,
4341 &describe_wt,
4342 &wt_equalp,
4343 &wt_data,
4344 &wt_set_data,
4345 &wt_length,
4346 &wt_set_length,
4347 &wt_freq,
4348 &wt_set_freq,
4349 &wt_phase,
4350 &wt_set_phase,
4351 &fallback_scaler, 0,
4352 0, 0,
4353 &run_wave_train,
4354 MUS_NOT_SPECIAL,
4355 NULL,
4356 &wt_interp_type,
4357 0, 0,
4358 0, 0, 0, 0, 0, 0, 0, 0,
4359 0, 0, 0, 0, 0, 0, 0,
4360 0, 0, 0, 0,
4361 &wt_reset,
4362 0, &wt_copy
4363 };
4364
4365
mus_make_wave_train(mus_float_t freq,mus_float_t phase,mus_float_t * wave,mus_long_t wave_size,mus_interp_t type)4366 mus_any *mus_make_wave_train(mus_float_t freq, mus_float_t phase, mus_float_t *wave, mus_long_t wave_size, mus_interp_t type)
4367 {
4368 wt *gen;
4369 gen = (wt *)malloc(sizeof(wt));
4370 gen->core = &WAVE_TRAIN_CLASS;
4371 gen->freq = freq;
4372 gen->phase = (wave_size * fmod(phase, TWO_PI)) / TWO_PI;
4373 gen->wave = wave;
4374 gen->wave_size = wave_size;
4375 gen->interp_type = type;
4376 gen->out_data_size = wave_size + 2;
4377 gen->out_data = (mus_float_t *)calloc(gen->out_data_size, sizeof(mus_float_t));
4378 gen->out_pos = gen->out_data_size;
4379 gen->next_wave_time = 0.0;
4380 gen->first_time = true;
4381 gen->yn1 = 0.0;
4382 return((mus_any *)gen);
4383 }
4384
4385
mus_is_wave_train(mus_any * ptr)4386 bool mus_is_wave_train(mus_any *ptr)
4387 {
4388 return((ptr) &&
4389 (ptr->core->type == MUS_WAVE_TRAIN));
4390 }
4391
4392
4393
4394
4395 /* ---------------- delay, comb, notch, all-pass, moving-average, filtered-comb ---------------- */
4396
4397 typedef struct dly {
4398 mus_any_class *core;
4399 uint32_t loc, size;
4400 bool zdly, line_allocated, filt_allocated;
4401 mus_float_t *line;
4402 uint32_t zloc, zsize;
4403 mus_float_t xscl, yscl, yn1, y1, norm;
4404 mus_interp_t type;
4405 mus_any *filt;
4406 struct dly *next;
4407 mus_float_t (*runf)(mus_any *gen, mus_float_t arg1, mus_float_t arg2);
4408 mus_float_t (*del)(mus_any *ptr, mus_float_t input); /* zdelay or normal tap */
4409 mus_float_t (*delt)(mus_any *ptr, mus_float_t input); /* just tick */
4410 mus_float_t (*delu)(mus_any *ptr, mus_float_t input); /* unmodulated */
4411 } dly;
4412
4413
4414
mus_delay_tick(mus_any * ptr,mus_float_t input)4415 mus_float_t mus_delay_tick(mus_any *ptr, mus_float_t input)
4416 {
4417 return(((dly *)ptr)->delt(ptr, input));
4418 }
4419
4420
mus_tap(mus_any * ptr,mus_float_t loc)4421 mus_float_t mus_tap(mus_any *ptr, mus_float_t loc)
4422 {
4423 return(((dly *)ptr)->del(ptr, loc));
4424 }
4425
4426
mus_delay_unmodulated(mus_any * ptr,mus_float_t input)4427 mus_float_t mus_delay_unmodulated(mus_any *ptr, mus_float_t input)
4428 {
4429 return(((dly *)ptr)->delu(ptr, input));
4430 }
4431
4432
ztap(mus_any * ptr,mus_float_t loc)4433 static mus_float_t ztap(mus_any *ptr, mus_float_t loc)
4434 {
4435 dly *gen = (dly *)ptr;
4436 /* this is almost always linear */
4437 if (gen->type == MUS_INTERP_LINEAR)
4438 return(mus_array_interp(gen->line, gen->zloc - loc, gen->zsize));
4439 gen->yn1 = mus_interpolate(gen->type, gen->zloc - loc, gen->line, gen->zsize, gen->yn1);
4440 return(gen->yn1);
4441 }
4442
4443
dtap(mus_any * ptr,mus_float_t loc)4444 static mus_float_t dtap(mus_any *ptr, mus_float_t loc)
4445 {
4446 dly *gen = (dly *)ptr;
4447 int taploc;
4448 if (gen->size == 0) return(gen->line[0]);
4449 if ((int)loc == 0) return(gen->line[gen->loc]);
4450 taploc = (int)(gen->loc - (int)loc) % (int)gen->size;
4451 /* cast to int for gen->size is needed, as Tito Latini noticed, because the % operator in C is not smart about uint32_ts:
4452 * (int)-1 % (uint32_t)10 => 5
4453 * (int)-1 % (int)10 => -1
4454 */
4455 if (taploc < 0) taploc += (int)gen->size;
4456 return(gen->line[taploc]);
4457 }
4458
4459
mus_tap_unmodulated(mus_any * ptr)4460 mus_float_t mus_tap_unmodulated(mus_any *ptr)
4461 {
4462 dly *gen = (dly *)ptr;
4463 return(gen->line[gen->loc]);
4464 }
4465
4466
zdelt(mus_any * ptr,mus_float_t input)4467 static mus_float_t zdelt(mus_any *ptr, mus_float_t input)
4468 {
4469 dly *gen = (dly *)ptr;
4470 gen->line[gen->loc] = input;
4471 gen->loc++;
4472 if (gen->loc >= gen->zsize) gen->loc = 0;
4473 gen->zloc++;
4474 if (gen->zloc >= gen->zsize) gen->zloc = 0;
4475 return(input);
4476 }
4477
4478
delt(mus_any * ptr,mus_float_t input)4479 static mus_float_t delt(mus_any *ptr, mus_float_t input)
4480 {
4481 dly *gen = (dly *)ptr;
4482 gen->line[gen->loc] = input;
4483 gen->loc++;
4484 if (gen->loc >= gen->size) gen->loc = 0;
4485 return(input);
4486 }
4487
4488
mus_delay(mus_any * ptr,mus_float_t input,mus_float_t pm)4489 mus_float_t mus_delay(mus_any *ptr, mus_float_t input, mus_float_t pm)
4490 {
4491 mus_float_t result;
4492 dly *gen = (dly *)ptr;
4493 if ((gen->size == 0) && (pm < 1.0))
4494 result = pm * gen->line[0] + (1.0 - pm) * input;
4495 else result = mus_tap(ptr, pm);
4496 mus_delay_tick(ptr, input);
4497 return(result);
4498 }
4499
4500
zdelay_unmodulated(mus_any * ptr,mus_float_t input)4501 static mus_float_t zdelay_unmodulated(mus_any *ptr, mus_float_t input)
4502 {
4503 dly *gen = (dly *)ptr;
4504 mus_float_t result;
4505 result = gen->line[gen->zloc];
4506 mus_delay_tick(ptr, input);
4507 return(result);
4508 }
4509
4510
delay_unmodulated_zero(mus_any * ptr,mus_float_t input)4511 static mus_float_t delay_unmodulated_zero(mus_any *ptr, mus_float_t input)
4512 {
4513 return(input);
4514 }
4515
4516
mus_delay_unmodulated_noz(mus_any * ptr,mus_float_t input)4517 mus_float_t mus_delay_unmodulated_noz(mus_any *ptr, mus_float_t input)
4518 {
4519 dly *gen = (dly *)ptr;
4520 mus_float_t result;
4521 result = gen->line[gen->loc];
4522 gen->line[gen->loc] = input;
4523 gen->loc++;
4524 if (gen->loc >= gen->size)
4525 gen->loc = 0;
4526 return(result);
4527 }
4528
4529 static dly *dly_free_list = NULL;
4530
free_delay(mus_any * gen)4531 static void free_delay(mus_any *gen)
4532 {
4533 dly *ptr = (dly *)gen;
4534 if ((ptr->line) && (ptr->line_allocated)) free(ptr->line);
4535 if ((ptr->filt) && (ptr->filt_allocated)) mus_free(ptr->filt);
4536 /* free(ptr); */
4537 ptr->next = dly_free_list;
4538 dly_free_list = ptr;
4539 }
4540
4541
dly_copy(mus_any * ptr)4542 static mus_any *dly_copy(mus_any *ptr)
4543 {
4544 dly *g, *p;
4545 p = (dly *)ptr;
4546 if (dly_free_list)
4547 {
4548 g = dly_free_list;
4549 dly_free_list = g->next;
4550 }
4551 else g = (dly *)malloc(sizeof(dly));
4552 memcpy((void *)g, (void *)ptr, sizeof(dly));
4553
4554 g->line = (mus_float_t *)malloc(g->size * sizeof(mus_float_t));
4555 mus_copy_floats(g->line, p->line, g->size);
4556 g->line_allocated = true;
4557
4558 if (p->filt)
4559 {
4560 g->filt = mus_copy(p->filt);
4561 g->filt_allocated = true;
4562 }
4563 return((mus_any *)g);
4564 }
4565
4566
describe_delay(mus_any * ptr)4567 static char *describe_delay(mus_any *ptr)
4568 {
4569 char *str = NULL;
4570 dly *gen = (dly *)ptr;
4571 char *describe_buffer;
4572 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
4573 if (gen->zdly)
4574 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s line[%u,%u, %s]: %s",
4575 mus_name(ptr),
4576 gen->size,
4577 gen->zsize,
4578 mus_interp_type_to_string(gen->type),
4579 str = float_array_to_string(gen->line, gen->size, gen->zloc));
4580 else snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s line[%u, %s]: %s",
4581 mus_name(ptr),
4582 gen->size,
4583 mus_interp_type_to_string(gen->type),
4584 str = float_array_to_string(gen->line, gen->size, gen->loc));
4585 if (str) free(str);
4586 return(describe_buffer);
4587 }
4588
4589
delay_equalp(mus_any * p1,mus_any * p2)4590 static bool delay_equalp(mus_any *p1, mus_any *p2)
4591 {
4592 dly *d1 = (dly *)p1;
4593 dly *d2 = (dly *)p2;
4594 if (p1 == p2) return(true);
4595 return((d1) && (d2) &&
4596 (d1->core->type == d2->core->type) &&
4597 (d1->size == d2->size) &&
4598 (d1->loc == d2->loc) &&
4599 (d1->zdly == d2->zdly) &&
4600 (d1->zloc == d2->zloc) &&
4601 (d1->zsize == d2->zsize) &&
4602 (d1->xscl == d2->xscl) &&
4603 (d1->yscl == d2->yscl) &&
4604 (d1->yn1 == d2->yn1) &&
4605 (d1->type == d2->type) &&
4606 (clm_arrays_are_equal(d1->line, d2->line, d1->size)));
4607 }
4608
4609
delay_length(mus_any * ptr)4610 static mus_long_t delay_length(mus_any *ptr)
4611 {
4612 dly *d = (dly *)ptr;
4613 if (d->size > 0) /* this is possible (not sure it's a good idea...) */
4614 return(d->size);
4615 return(d->zsize); /* maybe always use this? */
4616 }
4617
4618
delay_scaler(mus_any * ptr)4619 static mus_float_t delay_scaler(mus_any *ptr) {return(((dly *)ptr)->xscl);}
delay_set_scaler(mus_any * ptr,mus_float_t val)4620 static mus_float_t delay_set_scaler(mus_any *ptr, mus_float_t val) {((dly *)ptr)->xscl = val; return(val);}
4621
delay_fb(mus_any * ptr)4622 static mus_float_t delay_fb(mus_any *ptr) {return(((dly *)ptr)->yscl);}
delay_set_fb(mus_any * ptr,mus_float_t val)4623 static mus_float_t delay_set_fb(mus_any *ptr, mus_float_t val) {((dly *)ptr)->yscl = val; return(val);}
4624
delay_interp_type(mus_any * ptr)4625 static int delay_interp_type(mus_any *ptr) {return((int)(((dly *)ptr)->type));}
delay_loc(mus_any * ptr)4626 static mus_long_t delay_loc(mus_any *ptr){return((mus_long_t)(((dly *)ptr)->loc));}
delay_data(mus_any * ptr)4627 static mus_float_t *delay_data(mus_any *ptr) {return(((dly *)ptr)->line);}
delay_set_data(mus_any * ptr,mus_float_t * val)4628 static mus_float_t *delay_set_data(mus_any *ptr, mus_float_t *val)
4629 {
4630 dly *gen = (dly *)ptr;
4631 if (gen->line_allocated) {free(gen->line); gen->line_allocated = false;}
4632 gen->line = val;
4633 return(val);
4634 }
4635
4636
delay_set_length(mus_any * ptr,mus_long_t val)4637 static mus_long_t delay_set_length(mus_any *ptr, mus_long_t val)
4638 {
4639 dly *gen = (dly *)ptr;
4640 if (val > 0)
4641 {
4642 uint32_t old_size;
4643 old_size = gen->size;
4644 gen->size = (uint32_t)val;
4645 if (gen->size < old_size)
4646 {
4647 if (gen->loc > gen->size) gen->loc = 0;
4648 gen->zdly = false; /* otherwise too many ways to screw up */
4649 }
4650 }
4651 return((mus_long_t)(gen->size));
4652 }
4653
4654
mus_is_tap(mus_any * gen)4655 bool mus_is_tap(mus_any *gen)
4656 {
4657 return((gen) &&
4658 (gen->core->extended_type == MUS_DELAY_LINE));
4659 }
4660
4661
delay_reset(mus_any * ptr)4662 static void delay_reset(mus_any *ptr)
4663 {
4664 dly *gen = (dly *)ptr;
4665 gen->loc = 0;
4666 gen->zloc = 0;
4667 gen->yn1 = 0.0;
4668 mus_clear_floats(gen->line, gen->zsize);
4669 }
4670
4671
4672 static mus_any_class DELAY_CLASS = {
4673 MUS_DELAY,
4674 (char *)S_delay,
4675 &free_delay,
4676 &describe_delay,
4677 &delay_equalp,
4678 &delay_data,
4679 &delay_set_data,
4680 &delay_length,
4681 &delay_set_length,
4682 0, 0, 0, 0, /* freq phase */
4683 &delay_scaler,
4684 &delay_set_scaler,
4685 &delay_fb,
4686 &delay_set_fb,
4687 &mus_delay,
4688 MUS_DELAY_LINE,
4689 NULL,
4690 &delay_interp_type,
4691 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4692 0, 0, 0, 0,
4693 &delay_loc,
4694 0, 0,
4695 0, 0, 0, 0,
4696 &delay_reset,
4697 0, &dly_copy
4698 };
4699
4700
mus_make_delay(int size,mus_float_t * preloaded_line,int line_size,mus_interp_t type)4701 mus_any *mus_make_delay(int size, mus_float_t *preloaded_line, int line_size, mus_interp_t type)
4702 {
4703 /* if preloaded_line null, allocated locally.
4704 * if size == line_size, normal (non-interpolating) delay
4705 * in clm2xen.c, if size=0 and max-size unset, max-size=1 (line_size here)
4706 */
4707 dly *gen;
4708 if (dly_free_list)
4709 {
4710 gen = dly_free_list;
4711 dly_free_list = gen->next;
4712 }
4713 else gen = (dly *)malloc(sizeof(dly));
4714 gen->core = &DELAY_CLASS;
4715 gen->loc = 0;
4716 if (line_size < size) line_size = size;
4717 gen->size = size;
4718 gen->zsize = line_size;
4719 gen->zdly = ((line_size != size) || (type != MUS_INTERP_NONE));
4720 if (gen->zdly)
4721 {
4722 gen->del = ztap;
4723 gen->delt = zdelt;
4724 if (gen->size == 0)
4725 gen->delu = delay_unmodulated_zero;
4726 else gen->delu = zdelay_unmodulated;
4727 }
4728 else
4729 {
4730 gen->del = dtap;
4731 gen->delt = delt;
4732 if (gen->size == 0)
4733 gen->delu = delay_unmodulated_zero;
4734 else gen->delu = mus_delay_unmodulated_noz;
4735 }
4736 gen->type = type;
4737 if (preloaded_line)
4738 {
4739 gen->line = preloaded_line;
4740 gen->line_allocated = false;
4741 }
4742 else
4743 {
4744 gen->line = (mus_float_t *)calloc((line_size <= 0) ? 1 : line_size, sizeof(mus_float_t));
4745 gen->line_allocated = true;
4746 }
4747 gen->zloc = line_size - size;
4748 gen->filt = NULL;
4749 gen->filt_allocated = false;
4750 gen->xscl = 0.0;
4751 gen->yscl = 0.0;
4752 gen->yn1 = 0.0;
4753 gen->runf = NULL;
4754 return((mus_any *)gen);
4755 }
4756
4757
mus_is_delay(mus_any * ptr)4758 bool mus_is_delay(mus_any *ptr)
4759 {
4760 return((ptr) &&
4761 (ptr->core->type == MUS_DELAY));
4762 }
4763
4764
4765 /* ---------------- comb ---------------- */
4766
mus_comb(mus_any * ptr,mus_float_t input,mus_float_t pm)4767 mus_float_t mus_comb(mus_any *ptr, mus_float_t input, mus_float_t pm)
4768 {
4769 dly *gen = (dly *)ptr;
4770 if (gen->zdly)
4771 return(mus_delay(ptr, input + (gen->yscl * mus_tap(ptr, pm)), pm));
4772 /* mus.lisp has 0 in place of the final pm -- the question is whether the delay
4773 should interpolate as well as the tap. There is a subtle difference in
4774 output (the pm case is low-passed by the interpolation ("average")),
4775 but I don't know if there's a standard here, or what people expect.
4776 We're doing the outer-level interpolation in notch and all-pass.
4777 Should mus.lisp be changed?
4778 */
4779 else return(mus_delay_unmodulated(ptr, input + (gen->line[gen->loc] * gen->yscl)));
4780 }
4781
4782
mus_comb_unmodulated(mus_any * ptr,mus_float_t input)4783 mus_float_t mus_comb_unmodulated(mus_any *ptr, mus_float_t input)
4784 {
4785 dly *gen = (dly *)ptr;
4786 if (gen->zdly)
4787 return(mus_delay_unmodulated(ptr, input + (gen->line[gen->zloc] * gen->yscl)));
4788 return(mus_delay_unmodulated(ptr, input + (gen->line[gen->loc] * gen->yscl)));
4789 }
4790
4791
mus_comb_unmodulated_noz(mus_any * ptr,mus_float_t input)4792 mus_float_t mus_comb_unmodulated_noz(mus_any *ptr, mus_float_t input)
4793 {
4794 dly *gen = (dly *)ptr;
4795 mus_float_t result;
4796
4797 result = gen->line[gen->loc];
4798 gen->line[gen->loc] = input + (result * gen->yscl);
4799 gen->loc++;
4800 if (gen->loc >= gen->size)
4801 gen->loc = 0;
4802
4803 return(result);
4804 }
4805
4806
describe_comb(mus_any * ptr)4807 static char *describe_comb(mus_any *ptr)
4808 {
4809 char *str = NULL;
4810 dly *gen = (dly *)ptr;
4811 char *describe_buffer;
4812 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
4813 if (gen->zdly)
4814 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s scaler: %.3f, line[%u,%u, %s]: %s",
4815 mus_name(ptr),
4816 gen->yscl,
4817 gen->size,
4818 gen->zsize,
4819 mus_interp_type_to_string(gen->type),
4820 str = float_array_to_string(gen->line, gen->size, gen->zloc));
4821 else snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s scaler: %.3f, line[%u, %s]: %s",
4822 mus_name(ptr),
4823 gen->yscl,
4824 gen->size,
4825 mus_interp_type_to_string(gen->type),
4826 str = float_array_to_string(gen->line, gen->size, gen->loc));
4827 if (str) free(str);
4828 return(describe_buffer);
4829 }
4830
4831
4832 static mus_any_class COMB_CLASS = {
4833 MUS_COMB,
4834 (char *)S_comb,
4835 &free_delay,
4836 &describe_comb,
4837 &delay_equalp,
4838 &delay_data,
4839 &delay_set_data,
4840 &delay_length,
4841 &delay_set_length,
4842 0, 0, 0, 0, /* freq phase */
4843 &delay_scaler,
4844 &delay_set_scaler,
4845 &delay_fb,
4846 &delay_set_fb,
4847 &mus_comb,
4848 MUS_DELAY_LINE,
4849 NULL,
4850 &delay_interp_type,
4851 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4852 0, 0, 0, 0,
4853 &delay_loc,
4854 0, 0,
4855 0, 0, 0, 0,
4856 &delay_reset,
4857 0, &dly_copy
4858 };
4859
4860
mus_make_comb(mus_float_t scaler,int size,mus_float_t * line,int line_size,mus_interp_t type)4861 mus_any *mus_make_comb(mus_float_t scaler, int size, mus_float_t *line, int line_size, mus_interp_t type)
4862 {
4863 dly *gen;
4864 gen = (dly *)mus_make_delay(size, line, line_size, type);
4865 if (gen)
4866 {
4867 gen->core = &COMB_CLASS;
4868 gen->yscl = scaler;
4869 return((mus_any *)gen);
4870 }
4871 return(NULL);
4872 }
4873
4874
mus_is_comb(mus_any * ptr)4875 bool mus_is_comb(mus_any *ptr)
4876 {
4877 return((ptr) &&
4878 (ptr->core->type == MUS_COMB));
4879 }
4880
4881
4882
4883 /* ---------------- comb-bank ---------------- */
4884
4885 typedef struct {
4886 mus_any_class *core;
4887 int size;
4888 mus_any **gens;
4889 mus_float_t (*cmbf)(mus_any *ptr, mus_float_t input);
4890 } cmb_bank;
4891
4892
free_comb_bank(mus_any * ptr)4893 static void free_comb_bank(mus_any *ptr)
4894 {
4895 cmb_bank *f = (cmb_bank *)ptr;
4896 if (f->gens) {free(f->gens); f->gens = NULL;}
4897 free(ptr);
4898 }
4899
4900
cmb_bank_copy(mus_any * ptr)4901 static mus_any *cmb_bank_copy(mus_any *ptr)
4902 {
4903 cmb_bank *g, *p;
4904 int i;
4905
4906 p = (cmb_bank *)ptr;
4907 g = (cmb_bank *)malloc(sizeof(cmb_bank));
4908 memcpy((void *)g, (void *)ptr, sizeof(cmb_bank));
4909 g->gens = (mus_any **)malloc(p->size * sizeof(mus_any *));
4910 for (i = 0; i < p->size; i++)
4911 g->gens[i] = mus_copy(p->gens[i]);
4912
4913 return((mus_any *)g);
4914 }
4915
4916
run_comb_bank(mus_any * ptr,mus_float_t input,mus_float_t unused)4917 static mus_float_t run_comb_bank(mus_any *ptr, mus_float_t input, mus_float_t unused)
4918 {
4919 return(mus_comb_bank(ptr, input));
4920 }
4921
4922
comb_bank_length(mus_any * ptr)4923 static mus_long_t comb_bank_length(mus_any *ptr)
4924 {
4925 return(((cmb_bank *)ptr)->size);
4926 }
4927
4928
comb_bank_reset(mus_any * ptr)4929 static void comb_bank_reset(mus_any *ptr)
4930 {
4931 cmb_bank *f = (cmb_bank *)ptr;
4932 int i;
4933 for (i = 0; i < f->size; i++)
4934 mus_reset(f->gens[i]);
4935 }
4936
4937
comb_bank_equalp(mus_any * p1,mus_any * p2)4938 static bool comb_bank_equalp(mus_any *p1, mus_any *p2)
4939 {
4940 cmb_bank *f1 = (cmb_bank *)p1;
4941 cmb_bank *f2 = (cmb_bank *)p2;
4942 int i, size;
4943
4944 if (f1 == f2) return(true);
4945 if (f1->size != f2->size) return(false);
4946 size = f1->size;
4947
4948 for (i = 0; i < size; i++)
4949 if (!delay_equalp(f1->gens[i], f2->gens[i]))
4950 return(false);
4951
4952 /* now check the locals... */
4953 return(true);
4954 }
4955
4956
describe_comb_bank(mus_any * ptr)4957 static char *describe_comb_bank(mus_any *ptr)
4958 {
4959 cmb_bank *gen = (cmb_bank *)ptr;
4960 char *describe_buffer;
4961 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
4962 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s size: %d",
4963 mus_name(ptr),
4964 gen->size);
4965 return(describe_buffer);
4966 }
4967
4968 static mus_any_class COMB_BANK_CLASS = {
4969 MUS_COMB_BANK,
4970 (char *)S_comb_bank,
4971 &free_comb_bank,
4972 &describe_comb_bank,
4973 &comb_bank_equalp,
4974 0, 0,
4975 &comb_bank_length, 0,
4976 0, 0,
4977 0, 0,
4978 0, 0,
4979 0, 0,
4980 &run_comb_bank,
4981 MUS_NOT_SPECIAL,
4982 NULL, 0,
4983 0, 0, 0, 0,
4984 0, 0,
4985 0, 0, 0, 0,
4986 0, 0, 0, 0, 0, 0, 0,
4987 0, 0, 0, 0,
4988 &comb_bank_reset,
4989 0, &cmb_bank_copy
4990 };
4991
4992
comb_bank_any(mus_any * combs,mus_float_t inval)4993 static mus_float_t comb_bank_any(mus_any *combs, mus_float_t inval)
4994 {
4995 int i;
4996 mus_float_t sum = 0.0;
4997 cmb_bank *c = (cmb_bank *)combs;
4998 for (i = 0; i < c->size; i++)
4999 sum += mus_comb_unmodulated_noz(c->gens[i], inval);
5000 return(sum);
5001 }
5002
comb_bank_4(mus_any * combs,mus_float_t inval)5003 static mus_float_t comb_bank_4(mus_any *combs, mus_float_t inval)
5004 {
5005 cmb_bank *c = (cmb_bank *)combs;
5006 mus_any **gs;
5007 gs = c->gens;
5008 return(mus_comb_unmodulated_noz(gs[0], inval) +
5009 mus_comb_unmodulated_noz(gs[1], inval) +
5010 mus_comb_unmodulated_noz(gs[2], inval) +
5011 mus_comb_unmodulated_noz(gs[3], inval));
5012 }
5013
comb_bank_6(mus_any * combs,mus_float_t inval)5014 static mus_float_t comb_bank_6(mus_any *combs, mus_float_t inval)
5015 {
5016 cmb_bank *c = (cmb_bank *)combs;
5017 mus_any **gs;
5018 gs = c->gens;
5019 return(mus_comb_unmodulated_noz(gs[0], inval) +
5020 mus_comb_unmodulated_noz(gs[1], inval) +
5021 mus_comb_unmodulated_noz(gs[2], inval) +
5022 mus_comb_unmodulated_noz(gs[3], inval) +
5023 mus_comb_unmodulated_noz(gs[4], inval) +
5024 mus_comb_unmodulated_noz(gs[5], inval));
5025 }
5026
5027
mus_make_comb_bank(int size,mus_any ** combs)5028 mus_any *mus_make_comb_bank(int size, mus_any **combs)
5029 {
5030 cmb_bank *gen;
5031 int i;
5032
5033 gen = (cmb_bank *)malloc(sizeof(cmb_bank));
5034 gen->core = &COMB_BANK_CLASS;
5035 gen->size = size;
5036
5037 gen->gens = (mus_any **)malloc(size * sizeof(mus_any *));
5038 for (i = 0; i < size; i++)
5039 gen->gens[i] = combs[i];
5040
5041 if (size == 4)
5042 gen->cmbf = comb_bank_4;
5043 else
5044 {
5045 if (size == 6)
5046 gen->cmbf = comb_bank_6;
5047 else gen->cmbf = comb_bank_any;
5048 }
5049
5050 return((mus_any *)gen);
5051 }
5052
mus_is_comb_bank(mus_any * ptr)5053 bool mus_is_comb_bank(mus_any *ptr)
5054 {
5055 return((ptr) &&
5056 (ptr->core->type == MUS_COMB_BANK));
5057 }
5058
mus_comb_bank(mus_any * combs,mus_float_t inval)5059 mus_float_t mus_comb_bank(mus_any *combs, mus_float_t inval)
5060 {
5061 cmb_bank *gen = (cmb_bank *)combs;
5062 return((gen->cmbf)(combs, inval));
5063 }
5064
5065
5066
5067
5068 /* ---------------- notch ---------------- */
5069
describe_notch(mus_any * ptr)5070 static char *describe_notch(mus_any *ptr)
5071 {
5072 char *str = NULL;
5073 dly *gen = (dly *)ptr;
5074 char *describe_buffer;
5075 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
5076 if (gen->zdly)
5077 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s scaler: %.3f, line[%u,%u, %s]: %s",
5078 mus_name(ptr),
5079 gen->xscl,
5080 gen->size,
5081 gen->zsize,
5082 mus_interp_type_to_string(gen->type),
5083 str = float_array_to_string(gen->line, gen->size, gen->zloc));
5084 else snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s scaler: %.3f, line[%u, %s]: %s",
5085 mus_name(ptr),
5086 gen->xscl,
5087 gen->size,
5088 mus_interp_type_to_string(gen->type),
5089 str = float_array_to_string(gen->line, gen->size, gen->loc));
5090 if (str) free(str);
5091 return(describe_buffer);
5092 }
5093
5094
5095 static mus_any_class NOTCH_CLASS = {
5096 MUS_NOTCH,
5097 (char *)S_notch,
5098 &free_delay,
5099 &describe_notch,
5100 &delay_equalp,
5101 &delay_data,
5102 &delay_set_data,
5103 &delay_length,
5104 &delay_set_length,
5105 0, 0, 0, 0, /* freq phase */
5106 &delay_scaler,
5107 &delay_set_scaler,
5108 0, 0,
5109 &mus_notch,
5110 MUS_DELAY_LINE,
5111 NULL,
5112 &delay_interp_type,
5113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5114 0, 0, 0, 0,
5115 &delay_loc,
5116 0, 0,
5117 0, 0, 0, 0,
5118 &delay_reset,
5119 0, &dly_copy
5120 };
5121
5122
mus_notch(mus_any * ptr,mus_float_t input,mus_float_t pm)5123 mus_float_t mus_notch(mus_any *ptr, mus_float_t input, mus_float_t pm)
5124 {
5125 dly *gen = (dly *)ptr;
5126 return((input * gen->xscl) + mus_delay(ptr, input, pm));
5127 }
5128
5129
mus_notch_unmodulated(mus_any * ptr,mus_float_t input)5130 mus_float_t mus_notch_unmodulated(mus_any *ptr, mus_float_t input)
5131 {
5132 return((input * ((dly *)ptr)->xscl) + mus_delay_unmodulated(ptr, input));
5133 }
5134
5135 #if 0
5136 static mus_float_t mus_notch_unmodulated_noz(mus_any *ptr, mus_float_t input)
5137 {
5138 dly *gen = (dly *)ptr;
5139 mus_float_t result;
5140 result = gen->line[gen->loc] + (input * gen->xscl);
5141 gen->line[gen->loc] = input;
5142 gen->loc++;
5143 if (gen->loc >= gen->size)
5144 gen->loc = 0;
5145 return(result);
5146 }
5147 #endif
5148
mus_is_notch(mus_any * ptr)5149 bool mus_is_notch(mus_any *ptr)
5150 {
5151 return((ptr) &&
5152 (ptr->core->type == MUS_NOTCH));
5153 }
5154
5155
mus_make_notch(mus_float_t scaler,int size,mus_float_t * line,int line_size,mus_interp_t type)5156 mus_any *mus_make_notch(mus_float_t scaler, int size, mus_float_t *line, int line_size, mus_interp_t type)
5157 {
5158 dly *gen;
5159 gen = (dly *)mus_make_delay(size, line, line_size, type);
5160 if (gen)
5161 {
5162 gen->core = &NOTCH_CLASS;
5163 gen->xscl = scaler;
5164 return((mus_any *)gen);
5165 }
5166 return(NULL);
5167 }
5168
5169
mus_all_pass(mus_any * ptr,mus_float_t input,mus_float_t pm)5170 mus_float_t mus_all_pass(mus_any *ptr, mus_float_t input, mus_float_t pm)
5171 {
5172 mus_float_t din;
5173 dly *gen = (dly *)ptr;
5174 if (gen->zdly)
5175 din = input + (gen->yscl * mus_tap(ptr, pm));
5176 else din = input + (gen->yscl * gen->line[gen->loc]);
5177 return(mus_delay(ptr, din, pm) + (gen->xscl * din));
5178 }
5179
5180
mus_all_pass_unmodulated(mus_any * ptr,mus_float_t input)5181 mus_float_t mus_all_pass_unmodulated(mus_any *ptr, mus_float_t input)
5182 {
5183 mus_float_t din;
5184 dly *gen = (dly *)ptr;
5185 if (gen->zdly)
5186 din = input + (gen->yscl * gen->line[gen->zloc]);
5187 else din = input + (gen->yscl * gen->line[gen->loc]);
5188 return(mus_delay_unmodulated(ptr, din) + (gen->xscl * din));
5189 }
5190
5191
mus_all_pass_unmodulated_noz(mus_any * ptr,mus_float_t input)5192 mus_float_t mus_all_pass_unmodulated_noz(mus_any *ptr, mus_float_t input)
5193 {
5194 mus_float_t result, din;
5195 dly *gen = (dly *)ptr;
5196 uint32_t loc;
5197 loc = gen->loc++;
5198 din = input + (gen->yscl * gen->line[loc]);
5199 result = gen->line[loc] + (gen->xscl * din);
5200 gen->line[loc] = din;
5201 if (gen->loc >= gen->size)
5202 gen->loc = 0;
5203 return(result);
5204 }
5205
5206
mus_is_all_pass(mus_any * ptr)5207 bool mus_is_all_pass(mus_any *ptr)
5208 {
5209 return((ptr) &&
5210 (ptr->core->type == MUS_ALL_PASS));
5211 }
5212
5213
describe_all_pass(mus_any * ptr)5214 static char *describe_all_pass(mus_any *ptr)
5215 {
5216 char *str = NULL;
5217 dly *gen = (dly *)ptr;
5218 char *describe_buffer;
5219 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
5220 if (gen->zdly)
5221 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s feedback: %.3f, feedforward: %.3f, line[%u,%u, %s]:%s",
5222 mus_name(ptr),
5223 gen->yscl,
5224 gen->xscl,
5225 gen->size,
5226 gen->zsize,
5227 mus_interp_type_to_string(gen->type),
5228 str = float_array_to_string(gen->line, gen->size, gen->zloc));
5229 else snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s feedback: %.3f, feedforward: %.3f, line[%u, %s]:%s",
5230 mus_name(ptr),
5231 gen->yscl,
5232 gen->xscl,
5233 gen->size,
5234 mus_interp_type_to_string(gen->type),
5235 str = float_array_to_string(gen->line, gen->size, gen->loc));
5236 if (str) free(str);
5237 return(describe_buffer);
5238 }
5239
5240
5241 static mus_any_class ALL_PASS_CLASS = {
5242 MUS_ALL_PASS,
5243 (char *)S_all_pass,
5244 &free_delay,
5245 &describe_all_pass,
5246 &delay_equalp,
5247 &delay_data,
5248 &delay_set_data,
5249 &delay_length,
5250 &delay_set_length,
5251 0, 0, 0, 0, /* freq phase */
5252 &delay_scaler,
5253 &delay_set_scaler,
5254 &delay_fb,
5255 &delay_set_fb,
5256 &mus_all_pass,
5257 MUS_DELAY_LINE,
5258 NULL,
5259 &delay_interp_type,
5260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5261 0, 0, 0, 0,
5262 &delay_loc,
5263 0, 0,
5264 0, 0, 0, 0,
5265 &delay_reset,
5266 0, &dly_copy
5267 };
5268
5269
mus_make_all_pass(mus_float_t backward,mus_float_t forward,int size,mus_float_t * line,int line_size,mus_interp_t type)5270 mus_any *mus_make_all_pass(mus_float_t backward, mus_float_t forward, int size, mus_float_t *line, int line_size, mus_interp_t type)
5271 {
5272 dly *gen;
5273 gen = (dly *)mus_make_delay(size, line, line_size, type);
5274 if (gen)
5275 {
5276 gen->core = &ALL_PASS_CLASS;
5277 gen->xscl = forward;
5278 gen->yscl = backward;
5279 return((mus_any *)gen);
5280 }
5281 return(NULL);
5282 }
5283
5284
5285 /* ---------------- all_pass-bank ---------------- */
5286
5287 typedef struct {
5288 mus_any_class *core;
5289 int size;
5290 mus_any **gens;
5291 mus_float_t (*apf)(mus_any *ptr, mus_float_t input);
5292 } allp_bank;
5293
5294
free_all_pass_bank(mus_any * ptr)5295 static void free_all_pass_bank(mus_any *ptr)
5296 {
5297 allp_bank *f = (allp_bank *)ptr;
5298 if (f->gens) {free(f->gens); f->gens = NULL;}
5299 free(ptr);
5300 }
5301
5302
allp_bank_copy(mus_any * ptr)5303 static mus_any *allp_bank_copy(mus_any *ptr)
5304 {
5305 allp_bank *g, *p;
5306 int i;
5307
5308 p = (allp_bank *)ptr;
5309 g = (allp_bank *)malloc(sizeof(allp_bank));
5310 memcpy((void *)g, (void *)ptr, sizeof(allp_bank));
5311 g->gens = (mus_any **)malloc(p->size * sizeof(mus_any *));
5312 for (i = 0; i < p->size; i++)
5313 g->gens[i] = mus_copy(p->gens[i]);
5314
5315 return((mus_any *)g);
5316 }
5317
5318
run_all_pass_bank(mus_any * ptr,mus_float_t input,mus_float_t unused)5319 static mus_float_t run_all_pass_bank(mus_any *ptr, mus_float_t input, mus_float_t unused)
5320 {
5321 return(mus_all_pass_bank(ptr, input));
5322 }
5323
5324
all_pass_bank_length(mus_any * ptr)5325 static mus_long_t all_pass_bank_length(mus_any *ptr)
5326 {
5327 return(((allp_bank *)ptr)->size);
5328 }
5329
5330
all_pass_bank_reset(mus_any * ptr)5331 static void all_pass_bank_reset(mus_any *ptr)
5332 {
5333 allp_bank *f = (allp_bank *)ptr;
5334 int i;
5335 for (i = 0; i < f->size; i++)
5336 mus_reset(f->gens[i]);
5337 }
5338
5339
all_pass_bank_equalp(mus_any * p1,mus_any * p2)5340 static bool all_pass_bank_equalp(mus_any *p1, mus_any *p2)
5341 {
5342 allp_bank *f1 = (allp_bank *)p1;
5343 allp_bank *f2 = (allp_bank *)p2;
5344 int i, size;
5345
5346 if (f1 == f2) return(true);
5347 if (f1->size != f2->size) return(false);
5348 size = f1->size;
5349
5350 for (i = 0; i < size; i++)
5351 if (!delay_equalp(f1->gens[i], f2->gens[i]))
5352 return(false);
5353
5354 return(true);
5355 }
5356
5357
describe_all_pass_bank(mus_any * ptr)5358 static char *describe_all_pass_bank(mus_any *ptr)
5359 {
5360 allp_bank *gen = (allp_bank *)ptr;
5361 char *describe_buffer;
5362 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
5363 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s size: %d",
5364 mus_name(ptr),
5365 gen->size);
5366 return(describe_buffer);
5367 }
5368
5369 static mus_any_class ALL_PASS_BANK_CLASS = {
5370 MUS_ALL_PASS_BANK,
5371 (char *)S_all_pass_bank,
5372 &free_all_pass_bank,
5373 &describe_all_pass_bank,
5374 &all_pass_bank_equalp,
5375 0, 0,
5376 &all_pass_bank_length, 0,
5377 0, 0,
5378 0, 0,
5379 0, 0,
5380 0, 0,
5381 &run_all_pass_bank,
5382 MUS_NOT_SPECIAL,
5383 NULL, 0,
5384 0, 0, 0, 0,
5385 0, 0,
5386 0, 0, 0, 0,
5387 0, 0, 0, 0, 0, 0, 0,
5388 0, 0, 0, 0,
5389 &all_pass_bank_reset,
5390 0, &allp_bank_copy
5391 };
5392
5393
all_pass_bank_3(mus_any * all_passes,mus_float_t inval)5394 static mus_float_t all_pass_bank_3(mus_any *all_passes, mus_float_t inval)
5395 {
5396 allp_bank *c = (allp_bank *)all_passes;
5397 mus_any **gs;
5398 gs = c->gens;
5399 return(mus_all_pass_unmodulated_noz(gs[2], mus_all_pass_unmodulated_noz(gs[1], mus_all_pass_unmodulated_noz(gs[0], inval))));
5400 }
5401
all_pass_bank_4(mus_any * all_passes,mus_float_t inval)5402 static mus_float_t all_pass_bank_4(mus_any *all_passes, mus_float_t inval)
5403 {
5404 allp_bank *c = (allp_bank *)all_passes;
5405 mus_any **gs;
5406 gs = c->gens;
5407 return(mus_all_pass_unmodulated_noz(gs[3], mus_all_pass_unmodulated_noz(gs[2], mus_all_pass_unmodulated_noz(gs[1], mus_all_pass_unmodulated_noz(gs[0], inval)))));
5408 }
5409
all_pass_bank_any(mus_any * all_passs,mus_float_t inval)5410 static mus_float_t all_pass_bank_any(mus_any *all_passs, mus_float_t inval)
5411 {
5412 int i;
5413 mus_float_t sum = inval;
5414 allp_bank *c = (allp_bank *)all_passs;
5415 for (i = 0; i < c->size; i++)
5416 sum = mus_all_pass_unmodulated_noz(c->gens[i], sum);
5417 return(sum);
5418 }
5419
5420
mus_make_all_pass_bank(int size,mus_any ** all_passs)5421 mus_any *mus_make_all_pass_bank(int size, mus_any **all_passs)
5422 {
5423 allp_bank *gen;
5424 int i;
5425
5426 gen = (allp_bank *)malloc(sizeof(allp_bank));
5427 gen->core = &ALL_PASS_BANK_CLASS;
5428 gen->size = size;
5429
5430 gen->gens = (mus_any **)malloc(size * sizeof(mus_any *));
5431 for (i = 0; i < size; i++)
5432 gen->gens[i] = all_passs[i];
5433
5434 if (size == 3)
5435 gen->apf = all_pass_bank_3;
5436 else
5437 {
5438 if (size == 4)
5439 gen->apf = all_pass_bank_4;
5440 else gen->apf = all_pass_bank_any;
5441 }
5442
5443 return((mus_any *)gen);
5444 }
5445
5446
mus_is_all_pass_bank(mus_any * ptr)5447 bool mus_is_all_pass_bank(mus_any *ptr)
5448 {
5449 return((ptr) &&
5450 (ptr->core->type == MUS_ALL_PASS_BANK));
5451 }
5452
5453
mus_all_pass_bank(mus_any * all_passes,mus_float_t inval)5454 mus_float_t mus_all_pass_bank(mus_any *all_passes, mus_float_t inval)
5455 {
5456 allp_bank *gen = (allp_bank *)all_passes;
5457 return((gen->apf)(all_passes, inval));
5458 }
5459
5460
5461
5462
5463 /* ---------------- moving-average ---------------- */
5464
mus_is_moving_average(mus_any * ptr)5465 bool mus_is_moving_average(mus_any *ptr)
5466 {
5467 return((ptr) &&
5468 (ptr->core->type == MUS_MOVING_AVERAGE));
5469 }
5470
5471
mus_moving_average(mus_any * ptr,mus_float_t input)5472 mus_float_t mus_moving_average(mus_any *ptr, mus_float_t input)
5473 {
5474 dly *gen = (dly *)ptr;
5475 mus_float_t output;
5476 output = mus_delay_unmodulated_noz(ptr, input);
5477 gen->xscl += (input - output);
5478 return(gen->xscl * gen->yscl); /* xscl=sum, yscl=1/n */
5479 }
5480
5481
run_mus_moving_average(mus_any * ptr,mus_float_t input,mus_float_t unused)5482 static mus_float_t run_mus_moving_average(mus_any *ptr, mus_float_t input, mus_float_t unused) {return(mus_moving_average(ptr, input));}
5483
5484
moving_average_reset(mus_any * ptr)5485 static void moving_average_reset(mus_any *ptr)
5486 {
5487 dly *gen = (dly *)ptr;
5488 delay_reset(ptr);
5489 gen->xscl = 0.0;
5490 }
5491
5492
describe_moving_average(mus_any * ptr)5493 static char *describe_moving_average(mus_any *ptr)
5494 {
5495 char *str = NULL;
5496 dly *gen = (dly *)ptr;
5497 char *describe_buffer;
5498 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
5499 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s %.3f, line[%u]:%s",
5500 mus_name(ptr),
5501 gen->xscl * gen->yscl,
5502 gen->size,
5503 str = float_array_to_string(gen->line, gen->size, gen->loc));
5504 if (str) free(str);
5505 return(describe_buffer);
5506 }
5507
5508
5509 static mus_any_class MOVING_AVERAGE_CLASS = {
5510 MUS_MOVING_AVERAGE,
5511 (char *)S_moving_average,
5512 &free_delay,
5513 &describe_moving_average,
5514 &delay_equalp,
5515 &delay_data,
5516 &delay_set_data,
5517 &delay_length,
5518 &delay_set_length,
5519 0, 0, 0, 0, /* freq phase */
5520 &delay_scaler,
5521 &delay_set_scaler,
5522 &delay_fb,
5523 &delay_set_fb,
5524 &run_mus_moving_average,
5525 MUS_DELAY_LINE,
5526 NULL, 0,
5527 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5528 0, 0, 0, 0,
5529 &delay_loc,
5530 0, 0,
5531 0, 0, 0, 0,
5532 &moving_average_reset,
5533 0, &dly_copy
5534 };
5535
5536
mus_make_moving_average(int size,mus_float_t * line)5537 mus_any *mus_make_moving_average(int size, mus_float_t *line)
5538 {
5539 dly *gen;
5540 gen = (dly *)mus_make_delay(size, line, size, MUS_INTERP_NONE);
5541 if (gen)
5542 {
5543 int i;
5544 gen->core = &MOVING_AVERAGE_CLASS;
5545 gen->xscl = 0.0;
5546 for (i = 0; i < size; i++)
5547 gen->xscl += gen->line[i];
5548 gen->yscl = 1.0 / (mus_float_t)size;
5549 return((mus_any *)gen);
5550 }
5551 return(NULL);
5552 }
5553
mus_make_moving_average_with_initial_sum(int size,mus_float_t * line,mus_float_t sum)5554 mus_any *mus_make_moving_average_with_initial_sum(int size, mus_float_t *line, mus_float_t sum)
5555 {
5556 dly *gen;
5557 gen = (dly *)mus_make_delay(size, line, size, MUS_INTERP_NONE);
5558 if (gen)
5559 {
5560 gen->core = &MOVING_AVERAGE_CLASS;
5561 gen->xscl = sum;
5562 gen->yscl = 1.0 / (mus_float_t)size;
5563 return((mus_any *)gen);
5564 }
5565 return(NULL);
5566 }
5567
5568
5569 /* -------- moving-max -------- */
5570
mus_is_moving_max(mus_any * ptr)5571 bool mus_is_moving_max(mus_any *ptr)
5572 {
5573 return((ptr) &&
5574 (ptr->core->type == MUS_MOVING_MAX));
5575 }
5576
5577
mus_moving_max(mus_any * ptr,mus_float_t input)5578 mus_float_t mus_moving_max(mus_any *ptr, mus_float_t input)
5579 {
5580 dly *gen = (dly *)ptr;
5581 mus_float_t output, abs_input;
5582
5583 abs_input = fabs(input);
5584 output = mus_delay_unmodulated_noz(ptr, abs_input);
5585 if (abs_input >= gen->xscl)
5586 gen->xscl = abs_input;
5587 else
5588 {
5589 if (output >= gen->xscl)
5590 {
5591 uint32_t i;
5592 for (i = 0; i < gen->size; i++)
5593 if (gen->line[i] > abs_input)
5594 abs_input = gen->line[i];
5595 gen->xscl = abs_input;
5596 }
5597 }
5598 return(gen->xscl);
5599 }
5600
run_mus_moving_max(mus_any * ptr,mus_float_t input,mus_float_t unused)5601 static mus_float_t run_mus_moving_max(mus_any *ptr, mus_float_t input, mus_float_t unused) {return(mus_moving_max(ptr, input));}
5602
5603
moving_max_reset(mus_any * ptr)5604 static void moving_max_reset(mus_any *ptr)
5605 {
5606 dly *gen = (dly *)ptr;
5607 delay_reset(ptr);
5608 gen->xscl = 0.0;
5609 }
5610
5611
describe_moving_max(mus_any * ptr)5612 static char *describe_moving_max(mus_any *ptr)
5613 {
5614 char *str = NULL;
5615 dly *gen = (dly *)ptr;
5616 char *describe_buffer;
5617 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
5618 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s %.3f, line[%u]:%s",
5619 mus_name(ptr),
5620 gen->xscl,
5621 gen->size,
5622 str = float_array_to_string(gen->line, gen->size, gen->loc));
5623 if (str) free(str);
5624 return(describe_buffer);
5625 }
5626
5627
5628 static mus_any_class MOVING_MAX_CLASS = {
5629 MUS_MOVING_MAX,
5630 (char *)S_moving_max,
5631 &free_delay,
5632 &describe_moving_max,
5633 &delay_equalp,
5634 &delay_data,
5635 &delay_set_data,
5636 &delay_length,
5637 &delay_set_length,
5638 0, 0, 0, 0, /* freq phase */
5639 &delay_scaler,
5640 &delay_set_scaler,
5641 &delay_fb,
5642 &delay_set_fb,
5643 &run_mus_moving_max,
5644 MUS_DELAY_LINE,
5645 NULL, 0,
5646 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5647 0, 0, 0, 0,
5648 &delay_loc,
5649 0, 0,
5650 0, 0, 0, 0,
5651 &moving_max_reset,
5652 0, &dly_copy
5653 };
5654
5655
mus_make_moving_max(int size,mus_float_t * line)5656 mus_any *mus_make_moving_max(int size, mus_float_t *line)
5657 {
5658 dly *gen;
5659 gen = (dly *)mus_make_delay(size, line, size, MUS_INTERP_NONE);
5660 if (gen)
5661 {
5662 int i;
5663 gen->core = &MOVING_MAX_CLASS;
5664 gen->xscl = 0.0;
5665 for (i = 0; i < size; i++)
5666 if (fabs(gen->line[i]) > gen->xscl)
5667 gen->xscl = fabs(gen->line[i]);
5668 return((mus_any *)gen);
5669 }
5670 return(NULL);
5671 }
5672
5673
5674 /* -------- moving-norm -------- */
5675
mus_is_moving_norm(mus_any * ptr)5676 bool mus_is_moving_norm(mus_any *ptr)
5677 {
5678 return((ptr) &&
5679 (ptr->core->type == MUS_MOVING_NORM));
5680 }
5681
5682
mus_moving_norm(mus_any * ptr,mus_float_t input)5683 mus_float_t mus_moving_norm(mus_any *ptr, mus_float_t input)
5684 {
5685 dly *gen = (dly *)ptr;
5686 mus_float_t output, abs_input;
5687
5688 abs_input = fabs(input);
5689 if (abs_input < 0.01) abs_input = 0.01; /* 0.01 sets the max norm output (~100) -- maybe a parameter to make-norm? */
5690 output = mus_moving_max(ptr, abs_input);
5691 gen->y1 = output + (gen->yscl * gen->y1);
5692
5693 return(gen->norm / gen->y1);
5694 }
5695
moving_norm_norm(mus_any * ptr)5696 static mus_float_t moving_norm_norm(mus_any *ptr)
5697 {
5698 dly *gen = (dly *)ptr;
5699 return(gen->norm / (gen->size + 1.0));
5700 }
5701
run_mus_moving_norm(mus_any * ptr,mus_float_t input,mus_float_t unused)5702 static mus_float_t run_mus_moving_norm(mus_any *ptr, mus_float_t input, mus_float_t unused) {return(mus_moving_norm(ptr, input));}
5703
5704
moving_norm_reset(mus_any * ptr)5705 static void moving_norm_reset(mus_any *ptr)
5706 {
5707 dly *gen = (dly *)ptr;
5708 delay_reset(ptr);
5709 gen->xscl = 0.0;
5710 gen->y1 = 0.0;
5711 }
5712
5713
describe_moving_norm(mus_any * ptr)5714 static char *describe_moving_norm(mus_any *ptr)
5715 {
5716 char *str = NULL;
5717 dly *gen = (dly *)ptr;
5718 char *describe_buffer;
5719 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
5720 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s, max %.3f, y1 %.3f, weight %.3f, line[%u]:%s",
5721 mus_name(ptr),
5722 gen->xscl, gen->y1, gen->yscl,
5723 gen->size,
5724 str = float_array_to_string(gen->line, gen->size, gen->loc));
5725 if (str) free(str);
5726 return(describe_buffer);
5727 }
5728
5729
5730 static mus_any_class MOVING_NORM_CLASS = {
5731 MUS_MOVING_NORM,
5732 (char *)S_moving_norm,
5733 &free_delay,
5734 &describe_moving_norm,
5735 &delay_equalp,
5736 &delay_data,
5737 &delay_set_data,
5738 &delay_length,
5739 &delay_set_length,
5740 0, 0, 0, 0, /* freq phase */
5741 &delay_scaler,
5742 &delay_set_scaler,
5743 &delay_fb,
5744 &delay_set_fb,
5745 &run_mus_moving_norm,
5746 MUS_DELAY_LINE,
5747 NULL, 0,
5748 &moving_norm_norm, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5749 0, 0, 0, 0,
5750 &delay_loc,
5751 0, 0,
5752 0, 0, 0, 0,
5753 &moving_norm_reset,
5754 0, &dly_copy
5755 };
5756
5757
mus_make_moving_norm(int size,mus_float_t * line,mus_float_t norm)5758 mus_any *mus_make_moving_norm(int size, mus_float_t *line, mus_float_t norm)
5759 {
5760 dly *gen;
5761 gen = (dly *)mus_make_moving_max(size, line);
5762 if (gen)
5763 {
5764 gen->core = &MOVING_NORM_CLASS;
5765
5766 gen->yscl = (mus_float_t)size / (size + 1.0); /* one-pole -b1 = -feedback so this is a lowpass filter */
5767 gen->norm = norm * (size + 1.0);
5768 gen->yn1 = 1.0 / size;
5769 gen->y1 = size + 1.0;
5770
5771 return((mus_any *)gen);
5772 }
5773 return(NULL);
5774 }
5775
5776
5777
5778
5779
5780 /* ---------------------------------------- filtered-comb ---------------------------------------- */
5781
filtered_comb_reset(mus_any * ptr)5782 static void filtered_comb_reset(mus_any *ptr)
5783 {
5784 dly *fc = (dly *)ptr;
5785 delay_reset(ptr);
5786 mus_reset(fc->filt);
5787 }
5788
5789
filtered_comb_equalp(mus_any * p1,mus_any * p2)5790 static bool filtered_comb_equalp(mus_any *p1, mus_any *p2)
5791 {
5792 return((delay_equalp(p1, p2)) &&
5793 (mus_equalp(((dly *)p1)->filt,
5794 ((dly *)p2)->filt)));
5795 }
5796
5797
describe_filtered_comb(mus_any * ptr)5798 static char *describe_filtered_comb(mus_any *ptr)
5799 {
5800 char *comb_str, *filter_str, *res;
5801 int len;
5802 comb_str = describe_comb(ptr);
5803 filter_str = mus_describe(((dly *)ptr)->filt);
5804 len = strlen(comb_str) + ((filter_str) ? strlen(filter_str) : 0) + 64;
5805 res = (char *)malloc(len * sizeof(char));
5806 if (filter_str)
5807 snprintf(res, len, "%s, filter: [%s]", comb_str, filter_str);
5808 else snprintf(res, len, "%s, filter: none?", comb_str);
5809 if (comb_str) free(comb_str);
5810 if (filter_str) free(filter_str);
5811 return(res);
5812 }
5813
5814
mus_is_filtered_comb(mus_any * ptr)5815 bool mus_is_filtered_comb(mus_any *ptr)
5816 {
5817 return((ptr) &&
5818 (ptr->core->type == MUS_FILTERED_COMB));
5819 }
5820
5821
mus_filtered_comb(mus_any * ptr,mus_float_t input,mus_float_t pm)5822 mus_float_t mus_filtered_comb(mus_any *ptr, mus_float_t input, mus_float_t pm)
5823 {
5824 dly *fc = (dly *)ptr;
5825 if (fc->zdly)
5826 return(mus_delay(ptr,
5827 input + (fc->yscl *
5828 fc->runf(fc->filt,
5829 mus_tap(ptr, pm),
5830 0.0)),
5831 pm));
5832 return(mus_delay_unmodulated(ptr,
5833 input + (fc->yscl *
5834 fc->runf(fc->filt, fc->line[fc->loc], 0.0))));
5835 }
5836
5837
mus_filtered_comb_unmodulated(mus_any * ptr,mus_float_t input)5838 mus_float_t mus_filtered_comb_unmodulated(mus_any *ptr, mus_float_t input)
5839 {
5840 dly *fc = (dly *)ptr;
5841 return(mus_delay_unmodulated(ptr,
5842 input + (fc->yscl *
5843 fc->runf(fc->filt, fc->line[fc->loc], 0.0))));
5844 }
5845
5846
5847 static mus_any_class FILTERED_COMB_CLASS = {
5848 MUS_FILTERED_COMB,
5849 (char *)S_filtered_comb,
5850 &free_delay,
5851 &describe_filtered_comb,
5852 &filtered_comb_equalp,
5853 &delay_data,
5854 &delay_set_data,
5855 &delay_length,
5856 &delay_set_length,
5857 0, 0, 0, 0, /* freq phase */
5858 &delay_scaler,
5859 &delay_set_scaler,
5860 &delay_fb,
5861 &delay_set_fb,
5862 &mus_filtered_comb,
5863 MUS_DELAY_LINE,
5864 NULL,
5865 &delay_interp_type,
5866 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5867 0, 0, 0, 0,
5868 &delay_loc,
5869 0, 0,
5870 0, 0, 0, 0,
5871 &filtered_comb_reset,
5872 0, &dly_copy
5873 };
5874
5875
mus_make_filtered_comb(mus_float_t scaler,int size,mus_float_t * line,int line_size,mus_interp_t type,mus_any * filt)5876 mus_any *mus_make_filtered_comb(mus_float_t scaler, int size, mus_float_t *line, int line_size, mus_interp_t type, mus_any *filt)
5877 {
5878 dly *fc;
5879 fc = (dly *)mus_make_comb(scaler, size, line, line_size, type);
5880 if (fc)
5881 {
5882 fc->core = &FILTERED_COMB_CLASS;
5883 if (filt)
5884 fc->filt = filt;
5885 else
5886 {
5887 fc->filt = mus_make_one_zero(1.0, 0.0);
5888 fc->filt_allocated = true;
5889 }
5890 fc->runf = mus_run_function(fc->filt);
5891 return((mus_any *)fc);
5892 }
5893 else return(NULL);
5894 }
5895
5896
5897 /* ---------------- filtered-comb-bank ---------------- */
5898
5899 typedef struct {
5900 mus_any_class *core;
5901 int size;
5902 mus_any **gens;
5903 mus_float_t (*cmbf)(mus_any *ptr, mus_float_t input);
5904 } fltcmb_bank;
5905
5906
free_filtered_comb_bank(mus_any * ptr)5907 static void free_filtered_comb_bank(mus_any *ptr)
5908 {
5909 fltcmb_bank *f = (fltcmb_bank *)ptr;
5910 if (f->gens) {free(f->gens); f->gens = NULL;}
5911 free(ptr);
5912 }
5913
5914
fltcmb_bank_copy(mus_any * ptr)5915 static mus_any *fltcmb_bank_copy(mus_any *ptr)
5916 {
5917 fltcmb_bank *g, *p;
5918 int i;
5919
5920 p = (fltcmb_bank *)ptr;
5921 g = (fltcmb_bank *)malloc(sizeof(fltcmb_bank));
5922 memcpy((void *)g, (void *)ptr, sizeof(fltcmb_bank));
5923 g->gens = (mus_any **)malloc(p->size * sizeof(mus_any *));
5924 for (i = 0; i < p->size; i++)
5925 g->gens[i] = mus_copy(p->gens[i]);
5926
5927 return((mus_any *)g);
5928 }
5929
5930
run_filtered_comb_bank(mus_any * ptr,mus_float_t input,mus_float_t unused)5931 static mus_float_t run_filtered_comb_bank(mus_any *ptr, mus_float_t input, mus_float_t unused)
5932 {
5933 return(mus_filtered_comb_bank(ptr, input));
5934 }
5935
5936
filtered_comb_bank_length(mus_any * ptr)5937 static mus_long_t filtered_comb_bank_length(mus_any *ptr)
5938 {
5939 return(((fltcmb_bank *)ptr)->size);
5940 }
5941
5942
filtered_comb_bank_reset(mus_any * ptr)5943 static void filtered_comb_bank_reset(mus_any *ptr)
5944 {
5945 fltcmb_bank *f = (fltcmb_bank *)ptr;
5946 int i;
5947 for (i = 0; i < f->size; i++)
5948 mus_reset(f->gens[i]);
5949 }
5950
5951
filtered_comb_bank_equalp(mus_any * p1,mus_any * p2)5952 static bool filtered_comb_bank_equalp(mus_any *p1, mus_any *p2)
5953 {
5954 fltcmb_bank *f1 = (fltcmb_bank *)p1;
5955 fltcmb_bank *f2 = (fltcmb_bank *)p2;
5956 int i, size;
5957
5958 if (f1 == f2) return(true);
5959 if (f1->size != f2->size) return(false);
5960 size = f1->size;
5961
5962 for (i = 0; i < size; i++)
5963 if (!filtered_comb_equalp(f1->gens[i], f2->gens[i]))
5964 return(false);
5965
5966 return(true);
5967 }
5968
5969
describe_filtered_comb_bank(mus_any * ptr)5970 static char *describe_filtered_comb_bank(mus_any *ptr)
5971 {
5972 fltcmb_bank *gen = (fltcmb_bank *)ptr;
5973 char *describe_buffer;
5974 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
5975 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s size: %d",
5976 mus_name(ptr),
5977 gen->size);
5978 return(describe_buffer);
5979 }
5980
5981 static mus_any_class FILTERED_COMB_BANK_CLASS = {
5982 MUS_FILTERED_COMB_BANK,
5983 (char *)S_filtered_comb_bank,
5984 &free_filtered_comb_bank,
5985 &describe_filtered_comb_bank,
5986 &filtered_comb_bank_equalp,
5987 0, 0,
5988 &filtered_comb_bank_length, 0,
5989 0, 0,
5990 0, 0,
5991 0, 0,
5992 0, 0,
5993 &run_filtered_comb_bank,
5994 MUS_NOT_SPECIAL,
5995 NULL, 0,
5996 0, 0, 0, 0,
5997 0, 0,
5998 0, 0, 0, 0,
5999 0, 0, 0, 0, 0, 0, 0,
6000 0, 0, 0, 0,
6001 &filtered_comb_bank_reset,
6002 0, &fltcmb_bank_copy
6003 };
6004
6005
filtered_comb_one_zero(mus_any * ptr,mus_float_t input)6006 static mus_float_t filtered_comb_one_zero(mus_any *ptr, mus_float_t input)
6007 {
6008 dly *gen = (dly *)ptr;
6009 mus_float_t result;
6010 result = gen->line[gen->loc];
6011 gen->line[gen->loc] = input + mus_one_zero(gen->filt, result); /* gen->yscl folded into one_zero coeffs via smp_scl */
6012 gen->loc++;
6013 if (gen->loc >= gen->size)
6014 gen->loc = 0;
6015 return(result);
6016 }
6017
6018
filtered_comb_bank_8(mus_any * combs,mus_float_t inval)6019 static mus_float_t filtered_comb_bank_8(mus_any *combs, mus_float_t inval)
6020 {
6021 fltcmb_bank *c = (fltcmb_bank *)combs;
6022 mus_any **gs;
6023 gs = c->gens;
6024 return(filtered_comb_one_zero(gs[0], inval) +
6025 filtered_comb_one_zero(gs[1], inval) +
6026 filtered_comb_one_zero(gs[2], inval) +
6027 filtered_comb_one_zero(gs[3], inval) +
6028 filtered_comb_one_zero(gs[4], inval) +
6029 filtered_comb_one_zero(gs[5], inval) +
6030 filtered_comb_one_zero(gs[6], inval) +
6031 filtered_comb_one_zero(gs[7], inval));
6032 }
6033
filtered_comb_bank_any(mus_any * filtered_combs,mus_float_t inval)6034 static mus_float_t filtered_comb_bank_any(mus_any *filtered_combs, mus_float_t inval)
6035 {
6036 int i;
6037 mus_float_t sum = 0.0;
6038 fltcmb_bank *c = (fltcmb_bank *)filtered_combs;
6039 for (i = 0; i < c->size; i++)
6040 sum += mus_filtered_comb_unmodulated(c->gens[i], inval);
6041 return(sum);
6042 }
6043
6044 static void smp_scl(mus_any *ptr, mus_float_t scl);
6045
mus_make_filtered_comb_bank(int size,mus_any ** filtered_combs)6046 mus_any *mus_make_filtered_comb_bank(int size, mus_any **filtered_combs)
6047 {
6048 fltcmb_bank *gen;
6049 int i;
6050 bool zdly = false, oz = true;
6051
6052 gen = (fltcmb_bank *)malloc(sizeof(fltcmb_bank));
6053 gen->core = &FILTERED_COMB_BANK_CLASS;
6054 gen->size = size;
6055
6056 gen->gens = (mus_any **)malloc(size * sizeof(mus_any *));
6057 for (i = 0; i < size; i++)
6058 {
6059 gen->gens[i] = filtered_combs[i];
6060 zdly = (zdly) || (((dly *)(filtered_combs[i]))->zdly);
6061 oz = (oz) && (mus_is_one_zero(((dly *)(filtered_combs[i]))->filt));
6062 }
6063
6064 if ((size == 8) &&
6065 (oz) &&
6066 (!zdly))
6067 {
6068 gen->cmbf = filtered_comb_bank_8;
6069 for (i = 0; i < 8; i++)
6070 {
6071 dly *d;
6072 d = (dly *)gen->gens[i];
6073 smp_scl(d->filt, d->yscl);
6074 }
6075 }
6076 else gen->cmbf = filtered_comb_bank_any;
6077
6078 return((mus_any *)gen);
6079 }
6080
6081
mus_is_filtered_comb_bank(mus_any * ptr)6082 bool mus_is_filtered_comb_bank(mus_any *ptr)
6083 {
6084 return((ptr) &&
6085 (ptr->core->type == MUS_FILTERED_COMB_BANK));
6086 }
6087
6088
mus_filtered_comb_bank(mus_any * filtered_combs,mus_float_t inval)6089 mus_float_t mus_filtered_comb_bank(mus_any *filtered_combs, mus_float_t inval)
6090 {
6091 fltcmb_bank *gen = (fltcmb_bank *)filtered_combs;
6092 return((gen->cmbf)(filtered_combs, inval));
6093 }
6094
6095
mus_bank_generator(mus_any * g,int i)6096 mus_any *mus_bank_generator(mus_any *g, int i)
6097 {
6098 if (mus_is_comb_bank(g))
6099 return(((cmb_bank *)g)->gens[i]);
6100 if (mus_is_all_pass_bank(g))
6101 return(((allp_bank *)g)->gens[i]);
6102 if (mus_is_filtered_comb_bank(g))
6103 return(((fltcmb_bank *)g)->gens[i]);
6104 return(NULL);
6105 }
6106
6107
6108
6109
6110 /* ---------------- sawtooth et al ---------------- */
6111
6112 typedef struct {
6113 mus_any_class *core;
6114 mus_float_t current_value;
6115 mus_float_t freq, phase, base, width;
6116 } sw;
6117
6118
free_sw(mus_any * ptr)6119 static void free_sw(mus_any *ptr) {free(ptr);}
6120
sw_copy(mus_any * ptr)6121 static mus_any *sw_copy(mus_any *ptr)
6122 {
6123 sw *g;
6124 g = (sw *)malloc(sizeof(sw));
6125 memcpy((void *)g, (void *)ptr, sizeof(sw));
6126 return((mus_any *)g);
6127 }
6128
6129
mus_sawtooth_wave(mus_any * ptr,mus_float_t fm)6130 mus_float_t mus_sawtooth_wave(mus_any *ptr, mus_float_t fm)
6131 {
6132 sw *gen = (sw *)ptr;
6133 mus_float_t result;
6134 result = gen->current_value;
6135 gen->phase += (gen->freq + fm);
6136 if ((gen->phase >= TWO_PI) || (gen->phase < 0.0))
6137 {
6138 gen->phase = fmod(gen->phase, TWO_PI);
6139 if (gen->phase < 0.0) gen->phase += TWO_PI;
6140 }
6141 gen->current_value = gen->base * (gen->phase - M_PI);
6142 return(result);
6143 }
6144
6145
run_sawtooth_wave(mus_any * ptr,mus_float_t fm,mus_float_t unused)6146 static mus_float_t run_sawtooth_wave(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_sawtooth_wave(ptr, fm));}
6147
mus_is_sawtooth_wave(mus_any * ptr)6148 bool mus_is_sawtooth_wave(mus_any *ptr)
6149 {
6150 return((ptr) &&
6151 (ptr->core->type == MUS_SAWTOOTH_WAVE));
6152 }
6153
6154
sw_freq(mus_any * ptr)6155 static mus_float_t sw_freq(mus_any *ptr) {return(mus_radians_to_hz(((sw *)ptr)->freq));}
sw_set_freq(mus_any * ptr,mus_float_t val)6156 static mus_float_t sw_set_freq(mus_any *ptr, mus_float_t val) {((sw *)ptr)->freq = mus_hz_to_radians(val); return(val);}
6157
sw_increment(mus_any * ptr)6158 static mus_float_t sw_increment(mus_any *ptr) {return(((sw *)ptr)->freq);}
sw_set_increment(mus_any * ptr,mus_float_t val)6159 static mus_float_t sw_set_increment(mus_any *ptr, mus_float_t val) {((sw *)ptr)->freq = val; return(val);}
6160
sw_phase(mus_any * ptr)6161 static mus_float_t sw_phase(mus_any *ptr) {return(fmod(((sw *)ptr)->phase, TWO_PI));}
sw_set_phase(mus_any * ptr,mus_float_t val)6162 static mus_float_t sw_set_phase(mus_any *ptr, mus_float_t val) {((sw *)ptr)->phase = val; return(val);}
6163
sw_width(mus_any * ptr)6164 static mus_float_t sw_width(mus_any *ptr) {return((((sw *)ptr)->width) / ( 2 * M_PI));}
sw_set_width(mus_any * ptr,mus_float_t val)6165 static mus_float_t sw_set_width(mus_any *ptr, mus_float_t val) {((sw *)ptr)->width = (2 * M_PI * val); return(val);}
6166
sawtooth_scaler(mus_any * ptr)6167 static mus_float_t sawtooth_scaler(mus_any *ptr) {return(((sw *)ptr)->base * M_PI);}
sawtooth_set_scaler(mus_any * ptr,mus_float_t val)6168 static mus_float_t sawtooth_set_scaler(mus_any *ptr, mus_float_t val) {((sw *)ptr)->base = val / M_PI; return(val);}
6169
6170
sw_equalp(mus_any * p1,mus_any * p2)6171 static bool sw_equalp(mus_any *p1, mus_any *p2)
6172 {
6173 sw *s1, *s2;
6174 s1 = (sw *)p1;
6175 s2 = (sw *)p2;
6176 return((p1 == p2) ||
6177 ((s1) && (s2) &&
6178 (s1->core->type == s2->core->type) &&
6179 (s1->freq == s2->freq) &&
6180 (s1->phase == s2->phase) &&
6181 (s1->base == s2->base) &&
6182 (s1->current_value == s2->current_value)));
6183 }
6184
6185
describe_sw(mus_any * ptr)6186 static char *describe_sw(mus_any *ptr)
6187 {
6188 char *describe_buffer;
6189 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
6190 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, amp: %.3f",
6191 mus_name(ptr),
6192 mus_frequency(ptr),
6193 mus_phase(ptr),
6194 mus_scaler(ptr));
6195 return(describe_buffer);
6196 }
6197
6198
sawtooth_reset(mus_any * ptr)6199 static void sawtooth_reset(mus_any *ptr)
6200 {
6201 sw *gen = (sw *)ptr;
6202 gen->phase = M_PI;
6203 gen->current_value = 0.0;
6204 }
6205
6206
6207 static mus_any_class SAWTOOTH_WAVE_CLASS = {
6208 MUS_SAWTOOTH_WAVE,
6209 (char *)S_sawtooth_wave,
6210 &free_sw,
6211 &describe_sw,
6212 &sw_equalp,
6213 0, 0, 0, 0,
6214 &sw_freq,
6215 &sw_set_freq,
6216 &sw_phase,
6217 &sw_set_phase,
6218 &sawtooth_scaler,
6219 &sawtooth_set_scaler,
6220 &sw_increment,
6221 &sw_set_increment,
6222 &run_sawtooth_wave,
6223 MUS_NOT_SPECIAL,
6224 NULL, 0,
6225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6226 0, 0, 0, 0, 0, 0, 0,
6227 0, 0, 0, 0,
6228 &sawtooth_reset,
6229 0, &sw_copy
6230 };
6231
6232
mus_make_sawtooth_wave(mus_float_t freq,mus_float_t amp,mus_float_t phase)6233 mus_any *mus_make_sawtooth_wave(mus_float_t freq, mus_float_t amp, mus_float_t phase) /* M_PI as initial phase, normally */
6234 {
6235 sw *gen;
6236 gen = (sw *)malloc(sizeof(sw));
6237 gen->core = &SAWTOOTH_WAVE_CLASS;
6238 gen->freq = mus_hz_to_radians(freq);
6239 gen->base = (amp / M_PI);
6240 gen->phase = phase;
6241 gen->current_value = gen->base * (gen->phase - M_PI);
6242 return((mus_any *)gen);
6243 }
6244
6245
mus_square_wave(mus_any * ptr,mus_float_t fm)6246 mus_float_t mus_square_wave(mus_any *ptr, mus_float_t fm)
6247 {
6248 sw *gen = (sw *)ptr;
6249 mus_float_t result;
6250 result = gen->current_value;
6251 gen->phase += (gen->freq + fm);
6252 if ((gen->phase >= TWO_PI) || (gen->phase < 0.0))
6253 {
6254 gen->phase = fmod(gen->phase, TWO_PI);
6255 if (gen->phase < 0.0) gen->phase += TWO_PI;
6256 }
6257 if (gen->phase < gen->width)
6258 gen->current_value = gen->base;
6259 else gen->current_value = 0.0;
6260 return(result);
6261 }
6262
6263
mus_is_square_wave(mus_any * ptr)6264 bool mus_is_square_wave(mus_any *ptr)
6265 {
6266 return((ptr) &&
6267 (ptr->core->type == MUS_SQUARE_WAVE));
6268 }
6269
6270
run_square_wave(mus_any * ptr,mus_float_t fm,mus_float_t unused)6271 static mus_float_t run_square_wave(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_square_wave(ptr, fm));}
6272
square_wave_scaler(mus_any * ptr)6273 static mus_float_t square_wave_scaler(mus_any *ptr) {return(((sw *)ptr)->base);}
square_wave_set_scaler(mus_any * ptr,mus_float_t val)6274 static mus_float_t square_wave_set_scaler(mus_any *ptr, mus_float_t val) {((sw *)ptr)->base = val; return(val);}
6275
6276
square_wave_reset(mus_any * ptr)6277 static void square_wave_reset(mus_any *ptr)
6278 {
6279 sw *gen = (sw *)ptr;
6280 gen->phase = 0.0;
6281 gen->current_value = gen->base;
6282 }
6283
6284
6285 static mus_any_class SQUARE_WAVE_CLASS = {
6286 MUS_SQUARE_WAVE,
6287 (char *)S_square_wave,
6288 &free_sw,
6289 &describe_sw,
6290 &sw_equalp,
6291 0, 0, 0, 0,
6292 &sw_freq,
6293 &sw_set_freq,
6294 &sw_phase,
6295 &sw_set_phase,
6296 &square_wave_scaler,
6297 &square_wave_set_scaler,
6298 &sw_increment,
6299 &sw_set_increment,
6300 &run_square_wave,
6301 MUS_NOT_SPECIAL,
6302 NULL, 0,
6303 0, 0,
6304 &sw_width, &sw_set_width,
6305 0, 0,
6306 0, 0, 0, 0,
6307 0, 0, 0, 0, 0, 0, 0,
6308 0, 0, 0, 0,
6309 &square_wave_reset,
6310 0, &sw_copy
6311 };
6312
6313
mus_make_square_wave(mus_float_t freq,mus_float_t amp,mus_float_t phase)6314 mus_any *mus_make_square_wave(mus_float_t freq, mus_float_t amp, mus_float_t phase)
6315 {
6316 sw *gen;
6317 gen = (sw *)malloc(sizeof(sw));
6318 gen->core = &SQUARE_WAVE_CLASS;
6319 gen->freq = mus_hz_to_radians(freq);
6320 gen->base = amp;
6321 gen->phase = phase;
6322 gen->width = M_PI;
6323 if (gen->phase < gen->width)
6324 gen->current_value = gen->base;
6325 else gen->current_value = 0.0;
6326 return((mus_any *)gen);
6327 }
6328
6329
mus_triangle_wave(mus_any * ptr,mus_float_t fm)6330 mus_float_t mus_triangle_wave(mus_any *ptr, mus_float_t fm)
6331 {
6332 sw *gen = (sw *)ptr;
6333 mus_float_t result;
6334
6335 result = gen->current_value;
6336 gen->phase += (gen->freq + fm);
6337 if ((gen->phase >= TWO_PI) || (gen->phase < 0.0))
6338 {
6339 gen->phase = fmod(gen->phase, TWO_PI);
6340 if (gen->phase < 0.0) gen->phase += TWO_PI;
6341 }
6342 if (gen->phase < (M_PI / 2.0))
6343 gen->current_value = gen->base * gen->phase;
6344 else
6345 if (gen->phase < (M_PI * 1.5))
6346 gen->current_value = gen->base * (M_PI - gen->phase);
6347 else gen->current_value = gen->base * (gen->phase - TWO_PI);
6348 return(result);
6349 }
6350
6351
mus_triangle_wave_unmodulated(mus_any * ptr)6352 mus_float_t mus_triangle_wave_unmodulated(mus_any *ptr)
6353 {
6354 sw *gen = (sw *)ptr;
6355 mus_float_t result;
6356
6357 result = gen->current_value;
6358 gen->phase += gen->freq;
6359 TRY_AGAIN:
6360 if (gen->phase < (M_PI / 2.0))
6361 gen->current_value = gen->base * gen->phase;
6362 else
6363 {
6364 if (gen->phase < (M_PI * 1.5))
6365 gen->current_value = gen->base * (M_PI - gen->phase);
6366 else
6367 {
6368 if (gen->phase < TWO_PI)
6369 gen->current_value = gen->base * (gen->phase - TWO_PI);
6370 else
6371 {
6372 gen->phase -= TWO_PI;
6373 goto TRY_AGAIN;
6374 }
6375 }
6376 }
6377 return(result);
6378 }
6379
6380
mus_is_triangle_wave(mus_any * ptr)6381 bool mus_is_triangle_wave(mus_any *ptr)
6382 {
6383 return((ptr) &&
6384 (ptr->core->type == MUS_TRIANGLE_WAVE));
6385 }
6386
6387
run_triangle_wave(mus_any * ptr,mus_float_t fm,mus_float_t unused)6388 static mus_float_t run_triangle_wave(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_triangle_wave(ptr, fm));}
6389
triangle_wave_scaler(mus_any * ptr)6390 static mus_float_t triangle_wave_scaler(mus_any *ptr) {return(((sw *)ptr)->base * M_PI_2);}
triangle_wave_set_scaler(mus_any * ptr,mus_float_t val)6391 static mus_float_t triangle_wave_set_scaler(mus_any *ptr, mus_float_t val) {((sw *)ptr)->base = (val * 2.0 / M_PI); return(val);}
6392
6393
triangle_wave_reset(mus_any * ptr)6394 static void triangle_wave_reset(mus_any *ptr)
6395 {
6396 sw *gen = (sw *)ptr;
6397 gen->phase = 0.0;
6398 gen->current_value = 0.0;
6399 }
6400
6401
6402 static mus_any_class TRIANGLE_WAVE_CLASS = {
6403 MUS_TRIANGLE_WAVE,
6404 (char *)S_triangle_wave,
6405 &free_sw,
6406 &describe_sw,
6407 &sw_equalp,
6408 0, 0, 0, 0,
6409 &sw_freq,
6410 &sw_set_freq,
6411 &sw_phase,
6412 &sw_set_phase,
6413 &triangle_wave_scaler,
6414 &triangle_wave_set_scaler,
6415 &sw_increment,
6416 &sw_set_increment,
6417 &run_triangle_wave,
6418 MUS_NOT_SPECIAL,
6419 NULL, 0,
6420 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6421 0, 0, 0, 0, 0, 0, 0,
6422 0, 0, 0, 0,
6423 &triangle_wave_reset,
6424 0, &sw_copy
6425 };
6426
6427
mus_make_triangle_wave(mus_float_t freq,mus_float_t amp,mus_float_t phase)6428 mus_any *mus_make_triangle_wave(mus_float_t freq, mus_float_t amp, mus_float_t phase)
6429 {
6430 sw *gen;
6431 gen = (sw *)malloc(sizeof(sw));
6432 gen->core = &TRIANGLE_WAVE_CLASS;
6433 if (freq < 0.0)
6434 {
6435 freq = -freq;
6436 phase += M_PI;
6437 if (phase > TWO_PI) phase -= TWO_PI;
6438 }
6439 gen->freq = mus_hz_to_radians(freq);
6440 gen->base = (2.0 * amp / M_PI);
6441 gen->phase = phase;
6442 if (gen->phase < M_PI_2)
6443 gen->current_value = gen->base * gen->phase;
6444 else
6445 if (gen->phase < (M_PI * 1.5))
6446 gen->current_value = gen->base * (M_PI - gen->phase);
6447 else gen->current_value = gen->base * (gen->phase - TWO_PI);
6448 return((mus_any *)gen);
6449 }
6450
6451
mus_pulse_train(mus_any * ptr,mus_float_t fm)6452 mus_float_t mus_pulse_train(mus_any *ptr, mus_float_t fm)
6453 {
6454 sw *gen = (sw *)ptr;
6455 if ((gen->phase >= TWO_PI) || (gen->phase < 0.0))
6456 {
6457 gen->phase = fmod(gen->phase, TWO_PI);
6458 if (gen->phase < 0.0) gen->phase += TWO_PI;
6459 gen->current_value = gen->base;
6460 }
6461 else gen->current_value = 0.0;
6462 gen->phase += (gen->freq + fm);
6463 return(gen->current_value);
6464 }
6465
6466
mus_pulse_train_unmodulated(mus_any * ptr)6467 mus_float_t mus_pulse_train_unmodulated(mus_any *ptr)
6468 {
6469 sw *gen = (sw *)ptr;
6470 /* here unfortunately, we might get any phase: (pulse-train p (+ (pulse-train p) -1.0))
6471 */
6472 if ((gen->phase >= TWO_PI) || (gen->phase < 0.0))
6473 {
6474 gen->phase = fmod(gen->phase, TWO_PI);
6475 if (gen->phase < 0.0) gen->phase += TWO_PI;
6476 gen->current_value = gen->base;
6477 }
6478 else gen->current_value = 0.0;
6479 gen->phase += gen->freq;
6480 return(gen->current_value);
6481 }
6482
6483
mus_is_pulse_train(mus_any * ptr)6484 bool mus_is_pulse_train(mus_any *ptr)
6485 {
6486 return((ptr) &&
6487 (ptr->core->type == MUS_PULSE_TRAIN));
6488 }
6489
6490
run_pulse_train(mus_any * ptr,mus_float_t fm,mus_float_t unused)6491 static mus_float_t run_pulse_train(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_pulse_train(ptr, fm));}
6492
pulse_train_scaler(mus_any * ptr)6493 static mus_float_t pulse_train_scaler(mus_any *ptr) {return(((sw *)ptr)->base);}
pulse_train_set_scaler(mus_any * ptr,mus_float_t val)6494 static mus_float_t pulse_train_set_scaler(mus_any *ptr, mus_float_t val) {((sw *)ptr)->base = val; return(val);}
6495
6496
pulse_train_reset(mus_any * ptr)6497 static void pulse_train_reset(mus_any *ptr)
6498 {
6499 sw *gen = (sw *)ptr;
6500 gen->phase = TWO_PI;
6501 gen->current_value = 0.0;
6502 }
6503
6504
6505 static mus_any_class PULSE_TRAIN_CLASS = {
6506 MUS_PULSE_TRAIN,
6507 (char *)S_pulse_train,
6508 &free_sw,
6509 &describe_sw,
6510 &sw_equalp,
6511 0, 0, 0, 0,
6512 &sw_freq,
6513 &sw_set_freq,
6514 &sw_phase,
6515 &sw_set_phase,
6516 &pulse_train_scaler,
6517 &pulse_train_set_scaler,
6518 &sw_increment,
6519 &sw_set_increment,
6520 &run_pulse_train,
6521 MUS_NOT_SPECIAL,
6522 NULL, 0,
6523 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6524 0, 0, 0, 0, 0, 0, 0,
6525 0, 0, 0, 0,
6526 &pulse_train_reset,
6527 0, &sw_copy
6528 };
6529
6530
mus_make_pulse_train(mus_float_t freq,mus_float_t amp,mus_float_t phase)6531 mus_any *mus_make_pulse_train(mus_float_t freq, mus_float_t amp, mus_float_t phase) /* TWO_PI initial phase, normally */
6532 {
6533 sw *gen;
6534 gen = (sw *)malloc(sizeof(sw));
6535 gen->core = &PULSE_TRAIN_CLASS;
6536 if (freq < 0.0) freq = -freq;
6537 gen->freq = mus_hz_to_radians(freq);
6538 gen->base = amp;
6539 gen->phase = phase;
6540 gen->current_value = 0.0;
6541 return((mus_any *)gen);
6542 }
6543
6544
6545
6546 /* ---------------- rand, rand_interp ---------------- */
6547
6548 typedef struct {
6549 mus_any_class *core;
6550 mus_float_t freq, phase, base, incr, norm;
6551 mus_float_t output;
6552 mus_float_t *distribution;
6553 int distribution_size;
6554 mus_float_t (*ran_unmod)(mus_any *ptr);
6555 } noi;
6556
6557
6558 /* rand taken from the ANSI C standard (essentially the same as the Cmix form used earlier) */
6559
6560 static uint64_t randx = 1;
6561 #define INVERSE_MAX_RAND 0.0000610351563
6562 #define INVERSE_MAX_RAND2 0.000030517579
6563
6564
mus_set_rand_seed(uint64_t val)6565 void mus_set_rand_seed(uint64_t val) {randx = val;}
6566
mus_rand_seed(void)6567 uint64_t mus_rand_seed(void) {return(randx);}
6568
6569
next_random(void)6570 static mus_float_t next_random(void)
6571 {
6572 randx = randx * 1103515245 + 12345;
6573 return((mus_float_t)((uint32_t)(randx >> 16) & 32767));
6574 }
6575
6576
mus_random(mus_float_t amp)6577 mus_float_t mus_random(mus_float_t amp) /* -amp to amp as mus_float_t */
6578 {
6579 return(amp * (next_random() * INVERSE_MAX_RAND - 1.0));
6580 }
6581
6582
mus_frandom(mus_float_t amp)6583 mus_float_t mus_frandom(mus_float_t amp) /* 0.0 to amp as mus_float_t */
6584 {
6585 return(amp * next_random() * INVERSE_MAX_RAND2);
6586 }
6587
6588
mus_irandom(int amp)6589 int mus_irandom(int amp)
6590 {
6591 return((int)(amp * next_random() * INVERSE_MAX_RAND2));
6592 }
6593
6594
random_any(noi * gen)6595 static mus_float_t random_any(noi *gen) /* -amp to amp possibly through distribution */
6596 {
6597 if (gen->distribution)
6598 return(gen->base * mus_array_interp(gen->distribution,
6599 next_random() * INVERSE_MAX_RAND2 * gen->distribution_size,
6600 gen->distribution_size));
6601 return(gen->base * (next_random() * INVERSE_MAX_RAND - 1.0));
6602 }
6603
6604
mus_rand(mus_any * ptr,mus_float_t fm)6605 mus_float_t mus_rand(mus_any *ptr, mus_float_t fm)
6606 {
6607 noi *gen = (noi *)ptr;
6608 if ((gen->phase >= TWO_PI) || (gen->phase < 0.0))
6609 {
6610 gen->phase = fmod(gen->phase, TWO_PI);
6611 if (gen->phase < 0.0) gen->phase += TWO_PI;
6612 gen->output = random_any(gen);
6613 }
6614 gen->phase += (gen->freq + fm);
6615 return(gen->output);
6616 }
6617
6618
zero_unmodulated(mus_any * ptr)6619 static mus_float_t zero_unmodulated(mus_any *ptr) {return(0.0);}
6620
mus_rand_unmodulated(mus_any * ptr)6621 mus_float_t mus_rand_unmodulated(mus_any *ptr)
6622 {
6623 noi *gen = (noi *)ptr;
6624 if (gen->phase >= TWO_PI)
6625 {
6626 gen->phase -= TWO_PI;
6627 gen->output = random_any(gen);
6628 }
6629 gen->phase += gen->freq;
6630 return(gen->output);
6631 }
6632
6633
mus_rand_interp(mus_any * ptr,mus_float_t fm)6634 mus_float_t mus_rand_interp(mus_any *ptr, mus_float_t fm)
6635 {
6636 /* fm can change the increment step during a ramp */
6637 noi *gen = (noi *)ptr;
6638 gen->output += gen->incr;
6639 if (gen->output > gen->base)
6640 gen->output = gen->base;
6641 else
6642 {
6643 if (gen->output < -gen->base)
6644 gen->output = -gen->base;
6645 }
6646 if ((gen->phase >= TWO_PI) || (gen->phase < 0.0))
6647 {
6648 double divisor;
6649 gen->phase = fmod(gen->phase, TWO_PI);
6650 if (gen->phase < 0.0) gen->phase += TWO_PI;
6651 gen->incr = random_any(gen) - gen->output;
6652 divisor = gen->freq + fm;
6653 if (divisor != 0.0)
6654 {
6655 divisor = ceil(TWO_PI / divisor);
6656 if (divisor != 0.0)
6657 gen->incr /= divisor;
6658 }
6659 }
6660 gen->phase += (gen->freq + fm);
6661 return(gen->output);
6662 }
6663
6664
mus_rand_interp_unmodulated(mus_any * ptr)6665 mus_float_t mus_rand_interp_unmodulated(mus_any *ptr)
6666 {
6667 return(((noi *)ptr)->ran_unmod(ptr));
6668 }
6669
6670
6671 mus_float_t (*mus_rand_interp_unmodulated_function(mus_any *g))(mus_any *gen);
mus_rand_interp_unmodulated_function(mus_any * g)6672 mus_float_t (*mus_rand_interp_unmodulated_function(mus_any *g))(mus_any *gen)
6673 {
6674 if (mus_is_rand_interp(g))
6675 return(((noi *)g)->ran_unmod);
6676 return(NULL);
6677 }
6678
rand_interp_unmodulated_with_distribution(mus_any * ptr)6679 static mus_float_t rand_interp_unmodulated_with_distribution(mus_any *ptr)
6680 {
6681 noi *gen = (noi *)ptr;
6682 gen->output += gen->incr;
6683 if (gen->phase >= TWO_PI)
6684 {
6685 gen->phase -= TWO_PI;
6686 gen->incr = (random_any(gen) - gen->output) * gen->norm;
6687 }
6688 gen->phase += gen->freq;
6689 return(gen->output);
6690 }
6691
6692
rand_interp_unmodulated(mus_any * ptr)6693 static mus_float_t rand_interp_unmodulated(mus_any *ptr)
6694 {
6695 noi *gen = (noi *)ptr;
6696 gen->output += gen->incr;
6697 gen->phase += gen->freq;
6698 if (gen->phase >= TWO_PI)
6699 {
6700 gen->phase -= TWO_PI;
6701 gen->incr = (mus_random(gen->base) - gen->output) * gen->norm;
6702 }
6703 return(gen->output);
6704 }
6705
6706
run_rand(mus_any * ptr,mus_float_t fm,mus_float_t unused)6707 static mus_float_t run_rand(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_rand(ptr, fm));}
run_rand_interp(mus_any * ptr,mus_float_t fm,mus_float_t unused)6708 static mus_float_t run_rand_interp(mus_any *ptr, mus_float_t fm, mus_float_t unused) {return(mus_rand_interp(ptr, fm));}
6709
6710
mus_is_rand(mus_any * ptr)6711 bool mus_is_rand(mus_any *ptr)
6712 {
6713 return((ptr) &&
6714 (ptr->core->type == MUS_RAND));
6715 }
6716
mus_is_rand_interp(mus_any * ptr)6717 bool mus_is_rand_interp(mus_any *ptr)
6718 {
6719 return((ptr) &&
6720 (ptr->core->type == MUS_RAND_INTERP));
6721 }
6722
6723
free_noi(mus_any * ptr)6724 static void free_noi(mus_any *ptr) {free(ptr);}
6725
noi_copy(mus_any * ptr)6726 static mus_any *noi_copy(mus_any *ptr)
6727 {
6728 noi *g;
6729 g = (noi *)malloc(sizeof(noi));
6730 memcpy((void *)g, (void *)ptr, sizeof(noi));
6731 /* if ptr->distribution, it comes from elsewhere -- we don't touch it here,
6732 * and in clm2xen, we merely wrap it.
6733 */
6734 return((mus_any *)g);
6735 }
6736
noi_freq(mus_any * ptr)6737 static mus_float_t noi_freq(mus_any *ptr) {return(mus_radians_to_hz(((noi *)ptr)->freq));}
noi_set_freq(mus_any * ptr,mus_float_t val)6738 static mus_float_t noi_set_freq(mus_any *ptr, mus_float_t val)
6739 {
6740 if (val < 0.0) val = -val;
6741 ((noi *)ptr)->freq = mus_hz_to_radians(val);
6742 return(val);
6743 }
6744
interp_noi_set_freq(mus_any * ptr,mus_float_t val)6745 static mus_float_t interp_noi_set_freq(mus_any *ptr, mus_float_t val)
6746 {
6747 noi *gen = (noi *)ptr;
6748 if (val < 0.0) val = -val;
6749 gen->freq = mus_hz_to_radians(val);
6750 if (gen->freq != 0.0)
6751 gen->norm = 1.0 / (ceil(TWO_PI / gen->freq));
6752 return(val);
6753 }
6754
noi_increment(mus_any * ptr)6755 static mus_float_t noi_increment(mus_any *ptr) {return(((noi *)ptr)->freq);}
noi_set_increment(mus_any * ptr,mus_float_t val)6756 static mus_float_t noi_set_increment(mus_any *ptr, mus_float_t val) {((noi *)ptr)->freq = val; return(val);}
6757
noi_incr(mus_any * ptr)6758 static mus_float_t noi_incr(mus_any *ptr) {return(((noi *)ptr)->incr);}
noi_set_incr(mus_any * ptr,mus_float_t val)6759 static mus_float_t noi_set_incr(mus_any *ptr, mus_float_t val) {((noi *)ptr)->incr = val; return(val);}
6760
noi_phase(mus_any * ptr)6761 static mus_float_t noi_phase(mus_any *ptr) {return(fmod(((noi *)ptr)->phase, TWO_PI));}
noi_set_phase(mus_any * ptr,mus_float_t val)6762 static mus_float_t noi_set_phase(mus_any *ptr, mus_float_t val) {((noi *)ptr)->phase = val; return(val);}
6763
noi_scaler(mus_any * ptr)6764 static mus_float_t noi_scaler(mus_any *ptr) {return(((noi *)ptr)->base);}
noi_set_scaler(mus_any * ptr,mus_float_t val)6765 static mus_float_t noi_set_scaler(mus_any *ptr, mus_float_t val) {((noi *)ptr)->base = val; return(val);} /* rand, not rand-interp */
6766
noi_data(mus_any * ptr)6767 static mus_float_t *noi_data(mus_any *ptr) {return(((noi *)ptr)->distribution);}
noi_length(mus_any * ptr)6768 static mus_long_t noi_length(mus_any *ptr) {return(((noi *)ptr)->distribution_size);}
6769
6770
randi_set_scaler(mus_any * ptr,mus_float_t val)6771 static mus_float_t randi_set_scaler(mus_any *ptr, mus_float_t val)
6772 {
6773 noi *gen = (noi *)ptr;
6774 if (val == 0.0)
6775 gen->ran_unmod = zero_unmodulated;
6776 else
6777 {
6778 if (gen->base == 0.0)
6779 {
6780 if (gen->distribution)
6781 gen->ran_unmod = rand_interp_unmodulated_with_distribution;
6782 else gen->ran_unmod = rand_interp_unmodulated;
6783 }
6784 }
6785 gen->base = val;
6786 return(val);
6787 }
6788
noi_reset(mus_any * ptr)6789 static void noi_reset(mus_any *ptr)
6790 {
6791 noi *gen = (noi *)ptr;
6792 gen->phase = TWO_PI; /* 2*pi is the trigger, otherwise value after mus-reset is always 0.0, as Tito Latini noticed */
6793 gen->output = mus_is_rand_interp(ptr) ? random_any(gen) - gen->incr : 0.0;
6794 }
6795
6796
noi_equalp(mus_any * p1,mus_any * p2)6797 static bool noi_equalp(mus_any *p1, mus_any *p2)
6798 {
6799 noi *g1 = (noi *)p1;
6800 noi *g2 = (noi *)p2;
6801 return((p1 == p2) ||
6802 ((g1) && (g2) &&
6803 (g1->core->type == g2->core->type) &&
6804 (g1->freq == g2->freq) &&
6805 (g1->phase == g2->phase) &&
6806 (g1->output == g2->output) &&
6807 (g1->incr == g2->incr) &&
6808 (g1->base == g2->base) &&
6809 (g1->distribution_size == g2->distribution_size) &&
6810 (g1->distribution == g2->distribution)));
6811 }
6812
6813
describe_noi(mus_any * ptr)6814 static char *describe_noi(mus_any *ptr)
6815 {
6816 noi *gen = (noi *)ptr;
6817 char *describe_buffer;
6818 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
6819 if (mus_is_rand(ptr))
6820 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, amp: %.3f%s",
6821 mus_name(ptr),
6822 mus_frequency(ptr),
6823 mus_phase(ptr),
6824 mus_scaler(ptr),
6825 (gen->distribution) ? ", with distribution envelope" : "");
6826 else
6827 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s freq: %.3fHz, phase: %.3f, amp: %.3f, incr: %.3f, curval: %.3f%s",
6828 mus_name(ptr),
6829 mus_frequency(ptr),
6830 mus_phase(ptr),
6831 mus_scaler(ptr),
6832 gen->incr,
6833 gen->output,
6834 (gen->distribution) ? ", with distribution envelope" : "");
6835 return(describe_buffer);
6836 }
6837
6838
6839 static mus_any_class RAND_CLASS = {
6840 MUS_RAND,
6841 (char *)S_rand,
6842 &free_noi,
6843 &describe_noi,
6844 &noi_equalp,
6845 &noi_data, 0,
6846 &noi_length, 0,
6847 &noi_freq,
6848 &noi_set_freq,
6849 &noi_phase,
6850 &noi_set_phase,
6851 &noi_scaler,
6852 &noi_set_scaler,
6853 &noi_increment, /* this is the phase increment, not the incr field */
6854 &noi_set_increment,
6855 &run_rand,
6856 MUS_NOT_SPECIAL,
6857 NULL, 0,
6858 &noi_incr, &noi_set_incr,
6859 0, 0, 0, 0, 0, 0, 0, 0,
6860 0, 0, 0, 0, 0, 0, 0,
6861 0, 0, 0, 0,
6862 &noi_reset,
6863 0, &noi_copy
6864 };
6865
6866
6867 static mus_any_class RAND_INTERP_CLASS = {
6868 MUS_RAND_INTERP,
6869 (char *)S_rand_interp,
6870 &free_noi,
6871 &describe_noi,
6872 &noi_equalp,
6873 &noi_data, 0,
6874 &noi_length, 0,
6875 &noi_freq,
6876 &interp_noi_set_freq,
6877 &noi_phase,
6878 &noi_set_phase,
6879 &noi_scaler,
6880 &randi_set_scaler,
6881 &noi_increment, /* phase increment, not incr field */
6882 &noi_set_increment,
6883 &run_rand_interp,
6884 MUS_NOT_SPECIAL,
6885 NULL, 0,
6886 &noi_incr, &noi_set_incr, /* incr field == mus_offset method */
6887 0, 0, 0, 0, 0, 0, 0, 0,
6888 0, 0, 0, 0, 0, 0, 0,
6889 0, 0, 0, 0,
6890 &noi_reset,
6891 0, &noi_copy
6892 };
6893
6894
mus_make_rand(mus_float_t freq,mus_float_t base)6895 mus_any *mus_make_rand(mus_float_t freq, mus_float_t base)
6896 {
6897 noi *gen;
6898 gen = (noi *)calloc(1, sizeof(noi));
6899 gen->core = &RAND_CLASS;
6900 if (freq < 0.0) freq = -freq;
6901 gen->freq = mus_hz_to_radians(freq);
6902 gen->base = base;
6903 gen->incr = 0.0;
6904 gen->output = mus_random(base); /* this was always starting at 0.0 (changed 23-Dec-06) */
6905 return((mus_any *)gen);
6906 }
6907
6908
mus_make_rand_with_distribution(mus_float_t freq,mus_float_t base,mus_float_t * distribution,int distribution_size)6909 mus_any *mus_make_rand_with_distribution(mus_float_t freq, mus_float_t base, mus_float_t *distribution, int distribution_size)
6910 {
6911 noi *gen;
6912 gen = (noi *)calloc(1, sizeof(noi));
6913 gen->core = &RAND_CLASS;
6914 gen->distribution = distribution;
6915 gen->distribution_size = distribution_size;
6916 if (freq < 0.0) freq = -freq;
6917 gen->freq = mus_hz_to_radians(freq);
6918 gen->base = base;
6919 gen->incr = 0.0;
6920 gen->output = random_any(gen);
6921 return((mus_any *)gen);
6922 }
6923
6924
mus_make_rand_interp(mus_float_t freq,mus_float_t base)6925 mus_any *mus_make_rand_interp(mus_float_t freq, mus_float_t base)
6926 {
6927 noi *gen;
6928 gen = (noi *)calloc(1, sizeof(noi));
6929 gen->core = &RAND_INTERP_CLASS;
6930 /* gen->distribution = NULL; */
6931 if (freq < 0.0) freq = -freq;
6932 gen->freq = mus_hz_to_radians(freq);
6933 gen->base = base;
6934 gen->output = mus_random(base);
6935 gen->incr = (mus_random(base) - gen->output) * freq / sampling_rate;
6936 gen->output -= gen->incr;
6937 if (gen->freq != 0.0)
6938 gen->norm = 1.0 / (ceil(TWO_PI / gen->freq));
6939 else gen->norm = 1.0;
6940 gen->ran_unmod = ((base == 0.0) ? zero_unmodulated : rand_interp_unmodulated);
6941 return((mus_any *)gen);
6942 }
6943
6944
mus_make_rand_interp_with_distribution(mus_float_t freq,mus_float_t base,mus_float_t * distribution,int distribution_size)6945 mus_any *mus_make_rand_interp_with_distribution(mus_float_t freq, mus_float_t base, mus_float_t *distribution, int distribution_size)
6946 {
6947 noi *gen;
6948 gen = (noi *)calloc(1, sizeof(noi));
6949 gen->core = &RAND_INTERP_CLASS;
6950 gen->distribution = distribution;
6951 gen->distribution_size = distribution_size;
6952 if (freq < 0.0) freq = -freq;
6953 gen->freq = mus_hz_to_radians(freq);
6954 gen->base = base;
6955 gen->output = random_any(gen);
6956 gen->incr = (random_any(gen) - gen->output) * freq / sampling_rate;
6957 gen->output -= gen->incr;
6958 if (gen->freq != 0.0)
6959 gen->norm = 1.0 / (ceil(TWO_PI / gen->freq));
6960 else gen->norm = 1.0;
6961 gen->ran_unmod = ((base == 0.0) ? zero_unmodulated : rand_interp_unmodulated_with_distribution);
6962 return((mus_any *)gen);
6963 }
6964
6965
6966
6967 /* ---------------- simple filters ---------------- */
6968
6969 typedef struct {
6970 mus_any_class *core;
6971 mus_float_t xs[3];
6972 mus_float_t ys[3];
6973 mus_float_t x1, x2, y1, y2;
6974 } smpflt;
6975
6976
free_smpflt(mus_any * ptr)6977 static void free_smpflt(mus_any *ptr) {free(ptr);}
6978
smpflt_copy(mus_any * ptr)6979 static mus_any *smpflt_copy(mus_any *ptr)
6980 {
6981 smpflt *g;
6982 g = (smpflt *)malloc(sizeof(smpflt));
6983 memcpy((void *)g, (void *)ptr, sizeof(smpflt));
6984 return((mus_any *)g);
6985 }
6986
6987
smpflt_equalp(mus_any * p1,mus_any * p2)6988 static bool smpflt_equalp(mus_any *p1, mus_any *p2)
6989 {
6990 smpflt *g1 = (smpflt *)p1;
6991 smpflt *g2 = (smpflt *)p2;
6992 return((p1 == p2) ||
6993 ((g1->core->type == g2->core->type) &&
6994 (g1->xs[0] == g2->xs[0]) &&
6995 (g1->xs[1] == g2->xs[1]) &&
6996 (g1->xs[2] == g2->xs[2]) &&
6997 (g1->ys[1] == g2->ys[1]) &&
6998 (g1->ys[2] == g2->ys[2]) &&
6999 (g1->x1 == g2->x1) &&
7000 (g1->x2 == g2->x2) &&
7001 (g1->y1 == g2->y1) &&
7002 (g1->y2 == g2->y2)));
7003 }
7004
7005
describe_smpflt(mus_any * ptr)7006 static char *describe_smpflt(mus_any *ptr)
7007 {
7008 smpflt *gen = (smpflt *)ptr;
7009 char *describe_buffer;
7010 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
7011 switch (gen->core->type)
7012 {
7013 case MUS_ONE_ZERO:
7014 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s a0: %.3f, a1: %.3f, x1: %.3f",
7015 mus_name(ptr),
7016 gen->xs[0], gen->xs[1], gen->x1);
7017 break;
7018
7019 case MUS_ONE_POLE:
7020 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s a0: %.3f, b1: %.3f, y1: %.3f",
7021 mus_name(ptr),
7022 gen->xs[0], gen->ys[1], gen->y1);
7023 break;
7024
7025 case MUS_TWO_ZERO:
7026 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s a0: %.3f, a1: %.3f, a2: %.3f, x1: %.3f, x2: %.3f",
7027 mus_name(ptr),
7028 gen->xs[0], gen->xs[1], gen->xs[2], gen->x1, gen->x2);
7029 break;
7030
7031 case MUS_TWO_POLE:
7032 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s a0: %.3f, b1: %.3f, b2: %.3f, y1: %.3f, y2: %.3f",
7033 mus_name(ptr),
7034 gen->xs[0], gen->ys[1], gen->ys[2], gen->y1, gen->y2);
7035 break;
7036 }
7037 return(describe_buffer);
7038 }
7039
7040
mus_one_zero(mus_any * ptr,mus_float_t input)7041 mus_float_t mus_one_zero(mus_any *ptr, mus_float_t input)
7042 {
7043 smpflt *gen = (smpflt *)ptr;
7044 mus_float_t result;
7045 result = (gen->xs[0] * input) + (gen->xs[1] * gen->x1);
7046 gen->x1 = input;
7047 return(result);
7048 }
7049
7050
run_one_zero(mus_any * ptr,mus_float_t input,mus_float_t unused)7051 static mus_float_t run_one_zero(mus_any *ptr, mus_float_t input, mus_float_t unused) {return(mus_one_zero(ptr, input));}
7052
one_length(mus_any * ptr)7053 static mus_long_t one_length(mus_any *ptr) {return(1);}
two_length(mus_any * ptr)7054 static mus_long_t two_length(mus_any *ptr) {return(2);}
7055
smp_xcoeff(mus_any * ptr,int index)7056 static mus_float_t smp_xcoeff(mus_any *ptr, int index) {return(((smpflt *)ptr)->xs[index]);}
smp_set_xcoeff(mus_any * ptr,int index,mus_float_t val)7057 static mus_float_t smp_set_xcoeff(mus_any *ptr, int index, mus_float_t val) {((smpflt *)ptr)->xs[index] = val; return(val);}
7058
smp_ycoeff(mus_any * ptr,int index)7059 static mus_float_t smp_ycoeff(mus_any *ptr, int index) {return(((smpflt *)ptr)->ys[index]);}
smp_set_ycoeff(mus_any * ptr,int index,mus_float_t val)7060 static mus_float_t smp_set_ycoeff(mus_any *ptr, int index, mus_float_t val) {((smpflt *)ptr)->ys[index] = val; return(val);}
7061
smp_xcoeffs(mus_any * ptr)7062 static mus_float_t *smp_xcoeffs(mus_any *ptr) {return(((smpflt *)ptr)->xs);}
smp_ycoeffs(mus_any * ptr)7063 static mus_float_t *smp_ycoeffs(mus_any *ptr) {return(((smpflt *)ptr)->ys);}
7064
smp_scl(mus_any * ptr,mus_float_t scl)7065 static void smp_scl(mus_any *ptr, mus_float_t scl) {smpflt *g = (smpflt *)ptr; g->xs[0] *= scl; g->xs[1] *= scl;}
7066
smpflt_reset(mus_any * ptr)7067 static void smpflt_reset(mus_any *ptr)
7068 {
7069 smpflt *gen = (smpflt *)ptr;
7070 gen->x1 = 0.0;
7071 gen->x2 = 0.0;
7072 gen->y1 = 0.0;
7073 gen->y2 = 0.0;
7074 }
7075
7076
7077 static mus_any_class ONE_ZERO_CLASS = {
7078 MUS_ONE_ZERO,
7079 (char *)S_one_zero,
7080 &free_smpflt,
7081 &describe_smpflt,
7082 &smpflt_equalp,
7083 0, 0,
7084 &one_length, 0,
7085 0, 0, 0, 0,
7086 0, 0,
7087 0, 0,
7088 &run_one_zero,
7089 MUS_SIMPLE_FILTER,
7090 NULL, 0,
7091 0, 0,
7092 0, 0,
7093 &smp_xcoeff, &smp_set_xcoeff,
7094 0, 0, 0, 0,
7095 0, 0, 0, 0, 0, 0, 0,
7096 0, 0,
7097 &smp_xcoeffs, &smp_ycoeffs,
7098 &smpflt_reset,
7099 0, &smpflt_copy
7100 };
7101
7102
mus_make_one_zero(mus_float_t a0,mus_float_t a1)7103 mus_any *mus_make_one_zero(mus_float_t a0, mus_float_t a1)
7104 {
7105 smpflt *gen;
7106 gen = (smpflt *)calloc(1, sizeof(smpflt));
7107 gen->core = &ONE_ZERO_CLASS;
7108 gen->xs[0] = a0;
7109 gen->xs[1] = a1;
7110 return((mus_any *)gen);
7111 }
7112
7113
mus_is_one_zero(mus_any * ptr)7114 bool mus_is_one_zero(mus_any *ptr)
7115 {
7116 return((ptr) &&
7117 (ptr->core->type == MUS_ONE_ZERO));
7118 }
7119
7120
mus_one_pole(mus_any * ptr,mus_float_t input)7121 mus_float_t mus_one_pole(mus_any *ptr, mus_float_t input)
7122 {
7123 smpflt *gen = (smpflt *)ptr;
7124 gen->y1 = (gen->xs[0] * input) - (gen->ys[1] * gen->y1);
7125 return(gen->y1);
7126 }
7127
7128 /* incrementer: (make-one-pole 1.0 -1.0) */
7129
run_one_pole(mus_any * ptr,mus_float_t input,mus_float_t unused)7130 static mus_float_t run_one_pole(mus_any *ptr, mus_float_t input, mus_float_t unused) {return(mus_one_pole(ptr, input));}
7131
7132
7133 static mus_any_class ONE_POLE_CLASS = {
7134 MUS_ONE_POLE,
7135 (char *)S_one_pole,
7136 &free_smpflt,
7137 &describe_smpflt,
7138 &smpflt_equalp,
7139 0, 0,
7140 &one_length, 0,
7141 0, 0, 0, 0,
7142 0, 0, 0, 0,
7143 &run_one_pole,
7144 MUS_SIMPLE_FILTER,
7145 NULL, 0,
7146 0, 0, 0, 0,
7147 &smp_xcoeff, &smp_set_xcoeff,
7148 0, 0, 0, 0,
7149 0, 0, 0, 0, 0, 0, 0,
7150 &smp_ycoeff, &smp_set_ycoeff,
7151 &smp_xcoeffs, &smp_ycoeffs,
7152 &smpflt_reset,
7153 0, &smpflt_copy
7154 };
7155
7156
mus_make_one_pole(mus_float_t a0,mus_float_t b1)7157 mus_any *mus_make_one_pole(mus_float_t a0, mus_float_t b1)
7158 {
7159 smpflt *gen;
7160 gen = (smpflt *)calloc(1, sizeof(smpflt));
7161 gen->core = &ONE_POLE_CLASS;
7162 gen->xs[0] = a0;
7163 gen->ys[1] = b1;
7164 return((mus_any *)gen);
7165 }
7166
7167
mus_is_one_pole(mus_any * ptr)7168 bool mus_is_one_pole(mus_any *ptr)
7169 {
7170 return((ptr) &&
7171 (ptr->core->type == MUS_ONE_POLE));
7172 }
7173
7174
mus_two_zero(mus_any * ptr,mus_float_t input)7175 mus_float_t mus_two_zero(mus_any *ptr, mus_float_t input)
7176 {
7177 smpflt *gen = (smpflt *)ptr;
7178 mus_float_t result;
7179 result = (gen->xs[0] * input) + (gen->xs[1] * gen->x1) + (gen->xs[2] * gen->x2);
7180 gen->x2 = gen->x1;
7181 gen->x1 = input;
7182 return(result);
7183 }
7184
7185
run_two_zero(mus_any * ptr,mus_float_t input,mus_float_t unused)7186 static mus_float_t run_two_zero(mus_any *ptr, mus_float_t input, mus_float_t unused) {return(mus_two_zero(ptr, input));}
7187
7188
two_zero_radius(mus_any * ptr)7189 static mus_float_t two_zero_radius(mus_any *ptr)
7190 {
7191 smpflt *gen = (smpflt *)ptr;
7192 return(sqrt(gen->xs[2]));
7193 }
7194
7195
two_zero_set_radius(mus_any * ptr,mus_float_t new_radius)7196 static mus_float_t two_zero_set_radius(mus_any *ptr, mus_float_t new_radius)
7197 {
7198 smpflt *gen = (smpflt *)ptr;
7199 gen->xs[1] = -2.0 * new_radius * cos(mus_hz_to_radians(mus_frequency(ptr)));
7200 gen->xs[2] = new_radius * new_radius;
7201 return(new_radius);
7202 }
7203
7204
two_zero_frequency(mus_any * ptr)7205 static mus_float_t two_zero_frequency(mus_any *ptr)
7206 {
7207 smpflt *gen = (smpflt *)ptr;
7208 if (two_zero_radius(ptr) == 0.0) return(0.0); /* or srate/2 */
7209 return(mus_radians_to_hz(acos(gen->xs[1] / (-2.0 * two_zero_radius(ptr)))));
7210 }
7211
7212
two_zero_set_frequency(mus_any * ptr,mus_float_t new_freq)7213 static mus_float_t two_zero_set_frequency(mus_any *ptr, mus_float_t new_freq)
7214 {
7215 smpflt *gen = (smpflt *)ptr;
7216 gen->xs[1] = -2.0 * mus_scaler(ptr) * cos(mus_hz_to_radians(new_freq));
7217 return(new_freq);
7218 }
7219
7220
7221 static mus_any_class TWO_ZERO_CLASS = {
7222 MUS_TWO_ZERO,
7223 (char *)S_two_zero,
7224 &free_smpflt,
7225 &describe_smpflt,
7226 &smpflt_equalp,
7227 0, 0,
7228 &two_length, 0,
7229 &two_zero_frequency, &two_zero_set_frequency,
7230 0, 0,
7231 &two_zero_radius, &two_zero_set_radius,
7232 0, 0,
7233 &run_two_zero,
7234 MUS_SIMPLE_FILTER,
7235 NULL, 0,
7236 0, 0, 0, 0,
7237 &smp_xcoeff, &smp_set_xcoeff,
7238 0, 0, 0, 0,
7239 0, 0, 0, 0, 0, 0, 0,
7240 0, 0,
7241 &smp_xcoeffs, &smp_ycoeffs,
7242 &smpflt_reset,
7243 0, &smpflt_copy
7244 };
7245
7246
mus_make_two_zero(mus_float_t a0,mus_float_t a1,mus_float_t a2)7247 mus_any *mus_make_two_zero(mus_float_t a0, mus_float_t a1, mus_float_t a2)
7248 {
7249 smpflt *gen;
7250 gen = (smpflt *)calloc(1, sizeof(smpflt));
7251 gen->core = &TWO_ZERO_CLASS;
7252 gen->xs[0] = a0;
7253 gen->xs[1] = a1;
7254 gen->xs[2] = a2;
7255 return((mus_any *)gen);
7256 }
7257
7258
mus_is_two_zero(mus_any * ptr)7259 bool mus_is_two_zero(mus_any *ptr)
7260 {
7261 return((ptr) &&
7262 (ptr->core->type == MUS_TWO_ZERO));
7263 }
7264
7265
mus_make_two_zero_from_frequency_and_radius(mus_float_t frequency,mus_float_t radius)7266 mus_any *mus_make_two_zero_from_frequency_and_radius(mus_float_t frequency, mus_float_t radius)
7267 {
7268 return(mus_make_two_zero(1.0, -2.0 * radius * cos(mus_hz_to_radians(frequency)), radius * radius));
7269 }
7270
7271
mus_two_pole(mus_any * ptr,mus_float_t input)7272 mus_float_t mus_two_pole(mus_any *ptr, mus_float_t input)
7273 {
7274 smpflt *gen = (smpflt *)ptr;
7275 mus_float_t result;
7276 result = (gen->xs[0] * input) - (gen->ys[1] * gen->y1) - (gen->ys[2] * gen->y2);
7277 gen->y2 = gen->y1;
7278 gen->y1 = result;
7279 return(result);
7280 }
7281
7282
run_two_pole(mus_any * ptr,mus_float_t input,mus_float_t unused)7283 static mus_float_t run_two_pole(mus_any *ptr, mus_float_t input, mus_float_t unused) {return(mus_two_pole(ptr, input));}
7284
7285
two_pole_radius(mus_any * ptr)7286 static mus_float_t two_pole_radius(mus_any *ptr)
7287 {
7288 smpflt *gen = (smpflt *)ptr;
7289 return(sqrt(gen->ys[2]));
7290 }
7291
7292
two_pole_set_radius(mus_any * ptr,mus_float_t new_radius)7293 static mus_float_t two_pole_set_radius(mus_any *ptr, mus_float_t new_radius)
7294 {
7295 smpflt *gen = (smpflt *)ptr;
7296 gen->ys[1] = -2.0 * new_radius * cos(mus_hz_to_radians(mus_frequency(ptr)));
7297 gen->ys[2] = new_radius * new_radius;
7298 return(new_radius);
7299 }
7300
7301
two_pole_frequency(mus_any * ptr)7302 static mus_float_t two_pole_frequency(mus_any *ptr)
7303 {
7304 smpflt *gen = (smpflt *)ptr;
7305 return(mus_radians_to_hz(acos(gen->ys[1] / (-2.0 * two_pole_radius(ptr)))));
7306 }
7307
7308
two_pole_set_frequency(mus_any * ptr,mus_float_t new_freq)7309 static mus_float_t two_pole_set_frequency(mus_any *ptr, mus_float_t new_freq)
7310 {
7311 smpflt *gen = (smpflt *)ptr;
7312 gen->ys[1] = -2.0 * mus_scaler(ptr) * cos(mus_hz_to_radians(new_freq));
7313 return(new_freq);
7314 }
7315
7316
7317 static mus_any_class TWO_POLE_CLASS = {
7318 MUS_TWO_POLE,
7319 (char *)S_two_pole,
7320 &free_smpflt,
7321 &describe_smpflt,
7322 &smpflt_equalp,
7323 0, 0,
7324 &two_length, 0,
7325 &two_pole_frequency, &two_pole_set_frequency,
7326 0, 0,
7327 &two_pole_radius, &two_pole_set_radius,
7328 0, 0,
7329 &run_two_pole,
7330 MUS_SIMPLE_FILTER,
7331 NULL, 0,
7332 0, 0, 0, 0,
7333 &smp_xcoeff, &smp_set_xcoeff,
7334 0, 0, 0, 0,
7335 0, 0, 0, 0, 0, 0, 0,
7336 &smp_ycoeff, &smp_set_ycoeff,
7337 &smp_xcoeffs, &smp_ycoeffs,
7338 &smpflt_reset,
7339 0, &smpflt_copy
7340 };
7341
7342
mus_make_two_pole(mus_float_t a0,mus_float_t b1,mus_float_t b2)7343 mus_any *mus_make_two_pole(mus_float_t a0, mus_float_t b1, mus_float_t b2)
7344 {
7345 smpflt *gen;
7346 gen = (smpflt *)calloc(1, sizeof(smpflt));
7347 gen->core = &TWO_POLE_CLASS;
7348 gen->xs[0] = a0;
7349 gen->ys[1] = b1;
7350 gen->ys[2] = b2;
7351 return((mus_any *)gen);
7352 }
7353
7354
mus_is_two_pole(mus_any * ptr)7355 bool mus_is_two_pole(mus_any *ptr)
7356 {
7357 return((ptr) &&
7358 (ptr->core->type == MUS_TWO_POLE));
7359 }
7360
7361
mus_make_two_pole_from_frequency_and_radius(mus_float_t frequency,mus_float_t radius)7362 mus_any *mus_make_two_pole_from_frequency_and_radius(mus_float_t frequency, mus_float_t radius)
7363 {
7364 return(mus_make_two_pole(1.0, -2.0 * radius * cos(mus_hz_to_radians(frequency)), radius * radius));
7365 }
7366
7367
7368
7369 /* ---------------- formant ---------------- */
7370
7371 typedef struct {
7372 mus_any_class *core;
7373 mus_float_t frequency, radius;
7374 mus_float_t x1, x2, y1, y2;
7375 mus_float_t rr, gain, fdbk;
7376 } frm;
7377
7378
free_frm(mus_any * ptr)7379 static void free_frm(mus_any *ptr) {free(ptr);}
7380
7381
frm_copy(mus_any * ptr)7382 static mus_any *frm_copy(mus_any *ptr)
7383 {
7384 frm *g;
7385 g = (frm *)malloc(sizeof(frm));
7386 memcpy((void *)g, (void *)ptr, sizeof(frm));
7387 return((mus_any *)g);
7388 }
7389
7390
mus_is_formant(mus_any * ptr)7391 bool mus_is_formant(mus_any *ptr)
7392 {
7393 return((ptr) &&
7394 (ptr->core->type == MUS_FORMANT));
7395 }
7396
7397
frm_reset(mus_any * ptr)7398 static void frm_reset(mus_any *ptr)
7399 {
7400 frm *gen = (frm *)ptr;
7401 gen->x1 = 0.0;
7402 gen->x2 = 0.0;
7403 gen->y1 = 0.0;
7404 gen->y2 = 0.0;
7405 }
7406
7407
frm_equalp(mus_any * p1,mus_any * p2)7408 static bool frm_equalp(mus_any *p1, mus_any *p2)
7409 {
7410 frm *g1 = (frm *)p1;
7411 frm *g2 = (frm *)p2;
7412 return((p1 == p2) ||
7413 ((g1->core->type == g2->core->type) &&
7414 (g1->radius == g2->radius) &&
7415 (g1->frequency == g2->frequency) &&
7416 (g1->x1 == g2->x1) &&
7417 (g1->x2 == g2->x2) &&
7418 (g1->y1 == g2->y1) &&
7419 (g1->y2 == g2->y2)));
7420 }
7421
7422
describe_formant(mus_any * ptr)7423 static char *describe_formant(mus_any *ptr)
7424 {
7425 frm *gen = (frm *)ptr;
7426 char *describe_buffer;
7427 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
7428 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s frequency: %.3f, radius: %.3f",
7429 mus_name(ptr),
7430 mus_radians_to_hz(gen->frequency),
7431 gen->radius);
7432 return(describe_buffer);
7433 }
7434
7435
mus_formant(mus_any * ptr,mus_float_t input)7436 mus_float_t mus_formant(mus_any *ptr, mus_float_t input)
7437 {
7438 frm *gen = (frm *)ptr;
7439 mus_float_t x0, y0;
7440 x0 = gen->gain * input;
7441 y0 = x0 - gen->x2 + (gen->fdbk * gen->y1) - (gen->rr * gen->y2);
7442 gen->y2 = gen->y1;
7443 gen->y1 = y0;
7444 gen->x2 = gen->x1;
7445 gen->x1 = x0;
7446 return(y0);
7447 }
7448
7449
run_formant(mus_any * ptr,mus_float_t input,mus_float_t unused)7450 static mus_float_t run_formant(mus_any *ptr, mus_float_t input, mus_float_t unused) {return(mus_formant(ptr, input));}
7451
7452
mus_set_formant_radius_and_frequency_in_radians(mus_any * ptr,mus_float_t radius,mus_float_t freq_in_radians)7453 static void mus_set_formant_radius_and_frequency_in_radians(mus_any *ptr, mus_float_t radius, mus_float_t freq_in_radians)
7454 {
7455 frm *gen = (frm *)ptr;
7456 gen->radius = radius;
7457 gen->frequency = freq_in_radians;
7458 gen->rr = radius * radius;
7459 gen->gain = (1.0 - gen->rr) * 0.5;
7460 gen->fdbk = 2.0 * radius * cos(freq_in_radians);
7461 }
7462
7463
mus_set_formant_radius_and_frequency(mus_any * ptr,mus_float_t radius,mus_float_t freq_in_hz)7464 void mus_set_formant_radius_and_frequency(mus_any *ptr, mus_float_t radius, mus_float_t freq_in_hz)
7465 {
7466 mus_set_formant_radius_and_frequency_in_radians(ptr, radius, mus_hz_to_radians(freq_in_hz));
7467 }
7468
7469
formant_frequency(mus_any * ptr)7470 static mus_float_t formant_frequency(mus_any *ptr) {return(mus_radians_to_hz(((frm *)ptr)->frequency));}
7471
mus_set_formant_frequency(mus_any * ptr,mus_float_t freq_in_hz)7472 mus_float_t mus_set_formant_frequency(mus_any *ptr, mus_float_t freq_in_hz)
7473 {
7474 frm *gen = (frm *)ptr;
7475 mus_float_t fw;
7476 fw = mus_hz_to_radians(freq_in_hz);
7477 gen->frequency = fw;
7478 gen->fdbk = 2.0 * gen->radius * cos(fw);
7479 return(freq_in_hz);
7480 }
7481
7482
mus_formant_with_frequency(mus_any * ptr,mus_float_t input,mus_float_t freq_in_radians)7483 mus_float_t mus_formant_with_frequency(mus_any *ptr, mus_float_t input, mus_float_t freq_in_radians)
7484 {
7485 frm *gen = (frm *)ptr;
7486 if (gen->frequency != freq_in_radians)
7487 {
7488 gen->frequency = freq_in_radians;
7489 gen->fdbk = 2.0 * gen->radius * cos(freq_in_radians);
7490 }
7491 return(mus_formant(ptr, input));
7492 }
7493
7494
formant_radius(mus_any * ptr)7495 static mus_float_t formant_radius(mus_any *ptr) {return(((frm *)ptr)->radius);}
7496
formant_set_radius(mus_any * ptr,mus_float_t val)7497 static mus_float_t formant_set_radius(mus_any *ptr, mus_float_t val)
7498 {
7499 mus_set_formant_radius_and_frequency_in_radians(ptr, val, ((frm *)ptr)->frequency);
7500 return(val);
7501 }
7502
7503
7504 static mus_any_class FORMANT_CLASS = {
7505 MUS_FORMANT,
7506 (char *)S_formant,
7507 &free_frm,
7508 &describe_formant,
7509 &frm_equalp,
7510 0, 0,
7511 &two_length, 0,
7512 &formant_frequency, &mus_set_formant_frequency,
7513 0, 0,
7514 &formant_radius, &formant_set_radius,
7515 0, 0,
7516 &run_formant,
7517 MUS_SIMPLE_FILTER,
7518 NULL, 0,
7519 0, 0, 0, 0,
7520 0, 0,
7521 0, 0, 0, 0,
7522 0, 0, 0, 0, 0, 0, 0,
7523 0, 0, 0, 0,
7524 &frm_reset,
7525 0, &frm_copy
7526 };
7527
7528
mus_make_formant(mus_float_t frequency,mus_float_t radius)7529 mus_any *mus_make_formant(mus_float_t frequency, mus_float_t radius)
7530 {
7531 frm *gen;
7532 gen = (frm *)calloc(1, sizeof(frm));
7533 gen->core = &FORMANT_CLASS;
7534 mus_set_formant_radius_and_frequency((mus_any *)gen, radius, frequency);
7535 return((mus_any *)gen);
7536 }
7537
7538
7539 /* ---------------- formant-bank ---------------- */
7540
7541 typedef struct {
7542 mus_any_class *core;
7543 int size, mctr;
7544 mus_float_t *x0, *x1, *x2, *y0, *y1, *y2, *amps, *rr, *fdbk, *gain;
7545 mus_float_t c1, c2;
7546 mus_float_t (*one_input)(mus_any *fbank, mus_float_t inval);
7547 mus_float_t (*many_inputs)(mus_any *fbank, mus_float_t *inval);
7548 } frm_bank;
7549
7550
free_formant_bank(mus_any * ptr)7551 static void free_formant_bank(mus_any *ptr)
7552 {
7553 frm_bank *f = (frm_bank *)ptr;
7554 if (f->x0) {free(f->x0); f->x0 = NULL;}
7555 if (f->x1) {free(f->x1); f->x1 = NULL;}
7556 if (f->x2) {free(f->x2); f->x2 = NULL;}
7557 if (f->y0) {free(f->y0); f->y0 = NULL;}
7558 if (f->y1) {free(f->y1); f->y1 = NULL;}
7559 if (f->y2) {free(f->y2); f->y2 = NULL;}
7560 if (f->rr) {free(f->rr); f->rr = NULL;}
7561 if (f->fdbk) {free(f->fdbk); f->fdbk = NULL;}
7562 if (f->gain) {free(f->gain); f->gain = NULL;}
7563 free(ptr);
7564 }
7565
frm_bank_copy(mus_any * ptr)7566 static mus_any *frm_bank_copy(mus_any *ptr)
7567 {
7568 frm_bank *g, *p;
7569 int bytes;
7570
7571 p = (frm_bank *)ptr;
7572 g = (frm_bank *)malloc(sizeof(frm_bank));
7573 memcpy((void *)g, (void *)ptr, sizeof(frm_bank));
7574 bytes = g->size * sizeof(mus_float_t);
7575
7576 g->x0 = (mus_float_t *)malloc(bytes);
7577 mus_copy_floats(g->x0, p->x0, g->size);
7578 g->x1 = (mus_float_t *)malloc(bytes);
7579 mus_copy_floats(g->x1, p->x1, g->size);
7580 g->x2 = (mus_float_t *)malloc(bytes);
7581 mus_copy_floats(g->x2, p->x2, g->size);
7582 g->y0 = (mus_float_t *)malloc(bytes);
7583 mus_copy_floats(g->y0, p->y0, g->size);
7584 g->y1 = (mus_float_t *)malloc(bytes);
7585 mus_copy_floats(g->y1, p->y1, g->size);
7586 g->y2 = (mus_float_t *)malloc(bytes);
7587 mus_copy_floats(g->y2, p->y2, g->size);
7588
7589 g->rr = (mus_float_t *)malloc(bytes);
7590 mus_copy_floats(g->rr, p->rr, g->size);
7591 g->fdbk = (mus_float_t *)malloc(bytes);
7592 mus_copy_floats(g->fdbk, p->fdbk, g->size);
7593 g->gain = (mus_float_t *)malloc(bytes);
7594 mus_copy_floats(g->gain, p->gain, g->size);
7595
7596 return((mus_any *)g);
7597 }
7598
run_formant_bank(mus_any * ptr,mus_float_t input,mus_float_t unused)7599 static mus_float_t run_formant_bank(mus_any *ptr, mus_float_t input, mus_float_t unused)
7600 {
7601 return(mus_formant_bank(ptr, input));
7602 }
7603
7604
formant_bank_length(mus_any * ptr)7605 static mus_long_t formant_bank_length(mus_any *ptr)
7606 {
7607 return(((frm_bank *)ptr)->size);
7608 }
7609
7610
formant_bank_reset(mus_any * ptr)7611 static void formant_bank_reset(mus_any *ptr)
7612 {
7613 frm_bank *f = (frm_bank *)ptr;
7614 mus_clear_floats((f->x0), f->size);
7615 mus_clear_floats((f->x1), f->size);
7616 mus_clear_floats((f->x2), f->size);
7617 mus_clear_floats((f->y0), f->size);
7618 mus_clear_floats((f->y1), f->size);
7619 mus_clear_floats((f->y2), f->size);
7620 }
7621
7622
formant_bank_equalp(mus_any * p1,mus_any * p2)7623 static bool formant_bank_equalp(mus_any *p1, mus_any *p2)
7624 {
7625 frm_bank *f1 = (frm_bank *)p1;
7626 frm_bank *f2 = (frm_bank *)p2;
7627 #if 0
7628 int i, size;
7629 #endif
7630 if (f1 == f2) return(true);
7631 if (f1->size != f2->size) return(false);
7632 #if 0
7633 size = f1->size;
7634 for (i = 0; i < size; i++)
7635 if (!frm_equalp(f1->gens[i], f2->gens[i]))
7636 return(false);
7637 #endif
7638 /* now check the locals... */
7639 return(true);
7640 }
7641
7642
describe_formant_bank(mus_any * ptr)7643 static char *describe_formant_bank(mus_any *ptr)
7644 {
7645 frm_bank *gen = (frm_bank *)ptr;
7646 char *describe_buffer;
7647 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
7648 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s size: %d", mus_name(ptr), gen->size);
7649 return(describe_buffer);
7650 }
7651
7652
mus_formant_bank(mus_any * fbank,mus_float_t inval)7653 mus_float_t mus_formant_bank(mus_any *fbank, mus_float_t inval)
7654 {
7655 frm_bank *bank = (frm_bank *)fbank;
7656 return(bank->one_input(fbank, inval));
7657 }
7658
mus_formant_bank_with_inputs(mus_any * fbank,mus_float_t * inval)7659 mus_float_t mus_formant_bank_with_inputs(mus_any *fbank, mus_float_t *inval)
7660 {
7661 frm_bank *bank = (frm_bank *)fbank;
7662 return(bank->many_inputs(fbank, inval));
7663 }
7664
7665
fb_one_with_amps(mus_any * fbank,mus_float_t inval)7666 static mus_float_t fb_one_with_amps(mus_any *fbank, mus_float_t inval)
7667 {
7668 frm_bank *bank = (frm_bank *)fbank;
7669 int i, size4;
7670 mus_float_t sum = 0.0;
7671 mus_float_t *x0, *x1, *x2, *y0, *y1, *y2, *amps, *rr, *fdbk, *gain;
7672
7673 x0 = bank->x0;
7674 x1 = bank->x1;
7675 x2 = bank->x2;
7676 y0 = bank->y0;
7677 y1 = bank->y1;
7678 y2 = bank->y2;
7679 rr = bank->rr;
7680 fdbk = bank->fdbk;
7681 gain = bank->gain;
7682 amps = bank->amps;
7683 size4 = bank->size - 4;
7684
7685 i = 0;
7686 while (i <= size4)
7687 {
7688 x0[i] = gain[i] * inval;
7689 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr[i] * y2[i]);
7690 sum += amps[i] * y0[i];
7691 i++;
7692
7693 x0[i] = gain[i] * inval;
7694 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr[i] * y2[i]);
7695 sum += amps[i] * y0[i];
7696 i++;
7697
7698 x0[i] = gain[i] * inval;
7699 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr[i] * y2[i]);
7700 sum += amps[i] * y0[i];
7701 i++;
7702
7703 x0[i] = gain[i] * inval;
7704 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr[i] * y2[i]);
7705 sum += amps[i] * y0[i];
7706 i++;
7707 }
7708 for (; i < bank->size; i++)
7709 {
7710 x0[i] = gain[i] * inval;
7711 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr[i] * y2[i]);
7712 sum += amps[i] * y0[i];
7713 }
7714
7715 bank->x2 = x1;
7716 bank->x1 = x0;
7717 bank->x0 = x2;
7718
7719 bank->y2 = y1;
7720 bank->y1 = y0;
7721 bank->y0 = y2;
7722
7723 return(sum);
7724 }
7725
fb_one_without_amps(mus_any * fbank,mus_float_t inval)7726 static mus_float_t fb_one_without_amps(mus_any *fbank, mus_float_t inval)
7727 {
7728 frm_bank *bank = (frm_bank *)fbank;
7729 int i;
7730 mus_float_t sum = 0.0;
7731 mus_float_t *x0, *x1, *x2, *y0, *y1, *y2, *rr, *fdbk, *gain;
7732
7733 x0 = bank->x0;
7734 x1 = bank->x1;
7735 x2 = bank->x2;
7736 y0 = bank->y0;
7737 y1 = bank->y1;
7738 y2 = bank->y2;
7739 rr = bank->rr;
7740 fdbk = bank->fdbk;
7741 gain = bank->gain;
7742
7743 for (i = 0; i < bank->size; i++)
7744 {
7745 x0[i] = gain[i] * inval;
7746 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr[i] * y2[i]);
7747 sum += y0[i];
7748 }
7749
7750 bank->x2 = x1;
7751 bank->x1 = x0;
7752 bank->x0 = x2;
7753
7754 bank->y2 = y1;
7755 bank->y1 = y0;
7756 bank->y0 = y2;
7757
7758 return(sum);
7759 }
7760
fb_many_with_amps(mus_any * fbank,mus_float_t * inval)7761 static mus_float_t fb_many_with_amps(mus_any *fbank, mus_float_t *inval)
7762 {
7763 frm_bank *bank = (frm_bank *)fbank;
7764 int i;
7765 mus_float_t sum = 0.0;
7766 mus_float_t *x0, *x1, *x2, *y0, *y1, *y2, *amps, *rr, *fdbk, *gain;
7767
7768 x0 = bank->x0;
7769 x1 = bank->x1;
7770 x2 = bank->x2;
7771 y0 = bank->y0;
7772 y1 = bank->y1;
7773 y2 = bank->y2;
7774 rr = bank->rr;
7775 fdbk = bank->fdbk;
7776 gain = bank->gain;
7777 amps = bank->amps;
7778
7779 for (i = 0; i < bank->size; i++)
7780 {
7781 x0[i] = gain[i] * inval[i];
7782 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr[i] * y2[i]);
7783 sum += amps[i] * y0[i];
7784 }
7785
7786 bank->x2 = x1;
7787 bank->x1 = x0;
7788 bank->x0 = x2;
7789
7790 bank->y2 = y1;
7791 bank->y1 = y0;
7792 bank->y0 = y2;
7793
7794 return(sum);
7795 }
7796
fb_many_without_amps(mus_any * fbank,mus_float_t * inval)7797 static mus_float_t fb_many_without_amps(mus_any *fbank, mus_float_t *inval)
7798 {
7799 frm_bank *bank = (frm_bank *)fbank;
7800 int i;
7801 mus_float_t sum = 0.0;
7802 mus_float_t *x0, *x1, *x2, *y0, *y1, *y2, *rr, *fdbk, *gain;
7803
7804 x0 = bank->x0;
7805 x1 = bank->x1;
7806 x2 = bank->x2;
7807 y0 = bank->y0;
7808 y1 = bank->y1;
7809 y2 = bank->y2;
7810 rr = bank->rr;
7811 fdbk = bank->fdbk;
7812 gain = bank->gain;
7813
7814 for (i = 0; i < bank->size; i++)
7815 {
7816 x0[i] = gain[i] * inval[i];
7817 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr[i] * y2[i]);
7818 sum += y0[i];
7819 }
7820
7821 bank->x2 = x1;
7822 bank->x1 = x0;
7823 bank->x0 = x2;
7824
7825 bank->y2 = y1;
7826 bank->y1 = y0;
7827 bank->y0 = y2;
7828
7829 return(sum);
7830 }
7831
fb_one_with_amps_c1_c2(mus_any * fbank,mus_float_t inval)7832 static mus_float_t fb_one_with_amps_c1_c2(mus_any *fbank, mus_float_t inval)
7833 {
7834 frm_bank *bank = (frm_bank *)fbank;
7835 int i, size4;
7836 mus_float_t sum = 0.0, rr, gain;
7837 mus_float_t *x0, *x1, *x2, *y0, *y1, *y2, *amps, *fdbk;
7838
7839 x0 = bank->x0;
7840 x1 = bank->x1;
7841 x2 = bank->x2;
7842 y0 = bank->y0;
7843 y1 = bank->y1;
7844 y2 = bank->y2;
7845 fdbk = bank->fdbk;
7846 amps = bank->amps;
7847 size4 = bank->size - 4;
7848
7849 bank->mctr++;
7850
7851 rr = bank->c1;
7852 gain = (bank->c2 * inval);
7853 x0[0] = gain;
7854
7855 if (bank->mctr < 3)
7856 {
7857 i = 0;
7858 while (i <= size4)
7859 {
7860 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7861 sum += amps[i] * y0[i];
7862 i++;
7863 /* in isolation this looks like the x0[i]-x2[i] business could be handled outside the loop
7864 * by a single float, but formant-bank can be called in the same do-loop both with and
7865 * without multiple inputs, so fb_one has to be completely compatible sample-by-sample
7866 * with fb_many. Since we can't predict here when we'll need bank->x2, we can't collapse
7867 * this calculation.
7868 *
7869 * If we know we've had 2 fb_one calls just before this one, then x2[i] are all the same,
7870 * x0[i] will all be the same in this loop, so x0[i] - x2[i] can be collapsed, but
7871 * we still need to set x0[0]=gain: enter mctr.
7872 *
7873 * So in the current case, we can save x0[0]=gain -> x1 -> x2, then in fm_many
7874 * mctr=1 -- x2 is ok, x1[0] needs to be propagated
7875 * mctr>1 -- x2 and x1 need propagation
7876 * On the other side, if mctr>=3, then x2[i] was not set, so don't access it.
7877 */
7878
7879 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7880 sum += amps[i] * y0[i];
7881 i++;
7882
7883 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7884 sum += amps[i] * y0[i];
7885 i++;
7886
7887 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7888 sum += amps[i] * y0[i];
7889 i++;
7890 }
7891 for (; i < bank->size; i++)
7892 {
7893 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7894 sum += amps[i] * y0[i];
7895 }
7896 }
7897 else
7898 {
7899 mus_float_t g2;
7900 g2 = gain - x2[0];
7901 i = 0;
7902 while (i <= size4)
7903 {
7904 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
7905 sum += amps[i] * y0[i];
7906 i++;
7907
7908 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
7909 sum += amps[i] * y0[i];
7910 i++;
7911
7912 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
7913 sum += amps[i] * y0[i];
7914 i++;
7915
7916 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
7917 sum += amps[i] * y0[i];
7918 i++;
7919 }
7920 for (; i < bank->size; i++)
7921 {
7922 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
7923 sum += amps[i] * y0[i];
7924 }
7925 }
7926
7927 bank->x2 = x1;
7928 bank->x1 = x0;
7929 bank->x0 = x2;
7930
7931 bank->y2 = y1;
7932 bank->y1 = y0;
7933 bank->y0 = y2;
7934
7935 return(sum);
7936 }
7937
fb_many_with_amps_c1_c2(mus_any * fbank,mus_float_t * inval)7938 static mus_float_t fb_many_with_amps_c1_c2(mus_any *fbank, mus_float_t *inval)
7939 {
7940 frm_bank *bank = (frm_bank *)fbank;
7941 int i, size4;
7942 mus_float_t sum = 0.0, rr, gain;
7943 mus_float_t *x0, *x1, *x2, *y0, *y1, *y2, *amps, *fdbk;
7944
7945 x0 = bank->x0;
7946 x1 = bank->x1;
7947 x2 = bank->x2;
7948 y0 = bank->y0;
7949 y1 = bank->y1;
7950 y2 = bank->y2;
7951 fdbk = bank->fdbk;
7952 amps = bank->amps;
7953 size4 = bank->size - 4;
7954
7955 if (bank->mctr > 0)
7956 {
7957 if (bank->mctr == 1)
7958 {
7959 for (i = 1; i < bank->size; i++) x1[i] = x1[0];
7960 }
7961 else
7962 {
7963 for (i = 1; i < bank->size; i++) {x1[i] = x1[0]; x2[i] = x2[0];}
7964 }
7965 bank->mctr = 0;
7966 }
7967 rr = bank->c1;
7968 gain = bank->c2;
7969
7970 i = 0;
7971 while (i <= size4)
7972 {
7973 x0[i] = gain * inval[i];
7974 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7975 sum += amps[i] * y0[i];
7976 i++;
7977
7978 x0[i] = gain * inval[i];
7979 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7980 sum += amps[i] * y0[i];
7981 i++;
7982
7983 x0[i] = gain * inval[i];
7984 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7985 sum += amps[i] * y0[i];
7986 i++;
7987
7988 x0[i] = gain * inval[i];
7989 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7990 sum += amps[i] * y0[i];
7991 i++;
7992 }
7993 for (; i < bank->size; i++)
7994 {
7995 x0[i] = gain * inval[i];
7996 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
7997 sum += amps[i] * y0[i];
7998 }
7999
8000 bank->x2 = x1;
8001 bank->x1 = x0;
8002 bank->x0 = x2;
8003
8004 bank->y2 = y1;
8005 bank->y1 = y0;
8006 bank->y0 = y2;
8007
8008 return(sum);
8009 }
8010
8011
fb_one_without_amps_c1_c2(mus_any * fbank,mus_float_t inval)8012 static mus_float_t fb_one_without_amps_c1_c2(mus_any *fbank, mus_float_t inval)
8013 {
8014 frm_bank *bank = (frm_bank *)fbank;
8015 int i, size4;
8016 mus_float_t sum = 0.0, rr, gain;
8017 mus_float_t *x0, *x1, *x2, *y0, *y1, *y2, *fdbk;
8018
8019 x0 = bank->x0;
8020 x1 = bank->x1;
8021 x2 = bank->x2;
8022 y0 = bank->y0;
8023 y1 = bank->y1;
8024 y2 = bank->y2;
8025 fdbk = bank->fdbk;
8026 size4 = bank->size - 4;
8027
8028 bank->mctr++;
8029
8030 rr = bank->c1;
8031 gain = (bank->c2 * inval);
8032 x0[0] = gain;
8033
8034 if (bank->mctr < 3)
8035 {
8036 i = 0;
8037 while (i <= size4)
8038 {
8039 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8040 sum += y0[i];
8041 i++;
8042
8043 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8044 sum += y0[i];
8045 i++;
8046
8047 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8048 sum += y0[i];
8049 i++;
8050
8051 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8052 sum += y0[i];
8053 i++;
8054 }
8055 for (; i < bank->size; i++)
8056 {
8057 y0[i] = gain - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8058 sum += y0[i];
8059 }
8060 }
8061 else
8062 {
8063 mus_float_t g2;
8064 g2 = gain - x2[0];
8065 i = 0;
8066 while (i <= size4)
8067 {
8068 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
8069 sum += y0[i];
8070 i++;
8071
8072 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
8073 sum += y0[i];
8074 i++;
8075
8076 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
8077 sum += y0[i];
8078 i++;
8079
8080 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
8081 sum += y0[i];
8082 i++;
8083 }
8084 for (; i < bank->size; i++)
8085 {
8086 y0[i] = g2 + (fdbk[i] * y1[i]) - (rr * y2[i]);
8087 sum += y0[i];
8088 }
8089 }
8090
8091 bank->x2 = x1;
8092 bank->x1 = x0;
8093 bank->x0 = x2;
8094
8095 bank->y2 = y1;
8096 bank->y1 = y0;
8097 bank->y0 = y2;
8098
8099 return(sum);
8100 }
8101
8102
fb_many_without_amps_c1_c2(mus_any * fbank,mus_float_t * inval)8103 static mus_float_t fb_many_without_amps_c1_c2(mus_any *fbank, mus_float_t *inval)
8104 {
8105 frm_bank *bank = (frm_bank *)fbank;
8106 int i, size4;
8107 mus_float_t sum = 0.0, rr, gain;
8108 mus_float_t *x0, *x1, *x2, *y0, *y1, *y2, *fdbk;
8109
8110 x0 = bank->x0;
8111 x1 = bank->x1;
8112 x2 = bank->x2;
8113 y0 = bank->y0;
8114 y1 = bank->y1;
8115 y2 = bank->y2;
8116 fdbk = bank->fdbk;
8117 size4 = bank->size - 4;
8118
8119 if (bank->mctr > 0)
8120 {
8121 if (bank->mctr == 1)
8122 {
8123 for (i = 1; i < bank->size; i++) x1[i] = x1[0];
8124 }
8125 else
8126 {
8127 for (i = 1; i < bank->size; i++) {x1[i] = x1[0]; x2[i] = x2[0];}
8128 }
8129 bank->mctr = 0;
8130 }
8131
8132 rr = bank->c1;
8133 gain = bank->c2;
8134
8135 i = 0;
8136 while (i <= size4)
8137 {
8138 x0[i] = gain * inval[i];
8139 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8140 sum += y0[i];
8141 i++;
8142
8143 x0[i] = gain * inval[i];
8144 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8145 sum += y0[i];
8146 i++;
8147
8148 x0[i] = gain * inval[i];
8149 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8150 sum += y0[i];
8151 i++;
8152
8153 x0[i] = gain * inval[i];
8154 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8155 sum += y0[i];
8156 i++;
8157 }
8158 for (; i < bank->size; i++)
8159 {
8160 x0[i] = gain * inval[i];
8161 y0[i] = x0[i] - x2[i] + (fdbk[i] * y1[i]) - (rr * y2[i]);
8162 sum += y0[i];
8163 }
8164
8165 bank->x2 = x1;
8166 bank->x1 = x0;
8167 bank->x0 = x2;
8168
8169 bank->y2 = y1;
8170 bank->y1 = y0;
8171 bank->y0 = y2;
8172
8173 return(sum);
8174 }
8175
8176
8177 static mus_any_class FORMANT_BANK_CLASS = {
8178 MUS_FORMANT_BANK,
8179 (char *)S_formant_bank,
8180 &free_formant_bank,
8181 &describe_formant_bank,
8182 &formant_bank_equalp,
8183 0, 0,
8184 &formant_bank_length, 0,
8185 0, 0,
8186 0, 0,
8187 0, 0,
8188 0, 0,
8189 &run_formant_bank,
8190 MUS_NOT_SPECIAL,
8191 NULL, 0,
8192 0, 0, 0, 0,
8193 0, 0,
8194 0, 0, 0, 0,
8195 0, 0, 0, 0, 0, 0, 0,
8196 0, 0, 0, 0,
8197 &formant_bank_reset,
8198 0, &frm_bank_copy
8199 };
8200
8201
mus_make_formant_bank(int size,mus_any ** formants,mus_float_t * amps)8202 mus_any *mus_make_formant_bank(int size, mus_any **formants, mus_float_t *amps)
8203 {
8204 frm_bank *gen;
8205 int i;
8206
8207 gen = (frm_bank *)malloc(sizeof(frm_bank));
8208 gen->core = &FORMANT_BANK_CLASS;
8209 gen->size = size;
8210 gen->mctr = 0;
8211
8212 gen->x0 = (mus_float_t *)calloc(size, sizeof(mus_float_t));
8213 gen->x1 = (mus_float_t *)calloc(size, sizeof(mus_float_t));
8214 gen->x2 = (mus_float_t *)calloc(size, sizeof(mus_float_t));
8215 gen->y0 = (mus_float_t *)calloc(size, sizeof(mus_float_t));
8216 gen->y1 = (mus_float_t *)calloc(size, sizeof(mus_float_t));
8217 gen->y2 = (mus_float_t *)calloc(size, sizeof(mus_float_t));
8218 gen->amps = amps;
8219
8220 gen->rr = (mus_float_t *)malloc(size * sizeof(mus_float_t));
8221 gen->fdbk = (mus_float_t *)malloc(size * sizeof(mus_float_t));
8222 gen->gain = (mus_float_t *)malloc(size * sizeof(mus_float_t));
8223
8224 if (amps)
8225 {
8226 gen->one_input = fb_one_with_amps;
8227 gen->many_inputs = fb_many_with_amps;
8228 }
8229 else
8230 {
8231 gen->one_input = fb_one_without_amps;
8232 gen->many_inputs = fb_many_without_amps;
8233 }
8234
8235 for (i = 0; i < size; i++)
8236 {
8237 frm *g;
8238 g = (frm *)formants[i];
8239 gen->rr[i] = g->rr;
8240 gen->fdbk[i] = g->fdbk;
8241 gen->gain[i] = g->gain;
8242 /* one case: 1.0 val 0.0 throughout
8243 * also c1 x c2
8244 */
8245 }
8246 gen->c1 = gen->rr[0];
8247 gen->c2 = gen->gain[0];
8248 for (i = 1; i < size; i++)
8249 if ((gen->rr[i] != gen->c1) ||
8250 (gen->gain[i] != gen->c2))
8251 return((mus_any *)gen);
8252
8253 if (amps)
8254 {
8255 gen->one_input = fb_one_with_amps_c1_c2;
8256 gen->many_inputs = fb_many_with_amps_c1_c2;
8257 }
8258 else
8259 {
8260 gen->one_input = fb_one_without_amps_c1_c2;
8261 gen->many_inputs = fb_many_without_amps_c1_c2;
8262 }
8263
8264 return((mus_any *)gen);
8265 }
8266
mus_is_formant_bank(mus_any * ptr)8267 bool mus_is_formant_bank(mus_any *ptr)
8268 {
8269 return((ptr) &&
8270 (ptr->core->type == MUS_FORMANT_BANK));
8271 }
8272
8273
8274
8275 /* ---------------- firmant ---------------- */
8276
describe_firmant(mus_any * ptr)8277 static char *describe_firmant(mus_any *ptr)
8278 {
8279 frm *gen = (frm *)ptr;
8280 char *describe_buffer;
8281 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
8282 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s frequency: %.3f, radius: %.3f",
8283 mus_name(ptr),
8284 mus_radians_to_hz(gen->frequency),
8285 gen->radius);
8286 return(describe_buffer);
8287 }
8288
firmant_frequency(mus_any * ptr)8289 static mus_float_t firmant_frequency(mus_any *ptr) {return(mus_radians_to_hz(((frm *)ptr)->frequency));}
8290
firmant_set_frequency(mus_any * ptr,mus_float_t freq_in_hz)8291 static mus_float_t firmant_set_frequency(mus_any *ptr, mus_float_t freq_in_hz)
8292 {
8293 frm *gen = (frm *)ptr;
8294 mus_float_t fw;
8295 fw = mus_hz_to_radians(freq_in_hz);
8296 gen->frequency = fw;
8297 gen->fdbk = 2.0 * sin(gen->frequency * 0.5);
8298 return(freq_in_hz);
8299 }
8300
firmant_radius(mus_any * ptr)8301 static mus_float_t firmant_radius(mus_any *ptr) {return(((frm *)ptr)->radius);}
8302
firmant_set_radius(mus_any * ptr,mus_float_t radius)8303 static mus_float_t firmant_set_radius(mus_any *ptr, mus_float_t radius)
8304 {
8305 frm *gen = (frm *)ptr;
8306 gen->radius = radius;
8307 gen->gain = 1.0 - radius * radius;
8308 return(radius);
8309 }
8310
8311
mus_is_firmant(mus_any * ptr)8312 bool mus_is_firmant(mus_any *ptr)
8313 {
8314 return((ptr) &&
8315 (ptr->core->type == MUS_FIRMANT));
8316 }
8317
8318
mus_firmant(mus_any * ptr,mus_float_t input)8319 mus_float_t mus_firmant(mus_any *ptr, mus_float_t input)
8320 {
8321 frm *gen = (frm *)ptr;
8322 mus_float_t xn1, yn1;
8323 xn1 = gen->gain * input + gen->radius * (gen->x1 - gen->fdbk * gen->y1);
8324 yn1 = gen->radius * (gen->fdbk * xn1 + gen->y1);
8325 gen->x1 = xn1;
8326 gen->y1 = yn1;
8327 return(yn1);
8328 }
8329
8330
mus_firmant_with_frequency(mus_any * ptr,mus_float_t input,mus_float_t freq_in_radians)8331 mus_float_t mus_firmant_with_frequency(mus_any *ptr, mus_float_t input, mus_float_t freq_in_radians)
8332 {
8333 frm *gen = (frm *)ptr;
8334 gen->frequency = freq_in_radians;
8335 gen->fdbk = 2.0 * sin(gen->frequency * 0.5);
8336 return(mus_firmant(ptr, input));
8337 }
8338
8339
run_firmant(mus_any * ptr,mus_float_t input,mus_float_t unused)8340 static mus_float_t run_firmant(mus_any *ptr, mus_float_t input, mus_float_t unused) {return(mus_firmant(ptr, input));}
8341
8342
8343 static mus_any_class FIRMANT_CLASS = {
8344 MUS_FIRMANT,
8345 (char *)S_firmant,
8346 &free_frm,
8347 &describe_firmant,
8348 &frm_equalp,
8349 0, 0,
8350 &two_length, 0,
8351 &firmant_frequency, &firmant_set_frequency,
8352 0, 0,
8353 &firmant_radius, &firmant_set_radius,
8354 0, 0,
8355 &run_firmant,
8356 MUS_SIMPLE_FILTER,
8357 NULL, 0,
8358 0, 0, 0, 0,
8359 0, 0,
8360 0, 0, 0, 0,
8361 0, 0, 0, 0, 0, 0, 0,
8362 0, 0, 0, 0,
8363 &frm_reset,
8364 0, &frm_copy
8365 };
8366
8367
mus_make_firmant(mus_float_t frequency,mus_float_t radius)8368 mus_any *mus_make_firmant(mus_float_t frequency, mus_float_t radius)
8369 {
8370 frm *gen;
8371 gen = (frm *)calloc(1, sizeof(frm));
8372 gen->core = &FIRMANT_CLASS;
8373 gen->frequency = mus_hz_to_radians(frequency);
8374 gen->radius = radius;
8375 gen->fdbk = 2.0 * sin(gen->frequency * 0.5);
8376 gen->gain = 1.0 - radius * radius;
8377 return((mus_any *)gen);
8378 }
8379
8380
8381
8382
8383 /* ---------------- filter ---------------- */
8384
8385 typedef struct {
8386 mus_any_class *core;
8387 int order, allocated_size, loc;
8388 bool state_allocated;
8389 mus_float_t *x, *y, *state;
8390 mus_float_t (*filtw)(mus_any *ptr, mus_float_t fm);
8391 } flt;
8392
8393
mus_filter(mus_any * ptr,mus_float_t input)8394 mus_float_t mus_filter(mus_any *ptr, mus_float_t input)
8395 {
8396 return((((flt *)ptr)->filtw)(ptr, input));
8397 }
8398
8399
filter_eight(mus_any * ptr,mus_float_t input)8400 static mus_float_t filter_eight(mus_any *ptr, mus_float_t input)
8401 {
8402 /* oddly enough, this separated form is faster than the interleaved version below, or is valgrind confused?
8403 */
8404 flt *gen = (flt *)ptr;
8405 mus_float_t xout;
8406 mus_float_t *state, *ts, *ts1, *y, *x;
8407
8408 x = (mus_float_t *)(gen->x);
8409 y = (mus_float_t *)(gen->y + 1); /* assume y[0] = 1.0 I think */
8410 state = (mus_float_t *)(gen->state + gen->loc);
8411 ts = (mus_float_t *)(state + gen->order - 1);
8412 ts1 = (mus_float_t *)(state + gen->order);
8413
8414 gen->loc++;
8415 if (gen->loc == gen->order)
8416 gen->loc = 0;
8417
8418 input -= ((*ts--) * (*y++));
8419 input -= ((*ts--) * (*y++));
8420 input -= ((*ts--) * (*y++));
8421 input -= ((*ts--) * (*y++));
8422 input -= ((*ts--) * (*y++));
8423 input -= ((*ts--) * (*y++));
8424 input -= ((*ts--) * (*y++));
8425 input -= ((*ts) * (*y));
8426
8427 state[0] = input;
8428 state[gen->order] = input;
8429
8430 xout = (*ts1--) * (*x++);
8431 xout += (*ts1--) * (*x++);
8432 xout += (*ts1--) * (*x++);
8433 xout += (*ts1--) * (*x++);
8434 xout += (*ts1--) * (*x++);
8435 xout += (*ts1--) * (*x++);
8436 xout += (*ts1--) * (*x++);
8437 xout += (*ts1--) * (*x++);
8438 return(xout + ((*ts1) * (*x)));
8439
8440 /*
8441 * flt *gen = (flt *)ptr;
8442 * mus_float_t xout;
8443 * mus_float_t *state, *ts, *y, *x;
8444 *
8445 * x = (mus_float_t *)(gen->x + 1);
8446 * y = (mus_float_t *)(gen->y + 1);
8447 * state = (mus_float_t *)(gen->state + gen->loc);
8448 * ts = (mus_float_t *)(state + gen->order - 1);
8449 *
8450 * gen->loc++;
8451 * if (gen->loc == gen->order)
8452 * gen->loc = 0;
8453 *
8454 * xout = (*ts) * (*x++);
8455 * input -= ((*ts--) * (*y++));
8456 * xout += (*ts) * (*x++);
8457 * input -= ((*ts--) * (*y++));
8458 * xout += (*ts) * (*x++);
8459 * input -= ((*ts--) * (*y++));
8460 * xout += (*ts) * (*x++);
8461 * input -= ((*ts--) * (*y++));
8462 * xout += (*ts) * (*x++);
8463 * input -= ((*ts--) * (*y++));
8464 * xout += (*ts) * (*x++);
8465 * input -= ((*ts--) * (*y++));
8466 * xout += (*ts) * (*x++);
8467 * input -= ((*ts--) * (*y++));
8468 * xout += (*ts) * (*x);
8469 * input -= ((*ts--) * (*y));
8470 *
8471 * state[0] = input;
8472 * state[gen->order] = input;
8473 * return(xout + ((*ts) * gen->x[0]));
8474 */
8475 }
8476
8477
filter_four(mus_any * ptr,mus_float_t input)8478 static mus_float_t filter_four(mus_any *ptr, mus_float_t input)
8479 {
8480 flt *gen = (flt *)ptr;
8481 mus_float_t xout;
8482 mus_float_t *state, *ts, *ts1, *y, *x;
8483
8484 x = (mus_float_t *)(gen->x);
8485 y = (mus_float_t *)(gen->y + 1);
8486 state = (mus_float_t *)(gen->state + gen->loc);
8487 ts = (mus_float_t *)(state + gen->order - 1);
8488 ts1 = (mus_float_t *)(state + gen->order);
8489
8490 gen->loc++;
8491 if (gen->loc == gen->order)
8492 gen->loc = 0;
8493
8494 input -= ((*ts--) * (*y++));
8495 input -= ((*ts--) * (*y++));
8496 input -= ((*ts--) * (*y++));
8497 input -= ((*ts) * (*y));
8498
8499 state[0] = input;
8500 state[gen->order] = input;
8501
8502 xout = (*ts1--) * (*x++);
8503 xout += (*ts1--) * (*x++);
8504 xout += (*ts1--) * (*x++);
8505 xout += (*ts1--) * (*x++);
8506 return(xout + ((*ts1) * (*x)));
8507
8508 /*
8509 * flt *gen = (flt *)ptr;
8510 * mus_float_t xout;
8511 * mus_float_t *state, *ts, *y, *x;
8512 *
8513 * x = (mus_float_t *)(gen->x + 1);
8514 * y = (mus_float_t *)(gen->y + 1);
8515 * state = (mus_float_t *)(gen->state + gen->loc);
8516 * ts = (mus_float_t *)(state + gen->order - 1);
8517 *
8518 * gen->loc++;
8519 * if (gen->loc == gen->order)
8520 * gen->loc = 0;
8521 *
8522 * xout = (*ts) * (*x++);
8523 * input -= ((*ts--) * (*y++));
8524 * xout += (*ts) * (*x++);
8525 * input -= ((*ts--) * (*y++));
8526 * xout += (*ts) * (*x++);
8527 * input -= ((*ts--) * (*y++));
8528 * xout += (*ts) * (*x++);
8529 * input -= ((*ts--) * (*y++));
8530 *
8531 * state[0] = input;
8532 * state[gen->order] = input;
8533 * return(xout + ((*ts) * gen->x[0]));
8534 */
8535 }
8536
8537
filter_two(mus_any * ptr,mus_float_t input)8538 static mus_float_t filter_two(mus_any *ptr, mus_float_t input)
8539 {
8540 /* here the mus_float_t-delay form is not faster, but use it for consistency */
8541 flt *gen = (flt *)ptr;
8542 mus_float_t *state, *ts, *y, *x;
8543
8544 x = gen->x;
8545 y = gen->y;
8546 state = (mus_float_t *)(gen->state + gen->loc);
8547 ts = (mus_float_t *)(state + gen->order - 2);
8548
8549 gen->loc++;
8550 if (gen->loc == gen->order)
8551 gen->loc = 0;
8552
8553 state[0] = input - ((ts[1] * y[1]) + (ts[0] * y[2]));
8554 state[gen->order] = state[0];
8555
8556 return((ts[0] * x[2]) + (ts[1] * x[1]) + (ts[2] * x[0]));
8557 }
8558
8559
filter_lt_10(mus_any * ptr,mus_float_t input)8560 static mus_float_t filter_lt_10(mus_any *ptr, mus_float_t input)
8561 {
8562 flt *gen = (flt *)ptr;
8563 mus_float_t xout = 0.0;
8564 mus_float_t *state, *state1, *ts, *y, *x;
8565
8566 x = (mus_float_t *)(gen->x);
8567 y = (mus_float_t *)(gen->y + 1); /* assume y[0] = 1.0 I think */
8568 state = (mus_float_t *)(gen->state + gen->loc);
8569 state1 = (mus_float_t *)(state + 1);
8570 ts = (mus_float_t *)(state + gen->order - 1);
8571
8572 while (ts > state1)
8573 input -= ((*ts--) * (*y++));
8574 input -= ((*ts) * (*y));
8575
8576 state[0] = input;
8577 state[gen->order] = input;
8578
8579 ts = (mus_float_t *)(state + gen->order);
8580
8581 while (ts > state1)
8582 xout += (*ts--) * (*x++);
8583
8584 gen->loc++;
8585 if (gen->loc == gen->order)
8586 gen->loc = 0;
8587
8588 return(xout + ((*ts) * (*x)));
8589 }
8590
8591
filter_ge_10(mus_any * ptr,mus_float_t input)8592 static mus_float_t filter_ge_10(mus_any *ptr, mus_float_t input)
8593 {
8594 flt *gen = (flt *)ptr;
8595 mus_float_t xout = 0.0;
8596 mus_float_t *state, *state1, *state11, *ts, *y, *x;
8597
8598 x = (mus_float_t *)(gen->x);
8599 y = (mus_float_t *)(gen->y + 1); /* assume y[0] = 1.0 I think */
8600 state = (mus_float_t *)(gen->state + gen->loc);
8601 state1 = (mus_float_t *)(state + 1);
8602 state11 = (mus_float_t *)(state + 11);
8603 ts = (mus_float_t *)(state + gen->order - 1);
8604
8605 while (ts >= state11)
8606 {
8607 input -= ((*ts--) * (*y++));
8608 input -= ((*ts--) * (*y++));
8609 input -= ((*ts--) * (*y++));
8610 input -= ((*ts--) * (*y++));
8611 input -= ((*ts--) * (*y++));
8612 input -= ((*ts--) * (*y++));
8613 input -= ((*ts--) * (*y++));
8614 input -= ((*ts--) * (*y++));
8615 input -= ((*ts--) * (*y++));
8616 input -= ((*ts--) * (*y++));
8617 }
8618 while (ts > state1)
8619 input -= ((*ts--) * (*y++));
8620 input -= ((*ts) * (*y));
8621
8622 state[0] = input;
8623 state[gen->order] = input;
8624
8625 ts = (mus_float_t *)(state + gen->order);
8626 while (ts >= state11)
8627 {
8628 xout += (*ts--) * (*x++);
8629 xout += (*ts--) * (*x++);
8630 xout += (*ts--) * (*x++);
8631 xout += (*ts--) * (*x++);
8632 xout += (*ts--) * (*x++);
8633 xout += (*ts--) * (*x++);
8634 xout += (*ts--) * (*x++);
8635 xout += (*ts--) * (*x++);
8636 xout += (*ts--) * (*x++);
8637 xout += (*ts--) * (*x++);
8638 }
8639 while (ts > state1)
8640 xout += (*ts--) * (*x++);
8641
8642 gen->loc++;
8643 if (gen->loc == gen->order)
8644 gen->loc = 0;
8645
8646 return(xout + ((*ts) * (*x)));
8647 }
8648
8649
mus_fir_filter(mus_any * ptr,mus_float_t input)8650 mus_float_t mus_fir_filter(mus_any *ptr, mus_float_t input)
8651 {
8652 return((((flt *)ptr)->filtw)(ptr, input));
8653 }
8654
fir_n(mus_any * ptr,mus_float_t input)8655 static inline mus_float_t fir_n(mus_any *ptr, mus_float_t input)
8656 {
8657 mus_float_t xout = 0.0;
8658 flt *gen = (flt *)ptr;
8659 mus_float_t *state, *ts, *x, *end;
8660
8661 x = (mus_float_t *)(gen->x);
8662 state = (mus_float_t *)(gen->state + gen->loc);
8663 ts = (mus_float_t *)(state + gen->order);
8664
8665 (*state) = input;
8666 (*ts) = input;
8667 state++;
8668 end = (mus_float_t *)(state + 4);
8669
8670 while (ts > end)
8671 {
8672 xout += (*ts--) * (*x++);
8673 xout += (*ts--) * (*x++);
8674 xout += (*ts--) * (*x++);
8675 xout += (*ts--) * (*x++);
8676 }
8677 while (ts > state)
8678 xout += (*ts--) * (*x++);
8679
8680 gen->loc++;
8681 if (gen->loc == gen->order)
8682 gen->loc = 0;
8683
8684 return(xout + ((*ts) * (*x)));
8685 }
8686
8687
fir_3(mus_any * ptr,mus_float_t input)8688 static inline mus_float_t fir_3(mus_any *ptr, mus_float_t input)
8689 {
8690 mus_float_t xout;
8691 flt *gen = (flt *)ptr;
8692 mus_float_t *state, *ts, *x;
8693
8694 x = (mus_float_t *)(gen->x);
8695 state = (mus_float_t *)(gen->state + gen->loc);
8696 ts = (mus_float_t *)(state + 4); /* gen->order == 4 in this case */
8697
8698 /* gen->loc = (gen->loc == 3) ? 0 : (gen->loc + 1); */
8699 gen->loc = (gen->loc + 1) & 0x3;
8700 (*state) = input;
8701 (*ts) = input;
8702
8703 xout = (*ts--) * (*x++);
8704 xout += (*ts--) * (*x++);
8705 xout += (*ts--) * (*x++);
8706 return(xout + ((*ts) * (*x)));
8707 }
8708
fir_4(mus_any * ptr,mus_float_t input)8709 static inline mus_float_t fir_4(mus_any *ptr, mus_float_t input)
8710 {
8711 mus_float_t xout;
8712 flt *gen = (flt *)ptr;
8713 mus_float_t *state, *ts, *x;
8714
8715 x = (mus_float_t *)(gen->x);
8716 state = (mus_float_t *)(gen->state + gen->loc);
8717 ts = (mus_float_t *)(state + 5);
8718
8719 gen->loc = (gen->loc == 4) ? 0 : (gen->loc + 1);
8720 (*state) = input;
8721 (*ts) = input;
8722
8723 xout = (*ts--) * (*x++);
8724 xout += (*ts--) * (*x++);
8725 xout += (*ts--) * (*x++);
8726 xout += (*ts--) * (*x++);
8727 return(xout + ((*ts) * (*x)));
8728 }
8729
fir_9(mus_any * ptr,mus_float_t input)8730 static inline mus_float_t fir_9(mus_any *ptr, mus_float_t input)
8731 {
8732 mus_float_t xout;
8733 flt *gen = (flt *)ptr;
8734 mus_float_t *state, *ts, *x;
8735
8736 x = (mus_float_t *)(gen->x);
8737 state = (mus_float_t *)(gen->state + gen->loc);
8738 ts = (mus_float_t *)(state + 10);
8739
8740 gen->loc = (gen->loc == 9) ? 0 : (gen->loc + 1);
8741 (*state) = input;
8742 (*ts) = input;
8743
8744 xout = (*ts--) * (*x++);
8745 xout += (*ts--) * (*x++);
8746 xout += (*ts--) * (*x++);
8747 xout += (*ts--) * (*x++);
8748 xout += (*ts--) * (*x++);
8749 xout += (*ts--) * (*x++);
8750 xout += (*ts--) * (*x++);
8751 xout += (*ts--) * (*x++);
8752 xout += (*ts--) * (*x++);
8753 return(xout + ((*ts) * (*x)));
8754 }
8755
8756
fir_ge_20(mus_any * ptr,mus_float_t input)8757 static mus_float_t fir_ge_20(mus_any *ptr, mus_float_t input)
8758 {
8759 mus_float_t xout = 0.0;
8760 flt *gen = (flt *)ptr;
8761 mus_float_t *state, *ts, *x, *end;
8762
8763 x = (mus_float_t *)(gen->x);
8764 state = (mus_float_t *)(gen->state + gen->loc);
8765 ts = (mus_float_t *)(state + gen->order);
8766 end = (mus_float_t *)(state + 20);
8767
8768 (*state) = input;
8769 (*ts) = input;
8770 state++;
8771
8772 while (ts >= end)
8773 {
8774 xout += (*ts--) * (*x++);
8775 xout += (*ts--) * (*x++);
8776 xout += (*ts--) * (*x++);
8777 xout += (*ts--) * (*x++);
8778 xout += (*ts--) * (*x++);
8779 xout += (*ts--) * (*x++);
8780 xout += (*ts--) * (*x++);
8781 xout += (*ts--) * (*x++);
8782 xout += (*ts--) * (*x++);
8783 xout += (*ts--) * (*x++);
8784 xout += (*ts--) * (*x++);
8785 xout += (*ts--) * (*x++);
8786 xout += (*ts--) * (*x++);
8787 xout += (*ts--) * (*x++);
8788 xout += (*ts--) * (*x++);
8789 xout += (*ts--) * (*x++);
8790 xout += (*ts--) * (*x++);
8791 xout += (*ts--) * (*x++);
8792 xout += (*ts--) * (*x++);
8793 xout += (*ts--) * (*x++);
8794 }
8795 while (ts > state)
8796 xout += (*ts--) * (*x++);
8797
8798 gen->loc++;
8799 if (gen->loc == gen->order)
8800 gen->loc = 0;
8801
8802 return((ts == state) ? (xout + ((*ts) * (*x))) : xout);
8803 }
8804
8805
mus_iir_filter(mus_any * ptr,mus_float_t input)8806 mus_float_t mus_iir_filter(mus_any *ptr, mus_float_t input)
8807 {
8808 return((((flt *)ptr)->filtw)(ptr, input));
8809 }
8810
8811
iir_n(mus_any * ptr,mus_float_t input)8812 static mus_float_t iir_n(mus_any *ptr, mus_float_t input)
8813 {
8814 flt *gen = (flt *)ptr;
8815 mus_float_t *state, *ts, *y;
8816
8817 y = (mus_float_t *)(gen->y + 1); /* assume y[0] = 1.0 I think */
8818 state = (mus_float_t *)(gen->state + gen->loc);
8819 ts = (mus_float_t *)(state + gen->order - 1);
8820
8821 while (ts > state)
8822 input -= ((*ts--) * (*y++));
8823
8824 gen->loc++;
8825 if (gen->loc == gen->order)
8826 gen->loc = 0;
8827
8828 state[0] = input;
8829 state[gen->order] = input;
8830
8831 return(input);
8832 }
8833
8834
run_filter(mus_any * ptr,mus_float_t input,mus_float_t unused)8835 static mus_float_t run_filter(mus_any *ptr, mus_float_t input, mus_float_t unused)
8836 {
8837 return((((flt *)ptr)->filtw)(ptr, input));
8838 }
8839
mus_is_filter(mus_any * ptr)8840 bool mus_is_filter(mus_any *ptr)
8841 {
8842 return((ptr) &&
8843 ((ptr->core->type == MUS_FILTER) ||
8844 (ptr->core->type == MUS_FIR_FILTER) ||
8845 (ptr->core->type == MUS_IIR_FILTER)));
8846 }
8847
8848
mus_is_fir_filter(mus_any * ptr)8849 bool mus_is_fir_filter(mus_any *ptr)
8850 {
8851 return((ptr) &&
8852 (ptr->core->type == MUS_FIR_FILTER));
8853 }
8854
mus_is_iir_filter(mus_any * ptr)8855 bool mus_is_iir_filter(mus_any *ptr)
8856 {
8857 return((ptr) &&
8858 (ptr->core->type == MUS_IIR_FILTER));
8859 }
8860
8861
filter_data(mus_any * ptr)8862 static mus_float_t *filter_data(mus_any *ptr) {return(((flt *)ptr)->state);}
filter_length(mus_any * ptr)8863 static mus_long_t filter_length(mus_any *ptr) {return(((flt *)ptr)->order);}
8864
filter_xcoeffs(mus_any * ptr)8865 static mus_float_t *filter_xcoeffs(mus_any *ptr) {return(((flt *)ptr)->x);}
filter_ycoeffs(mus_any * ptr)8866 static mus_float_t *filter_ycoeffs(mus_any *ptr) {return(((flt *)ptr)->y);}
8867
8868
mus_filter_set_xcoeffs(mus_any * ptr,mus_float_t * new_data)8869 mus_float_t *mus_filter_set_xcoeffs(mus_any *ptr, mus_float_t *new_data)
8870 {
8871 /* needed by Snd if filter order increased during play */
8872 flt *gen = (flt *)ptr;
8873 mus_float_t *old_data;
8874 old_data = gen->x;
8875 gen->x = new_data;
8876 return(old_data);
8877 }
8878
8879
mus_filter_set_ycoeffs(mus_any * ptr,mus_float_t * new_data)8880 mus_float_t *mus_filter_set_ycoeffs(mus_any *ptr, mus_float_t *new_data)
8881 {
8882 flt *gen = (flt *)ptr;
8883 mus_float_t *old_data;
8884 old_data = gen->y;
8885 gen->y = new_data;
8886 return(old_data);
8887 }
8888
8889
filter_set_length(mus_any * ptr,mus_long_t val)8890 static mus_long_t filter_set_length(mus_any *ptr, mus_long_t val)
8891 {
8892 /* just resets order if order < allocated size */
8893 flt *gen = (flt *)ptr;
8894 if ((val > 0) && (val <= gen->allocated_size))
8895 gen->order = (int)val;
8896 return((mus_long_t)(gen->order));
8897 }
8898
8899
8900 static void set_filter_function(flt *gen);
8901
mus_filter_set_order(mus_any * ptr,int order)8902 int mus_filter_set_order(mus_any *ptr, int order)
8903 {
8904 /* resets order and fixes state array if needed (coeffs arrays should be handled separately by set_x|ycoeffs above) */
8905 /* returns either old order or -1 if state array can't be reallocated */
8906 flt *gen = (flt *)ptr;
8907 int old_order;
8908 if ((order > gen->allocated_size) &&
8909 (!(gen->state_allocated)))
8910 return(-1);
8911 old_order = gen->order;
8912 gen->order = order;
8913 if (order > gen->allocated_size)
8914 {
8915 int i;
8916 gen->allocated_size = order;
8917 gen->state = (mus_float_t *)realloc(gen->state, order * 2 * sizeof(mus_float_t));
8918 for (i = old_order; i < order; i++)
8919 {
8920 gen->state[i] = 0.0; /* try to minimize click */
8921 gen->state[i + order] = 0.0; /* just a guess */
8922 }
8923 }
8924 set_filter_function(gen);
8925 return(old_order);
8926 }
8927
8928
filter_xcoeff(mus_any * ptr,int index)8929 static mus_float_t filter_xcoeff(mus_any *ptr, int index)
8930 {
8931 flt *gen = (flt *)ptr;
8932 if (!(gen->x)) return((mus_float_t)mus_error(MUS_NO_XCOEFFS, S_mus_xcoeff ": no xcoeffs"));
8933 if ((index >= 0) && (index < gen->order))
8934 return(gen->x[index]);
8935 return((mus_float_t)mus_error(MUS_ARG_OUT_OF_RANGE, S_mus_xcoeff ": invalid index %d, order = %d?", index, gen->order));
8936 }
8937
8938
filter_set_xcoeff(mus_any * ptr,int index,mus_float_t val)8939 static mus_float_t filter_set_xcoeff(mus_any *ptr, int index, mus_float_t val)
8940 {
8941 flt *gen = (flt *)ptr;
8942 if (!(gen->x)) return((mus_float_t)mus_error(MUS_NO_XCOEFFS, S_set S_mus_xcoeff ": no xcoeffs"));
8943 if ((index >= 0) && (index < gen->order))
8944 {
8945 gen->x[index] = val;
8946 return(val);
8947 }
8948 return((mus_float_t)mus_error(MUS_ARG_OUT_OF_RANGE, S_set S_mus_xcoeff ": invalid index %d, order = %d?", index, gen->order));
8949 }
8950
8951
filter_ycoeff(mus_any * ptr,int index)8952 static mus_float_t filter_ycoeff(mus_any *ptr, int index)
8953 {
8954 flt *gen = (flt *)ptr;
8955 if (!(gen->y)) return((mus_float_t)mus_error(MUS_NO_YCOEFFS, S_mus_ycoeff ": no ycoeffs"));
8956 if ((index >= 0) && (index < gen->order))
8957 return(gen->y[index]);
8958 return((mus_float_t)mus_error(MUS_ARG_OUT_OF_RANGE, S_mus_ycoeff ": invalid index %d, order = %d?", index, gen->order));
8959 }
8960
8961
filter_set_ycoeff(mus_any * ptr,int index,mus_float_t val)8962 static mus_float_t filter_set_ycoeff(mus_any *ptr, int index, mus_float_t val)
8963 {
8964 flt *gen = (flt *)ptr;
8965 if (!(gen->y)) return((mus_float_t)mus_error(MUS_NO_YCOEFFS, S_set S_mus_ycoeff ": no ycoeffs"));
8966 if ((index >= 0) && (index < gen->order))
8967 {
8968 gen->y[index] = val;
8969 return(val);
8970 }
8971 return((mus_float_t)mus_error(MUS_ARG_OUT_OF_RANGE, S_set S_mus_ycoeff ": invalid index %d, order = %d?", index, gen->order));
8972 }
8973
8974
free_filter(mus_any * ptr)8975 static void free_filter(mus_any *ptr)
8976 {
8977 flt *gen = (flt *)ptr;
8978 if ((gen->state) && (gen->state_allocated)) free(gen->state);
8979 free(gen);
8980 }
8981
flt_copy(mus_any * ptr)8982 static mus_any *flt_copy(mus_any *ptr)
8983 {
8984 flt *g, *p;
8985
8986 p = (flt *)ptr;
8987 g = (flt *)malloc(sizeof(flt));
8988 memcpy((void *)g, (void *)ptr, sizeof(flt));
8989
8990 /* we have to make a new state array -- otherwise the original and copy step on each other */
8991 g->state_allocated = true;
8992 g->state = (mus_float_t *)malloc(p->order * 2 * sizeof(mus_float_t));
8993 mus_copy_floats(g->state, p->state, p->order * 2);
8994 return((mus_any *)g);
8995 }
8996
8997
filter_equalp(mus_any * p1,mus_any * p2)8998 static bool filter_equalp(mus_any *p1, mus_any *p2)
8999 {
9000 flt *f1, *f2;
9001 f1 = (flt *)p1;
9002 f2 = (flt *)p2;
9003 if (p1 == p2) return(true);
9004 return(((p1->core)->type == (p2->core)->type) &&
9005 ((mus_is_filter(p1)) || (mus_is_fir_filter(p1)) || (mus_is_iir_filter(p1))) &&
9006 (f1->order == f2->order) &&
9007 ((!(f1->x)) || (!(f2->x)) || (clm_arrays_are_equal(f1->x, f2->x, f1->order))) &&
9008 ((!(f1->y)) || (!(f2->y)) || (clm_arrays_are_equal(f1->y, f2->y, f1->order))) &&
9009 (clm_arrays_are_equal(f1->state, f2->state, f1->order)));
9010 }
9011
9012
describe_filter(mus_any * ptr)9013 static char *describe_filter(mus_any *ptr)
9014 {
9015 flt *gen = (flt *)ptr;
9016 char *xstr, *ystr;
9017 char *describe_buffer;
9018 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
9019 xstr = float_array_to_string(gen->x, gen->order, 0);
9020 ystr = float_array_to_string(gen->y, gen->order, 0);
9021 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s order: %d, xs: %s, ys: %s",
9022 mus_name(ptr),
9023 gen->order,
9024 xstr, ystr);
9025 if (xstr) free(xstr);
9026 if (ystr) free(ystr);
9027 return(describe_buffer);
9028 }
9029
9030
describe_fir_filter(mus_any * ptr)9031 static char *describe_fir_filter(mus_any *ptr)
9032 {
9033 flt *gen = (flt *)ptr;
9034 char *xstr;
9035 char *describe_buffer;
9036 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
9037 xstr = float_array_to_string(gen->x, gen->order, 0);
9038 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s order: %d, xs: %s",
9039 mus_name(ptr),
9040 gen->order,
9041 xstr);
9042 if (xstr) free(xstr);
9043 return(describe_buffer);
9044 }
9045
9046
describe_iir_filter(mus_any * ptr)9047 static char *describe_iir_filter(mus_any *ptr)
9048 {
9049 flt *gen = (flt *)ptr;
9050 char *ystr;
9051 char *describe_buffer;
9052 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
9053 ystr = float_array_to_string(gen->y, gen->order, 0);
9054 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s order: %d, ys: %s",
9055 mus_name(ptr),
9056 gen->order,
9057 ystr);
9058 if (ystr) free(ystr);
9059 return(describe_buffer);
9060 }
9061
9062
filter_reset(mus_any * ptr)9063 static void filter_reset(mus_any *ptr)
9064 {
9065 flt *gen = (flt *)ptr;
9066 mus_clear_floats(gen->state, gen->allocated_size * 2);
9067 }
9068
9069
9070 static mus_any_class FILTER_CLASS = {
9071 MUS_FILTER,
9072 (char *)S_filter,
9073 &free_filter,
9074 &describe_filter,
9075 &filter_equalp,
9076 &filter_data, 0,
9077 &filter_length,
9078 &filter_set_length,
9079 0, 0, 0, 0,
9080 0, 0,
9081 0, 0,
9082 &run_filter,
9083 MUS_FULL_FILTER,
9084 NULL, 0,
9085 0, 0, 0, 0,
9086 &filter_xcoeff, &filter_set_xcoeff,
9087 0, 0, 0, 0,
9088 0, 0, 0, 0, 0, 0, 0,
9089 &filter_ycoeff, &filter_set_ycoeff,
9090 &filter_xcoeffs, &filter_ycoeffs,
9091 &filter_reset,
9092 0, &flt_copy
9093 };
9094
9095
9096 static mus_any_class FIR_FILTER_CLASS = {
9097 MUS_FIR_FILTER,
9098 (char *)S_fir_filter,
9099 &free_filter,
9100 &describe_fir_filter,
9101 &filter_equalp,
9102 &filter_data, 0,
9103 &filter_length,
9104 &filter_set_length,
9105 0, 0, 0, 0,
9106 0, 0,
9107 0, 0,
9108 &run_filter,
9109 MUS_FULL_FILTER,
9110 NULL, 0,
9111 0, 0, 0, 0,
9112 &filter_xcoeff, &filter_set_xcoeff,
9113 0, 0, 0, 0,
9114 0, 0, 0, 0, 0, 0, 0,
9115 0, 0,
9116 &filter_xcoeffs, 0,
9117 &filter_reset,
9118 0, &flt_copy
9119 };
9120
9121
9122 static mus_any_class IIR_FILTER_CLASS = {
9123 MUS_IIR_FILTER,
9124 (char *)S_iir_filter,
9125 &free_filter,
9126 &describe_iir_filter,
9127 &filter_equalp,
9128 &filter_data, 0,
9129 &filter_length,
9130 &filter_set_length,
9131 0, 0, 0, 0,
9132 0, 0,
9133 0, 0,
9134 &run_filter,
9135 MUS_FULL_FILTER,
9136 NULL, 0,
9137 0, 0, 0, 0,
9138 0, 0,
9139 0, 0, 0, 0,
9140 0, 0, 0, 0, 0, 0, 0,
9141 &filter_ycoeff, &filter_set_ycoeff,
9142 0, &filter_ycoeffs,
9143 &filter_reset,
9144 0, &flt_copy
9145 };
9146
9147
set_filter_function(flt * gen)9148 static void set_filter_function(flt *gen)
9149 {
9150 /* choose the run-time function based on the current filter order and type */
9151 int order;
9152 order = gen->order - 1;
9153 if (gen->core == &FILTER_CLASS)
9154 {
9155 if (order == 2)
9156 gen->filtw = filter_two;
9157 else
9158 {
9159 if (order == 8)
9160 gen->filtw = filter_eight;
9161 else
9162 {
9163 if (order == 4)
9164 gen->filtw = filter_four;
9165 else
9166 {
9167 if (order >= 10)
9168 gen->filtw = filter_ge_10;
9169 else gen->filtw = filter_lt_10;
9170 }}}
9171 }
9172 else
9173 {
9174 if (gen->core == &FIR_FILTER_CLASS)
9175 {
9176 if (order >= 20)
9177 gen->filtw = fir_ge_20;
9178 else
9179 {
9180 if (order == 3)
9181 gen->filtw = fir_3;
9182 else
9183 {
9184 if (order == 4)
9185 gen->filtw = fir_4;
9186 else
9187 {
9188 if (order == 9)
9189 gen->filtw = fir_9;
9190 else gen->filtw = fir_n;
9191 }}}}
9192 else gen->filtw = iir_n;
9193 }
9194 }
9195
9196
make_filter(mus_any_class * cls,const char * name,int order,mus_float_t * xcoeffs,mus_float_t * ycoeffs,mus_float_t * state)9197 static mus_any *make_filter(mus_any_class *cls, const char *name, int order, mus_float_t *xcoeffs, mus_float_t *ycoeffs, mus_float_t *state)
9198 {
9199 /* if state is null, it is allocated locally, otherwise it's size should be at least 2 * order.
9200 */
9201 if (order <= 0)
9202 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_filter ": %s order = %d?", name, order);
9203 else
9204 {
9205 flt *gen;
9206 gen = (flt *)malloc(sizeof(flt));
9207 if (state)
9208 {
9209 gen->state = state;
9210 gen->state_allocated = false;
9211 }
9212 else
9213 {
9214 gen->state = (mus_float_t *)calloc(order * 2, sizeof(mus_float_t));
9215 gen->state_allocated = true;
9216 }
9217 gen->loc = 0;
9218
9219 if (cls == &FILTER_CLASS)
9220 {
9221 if (!ycoeffs)
9222 cls = &FIR_FILTER_CLASS;
9223 else
9224 {
9225 if (!xcoeffs)
9226 cls = &IIR_FILTER_CLASS;
9227 }
9228 }
9229 gen->core = cls;
9230 gen->order = order;
9231 gen->allocated_size = order;
9232 gen->x = xcoeffs;
9233 gen->y = ycoeffs;
9234 gen->filtw = NULL;
9235 set_filter_function(gen);
9236 return((mus_any *)gen);
9237 }
9238 return(NULL);
9239 }
9240
9241
mus_make_filter(int order,mus_float_t * xcoeffs,mus_float_t * ycoeffs,mus_float_t * state)9242 mus_any *mus_make_filter(int order, mus_float_t *xcoeffs, mus_float_t *ycoeffs, mus_float_t *state)
9243 {
9244 return(make_filter(&FILTER_CLASS, S_make_filter, order, xcoeffs, ycoeffs, state));
9245 }
9246
9247
mus_make_fir_filter(int order,mus_float_t * xcoeffs,mus_float_t * state)9248 mus_any *mus_make_fir_filter(int order, mus_float_t *xcoeffs, mus_float_t *state)
9249 {
9250 return(make_filter(&FIR_FILTER_CLASS, S_make_fir_filter, order, xcoeffs, NULL, state));
9251 }
9252
9253
mus_make_iir_filter(int order,mus_float_t * ycoeffs,mus_float_t * state)9254 mus_any *mus_make_iir_filter(int order, mus_float_t *ycoeffs, mus_float_t *state)
9255 {
9256 return(make_filter(&IIR_FILTER_CLASS, S_make_iir_filter, order, NULL, ycoeffs, state));
9257 }
9258
9259
mus_make_fir_coeffs(int order,mus_float_t * envl,mus_float_t * aa)9260 mus_float_t *mus_make_fir_coeffs(int order, mus_float_t *envl, mus_float_t *aa)
9261 {
9262 /* envl = evenly sampled freq response, has order samples */
9263 int n, i, j, jj;
9264 mus_float_t scl;
9265 mus_float_t *a;
9266
9267 n = order;
9268 if (n <= 0) return(aa);
9269 if (aa)
9270 a = aa;
9271 else a = (mus_float_t *)calloc(order + 1, sizeof(mus_float_t));
9272 if (!a) return(NULL);
9273 if (!(is_power_of_2(order)))
9274 {
9275 int m;
9276 mus_float_t am, q, xt0, x;
9277 m = (n + 1) / 2;
9278 am = 0.5 * (n + 1) - 1.0;
9279 scl = 2.0 / (mus_float_t)n;
9280 q = TWO_PI / (mus_float_t)n;
9281 xt0 = envl[0] * 0.5;
9282 for (j = 0, jj = n - 1; j < m; j++, jj--)
9283 {
9284 mus_float_t xt, qj;
9285 #if HAVE_SINCOS
9286 double s1, c1, s2, c2, qj1;
9287 xt = xt0;
9288 qj = q * (am - j);
9289 sincos(qj, &s1, &c1);
9290 qj1 = qj * 2.0;
9291 for (i = 1, x = qj; i < m; i += 2, x += qj1)
9292 {
9293 sincos(x, &s2, &c2);
9294 xt += (envl[i] * c2);
9295 if (i < (m - 1))
9296 xt += (envl[i + 1] * (c1 * c2 - s1 * s2));
9297 }
9298 #else
9299 xt = xt0;
9300 qj = q * (am - j);
9301 for (i = 1, x = qj; i < m; i++, x += qj)
9302 xt += (envl[i] * cos(x));
9303 #endif
9304 a[j] = xt * scl;
9305 a[jj] = a[j];
9306 }
9307 }
9308 else /* use fft if it's easy to match -- there must be a way to handle non-power-of-2 orders here
9309 * stretch envl to a power of 2, fft, subsample?
9310 */
9311 {
9312 mus_float_t *rl, *im;
9313 mus_long_t fsize;
9314 int lim;
9315 mus_float_t offset;
9316
9317 fsize = 2 * order; /* checked power of 2 above */
9318 rl = (mus_float_t *)calloc(fsize, sizeof(mus_float_t));
9319 im = (mus_float_t *)calloc(fsize, sizeof(mus_float_t));
9320 lim = order / 2;
9321 mus_copy_floats(rl, envl, lim);
9322
9323 mus_fft(rl, im, fsize, 1);
9324
9325 scl = 4.0 / fsize;
9326 offset = -2.0 * envl[0] / fsize;
9327 for (i = 0; i < fsize; i++)
9328 rl[i] = rl[i] * scl + offset;
9329 for (i = 1, j = lim - 1, jj = lim; i < order; i += 2, j--, jj++)
9330 {
9331 a[j] = rl[i];
9332 a[jj] = rl[i];
9333 }
9334 free(rl);
9335 free(im);
9336 }
9337
9338 return(a);
9339 }
9340
9341
9342
9343 /* ---------------- one-pole-all-pass ---------------- */
9344
9345 typedef struct {
9346 mus_any_class *core;
9347 int size;
9348 mus_float_t coeff;
9349 mus_float_t *x, *y;
9350 mus_float_t (*f)(mus_any *ptr, mus_float_t input);
9351 } onepall;
9352
9353
free_onepall(mus_any * ptr)9354 static void free_onepall(mus_any *ptr)
9355 {
9356 onepall *f = (onepall *)ptr;
9357 if (f->x) {free(f->x); f->x = NULL;}
9358 if (f->y) {free(f->y); f->y = NULL;}
9359 free(ptr);
9360 }
9361
onepall_copy(mus_any * ptr)9362 static mus_any *onepall_copy(mus_any *ptr)
9363 {
9364 onepall *g, *p;
9365 int bytes;
9366
9367 p = (onepall *)ptr;
9368 g = (onepall *)malloc(sizeof(onepall));
9369 memcpy((void *)g, (void *)ptr, sizeof(onepall));
9370
9371 bytes = g->size * sizeof(mus_float_t);
9372 g->x = (mus_float_t *)malloc(bytes);
9373 mus_copy_floats(g->x, p->x, g->size);
9374 g->y = (mus_float_t *)malloc(bytes);
9375 mus_copy_floats(g->y, p->y, g->size);
9376
9377 return((mus_any *)g);
9378 }
9379
9380
run_onepall(mus_any * ptr,mus_float_t input,mus_float_t unused)9381 static mus_float_t run_onepall(mus_any *ptr, mus_float_t input, mus_float_t unused)
9382 {
9383 return((((onepall *)ptr)->f)(ptr, input));
9384 }
9385
9386
onepall_length(mus_any * ptr)9387 static mus_long_t onepall_length(mus_any *ptr) {return(((onepall *)ptr)->size);}
onepall_scaler(mus_any * ptr)9388 static mus_float_t onepall_scaler(mus_any *ptr) {return(((onepall *)ptr)->coeff);}
9389
onepall_reset(mus_any * ptr)9390 static void onepall_reset(mus_any *ptr)
9391 {
9392 onepall *f = (onepall *)ptr;
9393 mus_clear_floats(f->x, f->size);
9394 mus_clear_floats(f->y, f->size);
9395 }
9396
9397
onepall_equalp(mus_any * p1,mus_any * p2)9398 static bool onepall_equalp(mus_any *p1, mus_any *p2)
9399 {
9400 onepall *f1 = (onepall *)p1;
9401 onepall *f2 = (onepall *)p2;
9402
9403 if (f1 == f2) return(true);
9404 if (f1->size != f2->size) return(false);
9405 if (f1->coeff != f2->coeff) return(false);
9406
9407 return((mus_arrays_are_equal(f1->x, f2->x, float_equal_fudge_factor, f1->size)) &&
9408 (mus_arrays_are_equal(f1->y, f2->y, float_equal_fudge_factor, f1->size)));
9409 }
9410
9411
describe_onepall(mus_any * ptr)9412 static char *describe_onepall(mus_any *ptr)
9413 {
9414 onepall *gen = (onepall *)ptr;
9415 char *describe_buffer;
9416 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
9417 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s size: %d, coeff: %f",
9418 mus_name(ptr),
9419 gen->size,
9420 gen->coeff);
9421 return(describe_buffer);
9422 }
9423
9424
mus_one_pole_all_pass(mus_any * ptr,mus_float_t input)9425 mus_float_t mus_one_pole_all_pass(mus_any *ptr, mus_float_t input)
9426 {
9427 return((((onepall *)ptr)->f)(ptr, input));
9428 }
9429
one_pole_all_pass_n(mus_any * f,mus_float_t input)9430 static mus_float_t one_pole_all_pass_n(mus_any *f, mus_float_t input)
9431 {
9432 onepall *p = (onepall *)f;
9433 int i;
9434 mus_float_t coeff, y0;
9435 mus_float_t *x, *y;
9436
9437 x = p->x;
9438 y = p->y;
9439 coeff = p->coeff;
9440
9441 y0 = input;
9442 for (i = 0; i < p->size; i++)
9443 {
9444 y[i] = x[i] + (coeff * (y0 - y[i]));
9445 x[i] = y0;
9446 y0 = y[i];
9447 }
9448 return(y0);
9449 }
9450
one_pole_all_pass_8(mus_any * f,mus_float_t input)9451 static mus_float_t one_pole_all_pass_8(mus_any *f, mus_float_t input)
9452 {
9453 onepall *p = (onepall *)f;
9454 mus_float_t coeff;
9455 mus_float_t *x, *y;
9456
9457 x = p->x;
9458 y = p->y;
9459 coeff = p->coeff;
9460
9461 y[0] = x[0] + (coeff * (input - y[0])); x[0] = input;
9462 y[1] = x[1] + (coeff * (y[0] - y[1])); x[1] = y[0];
9463 y[2] = x[2] + (coeff * (y[1] - y[2])); x[2] = y[1];
9464 y[3] = x[3] + (coeff * (y[2] - y[3])); x[3] = y[2];
9465 y[4] = x[4] + (coeff * (y[3] - y[4])); x[4] = y[3];
9466 y[5] = x[5] + (coeff * (y[4] - y[5])); x[5] = y[4];
9467 y[6] = x[6] + (coeff * (y[5] - y[6])); x[6] = y[5];
9468 y[7] = x[7] + (coeff * (y[6] - y[7])); x[7] = y[6];
9469
9470 return(y[7]);
9471 }
9472
one_pole_all_pass_1(mus_any * f,mus_float_t input)9473 static mus_float_t one_pole_all_pass_1(mus_any *f, mus_float_t input)
9474 {
9475 onepall *p = (onepall *)f;
9476
9477 p->y[0] = p->x[0] + (p->coeff * (input - p->y[0]));
9478 p->x[0] = input;
9479 return(p->y[0]);
9480 }
9481
9482
9483 static mus_any_class ONE_POLE_ALL_PASS_CLASS = {
9484 MUS_ONE_POLE_ALL_PASS,
9485 (char *)S_one_pole_all_pass,
9486 &free_onepall,
9487 &describe_onepall,
9488 &onepall_equalp,
9489 0, 0,
9490 &onepall_length, 0,
9491 0, 0,
9492 0, 0,
9493 &onepall_scaler, 0,
9494 0, 0,
9495 &run_onepall,
9496 MUS_NOT_SPECIAL,
9497 NULL, 0,
9498 0, 0, 0, 0,
9499 0, 0,
9500 0, 0, 0, 0,
9501 0, 0, 0, 0, 0, 0, 0,
9502 0, 0, 0, 0,
9503 &onepall_reset,
9504 0, &onepall_copy
9505 };
9506
9507
mus_make_one_pole_all_pass(int size,mus_float_t coeff)9508 mus_any *mus_make_one_pole_all_pass(int size, mus_float_t coeff)
9509 {
9510 onepall *gen;
9511
9512 gen = (onepall *)malloc(sizeof(onepall));
9513 gen->core = &ONE_POLE_ALL_PASS_CLASS;
9514 gen->size = size;
9515
9516 gen->x = (mus_float_t *)calloc(size, sizeof(mus_float_t));
9517 gen->y = (mus_float_t *)calloc(size, sizeof(mus_float_t));
9518 gen->coeff = coeff;
9519
9520 if (size == 1)
9521 gen->f = one_pole_all_pass_1;
9522 else
9523 {
9524 if (size == 8)
9525 gen->f = one_pole_all_pass_8;
9526 else gen->f = one_pole_all_pass_n;
9527 }
9528
9529 return((mus_any *)gen);
9530 }
9531
9532
mus_is_one_pole_all_pass(mus_any * ptr)9533 bool mus_is_one_pole_all_pass(mus_any *ptr)
9534 {
9535 return((ptr) &&
9536 (ptr->core->type == MUS_ONE_POLE_ALL_PASS));
9537 }
9538
9539
9540
9541 /* ---------------- env ---------------- */
9542
9543 typedef enum {MUS_ENV_LINEAR, MUS_ENV_EXPONENTIAL, MUS_ENV_STEP} mus_env_t;
9544
9545 typedef struct {
9546 mus_any_class *core;
9547 mus_float_t rate, current_value, base, offset, scaler, power, init_y, init_power, original_scaler, original_offset;
9548 mus_long_t loc, end;
9549 mus_env_t style;
9550 int index, size;
9551 mus_float_t *original_data;
9552 mus_float_t *rates;
9553 mus_long_t *locs;
9554 mus_float_t (*env_func)(mus_any *g);
9555 void *next;
9556 void (*free_env)(mus_any *ptr);
9557 } seg;
9558
9559 /* I used to use exp directly, but:
9560
9561 (define (texp1 start end num)
9562 (let* ((ls (log start))
9563 (le (log end))
9564 (cf (exp (/ (- le ls) (1- num))))
9565 (max-diff 0.0)
9566 (xstart start))
9567 (do ((i 0 (+ i 1)))
9568 ((= i num)
9569 max-diff)
9570 (let ((val1 (* start (exp (* (/ i (1- num)) (- le ls)))))
9571 (val2 xstart))
9572 (set! xstart (* xstart cf))
9573 (set! max-diff (max max-diff (abs (- val1 val2))))))))
9574
9575 returns:
9576
9577 :(texp1 1.0 3.0 1000000)
9578 2.65991229042584e-10
9579 :(texp1 1.0 10.0 100000000)
9580 2.24604939091932e-8
9581 :(texp1 10.0 1000.0 100000000)
9582 4.11786902532185e-6
9583 :(texp1 1.0 1.1 100000000)
9584 1.28246036013024e-9
9585 :(texp1 10.0 1000.0 1000000000)
9586 4.39423240550241e-5
9587
9588 so the repeated multiply version is more than accurate enough
9589 */
9590
9591
mus_is_env(mus_any * ptr)9592 bool mus_is_env(mus_any *ptr)
9593 {
9594 return((ptr) &&
9595 (ptr->core->type == MUS_ENV));
9596 }
9597
9598
mus_env(mus_any * ptr)9599 mus_float_t mus_env(mus_any *ptr)
9600 {
9601 seg *gen = (seg *)ptr;
9602 return((*(gen->env_func))(ptr));
9603 }
9604
9605
mus_env_function(mus_any * g)9606 mus_float_t (*mus_env_function(mus_any *g))(mus_any *gen)
9607 {
9608 if (mus_is_env(g))
9609 return(((seg *)g)->env_func);
9610 return(NULL);
9611 }
9612
9613
mus_env_step(mus_any * ptr)9614 static mus_float_t mus_env_step(mus_any *ptr)
9615 {
9616 seg *gen = (seg *)ptr;
9617 mus_float_t val;
9618 val = gen->current_value;
9619 if (gen->loc == 0)
9620 {
9621 gen->index++;
9622 gen->loc = gen->locs[gen->index] - gen->locs[gen->index - 1];
9623 gen->rate = gen->rates[gen->index];
9624 gen->current_value = gen->rate;
9625 }
9626 gen->loc--;
9627 return(val);
9628 }
9629
9630
mus_env_line(mus_any * ptr)9631 static mus_float_t mus_env_line(mus_any *ptr)
9632 {
9633 seg *gen = (seg *)ptr;
9634 return(gen->current_value);
9635 }
9636
9637
mus_env_linear(mus_any * ptr)9638 static mus_float_t mus_env_linear(mus_any *ptr)
9639 {
9640 seg *gen = (seg *)ptr;
9641 mus_float_t val;
9642
9643 val = gen->current_value;
9644 if (gen->loc == 0)
9645 {
9646 /* we can save about 10% total env time by checking here that we're on the last segment,
9647 * and setting gen->env_func to a version of mus_env_linear that does not watch gen->loc.
9648 * In any case, this code is strange -- change anything and it is 20% slower, sez callgrind.
9649 */
9650 gen->index++;
9651 gen->loc = gen->locs[gen->index] - gen->locs[gen->index - 1];
9652 gen->rate = gen->rates[gen->index];
9653 }
9654 gen->current_value += gen->rate;
9655 gen->loc--;
9656 return(val);
9657 }
9658
9659
mus_env_exponential(mus_any * ptr)9660 static mus_float_t mus_env_exponential(mus_any *ptr)
9661 {
9662 seg *gen = (seg *)ptr;
9663 mus_float_t val;
9664 val = gen->current_value;
9665 if (gen->loc == 0)
9666 {
9667 gen->index++;
9668 gen->loc = gen->locs[gen->index] - gen->locs[gen->index - 1];
9669 gen->rate = gen->rates[gen->index];
9670 }
9671 gen->power *= gen->rate;
9672 gen->current_value = gen->offset + (gen->scaler * gen->power);
9673 gen->loc--;
9674 return(val);
9675 }
9676
9677
run_env(mus_any * ptr,mus_float_t unused1,mus_float_t unused2)9678 static mus_float_t run_env(mus_any *ptr, mus_float_t unused1, mus_float_t unused2)
9679 {
9680 return(mus_env(ptr));
9681 }
9682
9683
canonicalize_env(seg * e,const mus_float_t * data,int pts,mus_long_t dur,mus_float_t scaler)9684 static void canonicalize_env(seg *e, const mus_float_t *data, int pts, mus_long_t dur, mus_float_t scaler)
9685 {
9686 int i, j, pts2;
9687 mus_float_t xscl, cur_loc, x1, y1, xdur;
9688 mus_long_t samps, pre_loc;
9689
9690 /* pts > 1 if we get here, so the loop below is always exercised */
9691
9692 pts2 = pts * 2;
9693 xdur = data[pts2 - 2] - data[0];
9694 if (xdur > 0.0)
9695 xscl = (mus_float_t)(dur - 1) / xdur;
9696 else xscl = 1.0;
9697 e->locs[pts - 2] = e->end;
9698
9699 x1 = data[0];
9700 y1 = data[1];
9701 pre_loc = 0;
9702
9703 for (j = 0, i = 2, cur_loc = 0.0; i < pts2; i += 2, j++)
9704 {
9705 mus_float_t cur_dx, x0, y0;
9706 x0 = x1;
9707 x1 = data[i];
9708 y0 = y1;
9709 y1 = data[i + 1];
9710
9711 cur_dx = xscl * (x1 - x0);
9712 if (cur_dx < 1.0)
9713 cur_loc += 1.0;
9714 else cur_loc += cur_dx;
9715
9716 switch (e->style)
9717 {
9718 case MUS_ENV_LINEAR:
9719 e->locs[j] = (mus_long_t)(cur_loc + 0.5);
9720 samps = e->locs[j] - pre_loc;
9721 pre_loc = e->locs[j];
9722
9723 if (samps == 0)
9724 e->rates[j] = 0.0;
9725 else e->rates[j] = scaler * (y1 - y0) / (mus_float_t)samps;
9726 break;
9727
9728 case MUS_ENV_EXPONENTIAL:
9729 e->locs[j] = (mus_long_t)(cur_loc + 0.5);
9730 samps = e->locs[j] - pre_loc;
9731 pre_loc = e->locs[j];
9732
9733 if (samps == 0)
9734 e->rates[j] = 1.0;
9735 else e->rates[j] = exp((y1 - y0) / (mus_float_t)samps);
9736 break;
9737
9738 case MUS_ENV_STEP:
9739 e->locs[j] = (mus_long_t)cur_loc; /* this is the change boundary (confusing...) */
9740 e->rates[j] = e->offset + (scaler * y0);
9741 break;
9742 }
9743 }
9744
9745 e->locs[pts - 1] = 1000000000;
9746 e->locs[pts] = 1000000000; /* guard cell at end to make bounds check simpler */
9747 }
9748
9749
fixup_exp_env(seg * e,const mus_float_t * data,int pts,mus_float_t offset,mus_float_t scaler,mus_float_t base)9750 static mus_float_t *fixup_exp_env(seg *e, const mus_float_t *data, int pts, mus_float_t offset, mus_float_t scaler, mus_float_t base)
9751 {
9752 mus_float_t min_y, max_y, val = 0.0, tmp, b1;
9753 int len, i;
9754 bool flat;
9755 mus_float_t *result = NULL;
9756
9757 if ((base <= 0.0) ||
9758 (base == 1.0))
9759 return(NULL);
9760
9761 min_y = offset + scaler * data[1];
9762 max_y = min_y;
9763 len = pts * 2;
9764
9765 /* fill "result" with x and (offset+scaler*y) */
9766
9767 result = (mus_float_t *)malloc(len * sizeof(mus_float_t));
9768 result[0] = data[0];
9769 result[1] = min_y;
9770
9771 for (i = 2; i < len; i += 2)
9772 {
9773 tmp = offset + scaler * data[i + 1];
9774 result[i] = data[i];
9775 result[i + 1] = tmp;
9776 if (tmp < min_y) min_y = tmp;
9777 if (tmp > max_y) max_y = tmp;
9778 }
9779
9780 b1 = base - 1.0;
9781 flat = (min_y == max_y);
9782 if (!flat)
9783 val = 1.0 / (max_y - min_y);
9784
9785 /* now logify result */
9786 for (i = 1; i < len; i += 2)
9787 {
9788 if (flat)
9789 tmp = 1.0;
9790 else tmp = val * (result[i] - min_y);
9791 result[i] = log1p(tmp * b1);
9792 }
9793
9794 e->scaler = (max_y - min_y) / b1;
9795 e->offset = min_y;
9796 return(result);
9797 }
9798
9799
env_equalp(mus_any * p1,mus_any * p2)9800 static bool env_equalp(mus_any *p1, mus_any *p2)
9801 {
9802 seg *e1 = (seg *)p1;
9803 seg *e2 = (seg *)p2;
9804 if (p1 == p2) return(true);
9805 return((e1) && (e2) &&
9806 (e1->core->type == e2->core->type) &&
9807 (e1->loc == e2->loc) &&
9808 (e1->end == e2->end) &&
9809 (e1->style == e2->style) &&
9810 (e1->index == e2->index) &&
9811 (e1->size == e2->size) &&
9812
9813 (e1->rate == e2->rate) &&
9814 (e1->base == e2->base) &&
9815 (e1->power == e2->power) &&
9816 (e1->current_value == e2->current_value) &&
9817 (e1->scaler == e2->scaler) &&
9818 (e1->offset == e2->offset) &&
9819 (e1->init_y == e2->init_y) &&
9820 (e1->init_power == e2->init_power) &&
9821 (clm_arrays_are_equal(e1->original_data, e2->original_data, e1->size * 2)));
9822 }
9823
9824
describe_env(mus_any * ptr)9825 static char *describe_env(mus_any *ptr)
9826 {
9827 char *str = NULL;
9828 seg *e = (seg *)ptr;
9829 char *describe_buffer;
9830 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
9831 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s %s, pass: %" print_mus_long " (dur: %" print_mus_long "), index: %d, scaler: %.4f, offset: %.4f, data: %s",
9832 mus_name(ptr),
9833 ((e->style == MUS_ENV_LINEAR) ? "linear" : ((e->style == MUS_ENV_EXPONENTIAL) ? "exponential" : "step")),
9834 (e->locs) ? (e->locs[e->index] - e->loc) : -1,
9835 e->end + 1,
9836 e->index,
9837 e->original_scaler,
9838 e->original_offset,
9839 str = float_array_to_string(e->original_data, e->size * 2, 0));
9840 if (str) free(str);
9841 return(describe_buffer);
9842 }
9843
9844
9845 static seg *e2_free_list = NULL, *e3_free_list = NULL, *e4_free_list = NULL;
9846
free_env_gen(mus_any * pt)9847 static void free_env_gen(mus_any *pt)
9848 {
9849 seg *ptr = (seg *)pt;
9850 (*(ptr->free_env))(pt);
9851 }
9852
fe2(mus_any * pt)9853 static void fe2(mus_any *pt)
9854 {
9855 seg *ptr = (seg *)pt;
9856 ptr->next = e2_free_list;
9857 e2_free_list = ptr;
9858 }
9859
fe3(mus_any * pt)9860 static void fe3(mus_any *pt)
9861 {
9862 seg *ptr = (seg *)pt;
9863 ptr->next = e3_free_list;
9864 e3_free_list = ptr;
9865 }
9866
fe4(mus_any * pt)9867 static void fe4(mus_any *pt)
9868 {
9869 seg *ptr = (seg *)pt;
9870 ptr->next = e4_free_list;
9871 e4_free_list = ptr;
9872 }
9873
ferest(mus_any * pt)9874 static void ferest(mus_any *pt)
9875 {
9876 seg *ptr = (seg *)pt;
9877 if (ptr->locs) {free(ptr->locs); ptr->locs = NULL;}
9878 if (ptr->rates) {free(ptr->rates); ptr->rates = NULL;}
9879 free(ptr);
9880 }
9881
seg_copy(mus_any * ptr)9882 static mus_any *seg_copy(mus_any *ptr)
9883 {
9884 seg *e = NULL, *p;
9885 p = (seg *)ptr;
9886
9887 switch (p->size) /* "npts" */
9888 {
9889 case 1:
9890 e = (seg *)malloc(sizeof(seg));
9891 memcpy((void *)e, (void *)ptr, sizeof(seg));
9892 return((mus_any *)e);
9893
9894 case 2: if (e2_free_list) {e = e2_free_list; e2_free_list = (seg *)(e->next);} break;
9895 case 3: if (e3_free_list) {e = e3_free_list; e3_free_list = (seg *)(e->next);} break;
9896 case 4: if (e4_free_list) {e = e4_free_list; e4_free_list = (seg *)(e->next);} break;
9897 default: break;
9898 }
9899
9900 if (!e)
9901 {
9902 e = (seg *)malloc(sizeof(seg));
9903 memcpy((void *)e, (void *)ptr, sizeof(seg));
9904 if (p->rates)
9905 {
9906 int bytes;
9907 e->rates = (mus_float_t *)malloc(p->size * sizeof(mus_float_t));
9908 mus_copy_floats(e->rates, p->rates, p->size);
9909
9910 bytes = (p->size + 1) * sizeof(mus_long_t);
9911 e->locs = (mus_long_t *)malloc(bytes);
9912 memcpy((void *)(e->locs), (void *)(p->locs), bytes);
9913 }
9914 }
9915 else
9916 {
9917 mus_float_t *r;
9918 mus_long_t *l;
9919 int bytes;
9920
9921 r = e->rates;
9922 mus_copy_floats(r, p->rates, p->size);
9923
9924 bytes = (p->size + 1) * sizeof(mus_long_t);
9925 l = e->locs;
9926 memcpy((void *)l, (void *)(p->locs), bytes);
9927
9928 memcpy((void *)e, (void *)ptr, sizeof(seg));
9929 e->rates = r;
9930 e->locs = l;
9931 }
9932 return((mus_any *)e);
9933 }
9934
env_data(mus_any * ptr)9935 static mus_float_t *env_data(mus_any *ptr) {return(((seg *)ptr)->original_data);} /* mus-data */
9936
env_scaler(mus_any * ptr)9937 static mus_float_t env_scaler(mus_any *ptr) {return(((seg *)ptr)->original_scaler);} /* "mus_float_t" for mus-scaler */
9938
env_offset(mus_any * ptr)9939 static mus_float_t env_offset(mus_any *ptr) {return(((seg *)ptr)->original_offset);}
9940
mus_env_breakpoints(mus_any * ptr)9941 int mus_env_breakpoints(mus_any *ptr) {return(((seg *)ptr)->size);}
9942
env_length(mus_any * ptr)9943 static mus_long_t env_length(mus_any *ptr) {return((((seg *)ptr)->end + 1));} /* this needs to match the :length arg to make-env (changed to +1, 20-Feb-08) */
9944
env_current_value(mus_any * ptr)9945 static mus_float_t env_current_value(mus_any *ptr) {return(((seg *)ptr)->current_value);}
9946
mus_env_passes(mus_any * gen)9947 mus_long_t *mus_env_passes(mus_any *gen) {return(((seg *)gen)->locs);}
9948
mus_env_rates(mus_any * gen)9949 mus_float_t *mus_env_rates(mus_any *gen) {return(((seg *)gen)->rates);}
9950
env_position(mus_any * ptr)9951 static int env_position(mus_any *ptr) {return(((seg *)ptr)->index);}
9952
mus_env_offset(mus_any * gen)9953 mus_float_t mus_env_offset(mus_any *gen) {return(((seg *)gen)->offset);}
9954
mus_env_scaler(mus_any * gen)9955 mus_float_t mus_env_scaler(mus_any *gen) {return(((seg *)gen)->scaler);}
9956
mus_env_initial_power(mus_any * gen)9957 mus_float_t mus_env_initial_power(mus_any *gen) {return(((seg *)gen)->init_power);}
9958
9959 static void env_set_location(mus_any *ptr, mus_long_t val);
9960
seg_set_pass(mus_any * ptr,mus_long_t val)9961 static mus_long_t seg_set_pass(mus_any *ptr, mus_long_t val) {env_set_location(ptr, val); return(val);}
9962
seg_pass(mus_any * ptr)9963 static mus_long_t seg_pass(mus_any *ptr)
9964 {
9965 seg *gen = (seg *)ptr;
9966 return(gen->locs[gen->index] - gen->loc);
9967 }
9968
9969
env_increment(mus_any * rd)9970 static mus_float_t env_increment(mus_any *rd)
9971 {
9972 if (((seg *)rd)->style == MUS_ENV_STEP)
9973 return(0.0);
9974 return(((seg *)rd)->base);
9975 }
9976
9977
env_reset(mus_any * ptr)9978 static void env_reset(mus_any *ptr)
9979 {
9980 seg *gen = (seg *)ptr;
9981 gen->current_value = gen->init_y;
9982 gen->index = 0;
9983 gen->loc = gen->locs[0];
9984 gen->rate = gen->rates[0];
9985 gen->power = gen->init_power;
9986 }
9987
9988
rebuild_env(seg * e,mus_float_t scl,mus_float_t off,mus_long_t end)9989 static void rebuild_env(seg *e, mus_float_t scl, mus_float_t off, mus_long_t end)
9990 {
9991 seg *new_e;
9992
9993 new_e = (seg *)mus_make_env(e->original_data, e->size, scl, off, e->base, 0.0, end, NULL);
9994 if (e->locs) free(e->locs);
9995 if (e->rates) free(e->rates);
9996 e->locs = new_e->locs;
9997 e->rates = new_e->rates;
9998
9999 e->init_y = new_e->init_y;
10000 e->init_power = new_e->init_power;
10001 env_reset((mus_any *)e);
10002
10003 free(new_e);
10004 }
10005
10006
env_set_scaler(mus_any * ptr,mus_float_t val)10007 static mus_float_t env_set_scaler(mus_any *ptr, mus_float_t val)
10008 {
10009 seg *e;
10010 e = (seg *)ptr;
10011 rebuild_env(e, val, e->original_offset, e->end);
10012 e->original_scaler = val;
10013 return(val);
10014 }
10015
10016
env_set_offset(mus_any * ptr,mus_float_t val)10017 static mus_float_t env_set_offset(mus_any *ptr, mus_float_t val)
10018 {
10019 seg *e;
10020 e = (seg *)ptr;
10021 rebuild_env(e, e->original_scaler, val, e->end);
10022 e->original_offset = val;
10023 return(val);
10024 }
10025
10026
env_set_length(mus_any * ptr,mus_long_t val)10027 static mus_long_t env_set_length(mus_any *ptr, mus_long_t val)
10028 {
10029 seg *e;
10030 e = (seg *)ptr;
10031 rebuild_env(e, e->original_scaler, e->original_offset, val - 1);
10032 e->end = val - 1;
10033 return(val);
10034 }
10035
10036
10037 static mus_any_class ENV_CLASS = {
10038 MUS_ENV,
10039 (char *)S_env,
10040 &free_env_gen,
10041 &describe_env,
10042 &env_equalp,
10043 &env_data, /* mus-data -> original breakpoints */
10044 0,
10045 &env_length, &env_set_length,
10046 0, 0,
10047 &env_current_value, 0, /* mus-phase?? -- used in snd-sig.c, but this needs a better access point */
10048 &env_scaler, &env_set_scaler,
10049 &env_increment,
10050 0,
10051 &run_env,
10052 MUS_NOT_SPECIAL,
10053 NULL,
10054 &env_position,
10055 &env_offset, &env_set_offset,
10056 0, 0, 0, 0, 0, 0, 0, 0,
10057 0, 0, 0, 0,
10058 &seg_pass, &seg_set_pass,
10059 0,
10060 0, 0, 0, 0,
10061 &env_reset,
10062 0, &seg_copy
10063 };
10064
10065
mus_make_env(mus_float_t * brkpts,int npts,mus_float_t scaler,mus_float_t offset,mus_float_t base,mus_float_t duration,mus_long_t end,mus_float_t * ignored)10066 mus_any *mus_make_env(mus_float_t *brkpts, int npts, mus_float_t scaler, mus_float_t offset, mus_float_t base, mus_float_t duration, mus_long_t end, mus_float_t *ignored)
10067 {
10068 /* brkpts are not freed by the new env gen when it is freed, but should be protected during its existence */
10069 int i;
10070 mus_long_t dur_in_samples;
10071 mus_float_t *edata;
10072 seg *e = NULL;
10073 void (*fe_release)(mus_any *ptr);
10074
10075 for (i = 2; i < npts * 2; i += 2)
10076 if (brkpts[i - 2] >= brkpts[i])
10077 {
10078 char *temp = NULL;
10079 mus_error(MUS_BAD_ENVELOPE, S_make_env ": env at breakpoint %d: x axis value: %f <= previous x value: %f (env: %s)",
10080 i / 2, brkpts[i], brkpts[i - 2],
10081 temp = float_array_to_string(brkpts, npts * 2, 0)); /* minor memleak here */
10082 if (temp) free(temp);
10083 return(NULL);
10084 }
10085
10086 switch (npts)
10087 {
10088 case 1:
10089 e = (seg *)calloc(1, sizeof(seg));
10090 e->core = &ENV_CLASS;
10091 e->current_value = offset + scaler * brkpts[1];
10092 e->env_func = mus_env_line;
10093 e->original_data = brkpts;
10094 e->free_env = ferest;
10095 return((mus_any *)e);
10096
10097 case 2:
10098 if (e2_free_list)
10099 {
10100 e = e2_free_list;
10101 e2_free_list = (seg *)(e->next);
10102 }
10103 fe_release = fe2;
10104 break;
10105
10106 case 3:
10107 if (e3_free_list)
10108 {
10109 e = e3_free_list;
10110 e3_free_list = (seg *)(e->next);
10111 }
10112 fe_release = fe3;
10113 break;
10114
10115 case 4:
10116 if (e4_free_list)
10117 {
10118 e = e4_free_list;
10119 e4_free_list = (seg *)(e->next);
10120 }
10121 fe_release = fe4;
10122 break;
10123
10124 default:
10125 fe_release = ferest;
10126 break;
10127 }
10128
10129 if (!e)
10130 {
10131 e = (seg *)malloc(sizeof(seg));
10132 e->core = &ENV_CLASS;
10133 e->size = npts;
10134 e->rates = (mus_float_t *)malloc(npts * sizeof(mus_float_t));
10135 e->locs = (mus_long_t *)malloc((npts + 1) * sizeof(mus_long_t));
10136 }
10137
10138 e->free_env = fe_release;
10139 e->original_data = brkpts;
10140
10141 if (duration != 0.0)
10142 dur_in_samples = (mus_long_t)(duration * sampling_rate);
10143 else dur_in_samples = (end + 1);
10144
10145 e->init_y = offset + scaler * brkpts[1];
10146 e->current_value = e->init_y;
10147 e->rate = 0.0;
10148 e->offset = offset;
10149 e->scaler = scaler;
10150 e->original_offset = offset;
10151 e->original_scaler = scaler;
10152 e->base = base;
10153 e->end = (dur_in_samples - 1);
10154 e->loc = 0;
10155 e->index = 0;
10156
10157 if (base == 1.0)
10158 {
10159 e->style = MUS_ENV_LINEAR;
10160 if ((npts == 2) &&
10161 (brkpts[1] == brkpts[3]))
10162 e->env_func = mus_env_line;
10163 else e->env_func = mus_env_linear;
10164 e->power = 0.0;
10165 e->init_power = 0.0;
10166 canonicalize_env(e, brkpts, npts, dur_in_samples, scaler);
10167 e->rates[npts - 1] = 0.0;
10168 }
10169 else
10170 {
10171 if (base == 0.0)
10172 {
10173 e->style = MUS_ENV_STEP;
10174 e->env_func = mus_env_step;
10175 e->power = 0.0;
10176 e->init_power = 0.0;
10177 canonicalize_env(e, brkpts, npts, dur_in_samples, scaler);
10178 e->rates[npts - 1] = e->offset + (scaler * brkpts[npts * 2 - 1]); /* stick at last value, which in this case is the value (not an increment) */
10179 }
10180 else
10181 {
10182 e->style = MUS_ENV_EXPONENTIAL;
10183 e->env_func = mus_env_exponential;
10184 edata = fixup_exp_env(e, brkpts, npts, offset, scaler, base);
10185 if (!edata)
10186 {
10187 free(e);
10188 return(NULL);
10189 }
10190 canonicalize_env(e, edata, npts, dur_in_samples, 1.0);
10191 e->rates[npts - 1] = 1.0;
10192 e->power = exp(edata[1]);
10193 e->init_power = e->power;
10194 e->offset -= e->scaler;
10195 free(edata);
10196 }
10197 }
10198
10199 e->rate = e->rates[0];
10200 e->loc = e->locs[0];
10201 return((mus_any *)e);
10202 }
10203
10204 /* one way to make an impulse: (make-env '(0 1 1 0) :length 1 :base 0.0)
10205 * a counter: (make-env '(0 0 1 1) :length 21 :scaler 20) -- length = 1+scaler
10206 */
10207
10208
env_set_location(mus_any * ptr,mus_long_t val)10209 static void env_set_location(mus_any *ptr, mus_long_t val)
10210 {
10211 seg *gen = (seg *)ptr;
10212 mus_long_t ctr = 0, loc;
10213
10214 loc = gen->locs[gen->index] - gen->loc;
10215 if (loc == val) return;
10216
10217 if (loc > val)
10218 mus_reset(ptr);
10219 else ctr = loc;
10220
10221 while ((gen->index < (gen->size - 1)) && /* this was gen->size */
10222 (ctr < val))
10223 {
10224 mus_long_t samps;
10225 if (val > gen->locs[gen->index])
10226 samps = gen->locs[gen->index] - ctr;
10227 else samps = val - ctr;
10228
10229 switch (gen->style)
10230 {
10231 case MUS_ENV_LINEAR:
10232 gen->current_value += (samps * gen->rate);
10233 break;
10234
10235 case MUS_ENV_STEP:
10236 gen->current_value = gen->rate;
10237 break;
10238
10239 case MUS_ENV_EXPONENTIAL:
10240 gen->power *= exp(samps * log(gen->rate));
10241 gen->current_value = gen->offset + (gen->scaler * gen->power);
10242 break;
10243 }
10244
10245 ctr += samps;
10246 if (ctr < val)
10247 {
10248 gen->index++;
10249 if (gen->index < gen->size)
10250 gen->rate = gen->rates[gen->index];
10251 }
10252 }
10253 gen->loc = gen->locs[gen->index] - ctr;
10254 }
10255
10256
mus_env_interp(mus_float_t x,mus_any * ptr)10257 mus_float_t mus_env_interp(mus_float_t x, mus_any *ptr)
10258 {
10259 /* the accuracy depends on the duration here -- more samples = more accurate */
10260 seg *gen = (seg *)ptr;
10261 env_set_location(ptr, (mus_long_t)((x * (gen->end + 1)) / (gen->original_data[gen->size * 2 - 2])));
10262 return(gen->current_value);
10263 }
10264
10265
mus_env_any(mus_any * e,mus_float_t (* connect_points)(mus_float_t val))10266 mus_float_t mus_env_any(mus_any *e, mus_float_t (*connect_points)(mus_float_t val))
10267 {
10268 /* "env_any" is supposed to mimic "out-any" */
10269 seg *gen = (seg *)e;
10270 mus_float_t *pts;
10271 int pt, size;
10272 mus_float_t y0, y1, new_val, val;
10273 mus_float_t scaler, offset;
10274
10275 scaler = gen->original_scaler;
10276 offset = gen->original_offset;
10277 size = gen->size;
10278
10279 if (size <= 1)
10280 return(offset + scaler * connect_points(0.0));
10281
10282 pts = gen->original_data;
10283 pt = gen->index;
10284 if (pt >= (size - 1)) pt = size - 2;
10285 if (pts[pt * 2 + 1] <= pts[pt * 2 + 3])
10286 {
10287 y0 = pts[pt * 2 + 1];
10288 y1 = pts[pt * 2 + 3];
10289 }
10290 else
10291 {
10292 y1 = pts[pt * 2 + 1];
10293 y0 = pts[pt * 2 + 3];
10294 }
10295
10296 val = (mus_env(e) - offset) / scaler;
10297 new_val = connect_points( (val - y0) / (y1 - y0));
10298 return(offset + scaler * (y0 + new_val * (y1 - y0)));
10299 }
10300
10301
10302 /* ---------------- pulsed-env ---------------- */
10303
10304 typedef struct {
10305 mus_any_class *core;
10306 mus_any *e, *p;
10307 bool gens_allocated;
10308 } plenv;
10309
10310
free_pulsed_env(mus_any * ptr)10311 static void free_pulsed_env(mus_any *ptr)
10312 {
10313 plenv *g;
10314 g = (plenv *)ptr;
10315 if (g->gens_allocated)
10316 {
10317 mus_free(g->e);
10318 mus_free(g->p);
10319 }
10320 free(ptr);
10321 }
10322
plenv_copy(mus_any * ptr)10323 static mus_any *plenv_copy(mus_any *ptr)
10324 {
10325 plenv *g, *p;
10326 p = (plenv *)ptr;
10327 g = (plenv *)malloc(sizeof(plenv));
10328 memcpy((void *)g, (void *)ptr, sizeof(plenv));
10329 g->gens_allocated = true;
10330 g->e = mus_copy(p->e);
10331 g->p = mus_copy(p->p);
10332 return((mus_any *)g);
10333 }
10334
10335
run_pulsed_env(mus_any * ptr,mus_float_t input,mus_float_t unused)10336 static mus_float_t run_pulsed_env(mus_any *ptr, mus_float_t input, mus_float_t unused)
10337 {
10338 return(mus_pulsed_env(ptr, input));
10339 }
10340
10341
pulsed_env_reset(mus_any * ptr)10342 static void pulsed_env_reset(mus_any *ptr)
10343 {
10344 plenv *pl = (plenv *)ptr;
10345 mus_reset(pl->e);
10346 mus_reset(pl->p);
10347 }
10348
10349
pulsed_env_equalp(mus_any * p1,mus_any * p2)10350 static bool pulsed_env_equalp(mus_any *p1, mus_any *p2)
10351 {
10352 plenv *f1 = (plenv *)p1;
10353 plenv *f2 = (plenv *)p2;
10354
10355 if (f1 == f2) return(true);
10356 return((env_equalp(f1->e, f2->e)) &&
10357 (sw_equalp(f1->p, f2->p)));
10358 }
10359
10360
describe_pulsed_env(mus_any * ptr)10361 static char *describe_pulsed_env(mus_any *ptr)
10362 {
10363 char *describe_buffer;
10364 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
10365 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s",
10366 mus_name(ptr));
10367 return(describe_buffer);
10368 }
10369
10370 static mus_any_class PULSED_ENV_CLASS = {
10371 MUS_PULSED_ENV,
10372 (char *)S_pulsed_env,
10373 &free_pulsed_env,
10374 &describe_pulsed_env,
10375 &pulsed_env_equalp,
10376 0, 0,
10377 0, 0,
10378 0, 0,
10379 0, 0,
10380 0, 0,
10381 0, 0,
10382 &run_pulsed_env,
10383 MUS_NOT_SPECIAL,
10384 NULL, 0,
10385 0, 0, 0, 0,
10386 0, 0,
10387 0, 0, 0, 0,
10388 0, 0, 0, 0, 0, 0, 0,
10389 0, 0, 0, 0,
10390 &pulsed_env_reset,
10391 0, &plenv_copy
10392 };
10393
10394
mus_make_pulsed_env(mus_any * e,mus_any * p)10395 mus_any *mus_make_pulsed_env(mus_any *e, mus_any *p)
10396 {
10397 plenv *gen;
10398
10399 gen = (plenv *)malloc(sizeof(plenv));
10400 gen->core = &PULSED_ENV_CLASS;
10401 gen->e = e;
10402 gen->p = p;
10403 gen->gens_allocated = false;
10404 return((mus_any *)gen);
10405 }
10406
mus_is_pulsed_env(mus_any * ptr)10407 bool mus_is_pulsed_env(mus_any *ptr)
10408 {
10409 return((ptr) &&
10410 (ptr->core->type == MUS_PULSED_ENV));
10411 }
10412
mus_pulsed_env(mus_any * g,mus_float_t inval)10413 mus_float_t mus_pulsed_env(mus_any *g, mus_float_t inval)
10414 {
10415 plenv *pl = (plenv *)g;
10416 mus_float_t pt_val;
10417 pt_val = mus_pulse_train(pl->p, inval);
10418 if (pt_val > 0.1)
10419 mus_reset(pl->e);
10420 return(mus_env(pl->e));
10421 }
10422
10423
mus_pulsed_env_unmodulated(mus_any * g)10424 mus_float_t mus_pulsed_env_unmodulated(mus_any *g)
10425 {
10426 plenv *pl = (plenv *)g;
10427 mus_float_t pt_val;
10428 pt_val = mus_pulse_train_unmodulated(pl->p);
10429 if (pt_val > 0.1)
10430 mus_reset(pl->e);
10431 return(mus_env(pl->e));
10432 }
10433
10434
10435
10436
10437 /* ---------------- input/output ---------------- */
10438
mus_read_sample(mus_any * fd,mus_long_t frample,int chan)10439 static mus_float_t mus_read_sample(mus_any *fd, mus_long_t frample, int chan)
10440 {
10441 if ((check_gen(fd, "mus-read-sample")) &&
10442 ((fd->core)->read_sample))
10443 return(((*(fd->core)->read_sample))(fd, frample, chan));
10444 return((mus_float_t)mus_error(MUS_NO_SAMPLE_INPUT,
10445 ":can't find %s's sample input function",
10446 mus_name(fd)));
10447 }
10448
10449
mus_is_input(mus_any * gen)10450 bool mus_is_input(mus_any *gen)
10451 {
10452 return((gen) &&
10453 (gen->core->extended_type == MUS_INPUT));
10454 }
10455
10456
mus_is_output(mus_any * gen)10457 bool mus_is_output(mus_any *gen)
10458 {
10459 return((gen) &&
10460 (gen->core->extended_type == MUS_OUTPUT));
10461 }
10462
10463
10464
10465 /* ---------------- file->sample ---------------- */
10466
10467 typedef struct {
10468 mus_any_class *core;
10469 int chan;
10470 int dir;
10471 mus_long_t loc;
10472 char *file_name;
10473 int chans;
10474 mus_float_t **ibufs, **saved_data;
10475 mus_float_t *sbuf;
10476 mus_long_t data_start, data_end, file_end;
10477 mus_long_t file_buffer_size;
10478 mus_float_t (*reader)(mus_any *ptr);
10479 } rdin;
10480
10481
describe_file_to_sample(mus_any * ptr)10482 static char *describe_file_to_sample(mus_any *ptr)
10483 {
10484 rdin *gen = (rdin *)ptr;
10485 char *describe_buffer;
10486 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
10487 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s \"%s\"",
10488 mus_name(ptr),
10489 gen->file_name);
10490 return(describe_buffer);
10491 }
10492
10493
rdin_equalp(mus_any * p1,mus_any * p2)10494 static bool rdin_equalp(mus_any *p1, mus_any *p2)
10495 {
10496 rdin *r1 = (rdin *)p1;
10497 rdin *r2 = (rdin *)p2;
10498 return((p1 == p2) ||
10499 ((r1) && (r2) &&
10500 (r1->core->type == r2->core->type) &&
10501 (r1->chan == r2->chan) &&
10502 (r1->loc == r2->loc) &&
10503 (r1->dir == r2->dir) &&
10504 (r1->file_name) &&
10505 (r2->file_name) &&
10506 (strcmp(r1->file_name, r2->file_name) == 0)));
10507 }
10508
10509
free_file_to_sample(mus_any * p)10510 static void free_file_to_sample(mus_any *p)
10511 {
10512 rdin *ptr = (rdin *)p;
10513 if (ptr->core->end) ((*ptr->core->end))(p);
10514 free(ptr->file_name);
10515 free(ptr);
10516 }
10517
make_ibufs(rdin * gen)10518 static mus_long_t make_ibufs(rdin *gen)
10519 {
10520 int i;
10521 mus_long_t len;
10522 len = gen->file_end + 1;
10523 if (len > gen->file_buffer_size)
10524 len = gen->file_buffer_size;
10525
10526 gen->ibufs = (mus_float_t **)malloc(gen->chans * sizeof(mus_float_t *));
10527 for (i = 0; i < gen->chans; i++)
10528 gen->ibufs[i] = (mus_float_t *)malloc(len * sizeof(mus_float_t));
10529
10530 return(len);
10531 }
10532
rdin_copy(mus_any * ptr)10533 static mus_any *rdin_copy(mus_any *ptr)
10534 {
10535 rdin *g, *p;
10536 p = (rdin *)ptr;
10537 g = (rdin *)malloc(sizeof(rdin));
10538 memcpy((void *)g, (void *)ptr, sizeof(rdin));
10539 g->file_name = mus_strdup(p->file_name);
10540 if (p->ibufs)
10541 {
10542 int i;
10543 mus_long_t len;
10544 len = make_ibufs(g);
10545 for (i = 0; i < g->chans; i++)
10546 mus_copy_floats(g->ibufs[i], p->ibufs[i], len);
10547 }
10548 return((mus_any *)g);
10549 }
10550
file_to_sample_length(mus_any * ptr)10551 static mus_long_t file_to_sample_length(mus_any *ptr) {return((((rdin *)ptr)->file_end));}
10552
file_to_sample_channels(mus_any * ptr)10553 static int file_to_sample_channels(mus_any *ptr) {return((int)(((rdin *)ptr)->chans));}
10554
file_to_sample_increment(mus_any * rd)10555 static mus_float_t file_to_sample_increment(mus_any *rd) {return((mus_float_t)(((rdin *)rd)->dir));}
file_to_sample_set_increment(mus_any * rd,mus_float_t val)10556 static mus_float_t file_to_sample_set_increment(mus_any *rd, mus_float_t val) {((rdin *)rd)->dir = (int)val; return(val);}
10557
file_to_sample_file_name(mus_any * ptr)10558 static char *file_to_sample_file_name(mus_any *ptr) {return(((rdin *)ptr)->file_name);}
10559
no_reset(mus_any * ptr)10560 static void no_reset(mus_any *ptr) {}
10561
mus_in_any_from_file(mus_any * ptr,mus_long_t samp,int chan)10562 static mus_float_t mus_in_any_from_file(mus_any *ptr, mus_long_t samp, int chan)
10563 {
10564 /* check in-core buffer bounds,
10565 * if needed read new buffer (taking into account dir)
10566 * return mus_float_t at samp (frample)
10567 */
10568 rdin *gen = (rdin *)ptr;
10569
10570 if (chan >= gen->chans)
10571 return(0.0);
10572
10573 if ((samp <= gen->data_end) &&
10574 (samp >= gen->data_start))
10575 return((mus_float_t)(gen->ibufs[chan][samp - gen->data_start]));
10576
10577 if ((samp >= 0) &&
10578 (samp < gen->file_end))
10579 {
10580 /* got to read it from the file */
10581 int fd;
10582 mus_long_t newloc;
10583 /* read in first buffer start either at samp (dir > 0) or samp-bufsize (dir < 0) */
10584
10585 if (samp >= gen->data_start) /* gen dir is irrelevant here (see grev in clm23.scm) */
10586 newloc = samp;
10587 else newloc = (mus_long_t)(samp - (gen->file_buffer_size * .75));
10588 /* The .75 in the backwards read is trying to avoid reading the full buffer on
10589 * nearly every sample when we're oscillating around the
10590 * nominal buffer start/end (in src driven by an oscil for example)
10591 */
10592 if (newloc < 0) newloc = 0;
10593 gen->data_start = newloc;
10594 gen->data_end = newloc + gen->file_buffer_size - 1;
10595 fd = mus_sound_open_input(gen->file_name);
10596 if (fd == -1)
10597 return((mus_float_t)mus_error(MUS_CANT_OPEN_FILE,
10598 "open(%s) -> %s",
10599 gen->file_name, STRERROR(errno)));
10600 else
10601 {
10602 if (!gen->ibufs)
10603 make_ibufs(gen);
10604 mus_file_seek_frample(fd, gen->data_start);
10605
10606 if ((gen->data_start + gen->file_buffer_size) >= gen->file_end)
10607 mus_file_read_chans(fd, gen->data_start, gen->file_end - gen->data_start, gen->chans, gen->ibufs, gen->ibufs);
10608 else mus_file_read_chans(fd, gen->data_start, gen->file_buffer_size, gen->chans, gen->ibufs, gen->ibufs);
10609
10610 /* we have to check file_end here because chunked files can have trailing chunks containing
10611 * comments or whatever. io.c (mus_file_read_*) merely calls read, and translates bytes --
10612 * if it gets fewer than requested, it zeros from the point where the incoming file data stopped,
10613 * but that can be far beyond the actual end of the sample data! It is at this level that
10614 * we know how much data is actually supposed to be in the file.
10615 *
10616 * Also, file_end is the number of framples, so we should not read samp # file_end (see above).
10617 */
10618
10619 mus_sound_close_input(fd);
10620 if (gen->data_end > gen->file_end) gen->data_end = gen->file_end;
10621 }
10622
10623 return((mus_float_t)(gen->ibufs[chan][samp - gen->data_start]));
10624 }
10625
10626 return(0.0);
10627 }
10628
10629
run_file_to_sample(mus_any * ptr,mus_float_t arg1,mus_float_t arg2)10630 static mus_float_t run_file_to_sample(mus_any *ptr, mus_float_t arg1, mus_float_t arg2)
10631 {
10632 /* mus_read_sample here? */
10633 return(mus_in_any_from_file(ptr, (int)arg1, (int)arg2));
10634 }
10635
10636
file_to_sample_end(mus_any * ptr)10637 static int file_to_sample_end(mus_any *ptr)
10638 {
10639 rdin *gen = (rdin *)ptr;
10640 if (gen)
10641 {
10642 if (gen->ibufs)
10643 {
10644 int i;
10645 for (i = 0; i < gen->chans; i++)
10646 if (gen->ibufs[i])
10647 free(gen->ibufs[i]);
10648 free(gen->ibufs);
10649 gen->ibufs = NULL;
10650 gen->sbuf = NULL;
10651 }
10652 }
10653 return(0);
10654 }
10655
10656
10657 static mus_any_class FILE_TO_SAMPLE_CLASS = {
10658 MUS_FILE_TO_SAMPLE,
10659 (char *)S_file_to_sample,
10660 &free_file_to_sample,
10661 &describe_file_to_sample,
10662 &rdin_equalp,
10663 0, 0,
10664 &file_to_sample_length, 0,
10665 0, 0, 0, 0,
10666 0, 0,
10667 &file_to_sample_increment,
10668 &file_to_sample_set_increment,
10669 &run_file_to_sample,
10670 MUS_INPUT,
10671 NULL,
10672 &file_to_sample_channels,
10673 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10674 &mus_in_any_from_file,
10675 0,
10676 &file_to_sample_file_name,
10677 &file_to_sample_end,
10678 0, /* location */
10679 0, /* set_location */
10680 0, /* channel */
10681 0, 0, 0, 0,
10682 &no_reset,
10683 0, &rdin_copy
10684 };
10685
10686
mus_is_file_to_sample(mus_any * ptr)10687 bool mus_is_file_to_sample(mus_any *ptr)
10688 {
10689 return((ptr) &&
10690 (ptr->core->type == MUS_FILE_TO_SAMPLE));
10691 }
10692
10693
mus_make_file_to_sample_with_buffer_size(const char * filename,mus_long_t buffer_size)10694 mus_any *mus_make_file_to_sample_with_buffer_size(const char *filename, mus_long_t buffer_size)
10695 {
10696 rdin *gen;
10697
10698 if (!filename)
10699 mus_error(MUS_NO_FILE_NAME_PROVIDED, S_make_file_to_sample " requires a file name");
10700 else
10701 {
10702 gen = (rdin *)calloc(1, sizeof(rdin));
10703 gen->core = &FILE_TO_SAMPLE_CLASS;
10704
10705 gen->file_name = (char *)malloc((strlen(filename) + 1) * sizeof(char));
10706 strcpy(gen->file_name, filename);
10707 gen->data_end = -1; /* force initial read */
10708
10709 gen->chans = mus_sound_chans(gen->file_name);
10710 if (gen->chans <= 0)
10711 mus_error(MUS_NO_CHANNELS, S_make_file_to_sample ": %s chans: %d", filename, gen->chans);
10712
10713 gen->file_end = mus_sound_framples(gen->file_name);
10714 if (gen->file_end < 0)
10715 mus_error(MUS_NO_LENGTH, S_make_file_to_sample ": %s framples: %" print_mus_long, filename, gen->file_end);
10716
10717 if (buffer_size < gen->file_end)
10718 gen->file_buffer_size = buffer_size;
10719 else gen->file_buffer_size = gen->file_end;
10720
10721 return((mus_any *)gen);
10722 }
10723 return(NULL);
10724 }
10725
10726
mus_make_file_to_sample(const char * filename)10727 mus_any *mus_make_file_to_sample(const char *filename)
10728 {
10729 return(mus_make_file_to_sample_with_buffer_size(filename, clm_file_buffer_size));
10730 }
10731
10732
mus_file_to_sample(mus_any * ptr,mus_long_t samp,int chan)10733 mus_float_t mus_file_to_sample(mus_any *ptr, mus_long_t samp, int chan)
10734 {
10735 rdin *gen = (rdin *)ptr;
10736
10737 if (chan >= gen->chans)
10738 return(0.0);
10739
10740 /* redundant in a sense, but saves the call overhead of mus_in_any_from_file */
10741 if ((samp <= gen->data_end) &&
10742 (samp >= gen->data_start))
10743 return((mus_float_t)(gen->ibufs[chan][samp - gen->data_start]));
10744
10745 return(mus_in_any_from_file(ptr, samp, chan));
10746 }
10747
10748
10749
10750 /* ---------------- readin ---------------- */
10751
10752 /* readin reads only the desired channel and increments the location by the direction
10753 * it inherits from and specializes the file_to_sample class
10754 */
10755
describe_readin(mus_any * ptr)10756 static char *describe_readin(mus_any *ptr)
10757 {
10758 rdin *gen = (rdin *)ptr;
10759 char *describe_buffer;
10760 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
10761 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s %s[chan %d], loc: %" print_mus_long ", dir: %d",
10762 mus_name(ptr),
10763 gen->file_name, gen->chan, gen->loc, gen->dir);
10764 return(describe_buffer);
10765 }
10766
10767
free_readin(mus_any * p)10768 static void free_readin(mus_any *p)
10769 {
10770 rdin *ptr = (rdin *)p;
10771 if (ptr->core->end) ((*ptr->core->end))(p);
10772 free(ptr->file_name);
10773 free(ptr);
10774 }
10775
run_readin(mus_any * ptr,mus_float_t unused1,mus_float_t unused2)10776 static mus_float_t run_readin(mus_any *ptr, mus_float_t unused1, mus_float_t unused2) {return(((rdin *)ptr)->reader(ptr));}
readin_to_sample(mus_any * ptr,mus_long_t samp,int chan)10777 static mus_float_t readin_to_sample(mus_any *ptr, mus_long_t samp, int chan) {return(((rdin *)ptr)->reader(ptr));}
10778
rd_increment(mus_any * ptr)10779 static mus_float_t rd_increment(mus_any *ptr) {return((mus_float_t)(((rdin *)ptr)->dir));}
rd_set_increment(mus_any * ptr,mus_float_t val)10780 static mus_float_t rd_set_increment(mus_any *ptr, mus_float_t val) {((rdin *)ptr)->dir = (int)val; return(val);}
10781
rd_location(mus_any * rd)10782 static mus_long_t rd_location(mus_any *rd) {return(((rdin *)rd)->loc);}
rd_set_location(mus_any * rd,mus_long_t loc)10783 static mus_long_t rd_set_location(mus_any *rd, mus_long_t loc) {((rdin *)rd)->loc = loc; return(loc);}
10784
rd_channel(mus_any * rd)10785 static int rd_channel(mus_any *rd) {return(((rdin *)rd)->chan);}
10786
10787 static mus_any_class READIN_CLASS = {
10788 MUS_READIN,
10789 (char *)S_readin,
10790 &free_readin,
10791 &describe_readin,
10792 &rdin_equalp,
10793 0, 0,
10794 &file_to_sample_length, 0,
10795 0, 0, 0, 0,
10796 &fallback_scaler, 0,
10797 &rd_increment,
10798 &rd_set_increment,
10799 &run_readin,
10800 MUS_INPUT,
10801 NULL,
10802 &file_to_sample_channels,
10803 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10804 &readin_to_sample,
10805 0,
10806 &file_to_sample_file_name,
10807 &file_to_sample_end,
10808 &rd_location,
10809 &rd_set_location,
10810 &rd_channel,
10811 0, 0, 0, 0,
10812 &no_reset,
10813 0, &rdin_copy
10814 };
10815
10816
mus_is_readin(mus_any * ptr)10817 bool mus_is_readin(mus_any *ptr)
10818 {
10819 return((ptr) &&
10820 (ptr->core->type == MUS_READIN));
10821 }
10822
10823
mus_readin(mus_any * ptr)10824 mus_float_t mus_readin(mus_any *ptr)
10825 {
10826 return(((rdin *)ptr)->reader(ptr));
10827 }
10828
10829
safe_readin(mus_any * ptr)10830 static mus_float_t safe_readin(mus_any *ptr)
10831 {
10832 mus_float_t res;
10833 rdin *rd = (rdin *)ptr;
10834
10835 if ((rd->loc < rd->file_end) &&
10836 (rd->loc >= 0))
10837 res = rd->sbuf[rd->loc];
10838 else res = 0.0;
10839 rd->loc += rd->dir;
10840 return(res);
10841 }
10842
10843
readin(mus_any * ptr)10844 static mus_float_t readin(mus_any *ptr)
10845 {
10846 mus_float_t res;
10847 rdin *rd = (rdin *)ptr;
10848
10849 if ((rd->loc <= rd->data_end) &&
10850 (rd->loc >= rd->data_start))
10851 res = rd->sbuf[rd->loc - rd->data_start];
10852 else
10853 {
10854 if ((rd->loc < 0) || (rd->loc >= rd->file_end))
10855 res = 0.0;
10856 else res = mus_in_any_from_file(ptr, rd->loc, rd->chan);
10857 }
10858
10859 rd->loc += rd->dir;
10860 return(res);
10861 }
10862
10863
mus_make_readin_with_buffer_size(const char * filename,int chan,mus_long_t start,int direction,mus_long_t buffer_size)10864 mus_any *mus_make_readin_with_buffer_size(const char *filename, int chan, mus_long_t start, int direction, mus_long_t buffer_size)
10865 {
10866 rdin *gen;
10867 if (chan >= mus_sound_chans(filename))
10868 mus_error(MUS_NO_SUCH_CHANNEL, S_make_readin ": %s, chan: %d, but chans: %d", filename, chan, mus_sound_chans(filename));
10869
10870 gen = (rdin *)mus_make_file_to_sample(filename);
10871 if (gen)
10872 {
10873 gen->core = &READIN_CLASS;
10874 gen->loc = start;
10875 gen->dir = direction;
10876 gen->chan = chan;
10877 /* the saved data option does not save us anything in file_to_sample above */
10878 gen->saved_data = mus_sound_saved_data(filename);
10879 if (!gen->saved_data)
10880 {
10881 char *str;
10882 str = mus_expand_filename(filename);
10883 if (str)
10884 {
10885 gen->saved_data = mus_sound_saved_data(str);
10886 free(str);
10887 }
10888 }
10889 if (gen->saved_data)
10890 {
10891 gen->file_buffer_size = gen->file_end;
10892 gen->sbuf = gen->saved_data[chan];
10893 gen->reader = safe_readin;
10894 gen->data_start = 0;
10895 gen->data_end = gen->file_end;
10896 }
10897 else
10898 {
10899 gen->ibufs = (mus_float_t **)calloc(gen->chans, sizeof(mus_float_t *));
10900 if (buffer_size > gen->file_end)
10901 {
10902 gen->file_buffer_size = gen->file_end;
10903 gen->reader = safe_readin;
10904 gen->ibufs[chan] = (mus_float_t *)malloc(gen->file_buffer_size * sizeof(mus_float_t));
10905 mus_in_any_from_file((mus_any *)gen, 0, chan);
10906 }
10907 else
10908 {
10909 gen->file_buffer_size = buffer_size;
10910 gen->reader = readin;
10911 gen->ibufs[chan] = (mus_float_t *)malloc(gen->file_buffer_size * sizeof(mus_float_t));
10912 }
10913 gen->sbuf = gen->ibufs[chan];
10914 }
10915 return((mus_any *)gen);
10916 }
10917 return(NULL);
10918 }
10919
10920 /* it would be easy to extend readin to read from a float-vector by using the saved_data and safe_readin
10921 * business above -- just need mus_make_readin_from_float_vector or something.
10922 */
10923
10924
10925 /* ---------------- in-any ---------------- */
10926
mus_in_any(mus_long_t samp,int chan,mus_any * IO)10927 mus_float_t mus_in_any(mus_long_t samp, int chan, mus_any *IO)
10928 {
10929 if (IO) return(mus_read_sample(IO, samp, chan));
10930 return(0.0);
10931 }
10932
10933
mus_in_any_is_safe(mus_any * ptr)10934 bool mus_in_any_is_safe(mus_any *ptr)
10935 {
10936 rdin *gen = (rdin *)ptr;
10937 return((gen) &&
10938 ((gen->core->read_sample == mus_in_any_from_file) ||
10939 (gen->core->read_sample == readin_to_sample)));
10940 }
10941
10942
10943
10944 /* ---------------- file->frample ---------------- */
10945
10946 /* also built on file->sample */
10947
describe_file_to_frample(mus_any * ptr)10948 static char *describe_file_to_frample(mus_any *ptr)
10949 {
10950 rdin *gen = (rdin *)ptr;
10951 char *describe_buffer;
10952 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
10953 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s \"%s\"",
10954 mus_name(ptr),
10955 gen->file_name);
10956 return(describe_buffer);
10957 }
10958
10959
run_file_to_frample(mus_any * ptr,mus_float_t arg1,mus_float_t arg2)10960 static mus_float_t run_file_to_frample(mus_any *ptr, mus_float_t arg1, mus_float_t arg2)
10961 {
10962 mus_error(MUS_NO_RUN, "no run method for file->frample");
10963 return(0.0);
10964 }
10965
10966
10967 static mus_any_class FILE_TO_FRAMPLE_CLASS = {
10968 MUS_FILE_TO_FRAMPLE,
10969 (char *)S_file_to_frample,
10970 &free_file_to_sample,
10971 &describe_file_to_frample,
10972 &rdin_equalp,
10973 0, 0,
10974 &file_to_sample_length, 0,
10975 0, 0, 0, 0,
10976 &fallback_scaler, 0,
10977 &file_to_sample_increment, /* allow backward reads */
10978 &file_to_sample_set_increment,
10979 &run_file_to_frample,
10980 MUS_INPUT,
10981 NULL,
10982 &file_to_sample_channels,
10983 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10984 &mus_in_any_from_file,
10985 0,
10986 &file_to_sample_file_name,
10987 &file_to_sample_end,
10988 0, /* location */
10989 0, /* set_location */
10990 0, /* channel */
10991 0, 0, 0, 0,
10992 &no_reset,
10993 0, &rdin_copy
10994 };
10995
10996
mus_make_file_to_frample_with_buffer_size(const char * filename,mus_long_t buffer_size)10997 mus_any *mus_make_file_to_frample_with_buffer_size(const char *filename, mus_long_t buffer_size)
10998 {
10999 rdin *gen;
11000 gen = (rdin *)mus_make_file_to_sample_with_buffer_size(filename, buffer_size);
11001 if (gen)
11002 {
11003 gen->core = &FILE_TO_FRAMPLE_CLASS;
11004 return((mus_any *)gen);
11005 }
11006 return(NULL);
11007 }
11008
11009
mus_make_file_to_frample(const char * filename)11010 mus_any *mus_make_file_to_frample(const char *filename)
11011 {
11012 return(mus_make_file_to_frample_with_buffer_size(filename, clm_file_buffer_size));
11013 }
11014
11015
mus_is_file_to_frample(mus_any * ptr)11016 bool mus_is_file_to_frample(mus_any *ptr)
11017 {
11018 return((ptr) &&
11019 (ptr->core->type == MUS_FILE_TO_FRAMPLE));
11020 }
11021
11022
mus_file_to_frample(mus_any * ptr,mus_long_t samp,mus_float_t * f)11023 mus_float_t *mus_file_to_frample(mus_any *ptr, mus_long_t samp, mus_float_t *f)
11024 {
11025 rdin *gen = (rdin *)ptr;
11026 int i;
11027
11028 if ((samp <= gen->data_end) &&
11029 (samp >= gen->data_start))
11030 {
11031 mus_long_t pos;
11032 pos = samp - gen->data_start;
11033 f[0] = gen->ibufs[0][pos];
11034 for (i = 1; i < gen->chans; i++)
11035 f[i] = gen->ibufs[i][pos];
11036 }
11037 else
11038 {
11039 if ((samp < 0) ||
11040 (samp >= gen->file_end))
11041 {
11042 for (i = 0; i < gen->chans; i++)
11043 f[i] = 0.0;
11044 }
11045 else
11046 {
11047 f[0] = mus_in_any_from_file(ptr, samp, 0);
11048 for (i = 1; i < gen->chans; i++)
11049 f[i] = mus_in_any_from_file(ptr, samp, i);
11050 }
11051 }
11052 return(f);
11053 }
11054
11055
11056
11057 /* ---------------- sample->file ---------------- */
11058
11059 /* in all output functions, the assumption is that we're adding to whatever already exists */
11060 /* also, the "end" methods need to flush the output buffer */
11061
11062 /* rdout struct is in clm.h */
11063
describe_sample_to_file(mus_any * ptr)11064 static char *describe_sample_to_file(mus_any *ptr)
11065 {
11066 rdout *gen = (rdout *)ptr;
11067 char *describe_buffer;
11068 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
11069 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s \"%s\"",
11070 mus_name(ptr),
11071 gen->file_name);
11072 return(describe_buffer);
11073 }
11074
11075
sample_to_file_equalp(mus_any * p1,mus_any * p2)11076 static bool sample_to_file_equalp(mus_any *p1, mus_any *p2) {return(p1 == p2);}
11077
11078
free_sample_to_file(mus_any * p)11079 static void free_sample_to_file(mus_any *p)
11080 {
11081 rdout *ptr = (rdout *)p;
11082 if (ptr->core->end) ((*ptr->core->end))(p);
11083 free(ptr->file_name);
11084 free(ptr);
11085 }
11086
rdout_copy(mus_any * ptr)11087 static mus_any *rdout_copy(mus_any *ptr)
11088 {
11089 rdout *g, *p;
11090 p = (rdout *)ptr;
11091 g = (rdout *)malloc(sizeof(rdout));
11092 memcpy((void *)g, (void *)ptr, sizeof(rdout));
11093 g->file_name = mus_strdup(p->file_name);
11094 if (p->obufs)
11095 {
11096 int i;
11097 g->obufs = (mus_float_t **)malloc(g->chans * sizeof(mus_float_t *));
11098 for (i = 0; i < g->chans; i++)
11099 {
11100 g->obufs[i] = (mus_float_t *)malloc(clm_file_buffer_size * sizeof(mus_float_t));
11101 mus_copy_floats(g->obufs[i], p->obufs[i], clm_file_buffer_size);
11102 }
11103 g->obuf0 = g->obufs[0];
11104 if (g->chans > 1)
11105 g->obuf1 = g->obufs[1];
11106 else g->obuf1 = NULL;
11107 }
11108 return((mus_any *)g);
11109 }
11110
sample_to_file_channels(mus_any * ptr)11111 static int sample_to_file_channels(mus_any *ptr) {return((int)(((rdout *)ptr)->chans));}
sample_to_file_samp_type(mus_any * ptr)11112 static mus_long_t sample_to_file_samp_type(mus_any *ptr) {return((int)(((rdout *)ptr)->output_sample_type));}
sample_to_file_head_type(mus_any * ptr)11113 static int sample_to_file_head_type(mus_any *ptr) {return((int)(((rdout *)ptr)->output_header_type));}
11114
bufferlen(mus_any * ptr)11115 static mus_long_t bufferlen(mus_any *ptr) {return(clm_file_buffer_size);}
11116
set_bufferlen(mus_any * ptr,mus_long_t len)11117 static mus_long_t set_bufferlen(mus_any *ptr, mus_long_t len) {clm_file_buffer_size = len; return(len);}
11118
sample_to_file_file_name(mus_any * ptr)11119 static char *sample_to_file_file_name(mus_any *ptr) {return(((rdout *)ptr)->file_name);}
11120
11121 static int sample_to_file_end(mus_any *ptr);
11122
run_sample_to_file(mus_any * ptr,mus_float_t arg1,mus_float_t arg2)11123 static mus_float_t run_sample_to_file(mus_any *ptr, mus_float_t arg1, mus_float_t arg2) {mus_error(MUS_NO_RUN, "no run method for sample->file"); return(0.0);}
11124
11125 static mus_any_class SAMPLE_TO_FILE_CLASS = {
11126 MUS_SAMPLE_TO_FILE,
11127 (char *)S_sample_to_file,
11128 &free_sample_to_file,
11129 &describe_sample_to_file,
11130 &sample_to_file_equalp,
11131 0, 0,
11132 &bufferlen, &set_bufferlen, /* does this have any effect on the current gen? */
11133 0, 0, 0, 0,
11134 &fallback_scaler, 0,
11135 0, 0,
11136 &run_sample_to_file,
11137 MUS_OUTPUT,
11138 NULL,
11139 &sample_to_file_channels,
11140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11141 0,
11142 &mus_out_any_to_file,
11143 &sample_to_file_file_name,
11144 &sample_to_file_end,
11145 &sample_to_file_samp_type, 0,
11146 &sample_to_file_head_type,
11147 0, 0, 0, 0,
11148 &no_reset,
11149 0, &rdout_copy
11150 };
11151
11152
11153 static int *sample_type_zero = NULL;
11154
mus_sample_type_zero(mus_sample_t samp_type)11155 int mus_sample_type_zero(mus_sample_t samp_type)
11156 {
11157 return(sample_type_zero[samp_type]);
11158 }
11159
11160
flush_buffers(rdout * gen)11161 static void flush_buffers(rdout *gen)
11162 {
11163 int fd;
11164
11165 if ((!gen->obufs) ||
11166 (mus_file_probe(gen->file_name) == 0) ||
11167 (gen->chans == 0))
11168 return; /* can happen if output abandoned, then later mus_free called via GC sweep */
11169
11170 fd = mus_sound_open_input(gen->file_name);
11171 if (fd == -1)
11172 {
11173 /* no output yet, so open the output file and write the current samples (no need to add to existing samples in this case) */
11174 fd = mus_sound_open_output(gen->file_name,
11175 (int)sampling_rate,
11176 gen->chans,
11177 gen->output_sample_type,
11178 gen->output_header_type,
11179 NULL);
11180 if (fd == -1)
11181 mus_error(MUS_CANT_OPEN_FILE,
11182 "open(%s) -> %s",
11183 gen->file_name, STRERROR(errno));
11184 else
11185 {
11186 mus_file_write(fd, 0, gen->out_end, gen->chans, gen->obufs);
11187 mus_sound_close_output(fd, (gen->out_end + 1) * gen->chans * mus_bytes_per_sample(mus_sound_sample_type(gen->file_name)));
11188 }
11189 }
11190 else
11191 {
11192 /* get existing samples, add new output, write back to output */
11193 mus_float_t **addbufs = NULL;
11194 int i;
11195 mus_sample_t sample_type;
11196 mus_long_t current_file_framples, framples_to_add;
11197
11198 sample_type = mus_sound_sample_type(gen->file_name);
11199 current_file_framples = mus_sound_framples(gen->file_name);
11200 /* this is often 0 (brand-new file) */
11201
11202 if (current_file_framples > gen->data_start)
11203 {
11204 bool allocation_failed = false;
11205 addbufs = (mus_float_t **)calloc(gen->chans, sizeof(mus_float_t *));
11206
11207 for (i = 0; i < gen->chans; i++)
11208 {
11209 /* clm_file_buffer_size may be too large, but it's very hard to tell that
11210 * in advance. In Linux, malloc returns a non-null pointer even when
11211 * there's no memory available, so you have to touch the memory to force
11212 * the OS to deal with it, then the next allocation returns null.
11213 */
11214 addbufs[i] = (mus_float_t *)malloc(clm_file_buffer_size * sizeof(mus_float_t));
11215 if (addbufs[i])
11216 addbufs[i][0] = 0.0;
11217 else
11218 {
11219 allocation_failed = true;
11220 break;
11221 }
11222 }
11223
11224 if (allocation_failed)
11225 {
11226 mus_long_t old_file_buffer_size = 0;
11227
11228 /* first clean up the mess we made */
11229 for (i = 0; i < gen->chans; i++)
11230 if (addbufs[i])
11231 {
11232 free(addbufs[i]);
11233 addbufs[i] = NULL;
11234 }
11235 free(addbufs);
11236
11237 /* it would take a lot of screwing around to find the biggest clm_file_buffer_size we could handle,
11238 * and it might fail on the next call (if more chans), so we'll throw an error. We could get
11239 * say 1024 samps per chan, then run through a loop outputting the current buffer, but geez...
11240 */
11241 /* but... if we hit this in with-sound, mus_error calls (eventually) s7_error which sees the
11242 * dynamic-wind and tries to call mus-close, which tries to flush the buffers and we have
11243 * an infinite loop. So, we need to clean up right now.
11244 */
11245 mus_sound_close_input(fd);
11246 old_file_buffer_size = clm_file_buffer_size;
11247 clm_file_buffer_size = MUS_DEFAULT_FILE_BUFFER_SIZE;
11248 mus_error(MUS_MEMORY_ALLOCATION_FAILED, S_mus_file_buffer_size " (%" print_mus_long ") is too large: we can't allocate the output buffers!", old_file_buffer_size);
11249 return;
11250 }
11251 }
11252
11253 framples_to_add = gen->out_end - gen->data_start;
11254
11255 /* if the caller reset clm_file_buffer_size during a run, framples_to_add might be greater than the assumed buffer size,
11256 * so we need to complain and fix up the limits. In CLM, the size is set in sound.lisp, begin-with-sound.
11257 * In Snd via mus_set_file_buffer_size in clm2xen.c. The initial default is set in mus_initialize
11258 * called in CLM by clm-initialize-links via in cmus.c, and in Snd in clm2xen.c when the module is setup.
11259 */
11260 if (framples_to_add >= clm_file_buffer_size)
11261 {
11262 mus_print("clm-file-buffer-size changed? %" print_mus_long " <= %" print_mus_long " (start: %" print_mus_long ", end: %" print_mus_long ", %" print_mus_long ")",
11263 clm_file_buffer_size, framples_to_add, gen->data_start, gen->data_end, gen->out_end);
11264
11265 framples_to_add = clm_file_buffer_size - 1;
11266 /* this means we drop samples -- the other choice (short of throwing an error) would
11267 * be to read/allocate the bigger size.
11268 */
11269 }
11270 if (addbufs)
11271 {
11272 mus_file_seek_frample(fd, gen->data_start);
11273 mus_file_read(fd, gen->data_start, framples_to_add + 1, gen->chans, addbufs);
11274 }
11275 mus_sound_close_input(fd); /* close previous mus_sound_open_input */
11276
11277 fd = mus_sound_reopen_output(gen->file_name, gen->chans, sample_type,
11278 mus_sound_header_type(gen->file_name),
11279 mus_sound_data_location(gen->file_name));
11280
11281 if ((current_file_framples < gen->data_start) &&
11282 (sample_type_zero[sample_type] != 0))
11283 {
11284 /* we're about to create a gap in the output file. mus_file_seek_frample calls lseek which (man lseek):
11285 *
11286 * "The lseek function allows the file offset to be set beyond the end of
11287 * the existing end-of-file of the file (but this does not change the size
11288 * of the file). If data is later written at this point, subsequent reads
11289 * of the data in the gap return bytes of zeros (until data is actually
11290 * written into the gap)."
11291 *
11292 * but 0 bytes in a file are not interpreted as sound samples of 0 in several sample types.
11293 * for example, mus-mulaw 0 => -.98, whereas sound sample 0 is a byte of 255.
11294 * see the table at the end of this file (sample_type_zero) for the other cases.
11295 *
11296 * So, we need to write explicit sample-type 0 values in those cases where machine 0's
11297 * won't be sample type 0. sample_type_zero[type] != 0 signals we have such a
11298 * case, and returns the nominal zero value. For unsigned shorts, we also need to
11299 * take endianness into account.
11300 */
11301
11302 mus_long_t filler, current_samps, bytes, bps;
11303 unsigned char *zeros;
11304 #define MAX_ZERO_SAMPLES 65536
11305
11306 bps = mus_bytes_per_sample(sample_type);
11307 filler = gen->data_start - current_file_framples;
11308 mus_file_seek_frample(fd, current_file_framples);
11309
11310 if (filler > MAX_ZERO_SAMPLES)
11311 bytes = MAX_ZERO_SAMPLES * bps * gen->chans;
11312 else bytes = filler * bps * gen->chans;
11313
11314 zeros = (unsigned char *)malloc(bytes);
11315 if (bps == 1)
11316 memset((void *)zeros, sample_type_zero[sample_type], bytes);
11317 else /* it has to be a short */
11318 {
11319 int df, b1, b2;
11320 df = sample_type_zero[sample_type];
11321 b1 = df >> 8;
11322 b2 = df & 0xff;
11323 for (i = 0; i < bytes; i += 2)
11324 {
11325 zeros[i] = b2;
11326 zeros[i + 1] = b1;
11327 }
11328 }
11329 /* (with-sound (:sample-type mus-ulshort) (fm-violin 10 1 440 .1)) */
11330 while (filler > 0)
11331 {
11332 ssize_t wbytes;
11333 if (filler > MAX_ZERO_SAMPLES)
11334 current_samps = MAX_ZERO_SAMPLES;
11335 else
11336 {
11337 current_samps = filler;
11338 bytes = current_samps * bps * gen->chans;
11339 }
11340 wbytes = write(fd, zeros, bytes);
11341 if (wbytes != bytes) fprintf(stderr, "%s[%d]: write trouble\n", __func__, __LINE__);
11342 filler -= current_samps;
11343 }
11344 free(zeros);
11345 }
11346
11347 if (addbufs)
11348 {
11349 int j;
11350 /* fill/write output buffers with current data added to saved data */
11351 for (j = 0; j < gen->chans; j++)
11352 {
11353 mus_float_t *adder, *vals;
11354 adder = addbufs[j];
11355 vals = gen->obufs[j];
11356 mus_add_floats(adder, vals, framples_to_add + 1);
11357 }
11358
11359 mus_file_seek_frample(fd, gen->data_start);
11360 mus_file_write(fd, 0, framples_to_add, gen->chans, addbufs);
11361 for (i = 0; i < gen->chans; i++)
11362 free(addbufs[i]);
11363 free(addbufs);
11364 }
11365 else
11366 {
11367 /* output currently empty, so just flush out the gen->obufs */
11368 mus_file_seek_frample(fd, gen->data_start);
11369 mus_file_write(fd, 0, framples_to_add, gen->chans, gen->obufs);
11370 }
11371
11372 if (current_file_framples <= gen->out_end)
11373 current_file_framples = gen->out_end + 1;
11374 mus_sound_close_output(fd, current_file_framples * gen->chans * mus_bytes_per_sample(sample_type));
11375 }
11376 }
11377
11378
mus_sample_to_file_add(mus_any * out1,mus_any * out2)11379 mus_any *mus_sample_to_file_add(mus_any *out1, mus_any *out2)
11380 {
11381 mus_long_t min_framples;
11382 rdout *dest = (rdout *)out1;
11383 rdout *in_coming = (rdout *)out2;
11384 int chn, min_chans;
11385
11386 min_chans = dest->chans;
11387 if (in_coming->chans < min_chans) min_chans = in_coming->chans;
11388 min_framples = in_coming->out_end;
11389
11390 for (chn = 0; chn < min_chans; chn++)
11391 {
11392 mus_long_t i;
11393 for (i = 0; i < min_framples; i++)
11394 dest->obufs[chn][i] += in_coming->obufs[chn][i];
11395 mus_clear_floats(in_coming->obufs[chn], min_framples);
11396 }
11397
11398 if (min_framples > dest->out_end)
11399 dest->out_end = min_framples;
11400
11401 in_coming->out_end = 0;
11402 in_coming->data_start = 0;
11403
11404 return((mus_any*)dest);
11405 }
11406
11407
mus_out_any_to_file(mus_any * ptr,mus_long_t samp,int chan,mus_float_t val)11408 mus_float_t mus_out_any_to_file(mus_any *ptr, mus_long_t samp, int chan, mus_float_t val)
11409 {
11410 rdout *gen = (rdout *)ptr;
11411 if (!ptr) return(val);
11412
11413 if ((chan >= gen->chans) || /* checking for (val == 0.0) here appears to make no difference overall */
11414 (!(gen->obufs)))
11415 return(val);
11416
11417 if ((samp <= gen->data_end) &&
11418 (samp >= gen->data_start))
11419 gen->obufs[chan][samp - gen->data_start] += val;
11420 else
11421 {
11422 int j;
11423 if (samp < 0) return(val);
11424 flush_buffers(gen);
11425 for (j = 0; j < gen->chans; j++)
11426 mus_clear_floats(gen->obufs[j], clm_file_buffer_size);
11427 gen->data_start = samp;
11428 gen->data_end = samp + clm_file_buffer_size - 1;
11429 gen->obufs[chan][0] += val;
11430 gen->out_end = samp; /* this resets the current notion of where in the buffer the new data ends */
11431 }
11432
11433 if (samp > gen->out_end)
11434 gen->out_end = samp;
11435 return(val);
11436 }
11437
11438
mus_out_chans_to_file(rdout * gen,mus_long_t samp,int chans,mus_float_t * vals)11439 static void mus_out_chans_to_file(rdout *gen, mus_long_t samp, int chans, mus_float_t *vals)
11440 {
11441 int i;
11442 if ((samp <= gen->data_end) &&
11443 (samp >= gen->data_start))
11444 {
11445 mus_long_t pos;
11446 pos = samp - gen->data_start;
11447 for (i = 0; i < chans; i++)
11448 gen->obufs[i][pos] += vals[i];
11449 }
11450 else
11451 {
11452 int j;
11453 if (samp < 0) return;
11454 flush_buffers(gen);
11455 for (j = 0; j < gen->chans; j++)
11456 mus_clear_floats(gen->obufs[j], clm_file_buffer_size);
11457 gen->data_start = samp;
11458 gen->data_end = samp + clm_file_buffer_size - 1;
11459 for (i = 0; i < chans; i++)
11460 gen->obufs[i][0] += vals[i];
11461 gen->out_end = samp; /* this resets the current notion of where in the buffer the new data ends */
11462 }
11463
11464 if (samp > gen->out_end)
11465 gen->out_end = samp;
11466 }
11467
11468
mus_outa_to_file(mus_any * ptr,mus_long_t samp,mus_float_t val)11469 static mus_float_t mus_outa_to_file(mus_any *ptr, mus_long_t samp, mus_float_t val)
11470 {
11471 rdout *gen = (rdout *)ptr;
11472 if (!ptr) return(val);
11473
11474 if ((!(gen->obuf0)) ||
11475 (!(gen->obufs)))
11476 return(val);
11477
11478 if ((samp <= gen->data_end) &&
11479 (samp >= gen->data_start))
11480 gen->obuf0[samp - gen->data_start] += val;
11481 else
11482 {
11483 int j;
11484 if (samp < 0) return(val);
11485 flush_buffers(gen);
11486 for (j = 0; j < gen->chans; j++)
11487 mus_clear_floats(gen->obufs[j], clm_file_buffer_size);
11488 gen->data_start = samp;
11489 gen->data_end = samp + clm_file_buffer_size - 1;
11490 gen->obuf0[0] += val;
11491 gen->out_end = samp; /* this resets the current notion of where in the buffer the new data ends */
11492 }
11493
11494 if (samp > gen->out_end)
11495 gen->out_end = samp;
11496 return(val);
11497 }
11498
11499
mus_outb_to_file(mus_any * ptr,mus_long_t samp,mus_float_t val)11500 static mus_float_t mus_outb_to_file(mus_any *ptr, mus_long_t samp, mus_float_t val)
11501 {
11502 rdout *gen = (rdout *)ptr;
11503 if (!ptr) return(val);
11504
11505 if ((!(gen->obuf1)) ||
11506 (!(gen->obufs)))
11507 return(val);
11508
11509 if ((samp <= gen->data_end) &&
11510 (samp >= gen->data_start))
11511 gen->obuf1[samp - gen->data_start] += val;
11512 else
11513 {
11514 int j;
11515 if (samp < 0) return(val);
11516 flush_buffers(gen);
11517 for (j = 0; j < gen->chans; j++)
11518 mus_clear_floats(gen->obufs[j], clm_file_buffer_size);
11519 gen->data_start = samp;
11520 gen->data_end = samp + clm_file_buffer_size - 1;
11521 gen->obuf1[0] += val;
11522 gen->out_end = samp; /* this resets the current notion of where in the buffer the new data ends */
11523 }
11524
11525 if (samp > gen->out_end)
11526 gen->out_end = samp;
11527 return(val);
11528 }
11529
11530
sample_to_file_end(mus_any * ptr)11531 static int sample_to_file_end(mus_any *ptr)
11532 {
11533 rdout *gen = (rdout *)ptr;
11534 if ((gen) && (gen->obufs))
11535 {
11536 if (gen->chans > 0)
11537 {
11538 int i;
11539 flush_buffers(gen); /* this forces the error handling stuff, unlike in free reader case */
11540 for (i = 0; i < gen->chans; i++)
11541 if (gen->obufs[i])
11542 free(gen->obufs[i]);
11543 }
11544 free(gen->obufs);
11545 gen->obufs = NULL;
11546 gen->obuf0 = NULL;
11547 gen->obuf1 = NULL;
11548 }
11549 return(0);
11550 }
11551
11552
mus_is_sample_to_file(mus_any * ptr)11553 bool mus_is_sample_to_file(mus_any *ptr)
11554 {
11555 return((ptr) &&
11556 (ptr->core->type == MUS_SAMPLE_TO_FILE));
11557 }
11558
11559
mus_make_sample_to_file_with_comment_1(const char * filename,int out_chans,mus_sample_t samp_type,mus_header_t head_type,const char * comment,bool reopen)11560 static mus_any *mus_make_sample_to_file_with_comment_1(const char *filename, int out_chans,
11561 mus_sample_t samp_type, mus_header_t head_type, const char *comment, bool reopen)
11562 {
11563 if (!filename)
11564 mus_error(MUS_NO_FILE_NAME_PROVIDED, S_make_sample_to_file " requires a file name");
11565 else
11566 {
11567 int fd;
11568 if (out_chans <= 0)
11569 return(NULL);
11570 if (reopen)
11571 fd = mus_sound_reopen_output(filename, out_chans, samp_type, head_type, mus_sound_data_location(filename));
11572 else fd = mus_sound_open_output(filename, (int)sampling_rate, out_chans, samp_type, head_type, comment);
11573 if (fd == -1)
11574 mus_error(MUS_CANT_OPEN_FILE,
11575 S_make_sample_to_file ": open(%s) -> %s",
11576 filename, STRERROR(errno));
11577 else
11578 {
11579 rdout *gen;
11580 int i;
11581
11582 gen = (rdout *)calloc(1, sizeof(rdout));
11583 gen->core = &SAMPLE_TO_FILE_CLASS;
11584 gen->file_name = (char *)calloc(strlen(filename) + 1, sizeof(char));
11585 strcpy(gen->file_name, filename);
11586 gen->data_start = 0;
11587 gen->data_end = clm_file_buffer_size - 1;
11588 gen->out_end = 0;
11589 gen->chans = out_chans;
11590 gen->output_sample_type = samp_type;
11591 gen->output_header_type = head_type;
11592 gen->obufs = (mus_float_t **)malloc(gen->chans * sizeof(mus_float_t *));
11593 for (i = 0; i < gen->chans; i++)
11594 gen->obufs[i] = (mus_float_t *)calloc(clm_file_buffer_size, sizeof(mus_float_t));
11595 gen->obuf0 = gen->obufs[0];
11596 if (out_chans > 1)
11597 gen->obuf1 = gen->obufs[1];
11598 else gen->obuf1 = NULL;
11599
11600 /* clear previous, if any */
11601 if (mus_file_close(fd) != 0)
11602 mus_error(MUS_CANT_CLOSE_FILE,
11603 S_make_sample_to_file ": close(%d, %s) -> %s",
11604 fd, gen->file_name, STRERROR(errno));
11605
11606 return((mus_any *)gen);
11607 }
11608 }
11609 return(NULL);
11610 }
11611
11612
mus_continue_sample_to_file(const char * filename)11613 mus_any *mus_continue_sample_to_file(const char *filename)
11614 {
11615 return(mus_make_sample_to_file_with_comment_1(filename,
11616 mus_sound_chans(filename),
11617 mus_sound_sample_type(filename),
11618 mus_sound_header_type(filename),
11619 NULL,
11620 true));
11621 }
11622
11623
mus_make_sample_to_file_with_comment(const char * filename,int out_chans,mus_sample_t samp_type,mus_header_t head_type,const char * comment)11624 mus_any *mus_make_sample_to_file_with_comment(const char *filename, int out_chans, mus_sample_t samp_type, mus_header_t head_type, const char *comment)
11625 {
11626 return(mus_make_sample_to_file_with_comment_1(filename, out_chans, samp_type, head_type, comment, false));
11627 }
11628
11629
mus_sample_to_file(mus_any * fd,mus_long_t samp,int chan,mus_float_t val)11630 mus_float_t mus_sample_to_file(mus_any *fd, mus_long_t samp, int chan, mus_float_t val)
11631 {
11632 /* return(mus_write_sample(ptr, samp, chan, val)); */
11633 if ((fd) &&
11634 ((fd->core)->write_sample))
11635 return(((*(fd->core)->write_sample))(fd, samp, chan, val));
11636 mus_error(MUS_NO_SAMPLE_OUTPUT,
11637 S_sample_to_file ": can't find %s's sample output function",
11638 mus_name(fd));
11639 return(val);
11640 }
11641
11642
mus_close_file(mus_any * ptr)11643 int mus_close_file(mus_any *ptr)
11644 {
11645 rdout *gen = (rdout *)ptr;
11646 if ((mus_is_output(ptr)) && (gen->obufs)) sample_to_file_end(ptr);
11647 return(0);
11648 }
11649
11650
11651 /* ---------------- out-any ---------------- */
11652
mus_out_any(mus_long_t samp,mus_float_t val,int chan,mus_any * IO)11653 mus_float_t mus_out_any(mus_long_t samp, mus_float_t val, int chan, mus_any *IO)
11654 {
11655 if ((IO) &&
11656 (samp >= 0))
11657 {
11658 if ((IO->core)->write_sample)
11659 return(((*(IO->core)->write_sample))(IO, samp, chan, val));
11660 mus_error(MUS_NO_SAMPLE_OUTPUT,
11661 "can't find %s's sample output function",
11662 mus_name(IO));
11663 }
11664 return(val);
11665 }
11666
11667
mus_safe_out_any_to_file(mus_long_t samp,mus_float_t val,int chan,mus_any * IO)11668 mus_float_t mus_safe_out_any_to_file(mus_long_t samp, mus_float_t val, int chan, mus_any *IO)
11669 {
11670 rdout *gen = (rdout *)IO;
11671 if (chan >= gen->chans) /* checking for (val == 0.0) here appears to make no difference overall */
11672 return(val);
11673 /* does this need to check obufs? */
11674
11675 if ((samp <= gen->data_end) &&
11676 (samp >= gen->data_start))
11677 {
11678 gen->obufs[chan][samp - gen->data_start] += val;
11679 if (samp > gen->out_end)
11680 gen->out_end = samp;
11681 }
11682 else
11683 {
11684 int j;
11685 if (samp < 0) return(val);
11686 flush_buffers(gen);
11687 for (j = 0; j < gen->chans; j++)
11688 mus_clear_floats(gen->obufs[j], clm_file_buffer_size);
11689 gen->data_start = samp;
11690 gen->data_end = samp + clm_file_buffer_size - 1;
11691 gen->obufs[chan][0] += val;
11692 gen->out_end = samp; /* this resets the current notion of where in the buffer the new data ends */
11693 }
11694 return(val);
11695
11696 }
11697
11698
mus_out_any_is_safe(mus_any * IO)11699 bool mus_out_any_is_safe(mus_any *IO)
11700 {
11701 rdout *gen = (rdout *)IO;
11702 return((gen) &&
11703 (gen->obufs) &&
11704 (gen->core->write_sample == mus_out_any_to_file));
11705 }
11706
11707
11708
11709 /* ---------------- frample->file ---------------- */
11710
describe_frample_to_file(mus_any * ptr)11711 static char *describe_frample_to_file(mus_any *ptr)
11712 {
11713 rdout *gen = (rdout *)ptr;
11714 char *describe_buffer;
11715 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
11716 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s \"%s\"",
11717 mus_name(ptr),
11718 gen->file_name);
11719 return(describe_buffer);
11720 }
11721
run_frample_to_file(mus_any * ptr,mus_float_t arg1,mus_float_t arg2)11722 static mus_float_t run_frample_to_file(mus_any *ptr, mus_float_t arg1, mus_float_t arg2)
11723 {
11724 mus_error(MUS_NO_RUN, "no run method for frample->file");
11725 return(0.0);
11726 }
11727
11728
11729 static mus_any_class FRAMPLE_TO_FILE_CLASS = {
11730 MUS_FRAMPLE_TO_FILE,
11731 (char *)S_frample_to_file,
11732 &free_sample_to_file,
11733 &describe_frample_to_file,
11734 &sample_to_file_equalp,
11735 0, 0,
11736 &bufferlen, &set_bufferlen,
11737 0, 0, 0, 0,
11738 &fallback_scaler, 0,
11739 0, 0,
11740 &run_frample_to_file,
11741 MUS_OUTPUT,
11742 NULL,
11743 &sample_to_file_channels,
11744 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11745 0,
11746 &mus_out_any_to_file,
11747 &sample_to_file_file_name,
11748 &sample_to_file_end,
11749 &sample_to_file_samp_type, 0,
11750 &sample_to_file_head_type,
11751 0, 0, 0, 0,
11752 &no_reset,
11753 0, &rdout_copy
11754 };
11755
11756
mus_make_frample_to_file_with_comment(const char * filename,int chans,mus_sample_t samp_type,mus_header_t head_type,const char * comment)11757 mus_any *mus_make_frample_to_file_with_comment(const char *filename, int chans, mus_sample_t samp_type, mus_header_t head_type, const char *comment)
11758 {
11759 rdout *gen;
11760 gen = (rdout *)mus_make_sample_to_file_with_comment(filename, chans, samp_type, head_type, comment);
11761 if (gen) gen->core = &FRAMPLE_TO_FILE_CLASS;
11762 return((mus_any *)gen);
11763 }
11764
11765
mus_is_frample_to_file(mus_any * ptr)11766 bool mus_is_frample_to_file(mus_any *ptr)
11767 {
11768 return((ptr) &&
11769 (ptr->core->type == MUS_FRAMPLE_TO_FILE));
11770 }
11771
11772
mus_frample_to_file(mus_any * ptr,mus_long_t samp,mus_float_t * data)11773 mus_float_t *mus_frample_to_file(mus_any *ptr, mus_long_t samp, mus_float_t *data)
11774 {
11775 rdout *gen = (rdout *)ptr;
11776 if (!gen) return(data);
11777
11778 if (gen->chans == 1)
11779 mus_outa_to_file(ptr, samp, data[0]);
11780 else
11781 {
11782 if (gen->chans == 2)
11783 {
11784 mus_outa_to_file(ptr, samp, data[0]);
11785 mus_outb_to_file(ptr, samp, data[1]);
11786 }
11787 else mus_out_chans_to_file(gen, samp, gen->chans, data);
11788 }
11789 return(data);
11790 }
11791
11792
mus_continue_frample_to_file(const char * filename)11793 mus_any *mus_continue_frample_to_file(const char *filename)
11794 {
11795 rdout *gen;
11796 gen = (rdout *)mus_continue_sample_to_file(filename);
11797 if (gen) gen->core = &FRAMPLE_TO_FILE_CLASS;
11798 return((mus_any *)gen);
11799 }
11800
11801
mus_frample_to_frample(mus_float_t * matrix,int mx_chans,mus_float_t * in_samps,int in_chans,mus_float_t * out_samps,int out_chans)11802 mus_float_t *mus_frample_to_frample(mus_float_t *matrix, int mx_chans, mus_float_t *in_samps, int in_chans, mus_float_t *out_samps, int out_chans)
11803 {
11804 /* in->out conceptually, so left index is in_chan, it (j below) steps by out_chans */
11805 int i, j, offset;
11806 if (mx_chans < out_chans) out_chans = mx_chans;
11807 if (mx_chans < in_chans) in_chans = mx_chans;
11808 for (i = 0; i < out_chans; i++)
11809 {
11810 out_samps[i] = in_samps[0] * matrix[i];
11811 for (j = 1, offset = mx_chans; j < in_chans; j++, offset += mx_chans)
11812 out_samps[i] += in_samps[j] * matrix[offset + i];
11813 }
11814 return(out_samps);
11815 }
11816
11817
11818
11819 /* ---------------- locsig ---------------- */
11820
11821 typedef struct {
11822 mus_any_class *core;
11823 mus_any *outn_writer;
11824 mus_any *revn_writer;
11825 mus_float_t *outf, *revf;
11826 mus_float_t *outn;
11827 mus_float_t *revn;
11828 int chans, rev_chans;
11829 mus_interp_t type;
11830 mus_float_t reverb, degree, distance;
11831 bool safe_output;
11832 void *closure;
11833 void (*locsig_func)(mus_any *ptr, mus_long_t loc, mus_float_t val);
11834 void (*detour)(mus_any *ptr, mus_long_t loc);
11835 } locs;
11836
11837
locsig_equalp(mus_any * p1,mus_any * p2)11838 static bool locsig_equalp(mus_any *p1, mus_any *p2)
11839 {
11840 locs *g1 = (locs *)p1;
11841 locs *g2 = (locs *)p2;
11842 if (p1 == p2) return(true);
11843 return((g1) && (g2) &&
11844 (g1->core->type == g2->core->type) &&
11845 (g1->chans == g2->chans) &&
11846 (clm_arrays_are_equal(g1->outn, g2->outn, g1->chans)) &&
11847 (((g1->revn) && (g2->revn)) ||
11848 ((!g1->revn) && (!g2->revn))) &&
11849 ((!(g1->revn)) || (clm_arrays_are_equal(g1->revn, g2->revn, g1->rev_chans))));
11850 }
11851
11852
describe_locsig(mus_any * ptr)11853 static char *describe_locsig(mus_any *ptr)
11854 {
11855 char *str;
11856 int i, lim = 16;
11857 locs *gen = (locs *)ptr;
11858
11859 char *describe_buffer;
11860 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
11861 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s chans %d, outn: [",
11862 mus_name(ptr),
11863 gen->chans);
11864 str = (char *)malloc(STR_SIZE * sizeof(char));
11865
11866 if (gen->outn)
11867 {
11868 if (gen->chans - 1 < lim) lim = gen->chans - 1;
11869 for (i = 0; i < lim; i++)
11870 {
11871 snprintf(str, STR_SIZE, "%.3f ", gen->outn[i]);
11872 if ((strlen(describe_buffer) + strlen(str)) < (DESCRIBE_BUFFER_SIZE - 16))
11873 strcat(describe_buffer, str);
11874 else break;
11875 }
11876 if (gen->chans - 1 > lim) strcat(describe_buffer, "...");
11877 snprintf(str, STR_SIZE, "%.3f]", gen->outn[gen->chans - 1]);
11878 strcat(describe_buffer, str);
11879 }
11880 else
11881 {
11882 strcat(describe_buffer, "nil!]");
11883 }
11884
11885 if ((gen->rev_chans > 0) && (gen->revn))
11886 {
11887 strcat(describe_buffer, ", revn: [");
11888 lim = 16;
11889 if (gen->rev_chans - 1 < lim) lim = gen->rev_chans - 1;
11890 for (i = 0; i < lim; i++)
11891 {
11892 snprintf(str, STR_SIZE, "%.3f ", gen->revn[i]);
11893 if ((strlen(describe_buffer) + strlen(str)) < (DESCRIBE_BUFFER_SIZE - 16))
11894 strcat(describe_buffer, str);
11895 else break;
11896 }
11897 if (gen->rev_chans - 1 > lim) strcat(describe_buffer, "...");
11898 snprintf(str, STR_SIZE, "%.3f]", gen->revn[gen->rev_chans - 1]);
11899 strcat(describe_buffer, str);
11900 }
11901
11902 snprintf(str, STR_SIZE, ", interp: %s", mus_interp_type_to_string(gen->type));
11903 strcat(describe_buffer, str);
11904 free(str);
11905 return(describe_buffer);
11906 }
11907
11908
free_locsig(mus_any * p)11909 static void free_locsig(mus_any *p)
11910 {
11911 locs *ptr = (locs *)p;
11912 if (ptr->outn)
11913 {
11914 free(ptr->outn);
11915 ptr->outn = NULL;
11916 }
11917 if (ptr->revn)
11918 {
11919 free(ptr->revn);
11920 ptr->revn = NULL;
11921 }
11922 if (ptr->outf) free(ptr->outf);
11923 ptr->outf = NULL;
11924 if (ptr->revf) free(ptr->revf);
11925 ptr->revf = NULL;
11926 ptr->outn_writer = NULL;
11927 ptr->revn_writer = NULL;
11928 ptr->chans = 0;
11929 ptr->rev_chans = 0;
11930 free(ptr);
11931 }
11932
locs_copy(mus_any * ptr)11933 static mus_any *locs_copy(mus_any *ptr)
11934 {
11935 locs *g, *p;
11936 int bytes;
11937 p = (locs *)ptr;
11938 g = (locs *)malloc(sizeof(locs));
11939 memcpy((void *)g, (void *)ptr, sizeof(locs));
11940 bytes = g->chans * sizeof(mus_float_t);
11941 if (p->outn)
11942 {
11943 g->outn = (mus_float_t *)malloc(bytes);
11944 mus_copy_floats(g->outn, p->outn, g->chans);
11945 }
11946 if (p->outf)
11947 {
11948 g->outf = (mus_float_t *)malloc(bytes);
11949 mus_copy_floats(g->outf, p->outf, g->chans);
11950 }
11951 bytes = g->rev_chans * sizeof(mus_float_t);
11952 if (p->revn)
11953 {
11954 g->revn = (mus_float_t *)malloc(bytes);
11955 mus_copy_floats(g->revn, p->revn, g->rev_chans);
11956 }
11957 if (p->revf)
11958 {
11959 g->revf = (mus_float_t *)malloc(bytes);
11960 mus_copy_floats(g->revf, p->revf, g->rev_chans);
11961 }
11962 return((mus_any *)g);
11963 }
11964
locsig_length(mus_any * ptr)11965 static mus_long_t locsig_length(mus_any *ptr) {return(((locs *)ptr)->chans);}
locsig_type(mus_any * ptr)11966 static mus_long_t locsig_type(mus_any *ptr) {return(((locs *)ptr)->type);}
locsig_degree(mus_any * ptr)11967 static mus_float_t locsig_degree(mus_any *ptr) {return(((locs *)ptr)->degree);}
locsig_distance(mus_any * ptr)11968 static mus_float_t locsig_distance(mus_any *ptr) {return(((locs *)ptr)->distance);}
locsig_reverb(mus_any * ptr)11969 static mus_float_t locsig_reverb(mus_any *ptr) {return(((locs *)ptr)->reverb);}
11970
locsig_channels(mus_any * ptr)11971 static int locsig_channels(mus_any *ptr) {return(((locs *)ptr)->chans);}
11972
locsig_data(mus_any * ptr)11973 static mus_float_t *locsig_data(mus_any *ptr) {return(((locs *)ptr)->outn);}
11974
locsig_xcoeffs(mus_any * ptr)11975 static mus_float_t *locsig_xcoeffs(mus_any *ptr) {return(((locs *)ptr)->revn);}
11976
mus_locsig_outf(mus_any * ptr)11977 mus_float_t *mus_locsig_outf(mus_any *ptr) {return(((locs *)ptr)->outf);} /* clm2xen.c */
mus_locsig_revf(mus_any * ptr)11978 mus_float_t *mus_locsig_revf(mus_any *ptr) {return(((locs *)ptr)->revf);}
11979
mus_locsig_closure(mus_any * ptr)11980 void *mus_locsig_closure(mus_any *ptr) {return(((locs *)ptr)->closure);}
locsig_set_closure(mus_any * ptr,void * e)11981 static void *locsig_set_closure(mus_any *ptr, void *e) {((locs *)ptr)->closure = e; return(e);}
11982
mus_locsig_set_detour(mus_any * ptr,void (* detour)(mus_any * ptr,mus_long_t val))11983 void mus_locsig_set_detour(mus_any *ptr, void (*detour)(mus_any *ptr, mus_long_t val))
11984 {
11985 locs *gen = (locs *)ptr;
11986 gen->detour = detour;
11987 }
11988
11989
locsig_reset(mus_any * ptr)11990 static void locsig_reset(mus_any *ptr)
11991 {
11992 locs *gen = (locs *)ptr;
11993 if (gen->outn) mus_clear_floats(gen->outn, gen->chans);
11994 if (gen->revn) mus_clear_floats(gen->revn, gen->rev_chans);
11995 }
11996
11997
locsig_xcoeff(mus_any * ptr,int index)11998 static mus_float_t locsig_xcoeff(mus_any *ptr, int index)
11999 {
12000 locs *gen = (locs *)ptr;
12001 if (gen->revn)
12002 return(gen->revn[index]);
12003 return(0.0);
12004 }
12005
12006
locsig_set_xcoeff(mus_any * ptr,int index,mus_float_t val)12007 static mus_float_t locsig_set_xcoeff(mus_any *ptr, int index, mus_float_t val)
12008 {
12009 locs *gen = (locs *)ptr;
12010 if (gen->revn)
12011 gen->revn[index] = val;
12012 return(val);
12013 }
12014
12015
12016 static mus_any *locsig_warned = NULL;
12017 /* these locsig error messages are a pain -- using the output pointer in the wan hope that
12018 * subsequent runs will use a different output generator.
12019 */
12020
mus_locsig_ref(mus_any * ptr,int chan)12021 mus_float_t mus_locsig_ref(mus_any *ptr, int chan)
12022 {
12023 locs *gen = (locs *)ptr;
12024 if ((ptr) && (mus_is_locsig(ptr)))
12025 {
12026 if ((chan >= 0) &&
12027 (chan < gen->chans))
12028 return(gen->outn[chan]);
12029 else
12030 {
12031 if (locsig_warned != gen->outn_writer)
12032 {
12033 mus_error(MUS_NO_SUCH_CHANNEL,
12034 S_locsig_ref ": chan %d >= %d",
12035 chan, gen->chans);
12036 locsig_warned = gen->outn_writer;
12037 }
12038 }
12039 }
12040 return(0.0);
12041 }
12042
12043
mus_locsig_set(mus_any * ptr,int chan,mus_float_t val)12044 mus_float_t mus_locsig_set(mus_any *ptr, int chan, mus_float_t val)
12045 {
12046 locs *gen = (locs *)ptr;
12047 if ((ptr) && (mus_is_locsig(ptr)))
12048 {
12049 if ((chan >= 0) &&
12050 (chan < gen->chans))
12051 gen->outn[chan] = val;
12052 else
12053 {
12054 if (locsig_warned != gen->outn_writer)
12055 {
12056 mus_error(MUS_NO_SUCH_CHANNEL,
12057 S_locsig_set ": chan %d >= %d",
12058 chan, gen->chans);
12059 locsig_warned = gen->outn_writer;
12060 }
12061 }
12062 }
12063 return(val);
12064 }
12065
12066
mus_locsig_reverb_ref(mus_any * ptr,int chan)12067 mus_float_t mus_locsig_reverb_ref(mus_any *ptr, int chan)
12068 {
12069 locs *gen = (locs *)ptr;
12070 if ((ptr) && (mus_is_locsig(ptr)))
12071 {
12072 if ((chan >= 0) &&
12073 (chan < gen->rev_chans))
12074 return(gen->revn[chan]);
12075 else
12076 {
12077 if (locsig_warned != gen->outn_writer)
12078 {
12079 mus_error(MUS_NO_SUCH_CHANNEL,
12080 S_locsig_reverb_ref ": chan %d, but this locsig has %d reverb chans",
12081 chan, gen->rev_chans);
12082 locsig_warned = gen->outn_writer;
12083 }
12084 }
12085 }
12086 return(0.0);
12087 }
12088
12089
mus_locsig_reverb_set(mus_any * ptr,int chan,mus_float_t val)12090 mus_float_t mus_locsig_reverb_set(mus_any *ptr, int chan, mus_float_t val)
12091 {
12092 locs *gen = (locs *)ptr;
12093 if ((ptr) && (mus_is_locsig(ptr)))
12094 {
12095 if ((chan >= 0) &&
12096 (chan < gen->rev_chans))
12097 gen->revn[chan] = val;
12098 else
12099 {
12100 if (locsig_warned != gen->outn_writer)
12101 {
12102 mus_error(MUS_NO_SUCH_CHANNEL,
12103 S_locsig_reverb_set ": chan %d >= %d",
12104 chan, gen->rev_chans);
12105 locsig_warned = gen->outn_writer;
12106 }
12107 }
12108 }
12109 return(val);
12110 }
12111
12112
run_locsig(mus_any * ptr,mus_float_t arg1,mus_float_t arg2)12113 static mus_float_t run_locsig(mus_any *ptr, mus_float_t arg1, mus_float_t arg2)
12114 {
12115 mus_locsig(ptr, (mus_long_t)arg1, arg2);
12116 return(arg2);
12117 }
12118
12119
12120 static mus_any_class LOCSIG_CLASS = {
12121 MUS_LOCSIG,
12122 (char *)S_locsig,
12123 &free_locsig,
12124 &describe_locsig,
12125 &locsig_equalp,
12126 &locsig_data, 0,
12127 &locsig_length,
12128 0,
12129 0, 0, 0, 0,
12130 &locsig_degree, 0,
12131 &locsig_distance, 0,
12132 &run_locsig,
12133 MUS_OUTPUT,
12134 &mus_locsig_closure,
12135 &locsig_channels,
12136 &locsig_reverb, 0,
12137 0, 0,
12138 &locsig_xcoeff, &locsig_set_xcoeff,
12139 &locsig_type, 0, 0, 0,
12140 0, 0, 0, 0, 0, 0, 0,
12141 0, 0,
12142 &locsig_xcoeffs, 0,
12143 &locsig_reset,
12144 &locsig_set_closure, /* the method name is set_environ (clm2xen.c) */
12145 &locs_copy
12146 };
12147
12148
mus_is_locsig(mus_any * ptr)12149 bool mus_is_locsig(mus_any *ptr)
12150 {
12151 return((ptr) &&
12152 (ptr->core->type == MUS_LOCSIG));
12153 }
12154
12155
mus_locsig_fill(mus_float_t * arr,int chans,mus_float_t degree,mus_float_t scaler,mus_interp_t type)12156 static void mus_locsig_fill(mus_float_t *arr, int chans, mus_float_t degree, mus_float_t scaler, mus_interp_t type)
12157 {
12158 if (chans == 1)
12159 arr[0] = scaler;
12160 else
12161 {
12162 mus_float_t deg, pos, frac, degs_per_chan;
12163 int left, right;
12164 /* this used to check for degree < 0.0 first, but as Michael Klingbeil noticed, that
12165 * means that in the stereo case, the location can jump to 90 => click.
12166 */
12167 if (chans == 2)
12168 {
12169 /* there's no notion of a circle of speakers here, so we don't have to equate, for example, -90 and 270 */
12170 if (degree > 90.0)
12171 deg = 90.0;
12172 else
12173 {
12174 if (degree < 0.0)
12175 deg = 0.0;
12176 else deg = degree;
12177 }
12178 degs_per_chan = 90.0;
12179 }
12180 else
12181 {
12182 deg = fmod(degree, 360.0);
12183 if (deg < 0.0)
12184 {
12185 /* -0.0 is causing trouble when mus_float_t == float */
12186 if (deg < -0.0000001)
12187 deg += 360.0; /* C's fmod can return negative results when modulus is positive */
12188 else deg = 0.0;
12189 }
12190 degs_per_chan = 360.0 / chans;
12191 }
12192 pos = deg / degs_per_chan;
12193 left = (int)pos; /* floor(pos) */
12194 right = left + 1;
12195 if (right >= chans) right = 0;
12196 frac = pos - left;
12197 if (type == MUS_INTERP_LINEAR)
12198 {
12199 arr[left] = scaler * (1.0 - frac);
12200 arr[right] = scaler * frac;
12201 }
12202 else
12203 {
12204 mus_float_t ldeg, c, s;
12205 ldeg = M_PI_2 * (0.5 - frac);
12206 scaler *= sqrt(2.0) / 2.0;
12207 c = cos(ldeg);
12208 s = sin(ldeg);
12209 arr[left] = scaler * (c + s);
12210 arr[right] = scaler * (c - s);
12211 }
12212 }
12213 }
12214
12215
mus_locsig_mono_no_reverb(mus_any * ptr,mus_long_t loc,mus_float_t val)12216 static void mus_locsig_mono_no_reverb(mus_any *ptr, mus_long_t loc, mus_float_t val)
12217 {
12218 locs *gen = (locs *)ptr;
12219 mus_outa_to_file(gen->outn_writer, loc, val * gen->outn[0]);
12220 }
12221
12222
mus_locsig_mono(mus_any * ptr,mus_long_t loc,mus_float_t val)12223 static void mus_locsig_mono(mus_any *ptr, mus_long_t loc, mus_float_t val)
12224 {
12225 locs *gen = (locs *)ptr;
12226 mus_outa_to_file(gen->outn_writer, loc, val * gen->outn[0]);
12227 mus_outa_to_file(gen->revn_writer, loc, val * gen->revn[0]);
12228 }
12229
12230
mus_locsig_stereo_no_reverb(mus_any * ptr,mus_long_t loc,mus_float_t val)12231 static void mus_locsig_stereo_no_reverb(mus_any *ptr, mus_long_t loc, mus_float_t val)
12232 {
12233 locs *gen = (locs *)ptr;
12234 mus_outa_to_file(gen->outn_writer, loc, val * gen->outn[0]);
12235 mus_outb_to_file(gen->outn_writer, loc, val * gen->outn[1]);
12236 }
12237
12238
mus_locsig_stereo(mus_any * ptr,mus_long_t loc,mus_float_t val)12239 static void mus_locsig_stereo(mus_any *ptr, mus_long_t loc, mus_float_t val) /* but mono rev */
12240 {
12241 locs *gen = (locs *)ptr;
12242 mus_outa_to_file(gen->outn_writer, loc, val * gen->outn[0]);
12243 mus_outb_to_file(gen->outn_writer, loc, val * gen->outn[1]);
12244 mus_outa_to_file(gen->revn_writer, loc, val * gen->revn[0]);
12245 }
12246
12247
mus_locsig_any(mus_any * ptr,mus_long_t loc,mus_float_t val)12248 static void mus_locsig_any(mus_any *ptr, mus_long_t loc, mus_float_t val)
12249 {
12250 int i;
12251 locs *gen = (locs *)ptr;
12252 rdout *writer = (rdout *)(gen->outn_writer);
12253 for (i = 0; i < gen->chans; i++)
12254 {
12255 gen->outf[i] = val * gen->outn[i];
12256 if (writer)
12257 mus_out_any_to_file((mus_any *)writer, loc, i, gen->outf[i]);
12258 }
12259 writer = (rdout *)(gen->revn_writer);
12260 for (i = 0; i < gen->rev_chans; i++)
12261 {
12262 gen->revf[i] = val * gen->revn[i];
12263 if (writer)
12264 mus_out_any_to_file((mus_any *)writer, loc, i, gen->revf[i]);
12265 }
12266 }
12267
mus_locsig_safe_mono_no_reverb(mus_any * ptr,mus_long_t loc,mus_float_t val)12268 static void mus_locsig_safe_mono_no_reverb(mus_any *ptr, mus_long_t loc, mus_float_t val)
12269 {
12270 /* here we know in each safe case that obufs fits loc chans and the output gen is ok */
12271 locs *gen = (locs *)ptr;
12272 rdout *writer = (rdout *)(gen->outn_writer);
12273
12274 if ((loc <= writer->data_end) &&
12275 (loc >= writer->data_start))
12276 {
12277 writer->obufs[0][loc - writer->data_start] += (val * gen->outn[0]);
12278 if (loc > writer->out_end)
12279 writer->out_end = loc;
12280 }
12281 else mus_outa_to_file((mus_any *)writer, loc, val * gen->outn[0]);
12282 }
12283
12284
mus_locsig_safe_mono(mus_any * ptr,mus_long_t loc,mus_float_t val)12285 static void mus_locsig_safe_mono(mus_any *ptr, mus_long_t loc, mus_float_t val)
12286 {
12287 locs *gen = (locs *)ptr;
12288 rdout *writer = (rdout *)(gen->outn_writer);
12289
12290 if ((loc <= writer->data_end) &&
12291 (loc >= writer->data_start))
12292 {
12293 writer->obufs[0][loc - writer->data_start] += (val * gen->outn[0]);
12294 if (loc > writer->out_end)
12295 writer->out_end = loc;
12296 }
12297 else mus_outa_to_file((mus_any *)writer, loc, val * gen->outn[0]);
12298
12299 writer = (rdout *)(gen->revn_writer);
12300 if ((loc <= writer->data_end) &&
12301 (loc >= writer->data_start))
12302 {
12303 writer->obufs[0][loc - writer->data_start] += (val * gen->revn[0]);
12304 if (loc > writer->out_end)
12305 writer->out_end = loc;
12306 }
12307 else mus_outa_to_file((mus_any *)writer, loc, val * gen->revn[0]);
12308 }
12309
mus_locsig_safe_stereo_no_reverb(mus_any * ptr,mus_long_t loc,mus_float_t val)12310 static void mus_locsig_safe_stereo_no_reverb(mus_any *ptr, mus_long_t loc, mus_float_t val)
12311 {
12312 locs *gen = (locs *)ptr;
12313 rdout *writer = (rdout *)(gen->outn_writer);
12314
12315 if ((loc <= writer->data_end) &&
12316 (loc >= writer->data_start))
12317 {
12318 mus_long_t pos;
12319 pos = loc - writer->data_start;
12320 writer->obufs[0][pos] += (val * gen->outn[0]);
12321 writer->obufs[1][pos] += (val * gen->outn[1]);
12322 if (loc > writer->out_end)
12323 writer->out_end = loc;
12324 }
12325 else
12326 {
12327 mus_outa_to_file((mus_any *)writer, loc, val * gen->outn[0]);
12328 mus_outb_to_file((mus_any *)writer, loc, val * gen->outn[1]);
12329 }
12330 }
12331
mus_locsig_safe_stereo(mus_any * ptr,mus_long_t loc,mus_float_t val)12332 static void mus_locsig_safe_stereo(mus_any *ptr, mus_long_t loc, mus_float_t val)
12333 {
12334 locs *gen = (locs *)ptr;
12335 rdout *writer = (rdout *)(gen->outn_writer);
12336
12337 if ((loc <= writer->data_end) &&
12338 (loc >= writer->data_start))
12339 {
12340 mus_long_t pos;
12341 pos = loc - writer->data_start;
12342 writer->obufs[0][pos] += (val * gen->outn[0]);
12343 writer->obufs[1][pos] += (val * gen->outn[1]);
12344 if (loc > writer->out_end)
12345 writer->out_end = loc;
12346 }
12347 else
12348 {
12349 mus_outa_to_file((mus_any *)writer, loc, val * gen->outn[0]);
12350 mus_outb_to_file((mus_any *)writer, loc, val * gen->outn[1]);
12351 }
12352
12353 writer = (rdout *)(gen->revn_writer);
12354 if ((loc <= writer->data_end) &&
12355 (loc >= writer->data_start))
12356 {
12357 writer->obufs[0][loc - writer->data_start] += (val * gen->revn[0]);
12358 if (loc > writer->out_end)
12359 writer->out_end = loc;
12360 }
12361 else mus_outa_to_file((mus_any *)writer, loc, val * gen->revn[0]);
12362 }
12363
12364
mus_locsig_detour(mus_any * ptr,mus_long_t loc,mus_float_t val)12365 static void mus_locsig_detour(mus_any *ptr, mus_long_t loc, mus_float_t val)
12366 {
12367 /* here we let the closure data decide what to do with the output */
12368 locs *gen = (locs *)ptr;
12369 if (gen->detour)
12370 {
12371 int i;
12372 for (i = 0; i < gen->chans; i++)
12373 gen->outf[i] = val * gen->outn[i];
12374
12375 for (i = 0; i < gen->rev_chans; i++)
12376 gen->revf[i] = val * gen->revn[i];
12377
12378 (*(gen->detour))(ptr, loc);
12379 }
12380 }
12381
mus_locsig_any_no_reverb(mus_any * ptr,mus_long_t loc,mus_float_t val)12382 static void mus_locsig_any_no_reverb(mus_any *ptr, mus_long_t loc, mus_float_t val)
12383 {
12384 int i;
12385 locs *gen = (locs *)ptr;
12386 rdout *writer = (rdout *)(gen->outn_writer);
12387 for (i = 0; i < gen->chans; i++)
12388 {
12389 gen->outf[i] = val * gen->outn[i];
12390 if (writer)
12391 mus_out_any_to_file((mus_any *)writer, loc, i, gen->outf[i]);
12392 }
12393 }
12394
mus_locsig_safe_any_no_reverb(mus_any * ptr,mus_long_t loc,mus_float_t val)12395 static void mus_locsig_safe_any_no_reverb(mus_any *ptr, mus_long_t loc, mus_float_t val)
12396 {
12397 int i;
12398 locs *gen = (locs *)ptr;
12399 rdout *writer = (rdout *)(gen->outn_writer);
12400
12401 if ((loc <= writer->data_end) &&
12402 (loc >= writer->data_start))
12403 {
12404 mus_long_t pos;
12405 pos = loc - writer->data_start;
12406 for (i = 0; i < gen->chans; i++)
12407 writer->obufs[i][pos] += (val * gen->outn[i]);
12408 if (loc > writer->out_end)
12409 writer->out_end = loc;
12410 }
12411 else
12412 {
12413 for (i = 0; i < gen->chans; i++)
12414 mus_safe_out_any_to_file(loc, val * gen->outn[i], i, (mus_any *)writer);
12415 }
12416 }
12417
12418
mus_locsig_safe_any(mus_any * ptr,mus_long_t loc,mus_float_t val)12419 static void mus_locsig_safe_any(mus_any *ptr, mus_long_t loc, mus_float_t val)
12420 {
12421 int i;
12422 locs *gen = (locs *)ptr;
12423 rdout *writer = (rdout *)(gen->outn_writer);
12424
12425 if ((loc <= writer->data_end) &&
12426 (loc >= writer->data_start))
12427 {
12428 mus_long_t pos;
12429 pos = loc - writer->data_start;
12430 for (i = 0; i < gen->chans; i++)
12431 writer->obufs[i][pos] += (val * gen->outn[i]);
12432 if (loc > writer->out_end)
12433 writer->out_end = loc;
12434 }
12435 else
12436 {
12437 for (i = 0; i < gen->chans; i++)
12438 mus_safe_out_any_to_file(loc, val * gen->outn[i], i, (mus_any *)writer);
12439 }
12440
12441 writer = (rdout *)(gen->revn_writer);
12442 if ((loc <= writer->data_end) &&
12443 (loc >= writer->data_start))
12444 {
12445 mus_long_t pos;
12446 pos = loc - writer->data_start;
12447 for (i = 0; i < gen->rev_chans; i++)
12448 writer->obufs[i][pos] += (val * gen->revn[i]);
12449 if (loc > writer->out_end)
12450 writer->out_end = loc;
12451 }
12452 else
12453 {
12454 for (i = 0; i < gen->rev_chans; i++)
12455 mus_safe_out_any_to_file(loc, val * gen->revn[i], i, (mus_any *)writer);
12456 }
12457 }
12458
12459
mus_make_locsig(mus_float_t degree,mus_float_t distance,mus_float_t reverb,int chans,mus_any * output,int rev_chans,mus_any * revput,mus_interp_t type)12460 mus_any *mus_make_locsig(mus_float_t degree, mus_float_t distance, mus_float_t reverb,
12461 int chans, mus_any *output, /* direct signal output */
12462 int rev_chans, mus_any *revput, /* reverb output */
12463 mus_interp_t type)
12464 {
12465 locs *gen;
12466 mus_float_t dist;
12467 if (chans <= 0)
12468 {
12469 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_locsig ": chans: %d", chans);
12470 return(NULL);
12471 }
12472 if (isnan(degree))
12473 {
12474 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_locsig ": degree: %f", degree);
12475 return(NULL);
12476 }
12477
12478 gen = (locs *)calloc(1, sizeof(locs));
12479 gen->core = &LOCSIG_CLASS;
12480 gen->outf = (mus_float_t *)calloc(chans, sizeof(mus_float_t));
12481
12482 gen->type = type;
12483 gen->reverb = reverb;
12484 gen->distance = distance;
12485 gen->degree = degree;
12486 gen->safe_output = false;
12487 if (distance > 1.0)
12488 dist = 1.0 / distance;
12489 else dist = 1.0;
12490
12491 if (mus_is_output(output))
12492 gen->outn_writer = output;
12493 gen->chans = chans;
12494 gen->outn = (mus_float_t *)calloc(gen->chans, sizeof(mus_float_t));
12495 mus_locsig_fill(gen->outn, gen->chans, degree, dist, type);
12496
12497 if (mus_is_output(revput))
12498 gen->revn_writer = revput;
12499 gen->rev_chans = rev_chans;
12500 if (gen->rev_chans > 0)
12501 {
12502 gen->revn = (mus_float_t *)calloc(gen->rev_chans, sizeof(mus_float_t));
12503 gen->revf = (mus_float_t *)calloc(gen->rev_chans, sizeof(mus_float_t));
12504 mus_locsig_fill(gen->revn, gen->rev_chans, degree, (reverb * sqrt(dist)), type);
12505 }
12506
12507 /* now choose the output function based on chans, and reverb
12508 */
12509 if ((!output) && (!revput))
12510 gen->locsig_func = mus_locsig_detour;
12511 else
12512 {
12513 gen->locsig_func = mus_locsig_any;
12514
12515 if ((mus_is_output(output)) &&
12516 (mus_out_any_is_safe(output)) &&
12517 (mus_channels(output) == chans))
12518 {
12519 if (rev_chans > 0)
12520 {
12521 if ((rev_chans == 1) &&
12522 (mus_is_output(revput)) &&
12523 (mus_out_any_is_safe(revput)) &&
12524 (mus_channels(revput) == 1))
12525 {
12526 gen->safe_output = true;
12527 switch (chans)
12528 {
12529 case 1: gen->locsig_func = mus_locsig_safe_mono; break;
12530 case 2: gen->locsig_func = mus_locsig_safe_stereo; break;
12531 default: gen->locsig_func = mus_locsig_safe_any; break;
12532 }
12533 }
12534 }
12535 else
12536 {
12537 gen->safe_output = true;
12538 switch (chans)
12539 {
12540 case 1: gen->locsig_func = mus_locsig_safe_mono_no_reverb; break;
12541 case 2: gen->locsig_func = mus_locsig_safe_stereo_no_reverb; break;
12542 default: gen->locsig_func = mus_locsig_safe_any_no_reverb; break;
12543 }
12544 }
12545 }
12546 else
12547 {
12548 if (rev_chans > 0)
12549 {
12550 if (rev_chans == 1)
12551 {
12552 switch (chans)
12553 {
12554 case 1: gen->locsig_func = mus_locsig_mono; break;
12555 case 2: gen->locsig_func = mus_locsig_stereo; break;
12556 default: gen->locsig_func = mus_locsig_any; break;
12557 }
12558 }
12559 }
12560 else
12561 {
12562 switch (chans)
12563 {
12564 case 1: gen->locsig_func = mus_locsig_mono_no_reverb; break;
12565 case 2: gen->locsig_func = mus_locsig_stereo_no_reverb; break;
12566 default: gen->locsig_func = mus_locsig_any_no_reverb; break;
12567 }
12568 }
12569 }
12570 }
12571 return((mus_any *)gen);
12572 }
12573
mus_locsig(mus_any * ptr,mus_long_t loc,mus_float_t val)12574 void mus_locsig(mus_any *ptr, mus_long_t loc, mus_float_t val)
12575 {
12576 locs *gen = (locs *)ptr;
12577 (*(gen->locsig_func))(ptr, loc, val);
12578 }
12579
mus_locsig_channels(mus_any * ptr)12580 int mus_locsig_channels(mus_any *ptr)
12581 {
12582 return(((locs *)ptr)->chans);
12583 }
12584
mus_locsig_reverb_channels(mus_any * ptr)12585 int mus_locsig_reverb_channels(mus_any *ptr)
12586 {
12587 return(((locs *)ptr)->rev_chans);
12588 }
12589
12590
mus_move_locsig(mus_any * ptr,mus_float_t degree,mus_float_t distance)12591 void mus_move_locsig(mus_any *ptr, mus_float_t degree, mus_float_t distance)
12592 {
12593 locs *gen = (locs *)ptr;
12594 mus_float_t dist;
12595
12596 if (distance > 1.0)
12597 dist = 1.0 / distance;
12598 else dist = 1.0;
12599
12600 if (gen->rev_chans > 0)
12601 {
12602 if (gen->rev_chans > 2)
12603 mus_clear_floats(gen->revn, gen->rev_chans);
12604 mus_locsig_fill(gen->revn, gen->rev_chans, degree, (gen->reverb * sqrt(dist)), gen->type);
12605 }
12606 if (gen->chans > 2)
12607 mus_clear_floats(gen->outn, gen->chans);
12608 mus_locsig_fill(gen->outn, gen->chans, degree, dist, gen->type);
12609 }
12610
12611
12612
12613 /* ---------------- move-sound ---------------- */
12614
12615 typedef struct {
12616 mus_any_class *core;
12617 mus_any *outn_writer;
12618 mus_any *revn_writer;
12619 mus_float_t *outf, *revf;
12620 int out_channels, rev_channels;
12621 mus_long_t start, end;
12622 mus_any *doppler_delay, *doppler_env, *rev_env;
12623 mus_any **out_delays, **out_envs, **rev_envs;
12624 int *out_map;
12625 bool free_arrays, free_gens;
12626 void *closure;
12627 void (*detour)(mus_any *ptr, mus_long_t loc);
12628 } dloc;
12629
12630
move_sound_equalp(mus_any * p1,mus_any * p2)12631 static bool move_sound_equalp(mus_any *p1, mus_any *p2) {return(p1 == p2);}
mus_move_sound_channels(mus_any * ptr)12632 int mus_move_sound_channels(mus_any *ptr) {return(((dloc *)ptr)->out_channels);}
mus_move_sound_reverb_channels(mus_any * ptr)12633 int mus_move_sound_reverb_channels(mus_any *ptr) {return(((dloc *)ptr)->rev_channels);}
move_sound_length(mus_any * ptr)12634 static mus_long_t move_sound_length(mus_any *ptr) {return(((dloc *)ptr)->out_channels);} /* need both because return types differ */
move_sound_reset(mus_any * ptr)12635 static void move_sound_reset(mus_any *ptr) {}
12636
mus_move_sound_outf(mus_any * ptr)12637 mus_float_t *mus_move_sound_outf(mus_any *ptr) {return(((dloc *)ptr)->outf);}
mus_move_sound_revf(mus_any * ptr)12638 mus_float_t *mus_move_sound_revf(mus_any *ptr) {return(((dloc *)ptr)->revf);}
12639
mus_move_sound_closure(mus_any * ptr)12640 void *mus_move_sound_closure(mus_any *ptr) {return(((dloc *)ptr)->closure);}
move_sound_set_closure(mus_any * ptr,void * e)12641 static void *move_sound_set_closure(mus_any *ptr, void *e) {((dloc *)ptr)->closure = e; return(e);}
12642
mus_move_sound_set_detour(mus_any * ptr,void (* detour)(mus_any * ptr,mus_long_t val))12643 void mus_move_sound_set_detour(mus_any *ptr, void (*detour)(mus_any *ptr, mus_long_t val))
12644 {
12645 dloc *gen = (dloc *)ptr;
12646 gen->detour = detour;
12647 }
12648
12649
describe_move_sound(mus_any * ptr)12650 static char *describe_move_sound(mus_any *ptr)
12651 {
12652 dloc *gen = (dloc *)ptr;
12653 char *dopdly, *dopenv, *revenv;
12654 char *outdlys, *outenvs, *revenvs;
12655 char *outmap;
12656 char *starts;
12657 char *str1 = NULL, *str2 = NULL, *str3 = NULL;
12658 char *allstr;
12659 int len;
12660
12661 starts = mus_format("%s start: %" print_mus_long ", end: %" print_mus_long ", out chans %d, rev chans: %d",
12662 mus_name(ptr),
12663 gen->start,
12664 gen->end,
12665 gen->out_channels,
12666 gen->rev_channels);
12667 dopdly = mus_format("doppler %s", str1 = mus_describe(gen->doppler_delay));
12668 dopenv = mus_format("doppler %s", str2 = mus_describe(gen->doppler_env));
12669 revenv = mus_format("global reverb %s", str3 = mus_describe(gen->rev_env));
12670 outdlys = clm_array_to_string(gen->out_delays, gen->out_channels, "out_delays", " ");
12671 outenvs = clm_array_to_string(gen->out_envs, gen->out_channels, "out_envs", " ");
12672 revenvs = clm_array_to_string(gen->rev_envs, gen->rev_channels, "rev_envs", " ");
12673 outmap = int_array_to_string(gen->out_map, gen->out_channels, "out_map");
12674
12675 len = 64 + strlen(starts) + strlen(dopdly) + strlen(dopenv) + strlen(revenv) +
12676 strlen(outdlys) + strlen(outenvs) + strlen(revenvs) + strlen(outmap);
12677 allstr = (char *)malloc(len * sizeof(char));
12678 snprintf(allstr, len, "%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n free: arrays: %s, gens: %s\n",
12679 starts, dopdly, dopenv, revenv, outdlys, outenvs, revenvs, outmap,
12680 (gen->free_arrays) ? "true" : "false",
12681 (gen->free_gens) ? "true" : "false");
12682 if (str1) free(str1);
12683 if (str2) free(str2);
12684 if (str3) free(str3);
12685 free(starts);
12686 free(dopdly);
12687 free(dopenv);
12688 free(revenv);
12689 free(outdlys);
12690 free(outenvs);
12691 free(revenvs);
12692 free(outmap);
12693 return(allstr);
12694 }
12695
12696
free_move_sound(mus_any * p)12697 static void free_move_sound(mus_any *p)
12698 {
12699 dloc *ptr = (dloc *)p;
12700 if (ptr->free_gens)
12701 {
12702 int i;
12703 /* free everything except outer arrays and IO stuff */
12704 if (ptr->doppler_delay) mus_free(ptr->doppler_delay);
12705 if (ptr->doppler_env) mus_free(ptr->doppler_env);
12706 if (ptr->rev_env) mus_free(ptr->rev_env);
12707 if (ptr->out_delays)
12708 for (i = 0; i < ptr->out_channels; i++)
12709 if (ptr->out_delays[i]) mus_free(ptr->out_delays[i]);
12710 if (ptr->out_envs)
12711 for (i = 0; i < ptr->out_channels; i++)
12712 if (ptr->out_envs[i]) mus_free(ptr->out_envs[i]);
12713 if (ptr->rev_envs)
12714 for (i = 0; i < ptr->rev_channels; i++)
12715 if (ptr->rev_envs[i]) mus_free(ptr->rev_envs[i]);
12716 }
12717
12718 if (ptr->free_arrays)
12719 {
12720 /* free outer arrays */
12721 if (ptr->out_envs) {free(ptr->out_envs); ptr->out_envs = NULL;}
12722 if (ptr->rev_envs) {free(ptr->rev_envs); ptr->rev_envs = NULL;}
12723 if (ptr->out_delays) {free(ptr->out_delays); ptr->out_delays = NULL;}
12724 if (ptr->out_map) free(ptr->out_map);
12725 }
12726
12727 /* we created these in make_move_sound, so it should always be safe to free them */
12728 if (ptr->outf) free(ptr->outf);
12729 if (ptr->revf) free(ptr->revf);
12730 free(ptr);
12731 }
12732
dloc_copy(mus_any * ptr)12733 static mus_any *dloc_copy(mus_any *ptr)
12734 {
12735 dloc *g, *p;
12736 int i, bytes;
12737 p = (dloc *)ptr;
12738 g = (dloc *)malloc(sizeof(dloc));
12739 memcpy((void *)g, (void *)ptr, sizeof(dloc));
12740
12741 if (p->outf)
12742 {
12743 bytes = p->out_channels * sizeof(mus_float_t);
12744 g->outf = (mus_float_t *)malloc(bytes);
12745 mus_copy_floats(g->outf, p->outf, p->out_channels);
12746 }
12747 if (p->revf)
12748 {
12749 bytes = p->rev_channels * sizeof(mus_float_t);
12750 g->revf = (mus_float_t *)malloc(bytes);
12751 mus_copy_floats(g->revf, p->revf, p->rev_channels);
12752 }
12753
12754 g->free_arrays = true;
12755 g->free_gens = true;
12756 if (p->doppler_delay) g->doppler_delay = mus_copy(p->doppler_delay);
12757 if (p->doppler_env) g->doppler_env = mus_copy(p->doppler_env);
12758 if (p->rev_env) g->rev_env = mus_copy(p->rev_env);
12759 if (p->out_envs)
12760 {
12761 g->out_envs = (mus_any **)malloc(p->out_channels * sizeof(mus_any *));
12762 for (i = 0; i < p->out_channels; i++) g->out_envs[i] = mus_copy(p->out_envs[i]);
12763 }
12764 if (p->rev_envs)
12765 {
12766 g->rev_envs = (mus_any **)malloc(p->rev_channels * sizeof(mus_any *));
12767 for (i = 0; i < p->rev_channels; i++) g->rev_envs[i] = mus_copy(p->rev_envs[i]);
12768 }
12769 if (p->out_delays)
12770 {
12771 g->out_delays = (mus_any **)malloc(p->out_channels * sizeof(mus_any *));
12772 for (i = 0; i < p->out_channels; i++) g->out_delays[i] = mus_copy(p->out_delays[i]);
12773 }
12774 if (p->out_map)
12775 {
12776 bytes = p->out_channels * sizeof(int);
12777 g->out_map = (int *)malloc(bytes);
12778 memcpy((void *)(g->out_map), (void *)(p->out_map), bytes);
12779 }
12780
12781 return((mus_any *)g);
12782 }
12783
mus_is_move_sound(mus_any * ptr)12784 bool mus_is_move_sound(mus_any *ptr)
12785 {
12786 return((ptr) &&
12787 (ptr->core->type == MUS_MOVE_SOUND));
12788 }
12789
12790
mus_move_sound(mus_any * ptr,mus_long_t loc,mus_float_t uval)12791 mus_float_t mus_move_sound(mus_any *ptr, mus_long_t loc, mus_float_t uval)
12792 {
12793 dloc *gen = (dloc *)ptr;
12794 mus_float_t val;
12795 int chan;
12796
12797 if (loc > gen->end) val = 0.0; else val = uval;
12798
12799 /* initial silence */
12800 if (loc < gen->start)
12801 {
12802 mus_delay_unmodulated(gen->doppler_delay, val);
12803 /* original calls out_any here with 0.0 -- a no-op */
12804 return(val);
12805 }
12806
12807 /* doppler */
12808 if (gen->doppler_delay)
12809 val = mus_delay(gen->doppler_delay, val, mus_env(gen->doppler_env));
12810
12811 /* direct signal */
12812 for (chan = 0; chan < gen->out_channels; chan++)
12813 {
12814 mus_float_t sample;
12815 sample = val * mus_env(gen->out_envs[chan]);
12816 if (gen->out_delays[chan])
12817 sample = mus_delay_unmodulated(gen->out_delays[chan], sample);
12818 gen->outf[gen->out_map[chan]] = sample;
12819 }
12820
12821 /* reverb */
12822 if ((gen->rev_env) &&
12823 (gen->revf))
12824 {
12825 val *= mus_env(gen->rev_env);
12826 if (gen->rev_envs)
12827 {
12828 if (gen->rev_channels == 1)
12829 gen->revf[0] = val * mus_env(gen->rev_envs[0]);
12830 else
12831 {
12832 for (chan = 0; chan < gen->rev_channels; chan++)
12833 gen->revf[gen->out_map[chan]] = val * mus_env(gen->rev_envs[chan]);
12834 }
12835 }
12836 else gen->revf[0] = val;
12837
12838 if (gen->revn_writer)
12839 mus_frample_to_file(gen->revn_writer, loc, gen->revf);
12840 }
12841
12842 /* file output */
12843 if (gen->outn_writer)
12844 mus_frample_to_file(gen->outn_writer, loc, gen->outf);
12845
12846 if (gen->detour)
12847 (*(gen->detour))(ptr, loc);
12848 return(uval);
12849 }
12850
12851
run_move_sound(mus_any * ptr,mus_float_t arg1,mus_float_t arg2)12852 static mus_float_t run_move_sound(mus_any *ptr, mus_float_t arg1, mus_float_t arg2)
12853 {
12854 mus_move_sound(ptr, (mus_long_t)arg1, arg2);
12855 return(arg2);
12856 }
12857
12858
12859 static mus_any_class MOVE_SOUND_CLASS = {
12860 MUS_MOVE_SOUND,
12861 (char *)S_move_sound,
12862 &free_move_sound,
12863 &describe_move_sound,
12864 &move_sound_equalp,
12865 0, 0,
12866 &move_sound_length,
12867 0,
12868 0, 0, 0, 0,
12869 0, 0,
12870 0, 0,
12871 &run_move_sound,
12872 MUS_OUTPUT,
12873 &mus_move_sound_closure,
12874 &mus_move_sound_channels,
12875 0, 0, 0, 0,
12876 0, 0,
12877 0, 0, 0, 0,
12878 0, 0, 0, 0, 0, 0, 0,
12879 0, 0,
12880 0, 0,
12881 &move_sound_reset,
12882 &move_sound_set_closure,
12883 &dloc_copy
12884 };
12885
12886
mus_make_move_sound(mus_long_t start,mus_long_t end,int out_channels,int rev_channels,mus_any * doppler_delay,mus_any * doppler_env,mus_any * rev_env,mus_any ** out_delays,mus_any ** out_envs,mus_any ** rev_envs,int * out_map,mus_any * output,mus_any * revput,bool free_arrays,bool free_gens)12887 mus_any *mus_make_move_sound(mus_long_t start, mus_long_t end, int out_channels, int rev_channels,
12888 mus_any *doppler_delay, mus_any *doppler_env, mus_any *rev_env,
12889 mus_any **out_delays, mus_any **out_envs, mus_any **rev_envs,
12890 int *out_map, mus_any *output, mus_any *revput, bool free_arrays, bool free_gens)
12891 {
12892 /* most of these args come to us in a list at the lisp/xen level ("dlocs" struct is actually a list)
12893 * so the make-move-sound function in lisp/xen is (make-move-sound dloc-list output revout)
12894 * where the trailing args mimic locsig.
12895 */
12896 dloc *gen;
12897 if (out_channels <= 0)
12898 {
12899 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_move_sound ": out chans: %d", out_channels);
12900 return(NULL);
12901 }
12902 gen = (dloc *)calloc(1, sizeof(dloc));
12903 gen->core = &MOVE_SOUND_CLASS;
12904
12905 gen->start = start;
12906 gen->end = end;
12907 gen->out_channels = out_channels;
12908 gen->rev_channels = rev_channels;
12909 gen->doppler_delay = doppler_delay;
12910 gen->doppler_env = doppler_env;
12911 gen->rev_env = rev_env;
12912 gen->out_delays = out_delays;
12913 gen->out_envs = out_envs;
12914 gen->rev_envs = rev_envs;
12915 gen->out_map = out_map;
12916
12917 /* default is to free only what we make ourselves */
12918 gen->free_gens = free_gens;
12919 gen->free_arrays = free_arrays;
12920
12921 gen->outf = (mus_float_t *)calloc(out_channels, sizeof(mus_float_t));
12922 if (mus_is_output(output))
12923 gen->outn_writer = output;
12924
12925 if (rev_channels > 0)
12926 {
12927 if (mus_is_output(revput))
12928 gen->revn_writer = revput;
12929 gen->revf = (mus_float_t *)calloc(rev_channels, sizeof(mus_float_t));
12930 }
12931
12932 return((mus_any *)gen);
12933 }
12934
12935
12936
12937 /* ---------------- src ---------------- */
12938
12939 /* sampling rate conversion */
12940 /* taken from sweep_srate.c of Perry Cook. To quote Perry:
12941 *
12942 * 'The conversion is performed by sinc interpolation.
12943 * J. O. Smith and P. Gossett, "A Flexible Sampling-Rate Conversion Method,"
12944 * Proc. of the IEEE Conference on Acoustics, Speech, and Signal Processing, San Diego, CA, March, 1984.
12945 * There are essentially two cases, one where the conversion factor
12946 * is less than one, and the sinc table is used as is yielding a sound
12947 * which is band limited to the 1/2 the new sampling rate (we don't
12948 * want to create bandwidth where there was none). The other case
12949 * is where the conversion factor is greater than one and we 'warp'
12950 * the sinc table to make the final cutoff equal to the original sampling
12951 * rate /2. Warping the sinc table is based on the similarity theorem
12952 * of the time and frequency domain, stretching the time domain (sinc
12953 * table) causes shrinking in the frequency domain.'
12954 *
12955 * we also scale the amplitude if interpolating to take into account the broadened sinc
12956 * this means that isolated pulses get scaled by 1/src, but that's a dumb special case
12957 */
12958
12959 typedef struct {
12960 mus_any_class *core;
12961 mus_float_t (*feeder)(void *arg, int direction);
12962 mus_float_t (*block_feeder)(void *arg, int direction, mus_float_t *block, mus_long_t start, mus_long_t end);
12963 mus_float_t x;
12964 mus_float_t incr, width_1;
12965 int width, lim, start, sinc4;
12966 int len;
12967 mus_float_t *data, *sinc_table, *coeffs;
12968 void *closure;
12969 } sr;
12970
12971
12972 #define SRC_SINC_DENSITY 2000
12973 #define SRC_SINC_WIDTH 10
12974 #define SRC_SINC_WINDOW_SIZE 8000
12975
12976 static mus_float_t **sinc_tables = NULL;
12977 static int *sinc_widths = NULL;
12978 static int sincs = 0;
12979 static mus_float_t *sinc = NULL, *sinc_window = NULL;
12980 static int sinc_size = 0;
12981
mus_clear_sinc_tables(void)12982 void mus_clear_sinc_tables(void)
12983 {
12984 if (sincs)
12985 {
12986 int i;
12987 for (i = 0; i < sincs; i++)
12988 if (sinc_tables[i])
12989 free(sinc_tables[i]);
12990 free(sinc_tables);
12991 sinc_tables = NULL;
12992
12993 free(sinc_window);
12994 sinc_window = NULL;
12995 free(sinc_widths);
12996 sinc_widths = NULL;
12997 sincs = 0;
12998 }
12999 }
13000
13001
init_sinc_table(int width)13002 static int init_sinc_table(int width)
13003 {
13004 int i, size, padded_size, loc;
13005 mus_float_t win_freq, win_phase;
13006 #if HAVE_SINCOS
13007 double sn, snp, cs, csp;
13008 #endif
13009
13010 if (width > sinc_size)
13011 {
13012 int old_end;
13013 mus_float_t sinc_phase, sinc_freq;
13014 if (sinc_size == 0)
13015 old_end = 1;
13016 else old_end = sinc_size * SRC_SINC_DENSITY + 4;
13017 padded_size = width * SRC_SINC_DENSITY + 4;
13018 if (sinc_size == 0)
13019 {
13020 sinc = (mus_float_t *)malloc(padded_size * sizeof(mus_float_t));
13021 sinc[0] = 1.0;
13022 }
13023 else sinc = (mus_float_t *)realloc(sinc, padded_size * sizeof(mus_float_t));
13024 sinc_size = width;
13025 sinc_freq = M_PI / (mus_float_t)SRC_SINC_DENSITY;
13026 sinc_phase = old_end * sinc_freq;
13027 #if HAVE_SINCOS
13028 sincos(sinc_freq, &sn, &cs);
13029 if (old_end == 1)
13030 {
13031 sinc[1] = sin(sinc_phase) / (2.0 * sinc_phase);
13032 old_end++;
13033 sinc_phase += sinc_freq;
13034 }
13035 for (i = old_end; i < padded_size;)
13036 {
13037 sincos(sinc_phase, &snp, &csp);
13038 sinc[i] = snp / (2.0 * sinc_phase);
13039 i++;
13040 sinc_phase += sinc_freq;
13041 sinc[i] = (snp * cs + csp * sn) / (2.0 * sinc_phase);
13042 i++;
13043 sinc_phase += sinc_freq;
13044 }
13045 #else
13046 for (i = old_end; i < padded_size; i++, sinc_phase += sinc_freq)
13047 sinc[i] = sin(sinc_phase) / (2.0 * sinc_phase);
13048 #endif
13049 }
13050
13051 for (i = 0; i < sincs; i++)
13052 if (sinc_widths[i] == width)
13053 return(i);
13054
13055 if (sincs == 0)
13056 {
13057 mus_float_t ph, incr;
13058 incr = M_PI / SRC_SINC_WINDOW_SIZE;
13059 sinc_window = (mus_float_t *)calloc(SRC_SINC_WINDOW_SIZE + 16, sizeof(mus_float_t));
13060 for (i = 0, ph = 0.0; i < SRC_SINC_WINDOW_SIZE; i++, ph += incr)
13061 sinc_window[i] = 1.0 + cos(ph);
13062
13063 sinc_tables = (mus_float_t **)calloc(8, sizeof(mus_float_t *));
13064 sinc_widths = (int *)calloc(8, sizeof(int));
13065 sincs = 8;
13066 loc = 0;
13067 }
13068 else
13069 {
13070 loc = -1;
13071 for (i = 0; i < sincs; i++)
13072 if (sinc_widths[i] == 0)
13073 {
13074 loc = i;
13075 break;
13076 }
13077 if (loc == -1)
13078 {
13079 sinc_tables = (mus_float_t **)realloc(sinc_tables, (sincs + 8) * sizeof(mus_float_t *));
13080 sinc_widths = (int *)realloc(sinc_widths, (sincs + 8) * sizeof(int));
13081 for (i = sincs; i < (sincs + 8); i++)
13082 {
13083 sinc_widths[i] = 0;
13084 sinc_tables[i] = NULL;
13085 }
13086 loc = sincs;
13087 sincs += 8;
13088 }
13089 }
13090
13091 sinc_widths[loc] = width;
13092 size = width * SRC_SINC_DENSITY;
13093 padded_size = size + 4;
13094 win_freq = (mus_float_t)SRC_SINC_WINDOW_SIZE / (mus_float_t)size;
13095
13096 sinc_tables[loc] = (mus_float_t *)malloc(padded_size * 2 * sizeof(mus_float_t));
13097 sinc_tables[loc][padded_size] = 1.0;
13098
13099 for (i = 1, win_phase = win_freq; i < padded_size; i++, win_phase += win_freq)
13100 {
13101 mus_float_t val;
13102 val = sinc[i] * sinc_window[(int)win_phase];
13103 sinc_tables[loc][padded_size + i] = val;
13104 sinc_tables[loc][padded_size - i] = val;
13105 }
13106
13107 return(loc);
13108 }
13109
13110
mus_is_src(mus_any * ptr)13111 bool mus_is_src(mus_any *ptr)
13112 {
13113 return((ptr) &&
13114 (ptr->core->type == MUS_SRC));
13115 }
13116
13117
free_src_gen(mus_any * srptr)13118 static void free_src_gen(mus_any *srptr)
13119 {
13120 sr *srp = (sr *)srptr;
13121 if (srp->data) free(srp->data);
13122 if (srp->coeffs) free(srp->coeffs);
13123 free(srp);
13124 }
13125
sr_copy(mus_any * ptr)13126 static mus_any *sr_copy(mus_any *ptr)
13127 {
13128 sr *g, *p;
13129 int bytes;
13130
13131 p = (sr *)ptr;
13132 g = (sr *)malloc(sizeof(sr));
13133 memcpy((void *)g, (void *)ptr, sizeof(sr));
13134
13135 bytes = (2 * g->lim + 1) * sizeof(mus_float_t);
13136 g->data = (mus_float_t *)malloc(bytes);
13137 mus_copy_floats(g->data, p->data, 2 * g->lim + 1);
13138
13139 if (p->coeffs)
13140 {
13141 bytes = p->lim * sizeof(mus_float_t);
13142 g->coeffs = (mus_float_t *)malloc(bytes);
13143 mus_copy_floats(g->coeffs, p->coeffs, p->lim);
13144 }
13145 return((mus_any *)g);
13146 }
13147
src_equalp(mus_any * p1,mus_any * p2)13148 static bool src_equalp(mus_any *p1, mus_any *p2) {return(p1 == p2);}
13149
13150
describe_src(mus_any * ptr)13151 static char *describe_src(mus_any *ptr)
13152 {
13153 sr *gen = (sr *)ptr;
13154 char *describe_buffer;
13155 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
13156 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s width: %d, x: %.3f, incr: %.3f, sinc table len: %d",
13157 mus_name(ptr),
13158 gen->width, gen->x, gen->incr, gen->len);
13159 return(describe_buffer);
13160 }
13161
13162
src_length(mus_any * ptr)13163 static mus_long_t src_length(mus_any *ptr) {return(((sr *)ptr)->width);}
run_src_gen(mus_any * srptr,mus_float_t sr_change,mus_float_t unused)13164 static mus_float_t run_src_gen(mus_any *srptr, mus_float_t sr_change, mus_float_t unused) {return(mus_src(srptr, sr_change, NULL));}
13165
src_closure(mus_any * rd)13166 static void *src_closure(mus_any *rd) {return(((sr *)rd)->closure);}
src_set_closure(mus_any * rd,void * e)13167 static void *src_set_closure(mus_any *rd, void *e) {((sr *)rd)->closure = e; return(e);}
13168
src_increment(mus_any * rd)13169 static mus_float_t src_increment(mus_any *rd) {return(((sr *)rd)->incr);}
src_set_increment(mus_any * rd,mus_float_t val)13170 static mus_float_t src_set_increment(mus_any *rd, mus_float_t val) {((sr *)rd)->incr = val; return(val);}
13171
src_sinc_table(mus_any * rd)13172 static mus_float_t *src_sinc_table(mus_any *rd) {return(((sr *)rd)->sinc_table);}
13173
src_reset(mus_any * ptr)13174 static void src_reset(mus_any *ptr)
13175 {
13176 sr *gen = (sr *)ptr;
13177 mus_clear_floats(gen->data, gen->lim + 1);
13178 gen->x = 0.0;
13179 /* center the data if possible */
13180 if (gen->feeder)
13181 {
13182 int i, dir = 1;
13183 if (gen->incr < 0.0) dir = -1;
13184 for (i = gen->width - 1; i < gen->lim; i++)
13185 gen->data[i] = gen->feeder(gen->closure, dir);
13186 }
13187 gen->start = 0;
13188 }
13189
mus_src_init(mus_any * ptr)13190 void mus_src_init(mus_any *ptr)
13191 {
13192 sr *srp = (sr *)ptr;
13193 if (srp->feeder)
13194 {
13195 int i, dir = 1;
13196 if (srp->incr < 0.0) dir = -1;
13197 for (i = srp->width - 1; i < srp->lim; i++)
13198 {
13199 srp->data[i] = srp->feeder(srp->closure, dir);
13200 srp->data[i + srp->lim] = srp->data[i];
13201 }
13202 }
13203 }
13204
13205 static mus_any_class SRC_CLASS = {
13206 MUS_SRC,
13207 (char *)S_src,
13208 &free_src_gen,
13209 &describe_src,
13210 &src_equalp,
13211 &src_sinc_table, 0,
13212 &src_length, /* sinc width actually */
13213 0,
13214 0, 0, 0, 0,
13215 &fallback_scaler, 0,
13216 &src_increment,
13217 &src_set_increment,
13218 &run_src_gen,
13219 MUS_NOT_SPECIAL,
13220 &src_closure,
13221 0,
13222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
13223 0, 0, 0, 0, 0, 0, 0,
13224 0, 0, 0, 0,
13225 &src_reset,
13226 &src_set_closure,
13227 &sr_copy
13228 };
13229
13230
mus_make_src_with_init(mus_float_t (* input)(void * arg,int direction),mus_float_t srate,int width,void * closure,void (* init)(void * p,mus_any * g))13231 mus_any *mus_make_src_with_init(mus_float_t (*input)(void *arg, int direction), mus_float_t srate, int width, void *closure, void (*init)(void *p, mus_any *g))
13232 {
13233 /* besides 1, 2, .5, other common cases: 1.5, 3
13234 */
13235
13236 if (fabs(srate) > MUS_MAX_CLM_SRC)
13237 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_src ": srate arg invalid: %f", srate);
13238 else
13239 {
13240 if ((width < 0) || (width > MUS_MAX_CLM_SINC_WIDTH))
13241 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_src ": width arg invalid: %d", width);
13242 else
13243 {
13244 sr *srp;
13245 int wid, loc;
13246
13247 if (width <= 0) width = SRC_SINC_WIDTH;
13248 if (width < (int)(fabs(srate) * 2))
13249 wid = (int)(ceil(fabs(srate)) * 2);
13250 else wid = width;
13251 if ((srate == 2.0) &&
13252 ((wid & 1) != 0))
13253 wid++;
13254
13255 srp = (sr *)calloc(1, sizeof(sr));
13256 srp->core = &SRC_CLASS;
13257 srp->x = 0.0;
13258 srp->feeder = input;
13259 srp->block_feeder = NULL;
13260 srp->closure = closure;
13261 srp->incr = srate;
13262 srp->width = wid;
13263 srp->lim = 2 * wid;
13264 srp->start = 0;
13265 srp->len = wid * SRC_SINC_DENSITY;
13266 srp->width_1 = 1.0 - wid;
13267 srp->sinc4 = srp->width * SRC_SINC_DENSITY + 4;
13268 srp->data = (mus_float_t *)calloc(2 * srp->lim + 1, sizeof(mus_float_t));
13269 loc = init_sinc_table(wid);
13270 srp->sinc_table = sinc_tables[loc];
13271 srp->coeffs = NULL;
13272
13273 if (init)
13274 init(closure, (mus_any *)srp);
13275
13276 if (srp->feeder)
13277 {
13278 int i, dir = 1;
13279 if (srate < 0.0) dir = -1;
13280 for (i = wid - 1; i < srp->lim; i++)
13281 {
13282 srp->data[i] = srp->feeder(closure, dir);
13283 srp->data[i + srp->lim] = srp->data[i];
13284 }
13285 /* was i = 0 here but we want the incoming data centered */
13286 }
13287 return((mus_any *)srp);
13288 }
13289 }
13290 return(NULL);
13291 }
13292
mus_make_src(mus_float_t (* input)(void * arg,int direction),mus_float_t srate,int width,void * closure)13293 mus_any *mus_make_src(mus_float_t (*input)(void *arg, int direction), mus_float_t srate, int width, void *closure)
13294 {
13295 return(mus_make_src_with_init(input, srate, width, closure, NULL));
13296 }
13297
mus_src(mus_any * srptr,mus_float_t sr_change,mus_float_t (* input)(void * arg,int direction))13298 mus_float_t mus_src(mus_any *srptr, mus_float_t sr_change, mus_float_t (*input)(void *arg, int direction))
13299 {
13300 sr *srp = (sr *)srptr;
13301 mus_float_t sum, zf, srx, factor;
13302 int lim, loc, xi;
13303 bool int_ok;
13304 mus_float_t *data, *sinc_table;
13305
13306 lim = srp->lim;
13307 loc = srp->start;
13308 data = srp->data;
13309 sinc_table = srp->sinc_table;
13310
13311 if (sr_change > MUS_MAX_CLM_SRC)
13312 sr_change = MUS_MAX_CLM_SRC;
13313 else
13314 {
13315 if (sr_change < -MUS_MAX_CLM_SRC)
13316 sr_change = -MUS_MAX_CLM_SRC;
13317 }
13318 srx = srp->incr + sr_change;
13319
13320 if (srp->x >= 1.0)
13321 {
13322 int i, fsx, dir = 1;
13323
13324 if (srx < 0.0) dir = -1;
13325 fsx = (int)(srp->x);
13326 srp->x -= fsx;
13327
13328 if (input) {srp->feeder = input; srp->block_feeder = NULL;}
13329
13330 data[loc] = srp->feeder(srp->closure, dir);
13331 data[loc + lim] = data[loc];
13332 loc++;
13333 if (loc == lim) loc = 0;
13334
13335 for (i = 1; i < fsx; i++)
13336 {
13337 /* there are two copies of the circular data buffer back-to-back so that we can
13338 * run the convolution below without worrying about the buffer end.
13339 */
13340 data[loc] = srp->feeder(srp->closure, dir);
13341 data[loc + lim] = data[loc];
13342 loc++;
13343 if (loc == lim) loc = 0;
13344 }
13345 srp->start = loc; /* next time around we start here */
13346 }
13347
13348 /* now loc = beginning of data */
13349
13350 /* if (srx == 0.0) srx = 0.01; */ /* can't decide about this ... */
13351 if (srx < 0.0) srx = -srx;
13352 if (srx > 1.0)
13353 {
13354 factor = 1.0 / srx;
13355 /* this is not exact since we're sampling the sinc and so on, but it's close over a wide range */
13356 zf = factor * (mus_float_t)SRC_SINC_DENSITY;
13357 xi = (int)(zf + 0.5);
13358
13359 /* (let ((e (make-env '(0 1 1 1.1) :length 11))) (src-channel e))
13360 */
13361 /* we're comparing adding xi lim times to zf and if there's no difference, using the int case */
13362 if (fabs((xi - zf) * lim) > 2.0) int_ok = false; else int_ok = true;
13363 }
13364 else
13365 {
13366 factor = 1.0;
13367 zf = (mus_float_t)SRC_SINC_DENSITY;
13368 xi = SRC_SINC_DENSITY;
13369 int_ok = true;
13370 }
13371
13372 sum = 0.0;
13373 if (int_ok)
13374 {
13375 int sinc_loc, sinc_incr, last, last10, xs;
13376
13377 xs = (int)(zf * (srp->width_1 - srp->x));
13378 sinc_loc = xs + srp->sinc4;
13379 sinc_incr = xi;
13380 last = loc + lim;
13381 last10 = last - 10;
13382
13383 while (loc <= last10)
13384 {
13385 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13386 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13387 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13388 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13389 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13390 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13391 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13392 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13393 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13394 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13395 }
13396 for (; loc < last; loc++, sinc_loc += sinc_incr)
13397 sum += data[loc] * sinc_table[sinc_loc];
13398 }
13399 else
13400 {
13401 mus_float_t sinc_loc, sinc_incr, x;
13402 int last, last10;
13403
13404 x = zf * (srp->width_1 - srp->x);
13405 sinc_loc = x + srp->sinc4;
13406 sinc_incr = zf;
13407 last = loc + lim;
13408
13409 last10 = last - 10;
13410
13411 while (loc <= last10)
13412 {
13413 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13414 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13415 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13416 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13417 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13418 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13419 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13420 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13421 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13422 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13423 }
13424 for (; loc < last; loc++, sinc_loc += sinc_incr)
13425 sum += data[loc] * sinc_table[(int)sinc_loc];
13426 }
13427
13428 srp->x += srx;
13429 return(sum * factor);
13430 }
13431
13432
mus_src_to_buffer(mus_any * srptr,mus_float_t (* input)(void * arg,int direction),mus_float_t * out_data,mus_long_t dur)13433 void mus_src_to_buffer(mus_any *srptr, mus_float_t (*input)(void *arg, int direction), mus_float_t *out_data, mus_long_t dur)
13434 {
13435 /* sr_change = 0.0
13436 */
13437 sr *srp = (sr *)srptr;
13438 mus_float_t x, zf, srx, factor, sincx, srpx;
13439 int lim, i, xi, xs, dir = 1;
13440 bool int_ok;
13441 mus_long_t k;
13442 mus_float_t *data, *sinc_table;
13443
13444 lim = srp->lim;
13445 sincx = (mus_float_t)SRC_SINC_DENSITY;
13446 data = srp->data;
13447 sinc_table = srp->sinc_table;
13448 srx = srp->incr;
13449 srpx = srp->x;
13450 if (srx < 0.0)
13451 {
13452 dir = -1;
13453 srx = -srx;
13454 }
13455 if (srx > 1.0)
13456 {
13457 factor = 1.0 / srx;
13458 /* this is not exact since we're sampling the sinc and so on, but it's close over a wide range */
13459 zf = factor * sincx;
13460 xi = (int)zf;
13461 if (fabs((xi - zf) * lim) > 2.0) int_ok = false; else int_ok = true;
13462 }
13463 else
13464 {
13465 factor = 1.0;
13466 zf = sincx;
13467 xi = SRC_SINC_DENSITY;
13468 int_ok = true;
13469 }
13470
13471 for (k = 0; k < dur; k++)
13472 {
13473 int loc;
13474 mus_float_t sum;
13475 loc = srp->start;
13476 if (srpx >= 1.0)
13477 {
13478 int fsx;
13479 /* modf here is very slow??! */
13480 fsx = (int)srpx;
13481 srpx -= fsx;
13482
13483 data[loc] = input(srp->closure, dir);
13484 data[loc + lim] = data[loc];
13485 loc++;
13486 if (loc == lim) loc = 0;
13487
13488 for (i = 1; i < fsx; i++)
13489 {
13490 /* there are two copies of the circular data buffer back-to-back so that we can
13491 * run the convolution below without worrying about the buffer end.
13492 */
13493 data[loc] = input(srp->closure, dir);
13494 data[loc + lim] = data[loc];
13495 loc++;
13496 if (loc == lim) loc = 0;
13497 }
13498 srp->start = loc; /* next time around we start here */
13499 }
13500
13501 sum = 0.0;
13502 if (int_ok)
13503 {
13504 int sinc_loc, sinc_incr, last, last10;
13505
13506 xs = (int)(zf * (srp->width_1 - srpx));
13507 sinc_loc = xs + srp->sinc4;
13508 sinc_incr = xi;
13509 last = loc + lim;
13510 last10 = last - 10;
13511
13512 while (loc <= last10)
13513 {
13514 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13515 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13516 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13517 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13518 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13519 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13520 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13521 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13522 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13523 sum += data[loc++] * sinc_table[sinc_loc]; sinc_loc += sinc_incr;
13524 }
13525 for (; loc < last; loc++, sinc_loc += sinc_incr)
13526 sum += data[loc] * sinc_table[sinc_loc];
13527 }
13528 else
13529 {
13530 mus_float_t sinc_loc, sinc_incr;
13531 int last, last10;
13532
13533 x = zf * (srp->width_1 - srpx);
13534 sinc_loc = x + srp->sinc4;
13535 sinc_incr = zf;
13536 last = loc + lim;
13537
13538 last10 = last - 10;
13539
13540 while (loc <= last10)
13541 {
13542 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13543 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13544 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13545 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13546 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13547 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13548 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13549 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13550 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13551 sum += data[loc++] * sinc_table[(int)sinc_loc]; sinc_loc += sinc_incr;
13552 }
13553 for (; loc < last; loc++, sinc_loc += sinc_incr)
13554 sum += data[loc] * sinc_table[(int)sinc_loc];
13555 }
13556 srpx += srx;
13557 out_data[k] = sum * factor;
13558 }
13559 srp->x = srpx;
13560 }
13561
13562
13563 /* it was a cold, rainy day...
13564 * and on an even colder day, I changed this to use a circular data buffer, rather than memmove
13565 * then changed yet again to use straight buffers
13566 */
13567
mus_src_20(mus_any * srptr,mus_float_t * in_data,mus_long_t dur)13568 mus_float_t *mus_src_20(mus_any *srptr, mus_float_t *in_data, mus_long_t dur)
13569 {
13570 sr *srp = (sr *)srptr;
13571 int lim, i, width, wid1, wid10, xs, xi;
13572 mus_long_t k, dur2;
13573 mus_float_t *out_data, *ldata, *coeffs;
13574
13575 dur2 = dur / 2 + 1;
13576 if ((dur & 1) != 0) dur2++;
13577 out_data = (mus_float_t *)malloc(dur2 * sizeof(mus_float_t));
13578
13579 lim = srp->lim; /* 2 * width so it's even */
13580 width = srp->width;
13581
13582 coeffs = (mus_float_t *)malloc(lim * sizeof(mus_float_t));
13583 if ((width & 1) != 0)
13584 xs = (int)((2 + width) * (SRC_SINC_DENSITY / 2)) + 4; /* Humph -- looks like crap -- maybe if odd width use the real one above, or insist on even width */
13585 else xs = (int)((1 + width) * (SRC_SINC_DENSITY / 2)) + 4;
13586 xi = SRC_SINC_DENSITY; /* skip a location (coeff=0.0) */
13587
13588 for (i = 0; i < width; i++, xs += xi)
13589 coeffs[i] = srp->sinc_table[xs];
13590
13591 for (i = 0; i < lim; i++)
13592 in_data[i] = srp->data[i];
13593
13594 ldata = (mus_float_t *)in_data;
13595 wid10 = width - 10;
13596 wid1 = width - 1;
13597
13598 for (k = 0; k < dur2; k++, ldata += 2)
13599 {
13600 int j;
13601 mus_float_t sum;
13602 sum = ldata[wid1];
13603 i = 0;
13604 j = 0;
13605 while (i <= wid10)
13606 {
13607 sum += (ldata[j] * coeffs[i++]); j += 2;
13608 sum += (ldata[j] * coeffs[i++]); j += 2;
13609 sum += (ldata[j] * coeffs[i++]); j += 2;
13610 sum += (ldata[j] * coeffs[i++]); j += 2;
13611 sum += (ldata[j] * coeffs[i++]); j += 2;
13612 sum += (ldata[j] * coeffs[i++]); j += 2;
13613 sum += (ldata[j] * coeffs[i++]); j += 2;
13614 sum += (ldata[j] * coeffs[i++]); j += 2;
13615 sum += (ldata[j] * coeffs[i++]); j += 2;
13616 sum += (ldata[j] * coeffs[i++]); j += 2;
13617 }
13618 for (; i < width; i++, j += 2)
13619 sum += (ldata[j] * coeffs[i]);
13620 out_data[k] = sum * 0.5;
13621 }
13622
13623 free(coeffs);
13624 return(out_data);
13625 }
13626
13627
mus_src_05(mus_any * srptr,mus_float_t * in_data,mus_long_t dur)13628 mus_float_t *mus_src_05(mus_any *srptr, mus_float_t *in_data, mus_long_t dur)
13629 {
13630 sr *srp = (sr *)srptr;
13631 int lim, i, width, wid1, wid10, xs, xi;
13632 mus_long_t k, dur2;
13633 mus_float_t *out_data, *ldata, *coeffs;
13634
13635 dur2 = dur * 2;
13636 out_data = (mus_float_t *)malloc((dur2 + 1) * sizeof(mus_float_t));
13637 out_data[dur2] = 0.0;
13638
13639 lim = srp->lim;
13640 width = srp->width;
13641
13642 coeffs = (mus_float_t *)malloc(lim * sizeof(mus_float_t));
13643 xs = (SRC_SINC_DENSITY / 2) + 4;
13644 xi = SRC_SINC_DENSITY;
13645
13646 for (i = 0; i < lim; i++, xs += xi)
13647 coeffs[i] = srp->sinc_table[xs];
13648
13649 for (i = 0; i < lim; i++)
13650 in_data[i] = srp->data[i];
13651
13652 ldata = (mus_float_t *)in_data;
13653 wid10 = lim - 10;
13654 wid1 = width - 1;
13655
13656 for (k = 0; k < dur2; k += 2)
13657 {
13658 mus_float_t sum;
13659 out_data[k] = ldata[wid1];
13660
13661 sum = 0.0;
13662 i = 0;
13663 while (i <= wid10)
13664 {
13665 sum += (ldata[i] * coeffs[i]); i++;
13666 sum += (ldata[i] * coeffs[i]); i++;
13667 sum += (ldata[i] * coeffs[i]); i++;
13668 sum += (ldata[i] * coeffs[i]); i++;
13669 sum += (ldata[i] * coeffs[i]); i++;
13670 sum += (ldata[i] * coeffs[i]); i++;
13671 sum += (ldata[i] * coeffs[i]); i++;
13672 sum += (ldata[i] * coeffs[i]); i++;
13673 sum += (ldata[i] * coeffs[i]); i++;
13674 sum += (ldata[i] * coeffs[i]); i++;
13675 }
13676 for (; i < lim; i++)
13677 sum += (ldata[i] * coeffs[i]);
13678 out_data[k + 1] = sum;
13679
13680 ldata++;
13681 }
13682
13683 free(coeffs);
13684 return(out_data);
13685 }
13686
13687
13688
13689
13690 /* ---------------- granulate ---------------- */
13691
13692 typedef struct {
13693 mus_any_class *core;
13694 mus_float_t (*rd)(void *arg, int direction);
13695 mus_float_t (*block_rd)(void *arg, int direction, mus_float_t *block, mus_long_t start, mus_long_t end);
13696 int s20;
13697 int s50;
13698 int rmp;
13699 mus_float_t amp, jitter;
13700 int cur_out;
13701 int input_hop;
13702 int ctr;
13703 int output_hop;
13704 mus_float_t *out_data; /* output buffer */
13705 int out_data_len;
13706 mus_float_t *in_data; /* input buffer */
13707 int in_data_len;
13708 void *closure;
13709 int (*edit)(void *closure);
13710 mus_float_t *grain; /* grain data */
13711 int grain_len;
13712 bool first_samp;
13713 uint64_t randx; /* gen-local random number seed */
13714 } grn_info;
13715
13716
mus_is_granulate(mus_any * ptr)13717 bool mus_is_granulate(mus_any *ptr)
13718 {
13719 return((ptr) &&
13720 (ptr->core->type == MUS_GRANULATE));
13721 }
13722
13723
granulate_equalp(mus_any * p1,mus_any * p2)13724 static bool granulate_equalp(mus_any *p1, mus_any *p2) {return(p1 == p2);}
13725
13726
describe_granulate(mus_any * ptr)13727 static char *describe_granulate(mus_any *ptr)
13728 {
13729 grn_info *gen = (grn_info *)ptr;
13730 char *describe_buffer;
13731 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
13732 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s expansion: %.3f (%d/%d), scaler: %.3f, length: %.3f secs (%d samps), ramp: %.3f, jitter: %.3f",
13733 mus_name(ptr),
13734 (mus_float_t)(gen->output_hop) / (mus_float_t)(gen->input_hop),
13735 gen->input_hop, gen->output_hop,
13736 gen->amp,
13737 (mus_float_t)(gen->grain_len) / (mus_float_t)sampling_rate, gen->grain_len,
13738 (mus_float_t)(gen->rmp) / (mus_float_t)gen->grain_len,
13739 gen->jitter);
13740 return(describe_buffer);
13741 }
13742
13743
free_granulate(mus_any * ptr)13744 static void free_granulate(mus_any *ptr)
13745 {
13746 grn_info *gen = (grn_info *)ptr;
13747 if (gen->out_data) free(gen->out_data);
13748 if (gen->in_data) free(gen->in_data);
13749 if (gen->grain) free(gen->grain);
13750 free(gen);
13751 }
13752
grn_info_copy(mus_any * ptr)13753 static mus_any *grn_info_copy(mus_any *ptr)
13754 {
13755 grn_info *g, *p;
13756 int bytes;
13757
13758 p = (grn_info *)ptr;
13759 g = (grn_info *)malloc(sizeof(grn_info));
13760 memcpy((void *)g, (void *)ptr, sizeof(grn_info));
13761
13762 bytes = g->out_data_len * sizeof(mus_float_t);
13763 g->out_data = (mus_float_t *)malloc(bytes);
13764 mus_copy_floats(g->out_data, p->out_data, g->out_data_len);
13765
13766 bytes = g->in_data_len * sizeof(mus_float_t);
13767 g->in_data = (mus_float_t *)malloc(bytes);
13768 mus_copy_floats(g->in_data, p->in_data, g->in_data_len);
13769 g->grain = (mus_float_t *)malloc(bytes);
13770 mus_copy_floats(g->grain, p->grain, g->in_data_len);
13771
13772 return((mus_any *)g);
13773 }
13774
grn_length(mus_any * ptr)13775 static mus_long_t grn_length(mus_any *ptr) {return(((grn_info *)ptr)->grain_len);}
13776
grn_set_length(mus_any * ptr,mus_long_t val)13777 static mus_long_t grn_set_length(mus_any *ptr, mus_long_t val)
13778 {
13779 grn_info *gen = ((grn_info *)ptr);
13780 if ((val > 0) && (val < gen->out_data_len))
13781 gen->grain_len = (int)val; /* larger -> segfault */
13782 return(gen->grain_len);
13783 }
13784
grn_scaler(mus_any * ptr)13785 static mus_float_t grn_scaler(mus_any *ptr) {return(((grn_info *)ptr)->amp);}
grn_set_scaler(mus_any * ptr,mus_float_t val)13786 static mus_float_t grn_set_scaler(mus_any *ptr, mus_float_t val) {((grn_info *)ptr)->amp = val; return(val);}
13787
grn_set_s20_and_s50(grn_info * gen)13788 static void grn_set_s20_and_s50(grn_info *gen)
13789 {
13790 gen->s20 = 2 * (int)(gen->jitter * gen->output_hop); /* was *.05 here and *.02 below */
13791 /* added "2 *" 21-Mar-05 and replaced irandom with (grn)mus_irandom below */
13792 gen->s50 = (int)(gen->jitter * gen->output_hop * 0.4);
13793 }
13794
grn_frequency(mus_any * ptr)13795 static mus_float_t grn_frequency(mus_any *ptr) {return(((mus_float_t)((grn_info *)ptr)->output_hop) / (mus_float_t)sampling_rate);}
grn_set_frequency(mus_any * ptr,mus_float_t val)13796 static mus_float_t grn_set_frequency(mus_any *ptr, mus_float_t val)
13797 {
13798 grn_info *gen = ((grn_info *)ptr);
13799 gen->output_hop = (int)((mus_float_t)sampling_rate * val);
13800 grn_set_s20_and_s50(gen);
13801 return(val);
13802 }
13803
grn_closure(mus_any * rd)13804 static void *grn_closure(mus_any *rd) {return(((grn_info *)rd)->closure);}
grn_set_closure(mus_any * rd,void * e)13805 static void *grn_set_closure(mus_any *rd, void *e) {((grn_info *)rd)->closure = e; return(e);}
13806
grn_increment(mus_any * ptr)13807 static mus_float_t grn_increment(mus_any *ptr)
13808 {
13809 grn_info *gen = ((grn_info *)ptr);
13810 return(((mus_float_t)(gen->output_hop)) / ((mus_float_t)(gen->input_hop)));
13811 }
13812
grn_set_increment(mus_any * ptr,mus_float_t val)13813 static mus_float_t grn_set_increment(mus_any *ptr, mus_float_t val)
13814 {
13815 grn_info *gen = ((grn_info *)ptr);
13816 if (val != 0.0)
13817 gen->input_hop = (int)(gen->output_hop / val);
13818 return(val);
13819 }
13820
grn_hop(mus_any * ptr)13821 static mus_long_t grn_hop(mus_any *ptr) {return(((grn_info *)ptr)->output_hop);}
grn_set_hop(mus_any * ptr,mus_long_t val)13822 static mus_long_t grn_set_hop(mus_any *ptr, mus_long_t val)
13823 {
13824 grn_info *gen = ((grn_info *)ptr);
13825 gen->output_hop = (int)val;
13826 grn_set_s20_and_s50(gen);
13827 return(val);
13828 }
13829
grn_ramp(mus_any * ptr)13830 static mus_long_t grn_ramp(mus_any *ptr) {return(((grn_info *)ptr)->rmp);}
13831
grn_set_ramp(mus_any * ptr,mus_long_t val)13832 static mus_long_t grn_set_ramp(mus_any *ptr, mus_long_t val)
13833 {
13834 grn_info *gen = (grn_info *)ptr;
13835 if (val < (gen->grain_len * .5))
13836 gen->rmp = (int)val;
13837 return(val);
13838 }
13839
granulate_data(mus_any * ptr)13840 static mus_float_t *granulate_data(mus_any *ptr) {return(((grn_info *)ptr)->grain);}
mus_granulate_grain_max_length(mus_any * ptr)13841 int mus_granulate_grain_max_length(mus_any *ptr) {return(((grn_info *)ptr)->in_data_len);}
13842
grn_location(mus_any * ptr)13843 static mus_long_t grn_location(mus_any *ptr) {return((mus_long_t)(((grn_info *)ptr)->randx));}
grn_set_location(mus_any * ptr,mus_long_t val)13844 static mus_long_t grn_set_location(mus_any *ptr, mus_long_t val) {((grn_info *)ptr)->randx = (uint64_t)val; return(val);}
13845
grn_jitter(mus_any * ptr)13846 static mus_float_t grn_jitter(mus_any *ptr) {return(((grn_info *)ptr)->jitter);}
grn_set_jitter(mus_any * ptr,mus_float_t val)13847 static mus_float_t grn_set_jitter(mus_any *ptr, mus_float_t val) /* K Matheussen 15-Jul-18 */
13848 {
13849 grn_info *gen = (grn_info *)ptr;
13850 gen->jitter = val;
13851 grn_set_s20_and_s50(gen);
13852 return(val);
13853 }
13854
run_granulate(mus_any * ptr,mus_float_t unused1,mus_float_t unused2)13855 static mus_float_t run_granulate(mus_any *ptr, mus_float_t unused1, mus_float_t unused2) {return(mus_granulate(ptr, NULL));}
13856
13857
grn_reset(mus_any * ptr)13858 static void grn_reset(mus_any *ptr)
13859 {
13860 grn_info *gen = (grn_info *)ptr;
13861 gen->cur_out = 0;
13862 gen->ctr = 0;
13863 mus_clear_floats(gen->out_data, gen->out_data_len);
13864 mus_clear_floats(gen->in_data, gen->in_data_len);
13865 mus_clear_floats(gen->grain, gen->in_data_len);
13866 gen->first_samp = true;
13867 }
13868
13869
grn_irandom(grn_info * spd,int amp)13870 static int grn_irandom(grn_info *spd, int amp)
13871 {
13872 /* gen-local next_random */
13873 spd->randx = spd->randx * 1103515245 + 12345;
13874 return((int)(amp * INVERSE_MAX_RAND2 * ((mus_float_t)((uint32_t)(spd->randx >> 16) & 32767))));
13875 }
13876
13877
13878 static mus_any_class GRANULATE_CLASS = {
13879 MUS_GRANULATE,
13880 (char *)S_granulate,
13881 &free_granulate,
13882 &describe_granulate,
13883 &granulate_equalp,
13884 &granulate_data, 0,
13885 &grn_length, /* segment-length */
13886 &grn_set_length,
13887 &grn_frequency, /* spd-out */
13888 &grn_set_frequency,
13889 0, 0,
13890 &grn_scaler, /* segment-scaler */
13891 &grn_set_scaler,
13892 &grn_increment,
13893 &grn_set_increment,
13894 &run_granulate,
13895 MUS_NOT_SPECIAL,
13896 &grn_closure,
13897 0,
13898 &grn_jitter, &grn_set_jitter,
13899 0, 0, 0, 0,
13900 &grn_hop, &grn_set_hop,
13901 &grn_ramp, &grn_set_ramp,
13902 0, 0, 0, 0,
13903 &grn_location, &grn_set_location, /* local randx */
13904 0, 0, 0, 0, 0,
13905 &grn_reset,
13906 &grn_set_closure,
13907 &grn_info_copy
13908 };
13909
13910
mus_make_granulate(mus_float_t (* input)(void * arg,int direction),mus_float_t expansion,mus_float_t length,mus_float_t scaler,mus_float_t hop,mus_float_t ramp,mus_float_t jitter,int max_size,int (* edit)(void * closure),void * closure)13911 mus_any *mus_make_granulate(mus_float_t (*input)(void *arg, int direction),
13912 mus_float_t expansion, mus_float_t length, mus_float_t scaler,
13913 mus_float_t hop, mus_float_t ramp, mus_float_t jitter, int max_size,
13914 int (*edit)(void *closure),
13915 void *closure)
13916 {
13917 grn_info *spd;
13918 int outlen;
13919 outlen = (int)(sampling_rate * (hop + length));
13920 if (max_size > outlen) outlen = max_size;
13921 if (expansion <= 0.0)
13922 {
13923 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_granulate ": expansion must be > 0.0: %f", expansion);
13924 return(NULL);
13925 }
13926 if (outlen <= 0)
13927 {
13928 mus_error(MUS_NO_LENGTH, S_make_granulate ": size is %d (hop: %f, segment-length: %f)?", outlen, hop, length);
13929 return(NULL);
13930 }
13931 if ((hop * sampling_rate) < expansion)
13932 {
13933 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_granulate ": expansion (%f) must be < hop * srate (%f)", expansion, hop * sampling_rate);
13934 return(NULL);
13935 }
13936 spd = (grn_info *)malloc(sizeof(grn_info));
13937 spd->core = &GRANULATE_CLASS;
13938 spd->cur_out = 0;
13939 spd->ctr = 0;
13940 spd->grain_len = (int)(ceil(length * sampling_rate));
13941 spd->rmp = (int)(ramp * spd->grain_len);
13942 spd->amp = scaler;
13943 spd->jitter = jitter;
13944 spd->output_hop = (int)(hop * sampling_rate);
13945 spd->input_hop = (int)((mus_float_t)(spd->output_hop) / expansion);
13946 grn_set_s20_and_s50(spd);
13947 spd->out_data_len = outlen;
13948 spd->out_data = (mus_float_t *)calloc(spd->out_data_len, sizeof(mus_float_t));
13949 /* spd->in_data_len = outlen + spd->s20 + 1; */
13950 spd->in_data_len = outlen + (2 * sampling_rate * hop) + 1;
13951 spd->in_data = (mus_float_t *)malloc(spd->in_data_len * sizeof(mus_float_t));
13952 spd->rd = input;
13953 spd->block_rd = NULL;
13954 spd->closure = closure;
13955 spd->edit = edit;
13956 spd->grain = (mus_float_t *)malloc(spd->in_data_len * sizeof(mus_float_t));
13957 spd->first_samp = true;
13958 spd->randx = mus_rand_seed(); /* caller can override this via the mus_location method */
13959 next_random();
13960 return((mus_any *)spd);
13961 }
13962
13963
mus_granulate_set_edit_function(mus_any * ptr,int (* edit)(void * closure))13964 void mus_granulate_set_edit_function(mus_any *ptr, int (*edit)(void *closure))
13965 {
13966 grn_info *gen = (grn_info *)ptr;
13967 if (!(gen->grain))
13968 gen->grain = (mus_float_t *)calloc(gen->in_data_len, sizeof(mus_float_t));
13969 gen->edit = edit;
13970 }
13971
13972
mus_granulate_with_editor(mus_any * ptr,mus_float_t (* input)(void * arg,int direction),int (* edit)(void * closure))13973 mus_float_t mus_granulate_with_editor(mus_any *ptr, mus_float_t (*input)(void *arg, int direction), int (*edit)(void *closure))
13974 {
13975 /* in_data_len is the max grain size (:maxsize arg), not the current grain size
13976 * out_data_len is the size of the output buffer
13977 * grain_len is the current grain size
13978 * cur_out is the out_data buffer location where we need to add in the next grain
13979 * ctr is where we are now in out_data
13980 */
13981 grn_info *spd = (grn_info *)ptr;
13982 mus_float_t result = 0.0;
13983
13984 if (spd->ctr < spd->out_data_len)
13985 result = spd->out_data[spd->ctr]; /* else return 0.0 */
13986 spd->ctr++;
13987
13988 if (spd->ctr >= spd->cur_out) /* time for next grain */
13989 {
13990 /* set up edit/input functions and possible outside-accessible grain array */
13991 int i;
13992 int (*spd_edit)(void *closure) = edit;
13993 if (input) {spd->rd = input; spd->block_rd = NULL;}
13994 if (!spd_edit) spd_edit = spd->edit;
13995
13996 if (spd->first_samp)
13997 {
13998 /* fill up in_data, out_data is already cleared */
13999 if (spd->block_rd)
14000 spd->block_rd(spd->closure, 1, spd->in_data, 0, spd->in_data_len);
14001 else
14002 {
14003 for (i = 0; i < spd->in_data_len; i++)
14004 spd->in_data[i] = spd->rd(spd->closure, 1);
14005 }
14006 }
14007 else
14008 {
14009
14010 /* align output buffer to flush the data we've already output, and zero out new trailing portion */
14011 if (spd->cur_out >= spd->out_data_len)
14012 {
14013 /* entire buffer has been output, and in fact we've been sending 0's for awhile to fill out hop */
14014 mus_clear_floats(spd->out_data, spd->out_data_len); /* so zero the entire thing (it's all old) */
14015 }
14016 else
14017 {
14018 /* move yet-un-output data to 0, zero trailers */
14019 int good_samps;
14020 good_samps = (spd->out_data_len - spd->cur_out);
14021 memmove((void *)(spd->out_data), (void *)(spd->out_data + spd->cur_out), good_samps * sizeof(mus_float_t));
14022 mus_clear_floats(spd->out_data + good_samps, spd->cur_out); /* must be cur_out trailing samples to 0 */
14023 }
14024
14025 /* align input buffer */
14026 if (spd->input_hop > spd->in_data_len)
14027 {
14028 /* need to flush enough samples to accommodate the fact that the hop is bigger than our data buffer */
14029 for (i = spd->in_data_len; i < spd->input_hop; i++) spd->rd(spd->closure, 1);
14030 /* then get a full input buffer */
14031 if (spd->block_rd)
14032 spd->block_rd(spd->closure, 1, spd->in_data, 0, spd->in_data_len);
14033 else
14034 {
14035 for (i = 0; i < spd->in_data_len; i++)
14036 spd->in_data[i] = spd->rd(spd->closure, 1);
14037 }
14038 }
14039 else
14040 {
14041 /* align input buffer with current input hop location */
14042 int good_samps;
14043 good_samps = (spd->in_data_len - spd->input_hop);
14044 memmove((void *)(spd->in_data), (void *)(spd->in_data + spd->input_hop), good_samps * sizeof(mus_float_t));
14045 if (spd->block_rd)
14046 spd->block_rd(spd->closure, 1, spd->in_data, good_samps, spd->in_data_len);
14047 else
14048 {
14049 for (i = good_samps; i < spd->in_data_len; i++)
14050 spd->in_data[i] = spd->rd(spd->closure, 1);
14051 }
14052 }
14053 }
14054
14055 /* create current grain */
14056 {
14057 int lim, curstart, j;
14058
14059 lim = spd->grain_len;
14060 curstart = grn_irandom(spd, spd->s20); /* start location in input buffer */
14061 if ((curstart + spd->grain_len) > spd->in_data_len)
14062 lim = (spd->in_data_len - curstart);
14063 if (lim > spd->grain_len)
14064 lim = spd->grain_len;
14065 else
14066 {
14067 if (lim < spd->grain_len)
14068 mus_clear_floats(spd->grain, spd->grain_len - lim);
14069 }
14070 if (spd->rmp > 0)
14071 {
14072 int steady_end, up_end;
14073 mus_float_t amp = 0.0, incr;
14074 steady_end = (spd->grain_len - spd->rmp);
14075 incr = (mus_float_t)(spd->amp) / (mus_float_t)(spd->rmp);
14076 up_end = spd->rmp;
14077 if (up_end > lim) up_end = lim;
14078 for (i = 0, j = curstart; i < up_end; i++, j++)
14079 {
14080 spd->grain[i] = (amp * spd->in_data[j]);
14081 amp += incr;
14082 }
14083 if (steady_end > lim) steady_end = lim;
14084 for (; i < steady_end; i++, j++)
14085 spd->grain[i] = (amp * spd->in_data[j]);
14086 for (; i < lim; i++, j++)
14087 {
14088 spd->grain[i] = (amp * spd->in_data[j]);
14089 amp -= incr;
14090 }
14091 }
14092 else
14093 {
14094 /* ramp is 0.0, so just scale the input buffer by the current amp */
14095 if (spd->amp == 1.0)
14096 mus_copy_floats(spd->grain, spd->in_data + curstart, lim);
14097 else
14098 {
14099 for (i = 0, j = curstart; i < lim; i++, j++)
14100 spd->grain[i] = (spd->amp * spd->in_data[j]);
14101 }
14102 }
14103 }
14104
14105 /* add new grain into output buffer */
14106 {
14107 int new_len;
14108 if (spd_edit)
14109 {
14110 new_len = (*spd_edit)(spd->closure);
14111 if (new_len <= 0)
14112 new_len = spd->grain_len;
14113 else
14114 {
14115 if (new_len > spd->out_data_len)
14116 new_len = spd->out_data_len;
14117 }
14118 }
14119 else new_len = spd->grain_len;
14120 if (new_len > spd->out_data_len) /* can be off-by-one here if hop is just barely greater then 0.0 (user is screwing around...) */
14121 new_len = spd->out_data_len;
14122 mus_add_floats(spd->out_data, spd->grain, new_len);
14123 }
14124
14125 /* set location of next grain */
14126 spd->ctr = 0;
14127 spd->cur_out = spd->output_hop + grn_irandom(spd, 2 * spd->s50) - spd->s50; /* irandom is 0..x */
14128 /* this form suggested by Marc Lehmann */
14129 /* "2 *" added 21-Mar-05 and irandom replaced with mus_irandom, grn_irandom 28-Feb-06 */
14130 /* in clm-2 (2004) it was spd->cur_out = spd->output_hop + irandom(spd->s50) */
14131 /* use of gen-local random sequence suggested by Kjetil Matheussen (to keep multi-channel grns in sync) */
14132 if (spd->cur_out < 0) spd->cur_out = 0;
14133
14134 if (spd->first_samp)
14135 {
14136 spd->first_samp = false;
14137 spd->ctr = 1;
14138 return(spd->out_data[0]);
14139 }
14140 }
14141 return(result);
14142 }
14143
14144
mus_granulate(mus_any * ptr,mus_float_t (* input)(void * arg,int direction))14145 mus_float_t mus_granulate(mus_any *ptr, mus_float_t (*input)(void *arg, int direction))
14146 {
14147 return(mus_granulate_with_editor(ptr, input, NULL));
14148 }
14149
14150
14151
14152 /* ---------------- Fourier transform ---------------- */
14153
14154 /* fft of mus_float_t data in zero-based arrays
14155 */
14156
14157 static void mus_big_fft(mus_float_t *rl, mus_float_t *im, mus_long_t n, int is);
14158
14159 #if HAVE_FFTW3 && HAVE_COMPLEX_TRIG
14160
14161 static fftw_complex *c_in_data = NULL, *c_out_data = NULL;
14162 static fftw_plan c_r_plan, c_i_plan;
14163 static int last_c_fft_size = 0;
14164
mus_fftw_with_imag(mus_float_t * rl,mus_float_t * im,int n,int dir)14165 static void mus_fftw_with_imag(mus_float_t *rl, mus_float_t *im, int n, int dir)
14166 {
14167 int i, n4;
14168
14169 if (n != last_c_fft_size)
14170 {
14171 if (c_in_data)
14172 {
14173 fftw_free(c_in_data);
14174 fftw_free(c_out_data);
14175 fftw_destroy_plan(c_r_plan);
14176 fftw_destroy_plan(c_i_plan);
14177 }
14178 c_in_data = (fftw_complex *)fftw_malloc(n * sizeof(fftw_complex)); /* rl/im data is mus_float_t */
14179 c_out_data = (fftw_complex *)fftw_malloc(n * sizeof(fftw_complex));
14180 c_r_plan = fftw_plan_dft_1d(n, c_in_data, c_out_data, FFTW_FORWARD, FFTW_ESTIMATE);
14181 c_i_plan = fftw_plan_dft_1d(n, c_in_data, c_out_data, FFTW_BACKWARD, FFTW_ESTIMATE);
14182 last_c_fft_size = n;
14183 }
14184
14185 n4 = n - 4;
14186 i = 0;
14187 while (i <= n4)
14188 {
14189 /* adding code to avoid this loop saves essentially nothing, mainly because the great majority of the calls
14190 * are actually handling two real arrays at once -- the imag=0 case is 1/10 of the total. In the zero case,
14191 * the savings here is about 10%, but that is swamped by the fft itself (say 5-10 in c*).
14192 * using the new split array code (see below) saves essentially nothing -- perhaps 1 to 2% overall.
14193 */
14194 c_in_data[i] = rl[i] + _Complex_I * im[i];
14195 i++;
14196 c_in_data[i] = rl[i] + _Complex_I * im[i];
14197 i++;
14198 c_in_data[i] = rl[i] + _Complex_I * im[i];
14199 i++;
14200 c_in_data[i] = rl[i] + _Complex_I * im[i];
14201 i++;
14202 }
14203 for (; i < n; i++)
14204 c_in_data[i] = rl[i] + _Complex_I * im[i];
14205
14206 if (dir == -1)
14207 fftw_execute(c_r_plan);
14208 else fftw_execute(c_i_plan);
14209
14210 i = 0;
14211 while (i <= n4)
14212 {
14213 rl[i] = creal(c_out_data[i]);
14214 im[i] = cimag(c_out_data[i]);
14215 i++;
14216 rl[i] = creal(c_out_data[i]);
14217 im[i] = cimag(c_out_data[i]);
14218 i++;
14219 rl[i] = creal(c_out_data[i]);
14220 im[i] = cimag(c_out_data[i]);
14221 i++;
14222 rl[i] = creal(c_out_data[i]);
14223 im[i] = cimag(c_out_data[i]);
14224 i++;
14225 }
14226 for (; i < n; i++)
14227 {
14228 rl[i] = creal(c_out_data[i]);
14229 im[i] = cimag(c_out_data[i]);
14230 }
14231 }
14232
14233
mus_fft(mus_float_t * rl,mus_float_t * im,mus_long_t n,int is)14234 void mus_fft(mus_float_t *rl, mus_float_t *im, mus_long_t n, int is)
14235 {
14236 /* simple timing tests indicate fftw is slightly faster than mus_fft in this context
14237 */
14238 if (n < (1 << 30))
14239 mus_fftw_with_imag(rl, im, n, is);
14240 else mus_big_fft(rl, im, n, is);
14241 }
14242
14243 #else
14244
mus_scramble(mus_float_t * rl,mus_float_t * im,int n)14245 static void mus_scramble(mus_float_t *rl, mus_float_t *im, int n)
14246 {
14247 /* bit reversal */
14248
14249 int i, j;
14250 mus_float_t vr, vi;
14251 j = 0;
14252 for (i = 0; i < n; i++)
14253 {
14254 int m;
14255 if (j > i)
14256 {
14257 vr = rl[j];
14258 vi = im[j];
14259 rl[j] = rl[i];
14260 im[j] = im[i];
14261 rl[i] = vr;
14262 im[i] = vi;
14263 }
14264 m = n >> 1;
14265 while ((m >= 2) && (j >= m))
14266 {
14267 j -= m;
14268 m = m >> 1;
14269 }
14270 j += m;
14271 }
14272 }
14273
14274
mus_fft(mus_float_t * rl,mus_float_t * im,mus_long_t n,int is)14275 void mus_fft(mus_float_t *rl, mus_float_t *im, mus_long_t n, int is)
14276 {
14277 /* standard fft: real part in rl, imaginary in im,
14278 * rl and im are zero-based.
14279 * see fxt/simplfft/fft.c (Joerg Arndt)
14280 */
14281 int m, j, mh, ldm, lg, i, i2, j2, imh;
14282 mus_float_t u, vr, vi, angle;
14283
14284 if (n >= (1 << 30))
14285 {
14286 mus_big_fft(rl, im, n, is);
14287 return;
14288 }
14289
14290 imh = (int)(log1p(n) / log(2.0));
14291 mus_scramble(rl, im, n);
14292 m = 2;
14293 ldm = 1;
14294 mh = n >> 1;
14295 angle = (M_PI * is);
14296 for (lg = 0; lg < imh; lg++)
14297 {
14298 mus_float_t c, s, ur, ui;
14299 c = cos(angle);
14300 s = sin(angle);
14301 ur = 1.0;
14302 ui = 0.0;
14303 for (i2 = 0; i2 < ldm; i2++)
14304 {
14305 i = i2;
14306 j = i2 + ldm;
14307 for (j2 = 0; j2 < mh; j2++)
14308 {
14309 vr = ur * rl[j] - ui * im[j];
14310 vi = ur * im[j] + ui * rl[j];
14311 rl[j] = rl[i] - vr;
14312 im[j] = im[i] - vi;
14313 rl[i] += vr;
14314 im[i] += vi;
14315 i += m;
14316 j += m;
14317 }
14318 u = ur;
14319 ur = (ur * c) - (ui * s);
14320 ui = (ui * c) + (u * s);
14321 }
14322 mh >>= 1;
14323 ldm = m;
14324 angle *= 0.5;
14325 m <<= 1;
14326 }
14327 }
14328 #endif
14329
14330
mus_big_fft(mus_float_t * rl,mus_float_t * im,mus_long_t n,int is)14331 static void mus_big_fft(mus_float_t *rl, mus_float_t *im, mus_long_t n, int is)
14332 {
14333 mus_long_t m, j, mh, ldm, i, i2, j2;
14334 int imh, lg;
14335 mus_float_t u, vr, vi, angle;
14336
14337 imh = (int)(log1p(n) / log(2.0));
14338
14339 j = 0;
14340 for (i = 0; i < n; i++)
14341 {
14342 if (j > i)
14343 {
14344 vr = rl[j];
14345 vi = im[j];
14346 rl[j] = rl[i];
14347 im[j] = im[i];
14348 rl[i] = vr;
14349 im[i] = vi;
14350 }
14351 m = n >> 1;
14352 while ((m >= 2) && (j >= m))
14353 {
14354 j -= m;
14355 m = m >> 1;
14356 }
14357 j += m;
14358 }
14359
14360 m = 2;
14361 ldm = 1;
14362 mh = n >> 1;
14363 angle = (M_PI * is);
14364 for (lg = 0; lg < imh; lg++)
14365 {
14366 mus_float_t c, s, ur, ui;
14367 c = cos(angle);
14368 s = sin(angle);
14369 ur = 1.0;
14370 ui = 0.0;
14371 for (i2 = 0; i2 < ldm; i2++)
14372 {
14373 i = i2;
14374 j = i2 + ldm;
14375 for (j2 = 0; j2 < mh; j2++)
14376 {
14377 vr = ur * rl[j] - ui * im[j];
14378 vi = ur * im[j] + ui * rl[j];
14379 rl[j] = rl[i] - vr;
14380 im[j] = im[i] - vi;
14381 rl[i] += vr;
14382 im[i] += vi;
14383 i += m;
14384 j += m;
14385 }
14386 u = ur;
14387 ur = (ur * c) - (ui * s);
14388 ui = (ui * c) + (u * s);
14389 }
14390 mh >>= 1;
14391 ldm = m;
14392 angle *= 0.5;
14393 m <<= 1;
14394 }
14395 }
14396
14397
14398 #if HAVE_GSL
14399 #include <gsl/gsl_sf_bessel.h>
14400
mus_bessi0(mus_float_t x)14401 mus_float_t mus_bessi0(mus_float_t x)
14402 {
14403 gsl_sf_result res;
14404 gsl_sf_bessel_I0_e(x, &res);
14405 return((mus_float_t)(res.val));
14406 }
14407
14408 #else
14409
mus_bessi0(mus_float_t x)14410 mus_float_t mus_bessi0(mus_float_t x)
14411 {
14412 if (x == 0.0) return(1.0);
14413 if (fabs(x) <= 15.0)
14414 {
14415 mus_float_t z, denominator, numerator;
14416 z = x * x;
14417 numerator = (z * (z * (z * (z * (z * (z * (z * (z * (z * (z * (z * (z * (z * (z *
14418 0.210580722890567e-22 + 0.380715242345326e-19) +
14419 0.479440257548300e-16) + 0.435125971262668e-13) +
14420 0.300931127112960e-10) + 0.160224679395361e-7) +
14421 0.654858370096785e-5) + 0.202591084143397e-2) +
14422 0.463076284721000e0) + 0.754337328948189e2) +
14423 0.830792541809429e4) + 0.571661130563785e6) +
14424 0.216415572361227e8) + 0.356644482244025e9) +
14425 0.144048298227235e10);
14426 denominator = (z * (z * (z - 0.307646912682801e4) +
14427 0.347626332405882e7) - 0.144048298227235e10);
14428 return(-numerator / denominator);
14429 }
14430 return(1.0);
14431 }
14432 #endif
14433
14434
14435 #if HAVE_COMPLEX_TRIG || HAVE_GSL
ultraspherical(int n,mus_float_t x,mus_float_t lambda)14436 static mus_float_t ultraspherical(int n, mus_float_t x, mus_float_t lambda)
14437 {
14438 /* this is also the algorithm used in gsl gegenbauer.c -- slow but not as bad as using the binomials! */
14439 mus_float_t fn1, fn2 = 1.0, fn = 1.0;
14440 int k;
14441 if (n == 0) return(1.0);
14442 if (lambda == 0.0)
14443 fn1 = 2.0 * x;
14444 else fn1 = 2.0 * x * lambda;
14445 if (n == 1) return(fn1);
14446 for (k = 2; k <= n; k++)
14447 {
14448 fn = ((2.0 * x * (k + lambda - 1.0) * fn1) - ((k + (2.0 * lambda) - 2.0) * fn2)) / (mus_float_t)k;
14449 fn2 = fn1;
14450 fn1 = fn;
14451 }
14452 return(fn);
14453 }
14454 #endif
14455
14456
mus_is_fft_window(int val)14457 bool mus_is_fft_window(int val)
14458 {
14459 switch (val)
14460 {
14461 case MUS_RECTANGULAR_WINDOW: case MUS_HANN_WINDOW: case MUS_WELCH_WINDOW: case MUS_PARZEN_WINDOW:
14462 case MUS_BARTLETT_WINDOW: case MUS_HAMMING_WINDOW: case MUS_BLACKMAN2_WINDOW: case MUS_BLACKMAN3_WINDOW:
14463 case MUS_BLACKMAN4_WINDOW: case MUS_EXPONENTIAL_WINDOW: case MUS_RIEMANN_WINDOW: case MUS_KAISER_WINDOW:
14464 case MUS_CAUCHY_WINDOW: case MUS_POISSON_WINDOW: case MUS_GAUSSIAN_WINDOW: case MUS_TUKEY_WINDOW:
14465 case MUS_DOLPH_CHEBYSHEV_WINDOW: case MUS_HANN_POISSON_WINDOW: case MUS_CONNES_WINDOW:
14466 case MUS_SAMARAKI_WINDOW: case MUS_ULTRASPHERICAL_WINDOW: case MUS_BARTLETT_HANN_WINDOW:
14467 case MUS_BOHMAN_WINDOW: case MUS_FLAT_TOP_WINDOW: case MUS_BLACKMAN5_WINDOW: case MUS_BLACKMAN6_WINDOW:
14468 case MUS_BLACKMAN7_WINDOW: case MUS_BLACKMAN8_WINDOW: case MUS_BLACKMAN9_WINDOW: case MUS_BLACKMAN10_WINDOW:
14469 case MUS_RV2_WINDOW: case MUS_RV3_WINDOW: case MUS_RV4_WINDOW: case MUS_MLT_SINE_WINDOW:
14470 case MUS_PAPOULIS_WINDOW: case MUS_DPSS_WINDOW: case MUS_SINC_WINDOW:
14471 return(true);
14472 }
14473 return(false);
14474 }
14475
14476
14477 #if HAVE_GSL
14478 #include <gsl/gsl_version.h>
14479 #if ((GSL_MAJOR_VERSION >= 1) && (GSL_MINOR_VERSION >= 9))
14480 #include <gsl/gsl_math.h>
14481 #include <gsl/gsl_eigen.h>
14482 #define HAVE_GSL_EIGEN_NONSYMMV_WORKSPACE 1
14483 #endif
14484 #endif
14485
14486
sqr(mus_float_t x)14487 static mus_float_t sqr(mus_float_t x) {return(x * x);}
14488
14489
mus_make_fft_window_with_window(mus_fft_window_t type,mus_long_t size,mus_float_t beta,mus_float_t mu,mus_float_t * window)14490 mus_float_t *mus_make_fft_window_with_window(mus_fft_window_t type, mus_long_t size, mus_float_t beta, mus_float_t mu, mus_float_t *window)
14491 {
14492 /* mostly taken from
14493 * Fredric J. Harris, "On the Use of Windows for Harmonic Analysis with the
14494 * Discrete Fourier Transform," Proceedings of the IEEE, Vol. 66, No. 1,
14495 * January 1978.
14496 *
14497 * Albert H. Nuttall, "Some Windows with Very Good Sidelobe Behaviour",
14498 * IEEE Transactions of Acoustics, Speech, and Signal Processing, Vol. ASSP-29,
14499 * No. 1, February 1981, pp 84-91
14500 */
14501
14502 mus_long_t i, j, midn, midp1;
14503 mus_float_t freq, rate, angle = 0.0, cx;
14504 if (!window) return(NULL);
14505
14506 midn = size >> 1;
14507 if (midn == 0) return(window);
14508 midp1 = (size + 1) / 2;
14509 freq = TWO_PI / (mus_float_t)size;
14510 rate = 1.0 / (mus_float_t)midn;
14511
14512 switch (type)
14513 {
14514 case MUS_RECTANGULAR_WINDOW:
14515 for (i = 0; i < size; i++)
14516 window[i] = 1.0;
14517 break;
14518
14519 case MUS_WELCH_WINDOW:
14520 for (i = 0, j = size - 1; i <= midn; i++, j--)
14521 {
14522 window[i] = 1.0 - sqr((mus_float_t)(i - midn) / (mus_float_t)midp1);
14523 window[j] = window[i];
14524 }
14525 break;
14526
14527 case MUS_CONNES_WINDOW:
14528 for (i = 0, j = size - 1; i <= midn; i++, j--)
14529 {
14530 window[i] = sqr(1.0 - sqr((mus_float_t)(i - midn) / (mus_float_t)midp1));
14531 window[j] = window[i];
14532 }
14533 break;
14534
14535 case MUS_PARZEN_WINDOW:
14536 for (i = 0, j = size - 1; i <= midn; i++, j--)
14537 {
14538 window[i] = 1.0 - fabs((mus_float_t)(i - midn) / (mus_float_t)midp1);
14539 window[j] = window[i];
14540 }
14541 break;
14542
14543 case MUS_BARTLETT_WINDOW:
14544 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += rate)
14545 {
14546 window[i] = angle;
14547 window[j] = angle;
14548 }
14549 break;
14550
14551 case MUS_BARTLETT_HANN_WINDOW:
14552 {
14553 mus_float_t ramp;
14554 rate *= 0.5;
14555 /* this definition taken from mathworks docs: they use size - 1 throughout -- this makes very little
14556 * difference unless you're using a small window. I decided to be consistent with all the other
14557 * windows, and besides, this way actually peaks at 1.0 (which matlab misses)
14558 */
14559 for (i = 0, j = size - 1, angle = -M_PI, ramp = 0.5; i <= midn; i++, j--, angle += freq, ramp -= rate)
14560 {
14561 window[i] = 0.62 - 0.48 * ramp + 0.38 * cos(angle);
14562 window[j] = window[i];
14563 }
14564 }
14565 break;
14566
14567 case MUS_BOHMAN_WINDOW:
14568 {
14569 mus_float_t ramp;
14570 /* definition from diracdelta docs and "DSP Handbook" -- used in bispectrum ("minimum bispectrum bias supremum") */
14571 for (i = 0, j = size - 1, angle = M_PI, ramp = 0.0; i <= midn; i++, j--, angle -= freq, ramp += rate)
14572 {
14573 window[i] = ramp * cos(angle) + (sin(angle) / M_PI);
14574 window[j] = window[i];
14575 }
14576 }
14577 break;
14578
14579 case MUS_HANN_WINDOW:
14580 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14581 {
14582 window[i] = 0.5 - 0.5 * cos(angle);
14583 window[j] = window[i];
14584 }
14585 break;
14586
14587 /* Rife-Vincent windows are an elaboration of this (Hann = RV1) */
14588
14589 case MUS_RV2_WINDOW:
14590 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14591 {
14592 window[i] = .375 - 0.5 * cos(angle) + .125 * cos(2 * angle);
14593 window[j] = window[i];
14594 }
14595 break;
14596
14597 case MUS_RV3_WINDOW:
14598 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14599 {
14600 window[i] = (10.0 / 32.0) -
14601 (15.0 / 32.0) * cos(angle) +
14602 (6.0 / 32.0) * cos(2 * angle) -
14603 (1.0 / 32.0) * cos(3 * angle);
14604 window[j] = window[i];
14605 }
14606 break;
14607
14608 case MUS_RV4_WINDOW:
14609 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14610 {
14611 window[i] = (35.0 / 128.0) -
14612 (56.0 / 128.0) * cos(angle) +
14613 (28.0 / 128.0) * cos(2 * angle) -
14614 (8.0 / 128.0) * cos(3 * angle) +
14615 (1.0 / 128.0) * cos(4 * angle);
14616 window[j] = window[i];
14617 }
14618 break;
14619
14620 case MUS_HAMMING_WINDOW:
14621 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14622 {
14623 window[i] = 0.54 - 0.46 * cos(angle);
14624 window[j] = window[i];
14625 }
14626 break;
14627
14628 /* Blackman 1 is the same as Hamming */
14629
14630 case MUS_BLACKMAN2_WINDOW: /* using Chebyshev polynomial equivalents here (this is also given as .42 .5 .08) */
14631 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14632 { /* (+ 0.42323 (* -0.49755 (cos a)) (* 0.07922 (cos (* a 2)))) */
14633 /* "A Family...": .42438 .49341 .078279 */
14634 cx = cos(angle);
14635 window[i] = .34401 + (cx * (-.49755 + (cx * .15844)));
14636 window[j] = window[i];
14637 }
14638 break;
14639
14640 case MUS_BLACKMAN3_WINDOW:
14641 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14642 { /* (+ 0.35875 (* -0.48829 (cos a)) (* 0.14128 (cos (* a 2))) (* -0.01168 (cos (* a 3)))) */
14643 /* (+ 0.36336 (* 0.48918 (cos a)) (* 0.13660 (cos (* a 2))) (* 0.01064 (cos (* a 3)))) is "Nuttall" window? */
14644 /* "A Family...": .36358 .489177 .136599 .0106411 */
14645
14646 cx = cos(angle);
14647 window[i] = .21747 + (cx * (-.45325 + (cx * (.28256 - (cx * .04672)))));
14648 window[j] = window[i];
14649 }
14650 break;
14651
14652 case MUS_BLACKMAN4_WINDOW:
14653 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14654 { /* (+ 0.287333 (* -0.44716 (cos a)) (* 0.20844 (cos (* a 2))) (* -0.05190 (cos (* a 3))) (* 0.005149 (cos (* a 4)))) */
14655 /* "A Family...": .32321 .471492 .175534 .0284969 .001261357 */
14656 cx = cos(angle);
14657 window[i] = .084037 + (cx * (-.29145 + (cx * (.375696 + (cx * (-.20762 + (cx * .041194)))))));
14658 window[j] = window[i];
14659 }
14660 break;
14661
14662 /* "A Family of Cosine-Sum Windows..." Albrecht */
14663
14664 case MUS_BLACKMAN5_WINDOW:
14665 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14666 {
14667 /* .293557 -.451935 .201416 -.047926 .00502619 -.000137555 */
14668 /* partials->polynomial -> -0.196389809 -0.308844775 0.3626224697 -0.188952908 0.0402095206 -0.002200880, then fixup constant */
14669 cx = cos(angle);
14670 window[i] = 0.097167 +
14671 (cx * (-.3088448 +
14672 (cx * (.3626224 +
14673 (cx * (-.1889530 +
14674 (cx * (.04020952 +
14675 (cx * -.0022008)))))))));
14676 window[j] = window[i];
14677 }
14678 break;
14679
14680 case MUS_BLACKMAN6_WINDOW:
14681 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14682 {
14683 /* .2712203 -.4334446 .2180041 -.0657853 .010761867 -.0007700127 .00001368088 */
14684 /* partials->polynomial -> -0.207255900 -0.239938736 0.3501594961
14685 * -0.247740954 0.0854382589 -0.012320203 0.0004377882
14686 */
14687 cx = cos(angle);
14688 window[i] = 0.063964353 +
14689 (cx * (-0.239938736 +
14690 (cx * (0.3501594961 +
14691 (cx * (-0.247740954 +
14692 (cx * (0.0854382589 +
14693 (cx * (-0.012320203 +
14694 (cx * 0.0004377882)))))))))));
14695 window[j] = window[i];
14696 }
14697 break;
14698
14699 case MUS_BLACKMAN7_WINDOW:
14700 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14701 {
14702 /* .2533176 -.4163269 .2288396 -.08157508 .017735924 -.0020967027 .00010677413 -.0000012807 */
14703 /* partials->polynomial -> -0.211210445 -0.182076216 0.3177137375 -0.284437984
14704 * 0.1367622316 -0.033403806 0.0034167722 -0.000081965
14705 */
14706 cx = cos(angle);
14707 window[i] = 0.04210723 +
14708 (cx * (-0.18207621 +
14709 (cx * (0.3177137375 +
14710 (cx * (-0.284437984 +
14711 (cx * (0.1367622316 +
14712 (cx * (-0.033403806 +
14713 (cx * (0.0034167722 +
14714 (cx * -0.000081965)))))))))))));
14715 window[j] = window[i];
14716 }
14717 break;
14718
14719 case MUS_BLACKMAN8_WINDOW:
14720 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14721 {
14722 /* .2384331 -.4005545 .2358242 -.09527918 .025373955 -.0041524329 .00036856041 -.00001384355 .0000001161808 */
14723 /* partials->polynomial -> -0.210818693 -0.135382235 0.2752871215 -0.298843294 0.1853193194
14724 * -0.064888448 0.0117641902 -0.000885987 0.0000148711
14725 */
14726 cx = cos(angle);
14727 window[i] = 0.027614462 +
14728 (cx * (-0.135382235 +
14729 (cx * (0.2752871215 +
14730 (cx * (-0.298843294 +
14731 (cx * (0.1853193194 +
14732 (cx * (-0.064888448 +
14733 (cx * (0.0117641902 +
14734 (cx * (-0.000885987 +
14735 (cx * 0.0000148711)))))))))))))));
14736 window[j] = window[i];
14737 }
14738 break;
14739
14740 case MUS_BLACKMAN9_WINDOW:
14741 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14742 {
14743 /* .2257345 -.3860122 .2401294 -.1070542 .03325916 -.00687337 .0008751673 -.0000600859 .000001710716 -.00000001027272 */
14744 /* partials->polynomial -> -0.207743675 -0.098795950 0.2298837751 -0.294112951 0.2243389785
14745 * -0.103248745 0.0275674108 -0.003839580 0.0002189716 -0.000002630
14746 */
14747 cx = cos(angle);
14748 window[i] = 0.01799071953 +
14749 (cx * (-0.098795950 +
14750 (cx * (0.2298837751 +
14751 (cx * (-0.294112951 +
14752 (cx * (0.2243389785 +
14753 (cx * (-0.103248745 +
14754 (cx * (0.0275674108 +
14755 (cx * (-0.003839580 +
14756 (cx * (0.0002189716 +
14757 (cx * -0.000002630)))))))))))))))));
14758 window[j] = window[i];
14759 }
14760 break;
14761
14762 case MUS_BLACKMAN10_WINDOW:
14763 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14764 {
14765 /* .2151527 -.3731348 .2424243 -.1166907 .04077422 -.01000904 .0016398069 -.0001651660 .000008884663 -.000000193817 .00000000084824 */
14766 /* partials->polynomial -> -0.203281015 -0.071953468 0.1878870875 -0.275808066
14767 * 0.2489042133 -0.141729787 0.0502002984 -0.010458985 0.0011361511 -0.000049617 0.0000004343
14768 */
14769 cx = cos(angle);
14770 window[i] = 0.0118717384 +
14771 (cx * (-0.071953468 +
14772 (cx * (0.1878870875 +
14773 (cx * (-0.275808066 +
14774 (cx * (0.2489042133 +
14775 (cx * (-0.141729787 +
14776 (cx * (0.0502002984 +
14777 (cx * (-0.010458985 +
14778 (cx * (0.0011361511 +
14779 (cx * (-0.000049617 +
14780 (cx * 0.0000004343)))))))))))))))))));
14781 window[j] = window[i];
14782 }
14783 break;
14784
14785 case MUS_FLAT_TOP_WINDOW:
14786 /* this definition taken from mathworks docs -- see above */
14787 for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq)
14788 {
14789 window[i] = 0.2156 - 0.4160 * cos(angle) + 0.2781 * cos(2 * angle) - 0.0836 * cos(3 * angle) + 0.0069 * cos(4 * angle);
14790 window[j] = window[i];
14791 }
14792 break;
14793
14794 case MUS_EXPONENTIAL_WINDOW:
14795 {
14796 mus_float_t expn, expsum = 1.0;
14797 expn = log(2) / (mus_float_t)midn + 1.0;
14798 for (i = 0, j = size - 1; i <= midn; i++, j--)
14799 {
14800 window[i] = expsum - 1.0;
14801 window[j] = window[i];
14802 expsum *= expn;
14803 }
14804 }
14805 break;
14806
14807 case MUS_KAISER_WINDOW:
14808 {
14809 mus_float_t I0beta;
14810 I0beta = mus_bessi0(beta); /* Harris multiplies beta by pi */
14811 for (i = 0, j = size - 1, angle = 1.0; i <= midn; i++, j--, angle -= rate)
14812 {
14813 window[i] = mus_bessi0(beta * sqrt(1.0 - sqr(angle))) / I0beta;
14814 window[j] = window[i];
14815 }
14816 }
14817 break;
14818
14819 case MUS_CAUCHY_WINDOW:
14820 for (i = 0, j = size - 1, angle = 1.0; i <= midn; i++, j--, angle -= rate)
14821 {
14822 window[i] = 1.0 / (1.0 + sqr(beta * angle));
14823 window[j] = window[i];
14824 }
14825 break;
14826
14827 case MUS_POISSON_WINDOW:
14828 for (i = 0, j = size - 1, angle = 1.0; i <= midn; i++, j--, angle -= rate)
14829 {
14830 window[i] = exp((-beta) * angle);
14831 window[j] = window[i];
14832 }
14833 break;
14834
14835 case MUS_HANN_POISSON_WINDOW:
14836 /* Hann * Poisson -- from JOS */
14837 {
14838 mus_float_t angle1;
14839 for (i = 0, j = size - 1, angle = 1.0, angle1 = 0.0; i <= midn; i++, j--, angle -= rate, angle1 += freq)
14840 {
14841 window[i] = exp((-beta) * angle) * (0.5 - 0.5 * cos(angle1));
14842 window[j] = window[i];
14843 }
14844 }
14845 break;
14846
14847 case MUS_RIEMANN_WINDOW:
14848 {
14849 mus_float_t sr1;
14850 sr1 = TWO_PI / (mus_float_t)size;
14851 for (i = 0, j = size - 1; i <= midn; i++, j--)
14852 {
14853 if (i == midn)
14854 window[i] = 1.0;
14855 else
14856 {
14857 cx = sr1 * (midn - i);
14858 window[i] = sin(cx) / cx;
14859 }
14860 window[j] = window[i];
14861 }
14862 }
14863 break;
14864
14865 case MUS_GAUSSIAN_WINDOW:
14866 for (i = 0, j = size - 1, angle = 1.0; i <= midn; i++, j--, angle -= rate)
14867 {
14868 window[i] = exp(-.5 * sqr(beta * angle));
14869 window[j] = window[i];
14870 }
14871 break;
14872
14873 case MUS_TUKEY_WINDOW:
14874 cx = midn * (1.0 - beta);
14875 for (i = 0, j = size - 1; i <= midn; i++, j--)
14876 {
14877 if (i >= cx)
14878 window[i] = 1.0;
14879 else window[i] = .5 * (1.0 - cos(M_PI * i / cx));
14880 window[j] = window[i];
14881 }
14882 break;
14883
14884 case MUS_MLT_SINE_WINDOW:
14885 {
14886 mus_float_t scl;
14887 scl = M_PI / (mus_float_t)size;
14888 for (i = 0, j = size - 1; i <= midn; i++, j--)
14889 {
14890 window[i] = sin((i + 0.5) * scl);
14891 window[j] = window[i];
14892 }
14893 }
14894 break;
14895
14896 case MUS_PAPOULIS_WINDOW:
14897 {
14898 int n2;
14899 n2 = size / 2;
14900 for (i = -n2; i < n2; i++)
14901 {
14902 mus_float_t ratio, pratio;
14903 ratio = (mus_float_t)i / (mus_float_t)n2;
14904 pratio = M_PI * ratio;
14905 window[i + n2] = (fabs(sin(pratio)) / M_PI) + (cos(pratio) * (1.0 - fabs(ratio)));
14906 }
14907 }
14908 break;
14909
14910 case MUS_SINC_WINDOW:
14911 {
14912 mus_float_t scl;
14913 scl = 2 * M_PI / (size - 1);
14914 for (i = -midn, j = 0; i < midn; i++, j++)
14915 {
14916 if (i == 0)
14917 window[j] = 1.0;
14918 else window[j] = sin(i * scl) / (i * scl);
14919 }
14920 }
14921 break;
14922
14923 case MUS_DPSS_WINDOW:
14924 #if HAVE_GSL_EIGEN_NONSYMMV_WORKSPACE
14925 {
14926 /* from Verma, Bilbao, Meng, "The Digital Prolate Spheroidal Window"
14927 * output checked using Julius Smith's dpssw.m, although my "beta" is different
14928 */
14929 double *data; /* "double" for gsl func */
14930 double cw, n1, pk = 0.0;
14931
14932 cw = cos(2 * M_PI * beta);
14933 n1 = (size - 1) * 0.5;
14934 if ((mus_long_t)(size * size * sizeof(double)) > mus_max_malloc())
14935 {
14936 mus_error(MUS_ARG_OUT_OF_RANGE, S_make_fft_window ": dpss window requires size^2 * 8 bytes, but that exceeds the current mus-max-malloc amount");
14937 return(window);
14938 }
14939
14940 data = (double *)calloc(size * size, sizeof(double));
14941 for (i = 0; i < size; i++)
14942 {
14943 double n2;
14944 n2 = n1 - i;
14945 data[i * size + i] = cw * n2 * n2;
14946 if (i < (size - 1))
14947 data[i * (size + 1) + 1] = 0.5 * (i + 1) * (size - 1 - i);
14948 if (i > 0)
14949 data[i * (size + 1) - 1] = 0.5 * i * (size - i);
14950 }
14951 {
14952 gsl_vector_complex_view evec_i;
14953 gsl_matrix_view m = gsl_matrix_view_array(data, size, size);
14954 gsl_vector_complex *eval = gsl_vector_complex_alloc(size);
14955 gsl_matrix_complex *evec = gsl_matrix_complex_alloc(size, size);
14956
14957 gsl_eigen_nonsymmv_workspace *w = gsl_eigen_nonsymmv_alloc(size);
14958 gsl_eigen_nonsymmv(&m.matrix, eval, evec, w);
14959 gsl_eigen_nonsymmv_free(w);
14960
14961 gsl_eigen_nonsymmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);
14962 evec_i = gsl_matrix_complex_column(evec, 0);
14963
14964 for (j = 0; j < size; j++)
14965 window[j] = GSL_REAL(gsl_vector_complex_get(&evec_i.vector, j));
14966
14967 gsl_vector_complex_free(eval);
14968 gsl_matrix_complex_free(evec);
14969 }
14970
14971 for (i = 0; i < size; i++)
14972 if (fabs(window[i]) > fabs(pk))
14973 pk = window[i];
14974 if (pk != 0.0)
14975 for (i = 0; i < size; i++)
14976 window[i] /= pk;
14977
14978 free(data);
14979 }
14980 #else
14981 mus_error(MUS_NO_SUCH_FFT_WINDOW, S_make_fft_window ": DPSS window needs GSL");
14982 #endif
14983 break;
14984
14985 case MUS_ULTRASPHERICAL_WINDOW:
14986 case MUS_SAMARAKI_WINDOW:
14987 case MUS_DOLPH_CHEBYSHEV_WINDOW:
14988 /* "Design of Ultraspherical Window Functions with Prescribed Spectral Characteristics", Bergen and Antoniou, EURASIP JASP 2004 */
14989 if (type == MUS_ULTRASPHERICAL_WINDOW)
14990 {
14991 if (mu == 0.0)
14992 type = MUS_DOLPH_CHEBYSHEV_WINDOW;
14993 else
14994 {
14995 if (mu == 1.0)
14996 type = MUS_SAMARAKI_WINDOW;
14997 }
14998 }
14999
15000 #if HAVE_COMPLEX_TRIG
15001 {
15002 mus_float_t *rl, *im;
15003 mus_float_t pk = 0.0;
15004 mus_float_t alpha;
15005
15006 freq = M_PI / (mus_float_t)size;
15007 if (beta < 0.2) beta = 0.2;
15008 alpha = creal(ccosh(cacosh(pow(10.0, beta)) / (mus_float_t)size));
15009
15010 rl = (mus_float_t *)malloc(size * sizeof(mus_float_t));
15011 im = (mus_float_t *)calloc(size, sizeof(mus_float_t));
15012
15013 for (i = 0, angle = 0.0; i < size; i++, angle += freq)
15014 {
15015 switch (type)
15016 {
15017 case MUS_DOLPH_CHEBYSHEV_WINDOW:
15018 rl[i] = creal(ccos(cacos(alpha * cos(angle)) * size)); /* here is Tn (Chebyshev polynomial first kind) */
15019 break;
15020
15021 case MUS_SAMARAKI_WINDOW:
15022 /* Samaraki window uses Un instead */
15023 rl[i] = creal(csin(cacos(alpha * cos(angle)) * (size + 1.0)) / csin(cacos(alpha * cos(angle))));
15024 break;
15025
15026 case MUS_ULTRASPHERICAL_WINDOW:
15027 /* Cn here */
15028 rl[i] = ultraspherical(size, alpha * cos(angle), mu);
15029 break;
15030
15031 default:
15032 break;
15033 }
15034 }
15035
15036 mus_fft(rl, im, size, -1); /* can be 1 here */
15037
15038 pk = 0.0;
15039 for (i = 0; i < size; i++)
15040 if (pk < rl[i])
15041 pk = rl[i];
15042 if ((pk != 0.0) && (pk != 1.0))
15043 {
15044 for (i = 0, j = size / 2; i < size; i++)
15045 {
15046 window[i] = rl[j++] / pk;
15047 if (j == size) j = 0;
15048 }
15049 }
15050 else
15051 {
15052 mus_copy_floats(window, rl, size);
15053 }
15054
15055 free(rl);
15056 free(im);
15057 }
15058 #else
15059 #if HAVE_GSL
15060 {
15061 mus_float_t *rl, *im;
15062 mus_float_t pk;
15063 mus_float_t alpha;
15064
15065 freq = M_PI / (mus_float_t)size;
15066 if (beta < 0.2) beta = 0.2;
15067 alpha = GSL_REAL(gsl_complex_cosh(
15068 gsl_complex_mul_real(
15069 gsl_complex_arccosh_real(pow(10.0, beta)),
15070 (mus_float_t)(1.0 / (mus_float_t)size))));
15071
15072 rl = (mus_float_t *)malloc(size * sizeof(mus_float_t));
15073 im = (mus_float_t *)calloc(size, sizeof(mus_float_t));
15074
15075 for (i = 0, angle = 0.0; i < size; i++, angle += freq)
15076 {
15077 switch (type)
15078 {
15079 case MUS_DOLPH_CHEBYSHEV_WINDOW:
15080 rl[i] = GSL_REAL(gsl_complex_cos(
15081 gsl_complex_mul_real(
15082 gsl_complex_arccos_real(alpha * cos(angle)),
15083 (mus_float_t)size)));
15084 break;
15085
15086 case MUS_SAMARAKI_WINDOW:
15087 rl[i] = GSL_REAL(gsl_complex_div(
15088 gsl_complex_sin(
15089 gsl_complex_mul_real(
15090 gsl_complex_arccos_real(alpha * cos(angle)),
15091 (mus_float_t)(size + 1.0))),
15092 gsl_complex_sin(
15093 gsl_complex_arccos_real(alpha * cos(angle)))));
15094 break;
15095
15096 case MUS_ULTRASPHERICAL_WINDOW:
15097 rl[i] = ultraspherical(size, alpha * cos(angle), mu);
15098 break;
15099
15100 default:
15101 break;
15102 }
15103
15104 }
15105
15106 mus_fft(rl, im, size, -1); /* can be 1 here */
15107
15108 pk = 0.0;
15109 for (i = 0; i < size; i++)
15110 if (pk < rl[i])
15111 pk = rl[i];
15112 if ((pk != 0.0) && (pk != 1.0))
15113 {
15114 for (i = 0, j = size / 2; i < size; i++)
15115 {
15116 window[i] = rl[j++] / pk;
15117 if (j == size) j = 0;
15118 }
15119 }
15120 else
15121 {
15122 mus_copy_floats(window, rl, size);
15123 }
15124 free(rl);
15125 free(im);
15126 }
15127 #else
15128 mus_error(MUS_NO_SUCH_FFT_WINDOW, S_make_fft_window ": Dolph-Chebyshev, Samaraki, and Ultraspherical windows need complex trig support");
15129 #endif
15130 #endif
15131 break;
15132
15133 default:
15134 mus_error(MUS_NO_SUCH_FFT_WINDOW, S_make_fft_window ": unknown fft data window: %d", (int)type);
15135 break;
15136 }
15137 return(window);
15138 }
15139
15140
mus_make_fft_window(mus_fft_window_t type,mus_long_t size,mus_float_t beta)15141 mus_float_t *mus_make_fft_window(mus_fft_window_t type, mus_long_t size, mus_float_t beta)
15142 {
15143 return(mus_make_fft_window_with_window(type, size, beta, 0.0, (mus_float_t *)calloc(size, sizeof(mus_float_t))));
15144 }
15145
15146
15147 static const char *fft_window_names[MUS_NUM_FFT_WINDOWS] =
15148 {"Rectangular", "Hann", "Welch", "Parzen", "Bartlett", "Hamming", "Blackman2", "Blackman3", "Blackman4",
15149 "Exponential", "Riemann", "Kaiser", "Cauchy", "Poisson", "Gaussian", "Tukey", "Dolph-Chebyshev", "Hann-Poisson", "Connes",
15150 "Samaraki", "Ultraspherical", "Bartlett-Hann", "Bohman", "Flat-top",
15151 "Blackman5", "Blackman6", "Blackman7", "Blackman8", "Blackman9", "Blackman10",
15152 "Rife-Vincent2", "Rife-Vincent3", "Rife-Vincent4", "MLT Sine", "Papoulis", "DPSS (Slepian)", "Sinc"
15153 };
15154
15155
mus_fft_window_name(mus_fft_window_t win)15156 const char *mus_fft_window_name(mus_fft_window_t win)
15157 {
15158 if (mus_is_fft_window((int)win))
15159 return(fft_window_names[(int)win]);
15160 return("unknown");
15161 }
15162
15163
mus_fft_window_names(void)15164 const char **mus_fft_window_names(void)
15165 {
15166 return(fft_window_names);
15167 }
15168
15169
mus_spectrum(mus_float_t * rdat,mus_float_t * idat,mus_float_t * window,mus_long_t n,mus_spectrum_t type)15170 mus_float_t *mus_spectrum(mus_float_t *rdat, mus_float_t *idat, mus_float_t *window, mus_long_t n, mus_spectrum_t type)
15171 {
15172 mus_long_t i;
15173 mus_float_t maxa, lowest;
15174
15175 if (window)
15176 {
15177 for (i = 0; i < n; i++)
15178 rdat[i] *= window[i];
15179 }
15180 mus_clear_floats(idat, n);
15181 mus_fft(rdat, idat, n, 1);
15182
15183 lowest = 0.000001;
15184 maxa = 0.0;
15185 n = n / 2;
15186 for (i = 0; i < n; i++)
15187 {
15188 mus_float_t val;
15189 val = rdat[i] * rdat[i] + idat[i] * idat[i];
15190 if (val < lowest)
15191 rdat[i] = 0.001;
15192 else
15193 {
15194 rdat[i] = sqrt(val);
15195 if (rdat[i] > maxa) maxa = rdat[i];
15196 }
15197 }
15198 if (maxa > 0.0)
15199 {
15200 maxa = 1.0 / maxa;
15201 if (type == MUS_SPECTRUM_IN_DB)
15202 {
15203 mus_float_t todb;
15204 todb = 20.0 / log(10.0);
15205 for (i = 0; i < n; i++)
15206 rdat[i] = todb * log(rdat[i] * maxa);
15207 }
15208 else
15209 {
15210 if (type == MUS_SPECTRUM_NORMALIZED)
15211 for (i = 0; i < n; i++)
15212 rdat[i] *= maxa;
15213 }
15214 }
15215 return(rdat);
15216 }
15217
15218
mus_autocorrelate(mus_float_t * data,mus_long_t n)15219 mus_float_t *mus_autocorrelate(mus_float_t *data, mus_long_t n)
15220 {
15221 mus_float_t *im;
15222 mus_float_t fscl;
15223 mus_long_t i, n2;
15224
15225 n2 = n / 2;
15226 fscl = 1.0 / (mus_float_t)n;
15227 im = (mus_float_t *)calloc(n, sizeof(mus_float_t));
15228
15229 mus_fft(data, im, n, 1);
15230 for (i = 0; i < n; i++)
15231 data[i] = data[i] * data[i] + im[i] * im[i];
15232 mus_clear_floats(im, n);
15233
15234 mus_fft(data, im, n, -1);
15235 for (i = 0; i <= n2; i++)
15236 data[i] *= fscl;
15237 for (i = n2 + 1; i < n; i++)
15238 data[i] = 0.0;
15239
15240 free(im);
15241 return(data);
15242 }
15243
15244
mus_correlate(mus_float_t * data1,mus_float_t * data2,mus_long_t n)15245 mus_float_t *mus_correlate(mus_float_t *data1, mus_float_t *data2, mus_long_t n)
15246 {
15247 mus_float_t *im1, *im2;
15248 mus_long_t i;
15249 mus_float_t fscl;
15250
15251 im1 = (mus_float_t *)calloc(n, sizeof(mus_float_t));
15252 im2 = (mus_float_t *)calloc(n, sizeof(mus_float_t));
15253
15254 mus_fft(data1, im1, n, 1);
15255 mus_fft(data2, im2, n, 1);
15256
15257 for (i = 0; i < n; i++)
15258 {
15259 mus_float_t tmp1, tmp2, tmp3, tmp4;
15260 tmp1 = data1[i] * data2[i];
15261 tmp2 = im1[i] * im2[i];
15262 tmp3 = data1[i] * im2[i];
15263 tmp4 = data2[i] * im1[i];
15264 data1[i] = tmp1 + tmp2;
15265 im1[i] = tmp3 - tmp4;
15266 }
15267
15268 mus_fft(data1, im1, n, -1);
15269 fscl = 1.0 / (mus_float_t)n;
15270 for (i = 0; i < n; i++)
15271 data1[i] *= fscl;
15272
15273 free(im1);
15274 free(im2);
15275
15276 return(data1);
15277 }
15278
15279
mus_cepstrum(mus_float_t * data,mus_long_t n)15280 mus_float_t *mus_cepstrum(mus_float_t *data, mus_long_t n)
15281 {
15282 mus_float_t *rl, *im;
15283 mus_float_t fscl, lowest;
15284 mus_long_t i;
15285
15286 lowest = 0.00000001;
15287 fscl = 2.0 / (mus_float_t)n;
15288
15289 rl = (mus_float_t *)malloc(n * sizeof(mus_float_t));
15290 im = (mus_float_t *)calloc(n, sizeof(mus_float_t));
15291 mus_copy_floats(rl, data, n);
15292
15293 mus_fft(rl, im, n, 1);
15294
15295 for (i = 0; i < n; i++)
15296 {
15297 rl[i] = rl[i] * rl[i] + im[i] * im[i];
15298 if (rl[i] < lowest)
15299 rl[i] = -10.0;
15300 else rl[i] = log(sqrt(rl[i]));
15301 }
15302 mus_clear_floats(im, n);
15303
15304 mus_fft(rl, im, n, -1);
15305
15306 for (i = 0; i < n; i++)
15307 if (fabs(rl[i]) > fscl)
15308 fscl = fabs(rl[i]);
15309
15310 if (fscl > 0.0)
15311 for (i = 0; i < n; i++)
15312 data[i] = rl[i] / fscl;
15313
15314 free(rl);
15315 free(im);
15316 return(data);
15317 }
15318
15319
15320
15321 /* ---------------- convolve ---------------- */
15322
mus_convolution(mus_float_t * rl1,mus_float_t * rl2,mus_long_t n)15323 mus_float_t *mus_convolution(mus_float_t *rl1, mus_float_t *rl2, mus_long_t n)
15324 {
15325 /* convolves two real arrays.
15326 * rl1 and rl2 are assumed to be set up correctly for the convolution
15327 * (that is, rl1 (the "signal") is zero-padded by length of
15328 * (non-zero part of) rl2 and rl2 is stored in wrap-around order)
15329 * We treat rl2 as the imaginary part of the first fft, then do
15330 * the split, scaling, and (complex) spectral multiply in one step.
15331 * result in rl1
15332 */
15333
15334 mus_long_t j, n2;
15335 mus_float_t invn;
15336
15337 mus_fft(rl1, rl2, n, 1);
15338
15339 n2 = n >> 1;
15340 invn = 0.25 / (mus_float_t)n;
15341 rl1[0] = ((rl1[0] * rl2[0]) / (mus_float_t)n);
15342 rl2[0] = 0.0;
15343
15344 for (j = 1; j <= n2; j++)
15345 {
15346 mus_long_t nn2;
15347 mus_float_t rem, rep, aim, aip;
15348
15349 nn2 = n - j;
15350 rep = (rl1[j] + rl1[nn2]);
15351 rem = (rl1[j] - rl1[nn2]);
15352 aip = (rl2[j] + rl2[nn2]);
15353 aim = (rl2[j] - rl2[nn2]);
15354
15355 rl1[j] = invn * (rep * aip + aim * rem);
15356 rl2[j] = invn * (aim * aip - rep * rem);
15357 rl1[nn2] = rl1[j];
15358 rl2[nn2] = -rl2[j];
15359 }
15360
15361 mus_fft(rl1, rl2, n, -1);
15362 return(rl1);
15363 }
15364
15365
15366 typedef struct {
15367 mus_any_class *core;
15368 mus_float_t (*feeder)(void *arg, int direction);
15369 mus_float_t (*block_feeder)(void *arg, int direction, mus_float_t *block, mus_long_t start, mus_long_t end);
15370 mus_long_t fftsize, fftsize2, ctr, filtersize;
15371 mus_float_t *rl1, *rl2, *buf, *filter;
15372 void *closure;
15373 } conv;
15374
15375
convolve_equalp(mus_any * p1,mus_any * p2)15376 static bool convolve_equalp(mus_any *p1, mus_any *p2) {return(p1 == p2);}
15377
15378
describe_convolve(mus_any * ptr)15379 static char *describe_convolve(mus_any *ptr)
15380 {
15381 conv *gen = (conv *)ptr;
15382 char *describe_buffer;
15383 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
15384 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s size: %" print_mus_long,
15385 mus_name(ptr),
15386 gen->fftsize);
15387 return(describe_buffer);
15388 }
15389
15390
free_convolve(mus_any * ptr)15391 static void free_convolve(mus_any *ptr)
15392 {
15393 conv *gen = (conv *)ptr;
15394 if (gen->rl1) free(gen->rl1);
15395 if (gen->rl2) free(gen->rl2);
15396 if (gen->buf) free(gen->buf);
15397 free(gen);
15398 }
15399
conv_copy(mus_any * ptr)15400 static mus_any *conv_copy(mus_any *ptr)
15401 {
15402 conv *g, *p;
15403 int bytes;
15404
15405 p = (conv *)ptr;
15406 g = (conv *)malloc(sizeof(conv));
15407 memcpy((void *)g, (void *)ptr, sizeof(conv));
15408 bytes = g->fftsize * sizeof(mus_float_t);
15409 g->rl1 = (mus_float_t *)malloc(bytes);
15410 mus_copy_floats(g->rl1, p->rl1, g->fftsize);
15411 g->rl2 = (mus_float_t *)malloc(bytes);
15412 mus_copy_floats(g->rl2, p->rl2, g->fftsize);
15413 g->buf = (mus_float_t *)malloc(bytes);
15414 mus_copy_floats(g->buf, p->buf, g->fftsize);
15415 return((mus_any *)g);
15416 }
15417
15418
conv_length(mus_any * ptr)15419 static mus_long_t conv_length(mus_any *ptr) {return(((conv *)ptr)->fftsize);}
run_convolve(mus_any * ptr,mus_float_t unused1,mus_float_t unused2)15420 static mus_float_t run_convolve(mus_any *ptr, mus_float_t unused1, mus_float_t unused2) {return(mus_convolve(ptr, NULL));}
15421
conv_closure(mus_any * rd)15422 static void *conv_closure(mus_any *rd) {return(((conv *)rd)->closure);}
conv_set_closure(mus_any * rd,void * e)15423 static void *conv_set_closure(mus_any *rd, void *e) {((conv *)rd)->closure = e; return(e);}
15424
convolve_reset(mus_any * ptr)15425 static void convolve_reset(mus_any *ptr)
15426 {
15427 conv *gen = (conv *)ptr;
15428 gen->ctr = gen->fftsize2;
15429 mus_clear_floats(gen->rl1, gen->fftsize);
15430 mus_clear_floats(gen->rl2, gen->fftsize);
15431 mus_clear_floats(gen->buf, gen->fftsize);
15432 }
15433
15434
15435 static mus_any_class CONVOLVE_CLASS = {
15436 MUS_CONVOLVE,
15437 (char *)S_convolve,
15438 &free_convolve,
15439 &describe_convolve,
15440 &convolve_equalp,
15441 0, 0,
15442 &conv_length,
15443 0,
15444 0, 0, 0, 0,
15445 0, 0,
15446 0, 0,
15447 &run_convolve,
15448 MUS_NOT_SPECIAL,
15449 &conv_closure,
15450 0,
15451 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
15452 0, 0, 0, 0, 0, 0, 0,
15453 0, 0, 0, 0,
15454 &convolve_reset,
15455 &conv_set_closure,
15456 &conv_copy
15457 };
15458
15459
mus_convolve(mus_any * ptr,mus_float_t (* input)(void * arg,int direction))15460 mus_float_t mus_convolve(mus_any *ptr, mus_float_t (*input)(void *arg, int direction))
15461 {
15462 conv *gen = (conv *)ptr;
15463 mus_float_t result;
15464 if (gen->ctr >= gen->fftsize2)
15465 {
15466 mus_long_t N;
15467 N = gen->fftsize2;
15468 if (input) {gen->feeder = input; gen->block_feeder = NULL;}
15469
15470 mus_clear_floats(gen->rl2, N * 2);
15471 mus_copy_floats(gen->rl2, gen->filter, gen->filtersize);
15472 mus_copy_floats(gen->buf, gen->buf + N, N);
15473 mus_clear_floats(gen->buf + N, N);
15474 mus_clear_floats(gen->rl1 + N, N);
15475
15476 if (gen->block_feeder)
15477 gen->block_feeder(gen->closure, 1, gen->rl1, 0, N);
15478 else
15479 {
15480 mus_long_t i;
15481 for (i = 0; i < N;)
15482 {
15483 gen->rl1[i] = gen->feeder(gen->closure, 1); i++;
15484 gen->rl1[i] = gen->feeder(gen->closure, 1); i++;
15485 }
15486 }
15487
15488 mus_convolution(gen->rl1, gen->rl2, gen->fftsize);
15489 mus_add_floats(gen->buf, gen->rl1, N);
15490 mus_copy_floats(gen->buf + N, gen->rl1 + N, N);
15491 gen->ctr = 0;
15492 }
15493 result = gen->buf[gen->ctr];
15494 gen->ctr++;
15495 return(result);
15496 }
15497
15498
mus_is_convolve(mus_any * ptr)15499 bool mus_is_convolve(mus_any *ptr)
15500 {
15501 return((ptr) &&
15502 (ptr->core->type == MUS_CONVOLVE));
15503 }
15504
15505
mus_make_convolve(mus_float_t (* input)(void * arg,int direction),mus_float_t * filter,mus_long_t fftsize,mus_long_t filtersize,void * closure)15506 mus_any *mus_make_convolve(mus_float_t (*input)(void *arg, int direction), mus_float_t *filter, mus_long_t fftsize, mus_long_t filtersize, void *closure)
15507 {
15508 conv *gen;
15509 gen = (conv *)malloc(sizeof(conv));
15510 gen->core = &CONVOLVE_CLASS;
15511 gen->feeder = input;
15512 gen->block_feeder = NULL;
15513 gen->closure = closure;
15514 gen->filter = filter;
15515 if (filter)
15516 {
15517 mus_long_t i;
15518 bool all_zero = true;
15519 for (i = 0; i < filtersize; i++)
15520 if (fabs(filter[i]) != 0.0) /* I'm getting -0.000 != 0.000 */
15521 {
15522 all_zero = false;
15523 break;
15524 }
15525 if (all_zero)
15526 mus_print("make_convolve: filter contains only 0.0.");
15527 }
15528 gen->filtersize = filtersize;
15529 gen->fftsize = fftsize;
15530 gen->fftsize2 = gen->fftsize / 2;
15531 gen->ctr = gen->fftsize2;
15532 gen->rl1 = (mus_float_t *)malloc(fftsize * sizeof(mus_float_t));
15533 gen->rl2 = (mus_float_t *)malloc(fftsize * sizeof(mus_float_t));
15534 gen->buf = (mus_float_t *)calloc(fftsize, sizeof(mus_float_t));
15535 return((mus_any *)gen);
15536 }
15537
15538
mus_convolve_files(const char * file1,const char * file2,mus_float_t maxamp,const char * output_file)15539 void mus_convolve_files(const char *file1, const char *file2, mus_float_t maxamp, const char *output_file)
15540 {
15541 mus_long_t file1_len, file2_len, outlen, totallen;
15542 int file1_chans, file2_chans, output_chans;
15543 mus_float_t *data1, *data2;
15544 const char *errmsg = NULL;
15545 mus_float_t maxval = 0.0;
15546 mus_long_t i, fftlen;
15547
15548 file1_len = mus_sound_framples(file1);
15549 file2_len = mus_sound_framples(file2);
15550 if ((file1_len <= 0) || (file2_len <= 0)) return;
15551
15552 file1_chans = mus_sound_chans(file1);
15553 if (file1_chans <= 0) mus_error(MUS_NO_CHANNELS, S_convolve_files ": %s chans: %d", file1, file1_chans);
15554 file2_chans = mus_sound_chans(file2);
15555 if (file2_chans <= 0) mus_error(MUS_NO_CHANNELS, S_convolve_files ": %s chans: %d", file2, file2_chans);
15556 output_chans = file1_chans;
15557 if (file2_chans > output_chans) output_chans = file2_chans;
15558
15559 fftlen = (mus_long_t)(pow(2.0, (int)ceil(log1p(file1_len + file2_len) / log(2.0))));
15560 outlen = file1_len + file2_len + 1;
15561 totallen = outlen * output_chans;
15562
15563 data1 = (mus_float_t *)calloc(fftlen, sizeof(mus_float_t));
15564 data2 = (mus_float_t *)calloc(fftlen, sizeof(mus_float_t));
15565
15566 if (output_chans == 1)
15567 {
15568 mus_float_t *samps;
15569 samps = (mus_float_t *)calloc(fftlen, sizeof(mus_float_t));
15570
15571 mus_file_to_array(file1, 0, 0, file1_len, samps);
15572 for (i = 0; i < file1_len; i++) data1[i] = samps[i];
15573 mus_file_to_array(file2, 0, 0, file2_len, samps);
15574 for (i = 0; i < file2_len; i++) data2[i] = samps[i];
15575
15576 mus_convolution(data1, data2, fftlen);
15577
15578 for (i = 0; i < outlen; i++)
15579 if (maxval < fabs(data1[i]))
15580 maxval = fabs(data1[i]);
15581
15582 if (maxval > 0.0)
15583 {
15584 maxval = maxamp / maxval;
15585 for (i = 0; i < outlen; i++) data1[i] *= maxval;
15586 }
15587
15588 for (i = 0; i < outlen; i++) samps[i] = data1[i];
15589 errmsg = mus_array_to_file_with_error(output_file, samps, outlen, mus_sound_srate(file1), 1);
15590
15591 free(samps);
15592 }
15593 else
15594 {
15595 mus_float_t *samps;
15596 mus_float_t *outdat;
15597 int c1 = 0, c2 = 0, chan;
15598
15599 samps = (mus_float_t *)calloc(totallen, sizeof(mus_float_t));
15600 outdat = (mus_float_t *)malloc(totallen * sizeof(mus_float_t));
15601
15602 for (chan = 0; chan < output_chans; chan++)
15603 {
15604 mus_long_t j, k;
15605
15606 mus_file_to_array(file1, c1, 0, file1_len, samps);
15607 for (k = 0; k < file1_len; k++) data1[k] = samps[k];
15608 mus_file_to_array(file2, c2, 0, file2_len, samps);
15609 for (k = 0; k < file2_len; k++) data2[k] = samps[k];
15610
15611 mus_convolution(data1, data2, fftlen);
15612
15613 for (j = chan, k = 0; j < totallen; j += output_chans, k++) outdat[j] = data1[k];
15614 c1++;
15615 if (c1 >= file1_chans) c1 = 0;
15616 c2++;
15617 if (c2 >= file2_chans) c2 = 0;
15618
15619 mus_clear_floats(data1, fftlen);
15620 mus_clear_floats(data2, fftlen);
15621 }
15622
15623 for (i = 0; i < totallen; i++)
15624 if (maxval < fabs(outdat[i]))
15625 maxval = fabs(outdat[i]);
15626
15627 if (maxval > 0.0)
15628 {
15629 maxval = maxamp / maxval;
15630 for (i = 0; i < totallen; i++) outdat[i] *= maxval;
15631 }
15632
15633 for (i = 0; i < totallen; i++)
15634 samps[i] = outdat[i];
15635
15636 errmsg = mus_array_to_file_with_error(output_file, samps, totallen, mus_sound_srate(file1), output_chans);
15637 free(samps);
15638 free(outdat);
15639 }
15640
15641 free(data1);
15642 free(data2);
15643
15644 if (errmsg)
15645 mus_error(MUS_CANT_OPEN_FILE, S_convolve_files ": %s", errmsg);
15646 }
15647
15648
15649
15650 /* ---------------- phase-vocoder ---------------- */
15651
15652 typedef struct {
15653 mus_any_class *core;
15654 mus_float_t pitch;
15655 mus_float_t (*input)(void *arg, int direction);
15656 mus_float_t (*block_input)(void *arg, int direction, mus_float_t *block, mus_long_t start, mus_long_t end);
15657 void *closure;
15658 bool (*analyze)(void *arg, mus_float_t (*input)(void *arg1, int direction));
15659 int (*edit)(void *arg);
15660 mus_float_t (*synthesize)(void *arg);
15661 int outctr, interp, filptr, N, D, topN;
15662 mus_float_t *win, *ampinc, *amps, *freqs, *phases, *phaseinc, *lastphase, *in_data;
15663
15664 mus_float_t sum1;
15665 bool calc;
15666 #if HAVE_SINCOS
15667 double *cs, *sn;
15668 bool *sc_safe;
15669 int *indices;
15670 #endif
15671 } pv_info;
15672
15673
mus_is_phase_vocoder(mus_any * ptr)15674 bool mus_is_phase_vocoder(mus_any *ptr)
15675 {
15676 return((ptr) &&
15677 (ptr->core->type == MUS_PHASE_VOCODER));
15678 }
15679
15680
phase_vocoder_equalp(mus_any * p1,mus_any * p2)15681 static bool phase_vocoder_equalp(mus_any *p1, mus_any *p2) {return(p1 == p2);}
15682
15683
describe_phase_vocoder(mus_any * ptr)15684 static char *describe_phase_vocoder(mus_any *ptr)
15685 {
15686 char *arr = NULL;
15687 pv_info *gen = (pv_info *)ptr;
15688 char *describe_buffer;
15689 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
15690 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s outctr: %d, interp: %d, filptr: %d, N: %d, D: %d, in_data: %s",
15691 mus_name(ptr),
15692 gen->outctr, gen->interp, gen->filptr, gen->N, gen->D,
15693 arr = float_array_to_string(gen->in_data, gen->N, 0));
15694 if (arr) free(arr);
15695 return(describe_buffer);
15696 }
15697
15698
free_phase_vocoder(mus_any * ptr)15699 static void free_phase_vocoder(mus_any *ptr)
15700 {
15701 pv_info *gen = (pv_info *)ptr;
15702 if (gen->in_data) free(gen->in_data);
15703 if (gen->amps) free(gen->amps);
15704 if (gen->freqs) free(gen->freqs);
15705 if (gen->phases) free(gen->phases);
15706 if (gen->win) free(gen->win);
15707 if (gen->phaseinc) free(gen->phaseinc);
15708 if (gen->lastphase) free(gen->lastphase);
15709 if (gen->ampinc) free(gen->ampinc);
15710 #if HAVE_SINCOS
15711 if (gen->indices) free(gen->indices);
15712 if (gen->sn) free(gen->sn);
15713 if (gen->cs) free(gen->cs);
15714 if (gen->sc_safe) free(gen->sc_safe);
15715 #endif
15716 free(gen);
15717 }
15718
15719
pv_info_copy(mus_any * ptr)15720 static mus_any *pv_info_copy(mus_any *ptr)
15721 {
15722 pv_info *g, *p;
15723 int bytes;
15724
15725 p = (pv_info *)ptr;
15726 g = (pv_info *)malloc(sizeof(pv_info));
15727 memcpy((void *)g, (void *)ptr, sizeof(pv_info));
15728
15729 bytes = p->N * sizeof(mus_float_t);
15730 g->freqs = (mus_float_t *)malloc(bytes);
15731 mus_copy_floats(g->freqs, p->freqs, p->N);
15732 g->ampinc = (mus_float_t *)malloc(bytes);
15733 mus_copy_floats(g->ampinc, p->ampinc, p->N);
15734 g->win = (mus_float_t *)malloc(bytes);
15735 mus_copy_floats(g->win, p->win, p->N);
15736 if (p->in_data)
15737 {
15738 g->in_data = (mus_float_t *)malloc(bytes);
15739 mus_copy_floats(g->in_data, p->in_data, p->N);
15740 }
15741
15742 bytes = (p->N / 2) * sizeof(mus_float_t);
15743 g->amps = (mus_float_t *)malloc(bytes);
15744 mus_copy_floats(g->amps, p->amps, p->N / 2);
15745 g->phases = (mus_float_t *)malloc(bytes);
15746 mus_copy_floats(g->phases, p->phases, p->N / 2);
15747 g->lastphase = (mus_float_t *)malloc(bytes);
15748 mus_copy_floats(g->lastphase, p->lastphase, p->N / 2);
15749 g->phaseinc = (mus_float_t *)malloc(bytes);
15750 mus_copy_floats(g->phaseinc, p->phaseinc, p->N / 2);
15751
15752 #if HAVE_SINCOS
15753 bytes = (p->N / 2) * sizeof(int);
15754 g->indices = (int *)malloc(bytes);
15755 memcpy((void *)(g->indices), (void *)(p->indices), bytes);
15756
15757 bytes = p->N * sizeof(double);
15758 g->sn = (double *)malloc(bytes);
15759 memcpy((void *)(g->sn), (void *)(p->sn), bytes);
15760 g->cs = (double *)malloc(bytes);
15761 memcpy((void *)(g->cs), (void *)(p->cs), bytes);
15762
15763 bytes = p->N * sizeof(bool);
15764 g->sc_safe = (bool *)malloc(bytes);
15765 memcpy((void *)(g->sc_safe), (void *)(p->sc_safe), bytes);
15766 #endif
15767
15768 return((mus_any *)g);
15769 }
15770
15771
pv_length(mus_any * ptr)15772 static mus_long_t pv_length(mus_any *ptr) {return(((pv_info *)ptr)->N);}
15773
pv_hop(mus_any * ptr)15774 static mus_long_t pv_hop(mus_any *ptr) {return(((pv_info *)ptr)->D);}
pv_set_hop(mus_any * ptr,mus_long_t val)15775 static mus_long_t pv_set_hop(mus_any *ptr, mus_long_t val) {((pv_info *)ptr)->D = (int)val; return(val);}
15776
pv_frequency(mus_any * ptr)15777 static mus_float_t pv_frequency(mus_any *ptr) {return(((pv_info *)ptr)->pitch);}
pv_set_frequency(mus_any * ptr,mus_float_t val)15778 static mus_float_t pv_set_frequency(mus_any *ptr, mus_float_t val) {((pv_info *)ptr)->pitch = val; return(val);}
15779
pv_closure(mus_any * rd)15780 static void *pv_closure(mus_any *rd) {return(((pv_info *)rd)->closure);}
pv_set_closure(mus_any * rd,void * e)15781 static void *pv_set_closure(mus_any *rd, void *e) {((pv_info *)rd)->closure = e; return(e);}
15782
mus_phase_vocoder_amp_increments(mus_any * ptr)15783 mus_float_t *mus_phase_vocoder_amp_increments(mus_any *ptr) {return(((pv_info *)ptr)->ampinc);}
mus_phase_vocoder_amps(mus_any * ptr)15784 mus_float_t *mus_phase_vocoder_amps(mus_any *ptr) {return(((pv_info *)ptr)->amps);}
15785
mus_phase_vocoder_freqs(mus_any * ptr)15786 mus_float_t *mus_phase_vocoder_freqs(mus_any *ptr) {return(((pv_info *)ptr)->freqs);}
mus_phase_vocoder_phases(mus_any * ptr)15787 mus_float_t *mus_phase_vocoder_phases(mus_any *ptr) {return(((pv_info *)ptr)->phases);}
mus_phase_vocoder_phase_increments(mus_any * ptr)15788 mus_float_t *mus_phase_vocoder_phase_increments(mus_any *ptr) {return(((pv_info *)ptr)->phaseinc);}
15789
pv_outctr(mus_any * ptr)15790 static mus_long_t pv_outctr(mus_any *ptr) {return((mus_long_t)(((pv_info *)ptr)->outctr));} /* mus_location wrapper */
pv_set_outctr(mus_any * ptr,mus_long_t val)15791 static mus_long_t pv_set_outctr(mus_any *ptr, mus_long_t val) {((pv_info *)ptr)->outctr = (int)val; return(val);}
15792
run_phase_vocoder(mus_any * ptr,mus_float_t unused1,mus_float_t unused2)15793 static mus_float_t run_phase_vocoder(mus_any *ptr, mus_float_t unused1, mus_float_t unused2) {return(mus_phase_vocoder(ptr, NULL));}
15794
pv_increment(mus_any * rd)15795 static mus_float_t pv_increment(mus_any *rd) {return((mus_float_t)(((pv_info *)rd)->interp));}
pv_set_increment(mus_any * rd,mus_float_t val)15796 static mus_float_t pv_set_increment(mus_any *rd, mus_float_t val) {((pv_info *)rd)->interp = (int)val; return(val);}
15797
15798
pv_reset(mus_any * ptr)15799 static void pv_reset(mus_any *ptr)
15800 {
15801 pv_info *gen = (pv_info *)ptr;
15802 if (gen->in_data) free(gen->in_data);
15803 gen->in_data = NULL;
15804 gen->outctr = gen->interp;
15805 gen->filptr = 0;
15806 mus_clear_floats(gen->ampinc, gen->N);
15807 mus_clear_floats(gen->freqs, gen->N);
15808 mus_clear_floats(gen->amps, gen->N / 2);
15809 mus_clear_floats(gen->phases, gen->N / 2);
15810 mus_clear_floats(gen->lastphase, gen->N / 2);
15811 mus_clear_floats(gen->phaseinc, gen->N / 2);
15812 }
15813
15814
15815 static mus_any_class PHASE_VOCODER_CLASS = {
15816 MUS_PHASE_VOCODER,
15817 (char *)S_phase_vocoder,
15818 &free_phase_vocoder,
15819 &describe_phase_vocoder,
15820 &phase_vocoder_equalp,
15821 0, 0,
15822 &pv_length, 0,
15823 &pv_frequency,
15824 &pv_set_frequency,
15825 0, 0,
15826 0, 0,
15827 &pv_increment,
15828 &pv_set_increment,
15829 &run_phase_vocoder,
15830 MUS_NOT_SPECIAL,
15831 &pv_closure,
15832 0,
15833 0, 0, 0, 0, 0, 0,
15834 &pv_hop, &pv_set_hop,
15835 0, 0,
15836 0, 0, 0, 0,
15837 &pv_outctr, &pv_set_outctr,
15838 0, 0, 0, 0, 0,
15839 &pv_reset,
15840 &pv_set_closure,
15841 &pv_info_copy
15842 };
15843
15844
15845 static int pv_last_fftsize = -1;
15846 static mus_float_t *pv_last_window = NULL;
15847
mus_make_phase_vocoder(mus_float_t (* input)(void * arg,int direction),int fftsize,int overlap,int interp,mus_float_t pitch,bool (* analyze)(void * arg,mus_float_t (* input)(void * arg1,int direction)),int (* edit)(void * arg),mus_float_t (* synthesize)(void * arg),void * closure)15848 mus_any *mus_make_phase_vocoder(mus_float_t (*input)(void *arg, int direction),
15849 int fftsize, int overlap, int interp,
15850 mus_float_t pitch,
15851 bool (*analyze)(void *arg, mus_float_t (*input)(void *arg1, int direction)),
15852 int (*edit)(void *arg),
15853 mus_float_t (*synthesize)(void *arg),
15854 void *closure)
15855 {
15856 /* order of args is trying to match src, granulate etc
15857 * the inclusion of pitch and interp provides built-in time/pitch scaling which is 99% of phase-vocoder use
15858 */
15859 pv_info *pv;
15860 int N2, D;
15861
15862 N2 = (int)(fftsize / 2);
15863 if (N2 == 0) return(NULL);
15864 D = fftsize / overlap;
15865 if (D == 0) return(NULL);
15866
15867 pv = (pv_info *)malloc(sizeof(pv_info));
15868 pv->core = &PHASE_VOCODER_CLASS;
15869 pv->N = fftsize;
15870 pv->D = D;
15871 pv->topN = 0;
15872 pv->interp = interp;
15873 pv->outctr = interp;
15874 pv->filptr = 0;
15875 pv->pitch = pitch;
15876 pv->ampinc = (mus_float_t *)calloc(fftsize, sizeof(mus_float_t));
15877 pv->freqs = (mus_float_t *)calloc(fftsize, sizeof(mus_float_t));
15878 pv->amps = (mus_float_t *)calloc(N2, sizeof(mus_float_t));
15879 pv->phases = (mus_float_t *)calloc(N2, sizeof(mus_float_t));
15880 pv->lastphase = (mus_float_t *)calloc(N2, sizeof(mus_float_t));
15881 pv->phaseinc = (mus_float_t *)calloc(N2, sizeof(mus_float_t));
15882 pv->in_data = NULL;
15883 pv->input = input;
15884 pv->block_input = NULL;
15885 pv->closure = closure;
15886 pv->analyze = analyze;
15887 pv->edit = edit;
15888 pv->synthesize = synthesize;
15889 pv->calc = true;
15890
15891 if ((fftsize == pv_last_fftsize) && (pv_last_window))
15892 {
15893 pv->win = (mus_float_t *)malloc(fftsize * sizeof(mus_float_t));
15894 mus_copy_floats(pv->win, pv_last_window, fftsize);
15895 }
15896 else
15897 {
15898 int i;
15899 mus_float_t scl;
15900 if (pv_last_window) free(pv_last_window);
15901 pv_last_fftsize = fftsize;
15902 pv_last_window = (mus_float_t *)malloc(fftsize * sizeof(mus_float_t));
15903 pv->win = mus_make_fft_window(MUS_HAMMING_WINDOW, fftsize, 0.0);
15904 scl = 2.0 / (0.54 * (mus_float_t)fftsize);
15905 for (i = 0; i < fftsize; i++)
15906 pv->win[i] *= scl;
15907 mus_copy_floats(pv_last_window, pv->win, fftsize);
15908 }
15909
15910 #if HAVE_SINCOS
15911 /* in some cases, sincos is slower than sin+cos? Callgrind is seriously confused by it!
15912 * in Linux at least, sincos is faster than sin+sin -- in my timing tests, although
15913 * callgrind is crazy, the actual runtimes are about 25% faster (sincos vs sin+sin).
15914 */
15915 pv->cs = (double *)calloc(fftsize, sizeof(double));
15916 pv->sn = (double *)calloc(fftsize, sizeof(double));
15917 pv->sc_safe = (bool *)calloc(fftsize, sizeof(bool));
15918 pv->indices = (int *)calloc(N2, sizeof(int));
15919 #endif
15920 return((mus_any *)pv);
15921 }
15922
15923
mus_phase_vocoder_with_editors(mus_any * ptr,mus_float_t (* input)(void * arg,int direction),bool (* analyze)(void * arg,mus_float_t (* input)(void * arg1,int direction)),int (* edit)(void * arg),mus_float_t (* synthesize)(void * arg))15924 mus_float_t mus_phase_vocoder_with_editors(mus_any *ptr,
15925 mus_float_t (*input)(void *arg, int direction),
15926 bool (*analyze)(void *arg, mus_float_t (*input)(void *arg1, int direction)),
15927 int (*edit)(void *arg),
15928 mus_float_t (*synthesize)(void *arg))
15929 {
15930 pv_info *pv = (pv_info *)ptr;
15931 int N2, i;
15932 mus_float_t (*pv_synthesize)(void *arg) = synthesize;
15933
15934 if (!pv_synthesize) pv_synthesize = pv->synthesize;
15935 N2 = pv->N / 2;
15936
15937 if (pv->outctr >= pv->interp)
15938 {
15939 mus_float_t scl;
15940 bool (*pv_analyze)(void *arg, mus_float_t (*input)(void *arg1, int direction)) = analyze;
15941 int (*pv_edit)(void *arg) = edit;
15942
15943 if (!pv_analyze) pv_analyze = pv->analyze;
15944 if (!pv_edit) pv_edit = pv->edit;
15945 if (input) {pv->input = input; pv->block_input = NULL;}
15946 pv->outctr = 0;
15947
15948 if ((!pv_analyze) ||
15949 ((*pv_analyze)(pv->closure, pv->input)))
15950 {
15951 int buf;
15952 mus_clear_floats(pv->freqs, pv->N);
15953 if (!pv->in_data)
15954 {
15955 pv->in_data = (mus_float_t *)malloc(pv->N * sizeof(mus_float_t));
15956 if (pv->block_input)
15957 pv->block_input(pv->closure, 1, pv->in_data, 0, pv->N);
15958 else
15959 {
15960 for (i = 0; i < pv->N; i++)
15961 pv->in_data[i] = pv->input(pv->closure, 1);
15962 }
15963 }
15964 else
15965 {
15966 int j;
15967 /* if back-to-back here we could omit a lot of data movement or just use a circle here! */
15968 for (i = 0, j = pv->D; j < pv->N; i++, j++)
15969 pv->in_data[i] = pv->in_data[j];
15970
15971 if (pv->block_input)
15972 pv->block_input(pv->closure, 1, pv->in_data, pv->N - pv->D, pv->N);
15973 else
15974 {
15975 for (i = pv->N - pv->D; i < pv->N; i++)
15976 pv->in_data[i] = pv->input(pv->closure, 1);
15977 }
15978 }
15979 buf = pv->filptr % pv->N; /* filptr and N are both ints */
15980 for (i = 0; i < pv->N; i++)
15981 {
15982 pv->ampinc[buf++] = pv->win[i] * pv->in_data[i];
15983 if (buf >= pv->N) buf = 0;
15984 }
15985 pv->filptr += pv->D;
15986 mus_fft(pv->ampinc, pv->freqs, pv->N, 1);
15987 mus_rectangular_to_polar(pv->ampinc, pv->freqs, N2);
15988 }
15989
15990 if ((!pv_edit) ||
15991 ((*pv_edit)(pv->closure)))
15992 {
15993 mus_float_t pscl, kscl, ks;
15994 pscl = 1.0 / (mus_float_t)(pv->D);
15995 kscl = TWO_PI / (mus_float_t)(pv->N);
15996 for (i = 0, ks = 0.0; i < N2; i++, ks += kscl)
15997 {
15998 mus_float_t diff;
15999 diff = pv->freqs[i] - pv->lastphase[i];
16000 pv->lastphase[i] = pv->freqs[i];
16001
16002 /* this used to be two while loops adding/subtracting two pi, but that can get into an infinite loop
16003 * while (diff > M_PI) diff -= TWO_PI;
16004 * while (diff < -M_PI) diff += TWO_PI;
16005 * (anything to avoid fmod!)
16006 */
16007 if (diff > M_PI)
16008 {
16009 diff -= TWO_PI;
16010 if (diff > M_PI)
16011 diff = fmod(diff, TWO_PI);
16012 }
16013 if (diff < -M_PI)
16014 {
16015 diff += TWO_PI;
16016 if (diff < -M_PI)
16017 {
16018 diff = fmod(diff, TWO_PI);
16019 if (diff < -M_PI)
16020 diff += TWO_PI;
16021 }
16022 }
16023 pv->freqs[i] = pv->pitch * (diff * pscl + ks);
16024 }
16025 }
16026 /* it's possible to build the endpoint waveforms here and interpolate, but there is no savings.
16027 * other pvocs use ifft rather than sin-bank, but then they have to make excuses.
16028 * Something I didn't expect -- the algorithm above focusses on the active frequency!
16029 * For example, the 4 or so bins around a given peak all tighten
16030 * to 4 bins running at almost exactly the same frequency (the center).
16031 */
16032
16033 scl = 1.0 / (mus_float_t)(pv->interp);
16034 #if HAVE_SINCOS
16035 pv->topN = 0;
16036 #else
16037 pv->topN = N2;
16038 #endif
16039
16040 for (i = 0; i < N2; i++)
16041 {
16042 #if HAVE_SINCOS
16043 double s, c;
16044 bool amp_zero;
16045
16046 amp_zero = ((pv->amps[i] < 1e-7) && (pv->ampinc[i] == 0.0));
16047 if (!amp_zero)
16048 {
16049 pv->indices[pv->topN++] = i;
16050
16051 pv->sc_safe[i] = (fabs(pv->freqs[i] - pv->phaseinc[i]) < 0.02); /* .5 is too big, .01 and .03 ok by tests */
16052 if (pv->sc_safe[i])
16053 {
16054 sincos((pv->freqs[i] + pv->phaseinc[i]) * 0.5, &s, &c);
16055 pv->sn[i] = s;
16056 pv->cs[i] = c;
16057 }
16058 }
16059
16060 if ((!(pv->synthesize)) && (amp_zero))
16061 {
16062 pv->phases[i] += (pv->interp * (pv->freqs[i] + pv->phaseinc[i]) * 0.5);
16063 pv->phaseinc[i] = pv->freqs[i];
16064 }
16065 else
16066 {
16067 pv->ampinc[i] = scl * (pv->ampinc[i] - pv->amps[i]);
16068 pv->freqs[i] = scl * (pv->freqs[i] - pv->phaseinc[i]);
16069 }
16070 #else
16071 pv->ampinc[i] = scl * (pv->ampinc[i] - pv->amps[i]);
16072 pv->freqs[i] = scl * (pv->freqs[i] - pv->phaseinc[i]);
16073 #endif
16074 }
16075 }
16076
16077 pv->outctr++;
16078 if (pv_synthesize)
16079 return((*pv_synthesize)(pv->closure));
16080
16081 if (pv->calc)
16082 {
16083 mus_float_t sum, sum1;
16084 mus_float_t *pinc, *frq, *ph, *amp, *panc;
16085 int topN;
16086 #if HAVE_SINCOS
16087 int j;
16088 double *cs, *sn;
16089 #endif
16090
16091 topN = pv->topN;
16092 pinc = pv->phaseinc;
16093 frq = pv->freqs;
16094 ph = pv->phases;
16095 amp = pv->amps;
16096 panc = pv->ampinc;
16097 #if HAVE_SINCOS
16098 cs = pv->cs;
16099 sn = pv->sn;
16100 #endif
16101
16102 sum = 0.0;
16103 sum1 = 0.0;
16104
16105 /* amps can be negative here due to rounding troubles
16106 * sincos is faster (using shell time command) except in virtualbox running linux on a mac?
16107 * (callgrind does not handle sincos correctly).
16108 *
16109 * this version (22-Jan-14) is slower if no sincos;
16110 * if sincos, we use sin(a + b) = sin(a)cos(b) + cos(a)sin(b)
16111 * since sin(b) and cos(b) are constant through the pv->interp (implicit) loop, they are calculated once above.
16112 * Then here we calculate 2 samples on each run through this loop. I wonder if we could center the true case,
16113 * and get 3 samples? If 2, the difference is very small (we're taking the midpoint of the phase increment change,
16114 * so the two are not quite the same). In tests, 10000 samples, channel-distance is ca .15.
16115 *
16116 * If the amp zero phase is off (incorrectly incremented above), the effect is a sort of low-pass filter??
16117 * Are we getting cancellation from the overlap?
16118 */
16119 #if HAVE_SINCOS
16120 for (j = 0; j < topN; j++)
16121 {
16122 double sx, cx;
16123
16124 i = pv->indices[j];
16125 pinc[i] += frq[i];
16126 ph[i] += pinc[i];
16127 amp[i] += panc[i];
16128 sincos(ph[i], &sx, &cx);
16129 sum += (amp[i] * sx);
16130
16131 pinc[i] += frq[i];
16132 ph[i] += pinc[i];
16133 amp[i] += panc[i];
16134 if (pv->sc_safe[i])
16135 sum1 += amp[i] * (sx * cs[i] + cx * sn[i]);
16136 else sum1 += amp[i] * sin(ph[i]);
16137 }
16138 #else
16139 for (i = 0; i < topN; i++)
16140 {
16141 pinc[i] += frq[i];
16142 ph[i] += pinc[i];
16143 amp[i] += panc[i];
16144 if (amp[i] > 0.0) sum += amp[i] * sin(ph[i]);
16145
16146 pinc[i] += frq[i];
16147 ph[i] += pinc[i];
16148 amp[i] += panc[i];
16149 if (amp[i] > 0.0) sum1 += amp[i] * sin(ph[i]);
16150 }
16151 #endif
16152 pv->sum1 = sum1;
16153 pv->calc = false;
16154 return(sum);
16155 }
16156 pv->calc = true;
16157 return(pv->sum1);
16158 }
16159
16160
mus_phase_vocoder(mus_any * ptr,mus_float_t (* input)(void * arg,int direction))16161 mus_float_t mus_phase_vocoder(mus_any *ptr, mus_float_t (*input)(void *arg, int direction))
16162 {
16163 return(mus_phase_vocoder_with_editors(ptr, input, NULL, NULL, NULL));
16164 }
16165
16166
mus_generator_set_feeders(mus_any * g,mus_float_t (* feed)(void * arg,int direction),mus_float_t (* block_feed)(void * arg,int direction,mus_float_t * block,mus_long_t start,mus_long_t end))16167 void mus_generator_set_feeders(mus_any *g,
16168 mus_float_t (*feed)(void *arg, int direction),
16169 mus_float_t (*block_feed)(void *arg, int direction, mus_float_t *block, mus_long_t start, mus_long_t end))
16170 {
16171 if (mus_is_src(g))
16172 {
16173 ((sr *)g)->feeder = feed;
16174 ((sr *)g)->block_feeder = block_feed;
16175 }
16176 else
16177 {
16178 if (mus_is_granulate(g))
16179 {
16180 ((grn_info *)g)->rd = feed;
16181 ((grn_info *)g)->block_rd = block_feed;
16182 }
16183 else
16184 {
16185 if (mus_is_phase_vocoder(g))
16186 {
16187 ((pv_info *)g)->input = feed;
16188 ((pv_info *)g)->block_input = block_feed;
16189 }
16190 else
16191 {
16192 if (mus_is_convolve(g))
16193 {
16194 ((conv *)g)->feeder = feed;
16195 ((conv *)g)->block_feeder = block_feed;
16196 }
16197 }
16198 }
16199 }
16200 }
16201
mus_generator_copy_feeders(mus_any * dest,mus_any * source)16202 void mus_generator_copy_feeders(mus_any *dest, mus_any *source)
16203 {
16204 if (mus_is_src(dest))
16205 {
16206 ((sr *)dest)->feeder = ((sr *)source)->feeder;
16207 ((sr *)dest)->block_feeder = ((sr *)source)->block_feeder;
16208 }
16209 else
16210 {
16211 if (mus_is_granulate(dest))
16212 {
16213 ((grn_info *)dest)->rd = ((grn_info *)source)->rd;
16214 ((grn_info *)dest)->block_rd = ((grn_info *)source)->block_rd;
16215 }
16216 else
16217 {
16218 if (mus_is_phase_vocoder(dest))
16219 {
16220 ((pv_info *)dest)->input = ((pv_info *)source)->input;
16221 ((pv_info *)dest)->block_input = ((pv_info *)source)->block_input;
16222 }
16223 else
16224 {
16225 if (mus_is_convolve(dest))
16226 {
16227 ((conv *)dest)->feeder = ((conv *)source)->feeder;
16228 ((conv *)dest)->block_feeder = ((conv *)source)->block_feeder;
16229 }
16230 }
16231 }
16232 }
16233 }
16234
16235
16236
16237 /* ---------------- single sideband "suppressed carrier" amplitude modulation (ssb-am) ---------------- */
16238
16239 typedef struct {
16240 mus_any_class *core;
16241 bool shift_up;
16242 mus_float_t *coeffs;
16243 mus_any *hilbert, *dly;
16244 #if (!HAVE_SINCOS)
16245 mus_any *sin_osc, *cos_osc;
16246 #else
16247 double phase, freq, sign;
16248 #endif
16249 int size;
16250 } ssbam;
16251
16252
mus_is_ssb_am(mus_any * ptr)16253 bool mus_is_ssb_am(mus_any *ptr)
16254 {
16255 return((ptr) &&
16256 (ptr->core->type == MUS_SSB_AM));
16257 }
16258
run_hilbert(flt * gen,mus_float_t input)16259 static mus_float_t run_hilbert(flt *gen, mus_float_t input)
16260 {
16261 mus_float_t xout = 0.0;
16262 mus_float_t *state, *ts, *x, *end;
16263
16264 x = (mus_float_t *)(gen->x);
16265 state = (mus_float_t *)(gen->state + gen->loc);
16266 ts = (mus_float_t *)(state + gen->order);
16267
16268 (*state) = input;
16269 (*ts) = input;
16270 state += 2;
16271 end = (mus_float_t *)(state + 20);
16272
16273 while (ts > end)
16274 {
16275 xout += (*ts) * (*x); ts -= 2; x += 2;
16276 xout += (*ts) * (*x); ts -= 2; x += 2;
16277 xout += (*ts) * (*x); ts -= 2; x += 2;
16278 xout += (*ts) * (*x); ts -= 2; x += 2;
16279 xout += (*ts) * (*x); ts -= 2; x += 2;
16280 xout += (*ts) * (*x); ts -= 2; x += 2;
16281 xout += (*ts) * (*x); ts -= 2; x += 2;
16282 xout += (*ts) * (*x); ts -= 2; x += 2;
16283 xout += (*ts) * (*x); ts -= 2; x += 2;
16284 xout += (*ts) * (*x); ts -= 2; x += 2;
16285 }
16286 while (ts > state)
16287 {
16288 xout += (*ts) * (*x); ts -= 2; x += 2;
16289 }
16290
16291 gen->loc++;
16292 if (gen->loc == gen->order)
16293 gen->loc = 0;
16294
16295 return(xout + ((*ts) * (*x)));
16296 #if 0
16297 int i, len;
16298 mus_float_t val = 0.0;
16299 len = g->order;
16300 g->state[0] = insig;
16301 for (i = 0; i < len; i += 2) val += (g->x[i] * g->state[i]);
16302 for (i = len - 1; i >= 1; i--) g->state[i] = g->state[i - 1];
16303 return(val);
16304 #endif
16305 }
16306
16307
mus_ssb_am_unmodulated(mus_any * ptr,mus_float_t insig)16308 mus_float_t mus_ssb_am_unmodulated(mus_any *ptr, mus_float_t insig)
16309 {
16310 ssbam *gen = (ssbam *)ptr;
16311 #if (!HAVE_SINCOS)
16312 return((mus_oscil_unmodulated(gen->cos_osc) * mus_delay_unmodulated_noz(gen->dly, insig)) +
16313 (mus_oscil_unmodulated(gen->sin_osc) * run_hilbert((flt *)(gen->hilbert), insig)));
16314 #else
16315 double cx, sx;
16316 sincos(gen->phase, &sx, &cx);
16317 gen->phase += gen->freq;
16318 return((cx * mus_delay_unmodulated_noz(gen->dly, insig)) +
16319 (sx * gen->sign * run_hilbert((flt *)(gen->hilbert), insig)));
16320 #endif
16321 }
16322
16323
mus_ssb_am(mus_any * ptr,mus_float_t insig,mus_float_t fm)16324 mus_float_t mus_ssb_am(mus_any *ptr, mus_float_t insig, mus_float_t fm)
16325 {
16326 ssbam *gen = (ssbam *)ptr;
16327 #if (!HAVE_SINCOS)
16328 return((mus_oscil_fm(gen->cos_osc, fm) * mus_delay_unmodulated_noz(gen->dly, insig)) +
16329 (mus_oscil_fm(gen->sin_osc, fm) * run_hilbert((flt *)(gen->hilbert), insig)));
16330 #else
16331 double cx, sx;
16332 sincos(gen->phase, &sx, &cx);
16333 gen->phase += (fm + gen->freq);
16334 return((cx * mus_delay_unmodulated_noz(gen->dly, insig)) +
16335 (sx * gen->sign * run_hilbert((flt *)(gen->hilbert), insig)));
16336 #endif
16337 }
16338
16339
free_ssb_am(mus_any * ptr)16340 static void free_ssb_am(mus_any *ptr)
16341 {
16342 ssbam *gen = (ssbam *)ptr;
16343 mus_free(gen->dly);
16344 mus_free(gen->hilbert);
16345 #if (!HAVE_SINCOS)
16346 mus_free(gen->cos_osc);
16347 mus_free(gen->sin_osc);
16348 #endif
16349 if (gen->coeffs) {free(gen->coeffs); gen->coeffs = NULL;}
16350 free(ptr);
16351 }
16352
16353
ssbam_copy(mus_any * ptr)16354 static mus_any *ssbam_copy(mus_any *ptr)
16355 {
16356 ssbam *g, *p;
16357 int bytes;
16358
16359 p = (ssbam *)ptr;
16360 g = (ssbam *)malloc(sizeof(ssbam));
16361 memcpy((void *)g, (void *)ptr, sizeof(ssbam));
16362
16363 g->dly = mus_copy(p->dly);
16364 g->hilbert = mus_copy(p->hilbert);
16365 #if (!HAVE_SINCOS)
16366 g->cos_osc = mus_copy(p->cos_osc);
16367 g->sin_osc = mus_copy(p->sin_osc);
16368 #endif
16369
16370 bytes = p->size * sizeof(mus_float_t);
16371 g->coeffs = (mus_float_t *)malloc(bytes);
16372 mus_copy_floats(g->coeffs, p->coeffs, p->size);
16373
16374 return((mus_any *)g);
16375 }
16376
16377
ssb_am_freq(mus_any * ptr)16378 static mus_float_t ssb_am_freq(mus_any *ptr)
16379 {
16380 #if (!HAVE_SINCOS)
16381 return(mus_radians_to_hz(((osc *)((ssbam *)ptr)->sin_osc)->freq));
16382 #else
16383 return(mus_radians_to_hz(((ssbam *)ptr)->freq));
16384 #endif
16385 }
16386
16387
ssb_am_set_freq(mus_any * ptr,mus_float_t val)16388 static mus_float_t ssb_am_set_freq(mus_any *ptr, mus_float_t val)
16389 {
16390 ssbam *gen = (ssbam *)ptr;
16391 mus_float_t rads;
16392 rads = mus_hz_to_radians(val);
16393 #if (!HAVE_SINCOS)
16394 ((osc *)(gen->sin_osc))->freq = rads;
16395 ((osc *)(gen->cos_osc))->freq = rads;
16396 #else
16397 gen->freq = rads;
16398 #endif
16399 return(val);
16400 }
16401
16402
ssb_am_increment(mus_any * ptr)16403 static mus_float_t ssb_am_increment(mus_any *ptr)
16404 {
16405 #if (!HAVE_SINCOS)
16406 return(((osc *)((ssbam *)ptr)->sin_osc)->freq);
16407 #else
16408 return(((ssbam *)ptr)->freq);
16409 #endif
16410 }
16411
16412
ssb_am_set_increment(mus_any * ptr,mus_float_t val)16413 static mus_float_t ssb_am_set_increment(mus_any *ptr, mus_float_t val)
16414 {
16415 ssbam *gen = (ssbam *)ptr;
16416 #if (!HAVE_SINCOS)
16417 ((osc *)(gen->sin_osc))->freq = val;
16418 ((osc *)(gen->cos_osc))->freq = val;
16419 #else
16420 gen->freq = val;
16421 #endif
16422 return(val);
16423 }
16424
16425
ssb_am_phase(mus_any * ptr)16426 static mus_float_t ssb_am_phase(mus_any *ptr)
16427 {
16428 #if (!HAVE_SINCOS)
16429 return(fmod(((osc *)((ssbam *)ptr)->cos_osc)->phase - 0.5 * M_PI, TWO_PI));
16430 #else
16431 return(fmod(((ssbam *)ptr)->phase, TWO_PI));
16432 #endif
16433 }
16434
16435
ssb_am_set_phase(mus_any * ptr,mus_float_t val)16436 static mus_float_t ssb_am_set_phase(mus_any *ptr, mus_float_t val)
16437 {
16438 ssbam *gen = (ssbam *)ptr;
16439 #if (!HAVE_SINCOS)
16440 if (gen->shift_up)
16441 ((osc *)(gen->sin_osc))->phase = val + M_PI;
16442 else ((osc *)(gen->sin_osc))->phase = val;
16443 ((osc *)(gen->cos_osc))->phase = val + 0.5 * M_PI;
16444 #else
16445 gen->phase = val;
16446 #endif
16447 return(val);
16448 }
16449
16450
ssb_am_order(mus_any * ptr)16451 static mus_long_t ssb_am_order(mus_any *ptr) {return(mus_order(((ssbam *)ptr)->dly));}
16452
ssb_am_interp_type(mus_any * ptr)16453 static int ssb_am_interp_type(mus_any *ptr) {return(delay_interp_type(((ssbam *)ptr)->dly));}
16454
ssb_am_data(mus_any * ptr)16455 static mus_float_t *ssb_am_data(mus_any *ptr) {return(filter_data(((ssbam *)ptr)->hilbert));}
ssb_am_run(mus_any * ptr,mus_float_t insig,mus_float_t fm)16456 static mus_float_t ssb_am_run(mus_any *ptr, mus_float_t insig, mus_float_t fm) {return(mus_ssb_am(ptr, insig, fm));}
16457
ssb_am_xcoeffs(mus_any * ptr)16458 static mus_float_t *ssb_am_xcoeffs(mus_any *ptr) {return(mus_xcoeffs(((ssbam *)ptr)->hilbert));}
ssb_am_xcoeff(mus_any * ptr,int index)16459 static mus_float_t ssb_am_xcoeff(mus_any *ptr, int index) {return(mus_xcoeff(((ssbam *)ptr)->hilbert, index));}
ssb_am_set_xcoeff(mus_any * ptr,int index,mus_float_t val)16460 static mus_float_t ssb_am_set_xcoeff(mus_any *ptr, int index, mus_float_t val) {return(mus_set_xcoeff(((ssbam *)ptr)->hilbert, index, val));}
16461
16462
ssb_am_equalp(mus_any * p1,mus_any * p2)16463 static bool ssb_am_equalp(mus_any *p1, mus_any *p2)
16464 {
16465 return((p1 == p2) ||
16466 ((mus_is_ssb_am((mus_any *)p1)) &&
16467 (mus_is_ssb_am((mus_any *)p2)) &&
16468 (((ssbam *)p1)->shift_up == ((ssbam *)p2)->shift_up) &&
16469 #if (!HAVE_SINCOS)
16470 (mus_equalp(((ssbam *)p1)->sin_osc, ((ssbam *)p2)->sin_osc)) &&
16471 (mus_equalp(((ssbam *)p1)->cos_osc, ((ssbam *)p2)->cos_osc)) &&
16472 #else
16473 (((ssbam *)p1)->freq == ((ssbam *)p2)->freq) &&
16474 (((ssbam *)p1)->phase == ((ssbam *)p2)->phase) &&
16475 #endif
16476 (mus_equalp(((ssbam *)p1)->dly, ((ssbam *)p2)->dly)) &&
16477 (mus_equalp(((ssbam *)p1)->hilbert, ((ssbam *)p2)->hilbert))));
16478 }
16479
16480
describe_ssb_am(mus_any * ptr)16481 static char *describe_ssb_am(mus_any *ptr)
16482 {
16483 ssbam *gen = (ssbam *)ptr;
16484 char *describe_buffer;
16485 describe_buffer = (char *)malloc(DESCRIBE_BUFFER_SIZE);
16486 snprintf(describe_buffer, DESCRIBE_BUFFER_SIZE, "%s shift: %s, sin/cos: %f Hz (%f radians), order: %d",
16487 mus_name(ptr),
16488 (gen->shift_up) ? "up" : "down",
16489 mus_frequency(ptr),
16490 mus_phase(ptr),
16491 (int)mus_order(ptr));
16492 return(describe_buffer);
16493 }
16494
16495
ssb_reset(mus_any * ptr)16496 static void ssb_reset(mus_any *ptr)
16497 {
16498 ssbam *gen = (ssbam *)ptr;
16499 ssb_am_set_phase(ptr, 0.0);
16500 mus_reset(gen->dly);
16501 mus_reset(gen->hilbert);
16502 }
16503
16504
16505 static mus_any_class SSB_AM_CLASS = {
16506 MUS_SSB_AM,
16507 (char *)S_ssb_am,
16508 &free_ssb_am,
16509 &describe_ssb_am,
16510 &ssb_am_equalp,
16511 &ssb_am_data, 0,
16512 &ssb_am_order, 0,
16513 &ssb_am_freq,
16514 &ssb_am_set_freq,
16515 &ssb_am_phase,
16516 &ssb_am_set_phase,
16517 &fallback_scaler, 0,
16518 &ssb_am_increment,
16519 &ssb_am_set_increment,
16520 &ssb_am_run,
16521 MUS_NOT_SPECIAL,
16522 NULL,
16523 &ssb_am_interp_type,
16524 0, 0, 0, 0,
16525 &ssb_am_xcoeff, &ssb_am_set_xcoeff,
16526 0, 0, 0, 0,
16527 0, 0, 0, 0, 0, 0, 0,
16528 0, 0,
16529 &ssb_am_xcoeffs, 0,
16530 &ssb_reset,
16531 0, &ssbam_copy
16532 };
16533
16534
16535 static int ssb_am_last_flen = -1;
16536 static mus_float_t *ssb_am_last_coeffs = NULL;
16537
mus_make_ssb_am(mus_float_t freq,int order)16538 mus_any *mus_make_ssb_am(mus_float_t freq, int order)
16539 {
16540 ssbam *gen;
16541 int len, flen;
16542
16543 if ((order & 1) == 0) order++; /* if order is even, the first Hilbert coeff is 0.0 */
16544 gen = (ssbam *)malloc(sizeof(ssbam));
16545 gen->core = &SSB_AM_CLASS;
16546
16547 if (freq > 0)
16548 gen->shift_up = true;
16549 else gen->shift_up = false;
16550 #if (!HAVE_SINCOS)
16551 gen->sin_osc = mus_make_oscil(fabs(freq), (gen->shift_up) ? M_PI : 0.0);
16552 gen->cos_osc = mus_make_oscil(fabs(freq), M_PI * 0.5);
16553 #else
16554 if (gen->shift_up) gen->sign = -1.0; else gen->sign = 1.0;
16555 gen->freq = mus_hz_to_radians(fabs(freq));
16556 gen->phase = 0.0;
16557 #endif
16558 gen->dly = mus_make_delay(order, NULL, order, MUS_INTERP_NONE);
16559
16560 len = order * 2 + 1;
16561 flen = len + 1; /* even -- need 4 */
16562 if ((flen & 2) != 0) flen += 2;
16563 gen->size = flen;
16564
16565 if ((flen == ssb_am_last_flen) && (ssb_am_last_coeffs))
16566 {
16567 gen->coeffs = (mus_float_t *)malloc(flen * sizeof(mus_float_t));
16568 mus_copy_floats(gen->coeffs, ssb_am_last_coeffs, flen);
16569 }
16570 else
16571 {
16572 int i, k;
16573 gen->coeffs = (mus_float_t *)calloc(flen, sizeof(mus_float_t));
16574 for (i = -order, k = 0; i <= order; i++, k++)
16575 {
16576 mus_float_t denom, num;
16577 denom = i * M_PI;
16578 num = 1.0 - cos(denom);
16579 if (i == 0)
16580 gen->coeffs[k] = 0.0;
16581 else gen->coeffs[k] = (num / denom) * (0.54 + (0.46 * cos(denom / order)));
16582 }
16583 /* so odd numbered coeffs are zero */
16584
16585 /* can't be too fancy here because there might be several of these gens running in parallel at different sizes */
16586 if (ssb_am_last_coeffs) free(ssb_am_last_coeffs);
16587 ssb_am_last_flen = flen;
16588 ssb_am_last_coeffs = (mus_float_t *)malloc(flen * sizeof(mus_float_t));
16589 mus_copy_floats(ssb_am_last_coeffs, gen->coeffs, flen);
16590 }
16591
16592 gen->hilbert = mus_make_fir_filter(flen, gen->coeffs, NULL);
16593 return((mus_any *)gen);
16594 }
16595
16596 /* (define (hi) (let ((g (make-ssb-am 100.0))) (ssb-am g 1.0) (ssb-am g 0.0))) */
16597
16598
16599
16600
16601
16602 /* ---------------- mus-apply ---------------- */
16603
mus_run_function(mus_any * g)16604 mus_float_t (*mus_run_function(mus_any *g))(mus_any *gen, mus_float_t arg1, mus_float_t arg2)
16605 {
16606 if (g)
16607 return(g->core->run);
16608 return(NULL);
16609 }
16610
mus_run1_function(mus_any * g)16611 mus_float_t (*mus_run1_function(mus_any *g))(mus_any *gen, mus_float_t arg)
16612 {
16613 if (g)
16614 {
16615 switch (g->core->type)
16616 {
16617 case MUS_FILTER:
16618 case MUS_FIR_FILTER:
16619 case MUS_IIR_FILTER: return(((flt *)g)->filtw);
16620
16621 case MUS_FORMANT: return(mus_formant);
16622 case MUS_FIRMANT: return(mus_firmant);
16623
16624 case MUS_ONE_POLE: return(mus_one_pole);
16625 case MUS_ONE_ZERO: return(mus_one_zero);
16626 case MUS_TWO_POLE: return(mus_two_pole);
16627 case MUS_TWO_ZERO: return(mus_two_zero);
16628 case MUS_ONE_POLE_ALL_PASS: return(((onepall *)g)->f);
16629
16630 case MUS_DELAY: return(mus_delay_unmodulated);
16631 case MUS_COMB: return(mus_comb_unmodulated);
16632 case MUS_NOTCH: return(mus_notch_unmodulated);
16633 case MUS_ALL_PASS: return(mus_all_pass_unmodulated);
16634
16635 case MUS_TRIANGLE_WAVE: return(mus_triangle_wave);
16636 case MUS_SAWTOOTH_WAVE: return(mus_sawtooth_wave);
16637 case MUS_SQUARE_WAVE: return(mus_square_wave);
16638 case MUS_PULSE_TRAIN: return(mus_pulse_train);
16639 case MUS_PULSED_ENV: return(mus_pulsed_env);
16640
16641 case MUS_OSCIL: return(mus_oscil_fm);
16642 case MUS_NCOS: return(mus_ncos);
16643 case MUS_NSIN: return(mus_nsin);
16644 case MUS_NRXYCOS: return(mus_ncos);
16645 case MUS_NRXYSIN: return(mus_nsin);
16646 case MUS_RXYKCOS: return(mus_ncos);
16647 case MUS_RXYKSIN: return(mus_nsin);
16648
16649 case MUS_TABLE_LOOKUP: return(((tbl *)g)->tbl_look);
16650 case MUS_POLYWAVE: return(((pw *)g)->polyw);
16651
16652 case MUS_WAVE_TRAIN: return(mus_wave_train);
16653 case MUS_COMB_BANK: return(((cmb_bank *)g)->cmbf);
16654 case MUS_ALL_PASS_BANK: return(((allp_bank *)g)->apf);
16655 case MUS_FILTERED_COMB_BANK: return(((fltcmb_bank *)g)->cmbf);
16656 case MUS_FORMANT_BANK: return(((frm_bank *)g)->one_input);
16657
16658 case MUS_MOVING_AVERAGE: return(mus_moving_average);
16659 case MUS_MOVING_MAX: return(mus_moving_max);
16660 case MUS_MOVING_NORM: return(mus_moving_norm);
16661
16662 case MUS_RAND: return(mus_rand);
16663 case MUS_RAND_INTERP: return(mus_rand_interp);
16664
16665 case MUS_SSB_AM: return(mus_ssb_am_unmodulated);
16666 }
16667 }
16668 return(NULL);
16669 }
16670
mus_apply(mus_any * gen,mus_float_t f1,mus_float_t f2)16671 mus_float_t mus_apply(mus_any *gen, mus_float_t f1, mus_float_t f2)
16672 {
16673 /* what about non-gen funcs such as polynomial, ring_modulate etc? */
16674 if ((gen) && (gen->core->run))
16675 return((*(gen->core->run))(gen, f1, f2));
16676 return(0.0);
16677 }
16678
16679
16680 /* ---------------- mix files ---------------- */
16681
16682 /* a mixing "instrument" along the lines of the mix function in clm */
16683 /* this is a very commonly used function, so it's worth picking out the special cases for optimization */
16684
16685 #define IDENTITY_MIX 0
16686 #define IDENTITY_MONO_MIX 1
16687 #define SCALED_MONO_MIX 2
16688 #define SCALED_MIX 3
16689 #define ENVELOPED_MONO_MIX 4
16690 #define ENVELOPED_MIX 5
16691 #define ALL_MIX 6
16692
mix_file_type(int out_chans,int in_chans,mus_float_t * mx,mus_any *** envs)16693 static int mix_file_type(int out_chans, int in_chans, mus_float_t *mx, mus_any ***envs)
16694 {
16695 if (envs)
16696 {
16697 if ((in_chans == 1) && (out_chans == 1))
16698 {
16699 if (envs[0][0])
16700 return(ENVELOPED_MONO_MIX);
16701 return(SCALED_MONO_MIX);
16702 }
16703 else
16704 {
16705 if (mx)
16706 return(ALL_MIX);
16707 return(ENVELOPED_MIX);
16708 }
16709 }
16710 if (mx)
16711 {
16712 int i, j;
16713 if ((in_chans == 1) && (out_chans == 1))
16714 {
16715 if (mx[0] == 1.0)
16716 return(IDENTITY_MONO_MIX);
16717 return(SCALED_MONO_MIX);
16718 }
16719 for (i = 0; i < out_chans; i++)
16720 for (j = 0; j < in_chans; j++)
16721 if (((i == j) && (mx[i * in_chans + j] != 1.0)) ||
16722 ((i != j) && (mx[i * in_chans + j] != 0.0)))
16723 return(SCALED_MIX);
16724 }
16725 if ((in_chans == 1) && (out_chans == 1))
16726 return(IDENTITY_MONO_MIX);
16727 return(IDENTITY_MIX);
16728 }
16729
16730
mus_file_mix_with_reader_and_writer(mus_any * outf,mus_any * inf,mus_long_t out_start,mus_long_t out_framples,mus_long_t in_start,mus_float_t * mx,int mx_chans,mus_any *** envs)16731 void mus_file_mix_with_reader_and_writer(mus_any *outf, mus_any *inf,
16732 mus_long_t out_start, mus_long_t out_framples, mus_long_t in_start,
16733 mus_float_t *mx, int mx_chans,
16734 mus_any ***envs)
16735 {
16736 int mixtype, in_chans, out_chans;
16737 mus_long_t inc, outc, out_end;
16738 mus_float_t *out_data, *in_data, *local_mx;
16739
16740 out_chans = mus_channels(outf);
16741 if (out_chans <= 0)
16742 mus_error(MUS_NO_CHANNELS, S_mus_file_mix ": %s chans: %d", mus_describe(outf), out_chans);
16743
16744 in_chans = mus_channels(inf);
16745 if (in_chans <= 0)
16746 mus_error(MUS_NO_CHANNELS, S_mus_file_mix ": %s chans: %d", mus_describe(inf), in_chans);
16747
16748 out_end = out_start + out_framples;
16749 mixtype = mix_file_type(out_chans, in_chans, mx, envs);
16750
16751 in_data = (mus_float_t *)calloc((in_chans < out_chans) ? out_chans : in_chans, sizeof(mus_float_t));
16752 out_data = (mus_float_t *)calloc((in_chans < out_chans) ? out_chans : in_chans, sizeof(mus_float_t));
16753
16754 local_mx = mx;
16755
16756 switch (mixtype)
16757 {
16758 case ENVELOPED_MONO_MIX:
16759 {
16760 mus_any *e;
16761 e = envs[0][0];
16762 for (inc = in_start, outc = out_start; outc < out_end; inc++, outc++)
16763 {
16764 mus_file_to_frample(inf, inc, in_data);
16765 mus_outa_to_file(outf, outc, in_data[0] * mus_env(e));
16766 }
16767 }
16768 break;
16769
16770 case ENVELOPED_MIX:
16771 if (!mx)
16772 {
16773 int i;
16774 mx_chans = (in_chans < out_chans) ? out_chans : in_chans;
16775 local_mx = (mus_float_t *)calloc(mx_chans * mx_chans, sizeof(mus_float_t));
16776 for (i = 0; i < mx_chans; i++)
16777 local_mx[i * mx_chans + i] = 1.0;
16778 }
16779 /* fall through */
16780
16781 case ALL_MIX:
16782 /* the general case -- possible envs/scalers on every mixer cell */
16783 for (inc = in_start, outc = out_start; outc < out_end; inc++, outc++)
16784 {
16785 int j, k;
16786 for (j = 0; j < in_chans; j++)
16787 for (k = 0; k < out_chans; k++)
16788 if (envs[j][k])
16789 local_mx[j * mx_chans + k] = mus_env(envs[j][k]);
16790 mus_frample_to_file(outf, outc, mus_frample_to_frample(local_mx, mx_chans, mus_file_to_frample(inf, inc, in_data), in_chans, out_data, out_chans));
16791 }
16792 if (!mx) free(local_mx);
16793 break;
16794
16795 case IDENTITY_MONO_MIX:
16796 for (inc = in_start, outc = out_start; outc < out_end; inc++, outc++)
16797 {
16798 mus_file_to_frample(inf, inc, in_data);
16799 mus_outa_to_file(outf, outc, in_data[0]);
16800 }
16801 break;
16802
16803 case IDENTITY_MIX:
16804 for (inc = in_start, outc = out_start; outc < out_end; inc++, outc++)
16805 mus_frample_to_file(outf, outc, mus_file_to_frample(inf, inc, in_data));
16806 break;
16807
16808 case SCALED_MONO_MIX:
16809 {
16810 mus_float_t scl;
16811 scl = mx[0];
16812 for (inc = in_start, outc = out_start; outc < out_end; inc++, outc++)
16813 {
16814 mus_file_to_frample(inf, inc, in_data);
16815 mus_outa_to_file(outf, outc, scl * in_data[0]);
16816 }
16817 }
16818 break;
16819
16820 case SCALED_MIX:
16821 for (inc = in_start, outc = out_start; outc < out_end; inc++, outc++)
16822 mus_frample_to_file(outf, outc, mus_frample_to_frample(mx, mx_chans, mus_file_to_frample(inf, inc, in_data), in_chans, out_data, out_chans));
16823 break;
16824
16825 }
16826 free(in_data);
16827 free(out_data);
16828 }
16829
16830
mus_file_mix(const char * outfile,const char * infile,mus_long_t out_start,mus_long_t out_framples,mus_long_t in_start,mus_float_t * mx,int mx_chans,mus_any *** envs)16831 void mus_file_mix(const char *outfile, const char *infile,
16832 mus_long_t out_start, mus_long_t out_framples, mus_long_t in_start,
16833 mus_float_t *mx, int mx_chans,
16834 mus_any ***envs)
16835 {
16836 int in_chans, out_chans, min_chans, mixtype;
16837
16838 out_chans = mus_sound_chans(outfile);
16839 if (out_chans <= 0)
16840 mus_error(MUS_NO_CHANNELS, S_mus_file_mix ": %s chans: %d", outfile, out_chans);
16841
16842 in_chans = mus_sound_chans(infile);
16843 if (in_chans <= 0)
16844 mus_error(MUS_NO_CHANNELS, S_mus_file_mix ": %s chans: %d", infile, in_chans);
16845 if (out_chans > in_chans)
16846 min_chans = in_chans;
16847 else min_chans = out_chans;
16848
16849 mixtype = mix_file_type(out_chans, in_chans, mx, envs);
16850 if (mixtype == ALL_MIX)
16851 {
16852 mus_any *inf, *outf;
16853 /* the general case -- possible envs/scalers on every mixer cell */
16854 outf = mus_continue_sample_to_file(outfile);
16855 inf = mus_make_file_to_frample(infile);
16856 mus_file_mix_with_reader_and_writer(outf, inf, out_start, out_framples, in_start, mx, mx_chans, envs);
16857 mus_free(inf);
16858 mus_free(outf);
16859 }
16860 else
16861 {
16862 mus_long_t j = 0;
16863 int i, m, ofd, ifd;
16864 mus_float_t scaler;
16865 mus_any *e;
16866 mus_float_t **obufs, **ibufs;
16867 mus_long_t offk, curoutframples;
16868
16869 /* highly optimizable cases */
16870 obufs = (mus_float_t **)malloc(out_chans * sizeof(mus_float_t *));
16871 for (i = 0; i < out_chans; i++)
16872 obufs[i] = (mus_float_t *)malloc(clm_file_buffer_size * sizeof(mus_float_t));
16873
16874 ibufs = (mus_float_t **)malloc(in_chans * sizeof(mus_float_t *));
16875 for (i = 0; i < in_chans; i++)
16876 ibufs[i] = (mus_float_t *)malloc(clm_file_buffer_size * sizeof(mus_float_t));
16877
16878 ifd = mus_sound_open_input(infile);
16879 mus_file_seek_frample(ifd, in_start);
16880 mus_file_read(ifd, in_start, clm_file_buffer_size, in_chans, ibufs);
16881 ofd = mus_sound_reopen_output(outfile,
16882 out_chans,
16883 mus_sound_sample_type(outfile),
16884 mus_sound_header_type(outfile),
16885 mus_sound_data_location(outfile));
16886 curoutframples = mus_sound_framples(outfile);
16887 mus_file_seek_frample(ofd, out_start);
16888 mus_file_read(ofd, out_start, clm_file_buffer_size, out_chans, obufs);
16889 mus_file_seek_frample(ofd, out_start);
16890
16891 switch (mixtype)
16892 {
16893 case IDENTITY_MONO_MIX:
16894 for (offk = 0, j = 0; offk < out_framples; offk++, j++)
16895 {
16896 if (j == clm_file_buffer_size)
16897 {
16898 mus_file_write(ofd, 0, j - 1, out_chans, obufs);
16899 j = 0;
16900 mus_file_seek_frample(ofd, out_start + offk);
16901 mus_file_read(ofd, out_start + offk, clm_file_buffer_size, out_chans, obufs);
16902 mus_file_seek_frample(ofd, out_start + offk);
16903 mus_file_read(ifd, in_start + offk, clm_file_buffer_size, in_chans, ibufs);
16904 }
16905 obufs[0][j] += ibufs[0][j];
16906 }
16907 break;
16908
16909 case IDENTITY_MIX:
16910 for (offk = 0, j = 0; offk < out_framples; offk++, j++)
16911 {
16912 if (j == clm_file_buffer_size)
16913 {
16914 mus_file_write(ofd, 0, j - 1, out_chans, obufs);
16915 j = 0;
16916 mus_file_seek_frample(ofd, out_start + offk);
16917 mus_file_read(ofd, out_start + offk, clm_file_buffer_size, out_chans, obufs);
16918 mus_file_seek_frample(ofd, out_start + offk);
16919 mus_file_read(ifd, in_start + offk, clm_file_buffer_size, in_chans, ibufs);
16920 }
16921 for (i = 0; i < min_chans; i++)
16922 obufs[i][j] += ibufs[i][j];
16923 }
16924 break;
16925
16926 case SCALED_MONO_MIX:
16927 scaler = mx[0];
16928 for (offk = 0, j = 0; offk < out_framples; offk++, j++)
16929 {
16930 if (j == clm_file_buffer_size)
16931 {
16932 mus_file_write(ofd, 0, j - 1, out_chans, obufs);
16933 j = 0;
16934 mus_file_seek_frample(ofd, out_start + offk);
16935 mus_file_read(ofd, out_start + offk, clm_file_buffer_size, out_chans, obufs);
16936 mus_file_seek_frample(ofd, out_start + offk);
16937 mus_file_read(ifd, in_start + offk, clm_file_buffer_size, in_chans, ibufs);
16938 }
16939 obufs[0][j] += (mus_float_t)(scaler * ibufs[0][j]);
16940 }
16941 break;
16942
16943 case SCALED_MIX:
16944 for (offk = 0, j = 0; offk < out_framples; offk++, j++)
16945 {
16946 if (j == clm_file_buffer_size)
16947 {
16948 mus_file_write(ofd, 0, j - 1, out_chans, obufs);
16949 j = 0;
16950 mus_file_seek_frample(ofd, out_start + offk);
16951 mus_file_read(ofd, out_start + offk, clm_file_buffer_size , out_chans, obufs);
16952 mus_file_seek_frample(ofd, out_start + offk);
16953 mus_file_read(ifd, in_start + offk, clm_file_buffer_size, in_chans, ibufs);
16954 }
16955 for (i = 0; i < min_chans; i++)
16956 for (m = 0; m < in_chans; m++)
16957 obufs[i][j] += (mus_float_t)(ibufs[m][j] * mx[m * mx_chans + i]);
16958 }
16959 break;
16960
16961 case ENVELOPED_MONO_MIX:
16962 e = envs[0][0];
16963 for (offk = 0, j = 0; offk < out_framples; offk++, j++)
16964 {
16965 if (j == clm_file_buffer_size)
16966 {
16967 mus_file_write(ofd, 0, j - 1, out_chans, obufs);
16968 j = 0;
16969 mus_file_seek_frample(ofd, out_start + offk);
16970 mus_file_read(ofd, out_start + offk, clm_file_buffer_size, out_chans, obufs);
16971 mus_file_seek_frample(ofd, out_start + offk);
16972 mus_file_read(ifd, in_start + offk, clm_file_buffer_size, in_chans, ibufs);
16973 }
16974 obufs[0][j] += (mus_float_t)(mus_env(e) * ibufs[0][j]);
16975 }
16976 break;
16977
16978 case ENVELOPED_MIX:
16979 e = envs[0][0];
16980 for (offk = 0, j = 0; offk < out_framples; offk++, j++)
16981 {
16982 if (j == clm_file_buffer_size)
16983 {
16984 mus_file_write(ofd, 0, j - 1, out_chans, obufs);
16985 j = 0;
16986 mus_file_seek_frample(ofd, out_start + offk);
16987 mus_file_read(ofd, out_start + offk, clm_file_buffer_size, out_chans, obufs);
16988 mus_file_seek_frample(ofd, out_start + offk);
16989 mus_file_read(ifd, in_start + offk, clm_file_buffer_size, in_chans, ibufs);
16990 }
16991 scaler = mus_env(e);
16992 for (i = 0; i < min_chans; i++)
16993 obufs[i][j] += (mus_float_t)(scaler * ibufs[i][j]);
16994 }
16995 break;
16996 }
16997
16998 if (j > 0)
16999 mus_file_write(ofd, 0, j - 1, out_chans, obufs);
17000 if (curoutframples < (out_framples + out_start))
17001 curoutframples = out_framples + out_start;
17002 mus_sound_close_output(ofd, curoutframples * out_chans * mus_bytes_per_sample(mus_sound_sample_type(outfile)));
17003 mus_sound_close_input(ifd);
17004 for (i = 0; i < in_chans; i++) free(ibufs[i]);
17005 free(ibufs);
17006 for (i = 0; i < out_chans; i++) free(obufs[i]);
17007 free(obufs);
17008 }
17009 }
17010
17011
17012
17013 /* ---------------- init clm ---------------- */
17014
mus_initialize(void)17015 void mus_initialize(void)
17016 {
17017 #define MULAW_ZERO 255
17018 #define ALAW_ZERO 213
17019 #define UBYTE_ZERO 128
17020
17021 mus_generator_type = MUS_INITIAL_GEN_TAG;
17022 sampling_rate = MUS_DEFAULT_SAMPLING_RATE;
17023 w_rate = (TWO_PI / MUS_DEFAULT_SAMPLING_RATE);
17024 array_print_length = MUS_DEFAULT_ARRAY_PRINT_LENGTH;
17025 clm_file_buffer_size = MUS_DEFAULT_FILE_BUFFER_SIZE;
17026
17027 #if HAVE_FFTW3 && HAVE_COMPLEX_TRIG
17028 last_c_fft_size = 0;
17029 /* is there a problem if the caller built fftw with --enable-threads?
17030 * How to tell via configure that we need to initialize the thread stuff in libfftw?
17031 */
17032 #endif
17033
17034 sincs = 0;
17035 locsig_warned = NULL;
17036
17037 sample_type_zero = (int *)calloc(MUS_NUM_SAMPLES, sizeof(int));
17038 sample_type_zero[MUS_MULAW] = MULAW_ZERO;
17039 sample_type_zero[MUS_ALAW] = ALAW_ZERO;
17040 sample_type_zero[MUS_UBYTE] = UBYTE_ZERO;
17041 #if MUS_LITTLE_ENDIAN
17042 sample_type_zero[MUS_UBSHORT] = 0x80;
17043 sample_type_zero[MUS_ULSHORT] = 0x8000;
17044 #else
17045 sample_type_zero[MUS_UBSHORT] = 0x8000;
17046 sample_type_zero[MUS_ULSHORT] = 0x80;
17047 #endif
17048 }
17049