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