1 /* libSoX synth - Synthesizer Effect.
2  *
3  * Copyright (c) 2001-2009 SoX contributors
4  * Copyright (c) Jan 2001  Carsten Borchardt
5  *
6  * This source code is freely redistributable and may be used for any purpose.
7  * This copyright notice must be maintained.  The authors are not responsible
8  * for the consequences of using this software.
9  *
10  * Except for synth types: pluck, tpdf, pinknoise, & brownnoise, and
11  *            sweep types: linear, square & exp, which are:
12  *
13  * Copyright (c) 2006-2013 robs@users.sourceforge.net
14  *
15  * This library is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU Lesser General Public License as published by
17  * the Free Software Foundation; either version 2.1 of the License, or (at
18  * your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
23  * General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public License
26  * along with this library; if not, write to the Free Software Foundation,
27  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28  */
29 
30 #include "sox_i.h"
31 
32 #include <string.h>
33 #include <ctype.h>
34 
35 typedef enum {
36   synth_sine,
37   synth_square,
38   synth_sawtooth,
39   synth_triangle,
40   synth_trapezium,
41   synth_trapetz  = synth_trapezium,   /* Deprecated name for trapezium */
42   synth_exp,
43                                       /* Tones above, noises below */
44   synth_whitenoise,
45   synth_noise = synth_whitenoise,     /* Just a handy alias */
46   synth_tpdfnoise,
47   synth_pinknoise,
48   synth_brownnoise,
49   synth_pluck
50 } type_t;
51 
52 static lsx_enum_item const synth_type[] = {
53   LSX_ENUM_ITEM(synth_, sine)
54   LSX_ENUM_ITEM(synth_, square)
55   LSX_ENUM_ITEM(synth_, sawtooth)
56   LSX_ENUM_ITEM(synth_, triangle)
57   LSX_ENUM_ITEM(synth_, trapezium)
58   LSX_ENUM_ITEM(synth_, trapetz)
59   LSX_ENUM_ITEM(synth_, exp)
60   LSX_ENUM_ITEM(synth_, whitenoise)
61   LSX_ENUM_ITEM(synth_, noise)
62   LSX_ENUM_ITEM(synth_, tpdfnoise)
63   LSX_ENUM_ITEM(synth_, pinknoise)
64   LSX_ENUM_ITEM(synth_, brownnoise)
65   LSX_ENUM_ITEM(synth_, pluck)
66   {0, 0}
67 };
68 
69 typedef enum {synth_create, synth_mix, synth_amod, synth_fmod} combine_t;
70 
71 static lsx_enum_item const combine_type[] = {
72   LSX_ENUM_ITEM(synth_, create)
73   LSX_ENUM_ITEM(synth_, mix)
74   LSX_ENUM_ITEM(synth_, amod)
75   LSX_ENUM_ITEM(synth_, fmod)
76   {0, 0}
77 };
78 
79 
80 
81 typedef enum {Linear, Square, Exp, Exp_cycle} sweep_t;
82 
83 typedef struct {
84   /* options */
85   type_t type;
86   combine_t combine;
87   double freq, freq2, mult;
88   sweep_t sweep;
89   double offset, phase;
90   double p1, p2, p3; /* Use depends on synth type */
91 
92   /* internal stuff */
93   double lp_last_out, hp_last_out, hp_last_in, ap_last_out, ap_last_in;
94   double cycle_start_time_s, c0, c1, c2, c3, c4, c5, c6;
95 
96   double * buffer;
97   size_t buffer_len, pos;
98 } channel_t;
99 
100 
101 
102 /* Private data for the synthesizer */
103 typedef struct {
104   char *        length_str;
105   channel_t *   getopts_channels;
106   size_t        getopts_nchannels;
107   uint64_t      samples_done;
108   uint64_t      samples_to_do;
109   channel_t *   channels;
110   size_t        number_of_channels;
111   sox_bool      no_headroom;
112   double        gain;
113 } priv_t;
114 
115 
116 
create_channel(channel_t * chan)117 static void create_channel(channel_t *  chan)
118 {
119   memset(chan, 0, sizeof(*chan));
120   chan->freq2 = chan->freq = 440;
121   chan->p3 = chan->p2 = chan->p1 = -1;
122 }
123 
124 
125 
set_default_parameters(channel_t * chan)126 static void set_default_parameters(channel_t *  chan)
127 {
128   switch (chan->type) {
129     case synth_square:    /* p1 is pulse width */
130       if (chan->p1 < 0)
131         chan->p1 = 0.5;   /* default to 50% duty cycle */
132       break;
133 
134     case synth_triangle:  /* p1 is position of maximum */
135       if (chan->p1 < 0)
136         chan->p1 = 0.5;
137       break;
138 
139     case synth_trapezium:
140       /* p1 is length of rising slope,
141        * p2 position where falling slope begins
142        * p3 position of end of falling slope
143        */
144       if (chan->p1 < 0) {
145         chan->p1 = 0.1;
146         chan->p2 = 0.5;
147         chan->p3 = 0.6;
148       } else if (chan->p2 < 0) { /* try a symmetric waveform */
149         if (chan->p1 <= 0.5) {
150           chan->p2 = (1 - 2 * chan->p1) / 2;
151           chan->p3 = chan->p2 + chan->p1;
152         } else {
153           /* symetric is not possible, fall back to asymmetrical triangle */
154           chan->p2 = chan->p1;
155           chan->p3 = 1;
156         }
157       } else if (chan->p3 < 0)
158         chan->p3 = 1;     /* simple falling slope to the end */
159       break;
160 
161     case synth_exp:
162       if (chan->p1 < 0) /* p1 is position of maximum */
163         chan->p1 = 0.5;
164       if (chan->p2 < 0) /* p2 is amplitude */
165         chan->p2 = .5;
166       break;
167 
168     case synth_pluck:
169       if (chan->p1 < 0)
170         chan->p1 = .4;
171       if (chan->p2 < 0)
172         chan->p2 = .2, chan->p3 = .9;
173 
174     default: break;
175   }
176 }
177 
178 
179 
180 #undef NUMERIC_PARAMETER
181 #define NUMERIC_PARAMETER(p, min, max) { \
182 char * end_ptr_np; \
183 double d_np = strtod(argv[argn], &end_ptr_np); \
184 if (end_ptr_np == argv[argn]) \
185   break; \
186 if (d_np < min || d_np > max || *end_ptr_np != '\0') { \
187   lsx_fail("parameter error"); \
188   return SOX_EOF; \
189 } \
190 chan->p = d_np / 100; /* adjust so abs(parameter) <= 1 */\
191 if (++argn == argc) \
192   break; \
193 }
194 
195 
196 
getopts(sox_effect_t * effp,int argc,char ** argv)197 static int getopts(sox_effect_t * effp, int argc, char **argv)
198 {
199   priv_t * p = (priv_t *) effp->priv;
200   channel_t master, * chan = &master;
201   int key = INT_MAX, argn = 0;
202   char dummy, * end_ptr;
203   const char *n;
204   --argc, ++argv;
205 
206   if (argc && !strcmp(*argv, "-n")) p->no_headroom = sox_true, ++argv, --argc;
207 
208   if (argc > 1 && !strcmp(*argv, "-j") && (
209         sscanf(argv[1], "%i %c", &key, &dummy) == 1 || (
210           (key = lsx_parse_note(argv[1], &end_ptr)) != INT_MAX &&
211           !*end_ptr))) {
212     argc -= 2;
213     argv += 2;
214   }
215 
216   /* Get duration if given (if first arg starts with digit) */
217   if (argc && (isdigit((int)argv[argn][0]) || argv[argn][0] == '.')) {
218     p->length_str = lsx_strdup(argv[argn]);
219     /* Do a dummy parse of to see if it will fail */
220     n = lsx_parsesamples(0., p->length_str, &p->samples_to_do, 't');
221     if (!n || *n)
222       return lsx_usage(effp);
223     argn++;
224   }
225 
226   create_channel(chan);
227   if (argn < argc) {            /* [off [ph [p1 [p2 [p3]]]]]] */
228     do { /* break-able block */
229       NUMERIC_PARAMETER(offset,-100, 100)
230       NUMERIC_PARAMETER(phase ,   0, 100)
231       NUMERIC_PARAMETER(p1,   0, 100)
232       NUMERIC_PARAMETER(p2,   0, 100)
233       NUMERIC_PARAMETER(p3,   0, 100)
234     } while (0);
235   }
236 
237   while (argn < argc) { /* type [combine] [f1[-f2] [off [ph [p1 [p2 [p3]]]]]] */
238     lsx_enum_item const * enum_p = lsx_find_enum_text(argv[argn], synth_type, lsx_find_enum_item_case_sensitive);
239 
240     if (enum_p == NULL) {
241       lsx_fail("no type given");
242       return SOX_EOF;
243     }
244     p->getopts_channels = lsx_realloc(p->getopts_channels, sizeof(*p->getopts_channels) * (p->getopts_nchannels + 1));
245     chan = &p->getopts_channels[p->getopts_nchannels++];
246     memcpy(chan, &master, sizeof(*chan));
247     chan->type = enum_p->value;
248     if (++argn == argc)
249       break;
250 
251     /* maybe there is a combine-type in next arg */
252     enum_p = lsx_find_enum_text(argv[argn], combine_type, lsx_find_enum_item_case_sensitive);
253     if (enum_p != NULL) {
254       chan->combine = enum_p->value;
255       if (++argn == argc)
256         break;
257     }
258 
259     /* read frequencies if given */
260     if (!lsx_find_enum_text(argv[argn], synth_type, lsx_find_enum_item_case_sensitive) &&
261         argv[argn][0] != '-') {
262       static const char sweeps[] = ":+/-";
263 
264       chan->freq2 = chan->freq = lsx_parse_frequency_k(argv[argn], &end_ptr, key);
265       if (chan->freq < (chan->type == synth_pluck? 27.5 : 0) ||
266           (chan->type == synth_pluck && chan->freq > 4220)) {
267         lsx_fail("invalid freq");
268         return SOX_EOF;
269       }
270       if (*end_ptr && strchr(sweeps, *end_ptr)) {         /* freq2 given? */
271         if (chan->type >= synth_noise) {
272           lsx_fail("can't sweep this type");
273           return SOX_EOF;
274         }
275         chan->sweep = strchr(sweeps, *end_ptr) - sweeps;
276         chan->freq2 = lsx_parse_frequency_k(end_ptr + 1, &end_ptr, key);
277         if (chan->freq2 < 0) {
278           lsx_fail("invalid freq2");
279           return SOX_EOF;
280         }
281         if (p->length_str == NULL) {
282           lsx_fail("duration must be given when using freq2");
283           return SOX_EOF;
284         }
285       }
286       if (*end_ptr) {
287         lsx_fail("frequency: invalid trailing character");
288         return SOX_EOF;
289       }
290       if (chan->sweep >= Exp && chan->freq * chan->freq2 == 0) {
291         lsx_fail("invalid frequency for exponential sweep");
292         return SOX_EOF;
293       }
294 
295       if (++argn == argc)
296         break;
297     }
298 
299     /* read rest of parameters */
300     do { /* break-able block */
301       NUMERIC_PARAMETER(offset,-100, 100)
302       NUMERIC_PARAMETER(phase ,   0, 100)
303       NUMERIC_PARAMETER(p1,   0, 100)
304       NUMERIC_PARAMETER(p2,   0, 100)
305       NUMERIC_PARAMETER(p3,   0, 100)
306     } while (0);
307   }
308 
309   /* If no channel parameters were given, create one default channel: */
310   if (!p->getopts_nchannels) {
311     p->getopts_channels = lsx_malloc(sizeof(*p->getopts_channels));
312     memcpy(&p->getopts_channels[0], &master, sizeof(channel_t));
313     ++p->getopts_nchannels;
314   }
315 
316   if (!effp->in_signal.channels)
317     effp->in_signal.channels = p->getopts_nchannels;
318 
319   return SOX_SUCCESS;
320 }
321 
322 
323 
start(sox_effect_t * effp)324 static int start(sox_effect_t * effp)
325 {
326   priv_t * p = (priv_t *)effp->priv;
327   size_t i, j, k;
328 
329   p->samples_done = 0;
330 
331   if (p->length_str) {
332     if (lsx_parsesamples(effp->in_signal.rate, p->length_str, &p->samples_to_do, 't') == NULL)
333       return lsx_usage(effp);
334   } else
335     p->samples_to_do = effp->in_signal.length != SOX_UNKNOWN_LEN ?
336         effp->in_signal.length / effp->in_signal.channels : 0;
337 
338   p->number_of_channels = effp->in_signal.channels;
339   p->channels = lsx_calloc(p->number_of_channels, sizeof(*p->channels));
340   for (i = 0; i < p->number_of_channels; ++i) {
341     channel_t *  chan = &p->channels[i];
342     *chan = p->getopts_channels[i % p->getopts_nchannels];
343     set_default_parameters(chan);
344     if (chan->type == synth_pluck) {
345       double min, max, frac, p2;
346 
347       /* Low pass: */
348       double const decay_rate = -2; /* dB / s */
349       double const decay_f = min(912, 266 + 106 * log(chan->freq));
350       double d = sqr(dB_to_linear(decay_rate / chan->freq));
351       d = (d * cos(2 * M_PI * decay_f / effp->in_signal.rate) - 1) / (d - 1);
352       chan->c0 = d - sqrt(d * d - 1);
353       chan->c1 = 1 - chan->c0;
354 
355       /* Single-pole low pass is very rate-dependent: */
356       if (effp->in_signal.rate < 44100 || effp->in_signal.rate > 48000) {
357         lsx_fail(
358           "sample rate for pluck must be 44100-48000; use `rate' to resample");
359         return SOX_EOF;
360       }
361       /* Decay: */
362       chan->c1 *= exp(-2e4/ (.05+chan->p1)/ chan->freq/ effp->in_signal.rate);
363 
364       /* High pass (DC-block): */
365       chan->c2 = exp(-2 * M_PI * 10 / effp->in_signal.rate);
366       chan->c3 = (1 + chan->c2) * .5;
367 
368       /* All pass (for fractional delay): */
369       d = chan->c0 / (chan->c0 + chan->c1);
370       chan->buffer_len = effp->in_signal.rate / chan->freq - d;
371       frac = effp->in_signal.rate / chan->freq - d - chan->buffer_len;
372       chan->c4 = (1 - frac) / (1 + frac);
373       chan->pos = 0;
374 
375       /* Exitation: */
376       chan->buffer = lsx_calloc(chan->buffer_len, sizeof(*chan->buffer));
377       for (k = 0, p2 = chan->p2; k < 2 && p2 >= 0; ++k, p2 = chan->p3) {
378         double d1 = 0, d2, colour = pow(2., 4 * (p2 - 1));
379         int32_t r = p2 * 100 + .5;
380         for (j = 0; j < chan->buffer_len; ++j) {
381           do d2 = d1 + (chan->phase? DRANQD1:dranqd1(r)) * colour;
382           while (fabs(d2) > 1);
383           chan->buffer[j] += d2 * (1 - .3 * k);
384           d1 = d2 * (colour != 1);
385 #ifdef TEST_PLUCK
386           chan->buffer[j] = sin(2 * M_PI * j / chan->buffer_len);
387 #endif
388         }
389       }
390 
391       /* In-delay filter graduation: */
392       for (j = 0, min = max = 0; j < chan->buffer_len; ++j) {
393         double d2, t = (double)j / chan->buffer_len;
394         chan->lp_last_out = d2 =
395           chan->buffer[j] * chan->c1 + chan->lp_last_out * chan->c0;
396 
397         chan->ap_last_out =
398           d2 * chan->c4 + chan->ap_last_in - chan->ap_last_out * chan->c4;
399         chan->ap_last_in = d2;
400 
401         chan->buffer[j] = chan->buffer[j] * (1 - t) + chan->ap_last_out * t;
402         min = min(min, chan->buffer[j]);
403         max = max(max, chan->buffer[j]);
404       }
405 
406       /* Normalise: */
407       for (j = 0, d = 0; j < chan->buffer_len; ++j) {
408         chan->buffer[j] = (2 * chan->buffer[j] - max - min) / (max - min);
409         d += sqr(chan->buffer[j]);
410       }
411       lsx_debug("rms=%f c0=%f c1=%f df=%f d3f=%f c2=%f c3=%f c4=%f frac=%f",
412           10 * log(d / chan->buffer_len), chan->c0, chan->c1, decay_f,
413           log(chan->c0)/ -2 / M_PI * effp->in_signal.rate,
414           chan->c2, chan->c3, chan->c4, frac);
415     }
416     switch (chan->sweep) {
417       case Linear: chan->mult = p->samples_to_do?
418           (chan->freq2 - chan->freq) / p->samples_to_do / 2 : 0;
419         break;
420       case Square: chan->mult = p->samples_to_do?
421            sqrt(fabs(chan->freq2 - chan->freq)) / p->samples_to_do / sqrt(3.) : 0;
422         if (chan->freq > chan->freq2)
423           chan->mult = -chan->mult;
424         break;
425       case Exp: chan->mult = p->samples_to_do?
426           log(chan->freq2 / chan->freq) / p->samples_to_do * effp->in_signal.rate : 1;
427         chan->freq /= chan->mult;
428         break;
429       case Exp_cycle: chan->mult = p->samples_to_do?
430           (log(chan->freq2) - log(chan->freq)) / p->samples_to_do : 1;
431         break;
432     }
433     lsx_debug("type=%s, combine=%s, samples_to_do=%" PRIu64 ", f1=%g, f2=%g, "
434               "offset=%g, phase=%g, p1=%g, p2=%g, p3=%g mult=%g",
435         lsx_find_enum_value(chan->type, synth_type)->text,
436         lsx_find_enum_value(chan->combine, combine_type)->text,
437         p->samples_to_do, chan->freq, chan->freq2,
438         chan->offset, chan->phase, chan->p1, chan->p2, chan->p3, chan->mult);
439   }
440   p->gain = 1;
441   effp->out_signal.mult = p->no_headroom? NULL : &p->gain;
442   effp->out_signal.length = p->samples_to_do ?
443     p->samples_to_do * effp->out_signal.channels : SOX_UNKNOWN_LEN;
444   return SOX_SUCCESS;
445 }
446 
447 #define elapsed_time_s p->samples_done / effp->in_signal.rate
448 
flow(sox_effect_t * effp,const sox_sample_t * ibuf,sox_sample_t * obuf,size_t * isamp,size_t * osamp)449 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf, sox_sample_t * obuf,
450     size_t * isamp, size_t * osamp)
451 {
452   priv_t * p = (priv_t *) effp->priv;
453   unsigned len = min(*isamp, *osamp) / effp->in_signal.channels;
454   unsigned c, done;
455   int result = SOX_SUCCESS;
456 
457   for (done = 0; done < len && result == SOX_SUCCESS; ++done) {
458     for (c = 0; c < effp->in_signal.channels; c++) {
459       sox_sample_t synth_input = *ibuf++;
460       channel_t *  chan = &p->channels[c];
461       double synth_out;              /* [-1, 1] */
462 
463       if (chan->type < synth_noise) { /* Need to calculate phase: */
464         double phase;            /* [0, 1) */
465         switch (chan->sweep) {
466           case Linear:
467             phase = (chan->freq + p->samples_done * chan->mult) *
468                 elapsed_time_s;
469             break;
470           case Square:
471             phase = (chan->freq + sign(chan->mult) *
472                 sqr(p->samples_done * chan->mult)) * elapsed_time_s;
473             break;
474           case Exp:
475             phase = chan->freq * exp(chan->mult * elapsed_time_s);
476             break;
477           case Exp_cycle: default: {
478             double f = chan->freq * exp(p->samples_done * chan->mult);
479             double cycle_elapsed_time_s = elapsed_time_s - chan->cycle_start_time_s;
480             if (f * cycle_elapsed_time_s >= 1) {  /* move to next cycle */
481               chan->cycle_start_time_s += 1 / f;
482               cycle_elapsed_time_s = elapsed_time_s - chan->cycle_start_time_s;
483             }
484             phase = f * cycle_elapsed_time_s;
485             break;
486           }
487         }
488         phase = fmod(phase + chan->phase, 1.0);
489 
490         switch (chan->type) {
491           case synth_sine:
492             synth_out = sin(2 * M_PI * phase);
493             break;
494 
495           case synth_square:
496             /* |_______           | +1
497              * |       |          |
498              * |_______|__________|  0
499              * |       |          |
500              * |       |__________| -1
501              * |                  |
502              * 0       p1          1
503              */
504             synth_out = -1 + 2 * (phase < chan->p1);
505             break;
506 
507           case synth_sawtooth:
508             /* |           __| +1
509              * |        __/  |
510              * |_______/_____|  0
511              * |  __/        |
512              * |_/           | -1
513              * |             |
514              * 0             1
515              */
516             synth_out = -1 + 2 * phase;
517             break;
518 
519           case synth_triangle:
520             /* |    .    | +1
521              * |   / \   |
522              * |__/___\__|  0
523              * | /     \ |
524              * |/       \| -1
525              * |         |
526              * 0   p1    1
527              */
528 
529             if (phase < chan->p1)
530               synth_out = -1 + 2 * phase / chan->p1;          /* In rising part of period */
531             else
532               synth_out = 1 - 2 * (phase - chan->p1) / (1 - chan->p1); /* In falling part */
533             break;
534 
535           case synth_trapezium:
536             /* |    ______             |+1
537              * |   /      \            |
538              * |__/________\___________| 0
539              * | /          \          |
540              * |/            \_________|-1
541              * |                       |
542              * 0   p1    p2   p3       1
543              */
544             if (phase < chan->p1)       /* In rising part of period */
545               synth_out = -1 + 2 * phase / chan->p1;
546             else if (phase < chan->p2)  /* In high part of period */
547               synth_out = 1;
548             else if (phase < chan->p3)  /* In falling part */
549               synth_out = 1 - 2 * (phase - chan->p2) / (chan->p3 - chan->p2);
550             else                        /* In low part of period */
551               synth_out = -1;
552             break;
553 
554           case synth_exp:
555             /* |             |              | +1
556              * |            | |             |
557              * |          _|   |_           | 0
558              * |       __-       -__        |
559              * |____---             ---____ | f(p2)
560              * |                            |
561              * 0             p1             1
562              */
563             synth_out = dB_to_linear(chan->p2 * -200);  /* 0 ..  1 */
564             if (phase < chan->p1)
565               synth_out = synth_out * exp(phase * log(1 / synth_out) / chan->p1);
566             else
567               synth_out = synth_out * exp((1 - phase) * log(1 / synth_out) / (1 - chan->p1));
568             synth_out = synth_out * 2 - 1;      /* map 0 .. 1 to -1 .. +1 */
569             break;
570 
571           default: synth_out = 0;
572         }
573       } else switch (chan->type) {
574         case synth_whitenoise:
575           synth_out = DRANQD1;
576           break;
577 
578         case synth_tpdfnoise:
579           synth_out = .5 * (DRANQD1 + DRANQD1);
580           break;
581 
582         case synth_pinknoise: { /* "Paul Kellet's refined method" */
583 #define _ .125 / (65536. * 32768.)
584           double d = RANQD1;
585           chan->c0 = .99886 * chan->c0 + d * (.0555179*_);
586           chan->c1 = .99332 * chan->c1 + d * (.0750759*_);
587           chan->c2 = .96900 * chan->c2 + d * (.1538520*_);
588           chan->c3 = .86650 * chan->c3 + d * (.3104856*_);
589           chan->c4 = .55000 * chan->c4 + d * (.5329522*_);
590           chan->c5 = -.7616 * chan->c5 - d * (.0168980*_);
591           synth_out = chan->c0 + chan->c1 + chan->c2 + chan->c3
592                     + chan->c4 + chan->c5 + chan->c6 + d * (.5362*_);
593           chan->c6 = d * (.115926*_);
594           break;
595 #undef _
596         }
597 
598         case synth_brownnoise:
599           do synth_out = chan->lp_last_out + DRANQD1 * (1. / 16);
600           while (fabs(synth_out) > 1);
601           chan->lp_last_out = synth_out;
602           break;
603 
604         case synth_pluck: {
605           double d = chan->buffer[chan->pos];
606 
607           chan->hp_last_out =
608              (d - chan->hp_last_in) * chan->c3 + chan->hp_last_out * chan->c2;
609           chan->hp_last_in = d;
610 
611           synth_out = range_limit(chan->hp_last_out, -1, 1);
612 
613           chan->lp_last_out = d = d * chan->c1 + chan->lp_last_out * chan->c0;
614 
615           chan->ap_last_out = chan->buffer[chan->pos] =
616             (d - chan->ap_last_out) * chan->c4 + chan->ap_last_in;
617           chan->ap_last_in = d;
618 
619           chan->pos = chan->pos + 1 == chan->buffer_len? 0 : chan->pos + 1;
620           break;
621         }
622 
623         default: synth_out = 0;
624       }
625 
626       /* Add offset, but prevent clipping: */
627       synth_out = synth_out * (1 - fabs(chan->offset)) + chan->offset;
628 
629       switch (chan->combine) {
630         case synth_create: synth_out *=  SOX_SAMPLE_MAX; break;
631         case synth_mix   : synth_out = (synth_out * SOX_SAMPLE_MAX + synth_input) * .5; break;
632         case synth_amod  : synth_out = (synth_out + 1) * synth_input * .5; break;
633         case synth_fmod  : synth_out *=  synth_input; break;
634       }
635       *obuf++ = synth_out < 0? synth_out * p->gain - .5 : synth_out * p->gain + .5;
636     }
637     if (++p->samples_done == p->samples_to_do)
638       result = SOX_EOF;
639   }
640   *isamp = *osamp = done * effp->in_signal.channels;
641   return result;
642 }
643 
644 
645 
stop(sox_effect_t * effp)646 static int stop(sox_effect_t * effp)
647 {
648   priv_t * p = (priv_t *) effp->priv;
649   size_t i;
650 
651   for (i = 0; i < p->number_of_channels; ++i)
652     free(p->channels[i].buffer);
653   free(p->channels);
654   return SOX_SUCCESS;
655 }
656 
657 
658 
lsx_kill(sox_effect_t * effp)659 static int lsx_kill(sox_effect_t * effp)
660 {
661   priv_t * p = (priv_t *) effp->priv;
662   free(p->getopts_channels);
663   free(p->length_str);
664   return SOX_SUCCESS;
665 }
666 
667 
668 
lsx_synth_effect_fn(void)669 const sox_effect_handler_t *lsx_synth_effect_fn(void)
670 {
671   static sox_effect_handler_t handler = {
672     "synth", "[-j KEY] [-n] [length [offset [phase [p1 [p2 [p3]]]]]]] {type [combine] [[%]freq[k][:|+|/|-[%]freq2[k]] [offset [phase [p1 [p2 [p3]]]]]]}",
673     SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_GAIN,
674     getopts, start, flow, 0, stop, lsx_kill, sizeof(priv_t)
675   };
676   return &handler;
677 }
678