1 /* libSoX synth - Synthesizer Effect.
3 * Copyright (c) 2001-2009 SoX contributors
4 * Copyright (c) Jan 2001 Carsten Borchardt
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.
10 * Except for synth types: pluck, tpdf, pinknoise, & brownnoise, and
11 * sweep types: linear, square & exp, which are:
13 * Copyright (c) 2006-2013 robs@users.sourceforge.net
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.
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.
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
41 synth_trapetz
= synth_trapezium
, /* Deprecated name for trapezium */
43 /* Tones above, noises below */
45 synth_noise
= synth_whitenoise
, /* Just a handy alias */
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
)
69 typedef enum {synth_create
, synth_mix
, synth_amod
, synth_fmod
} combine_t
;
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
)
81 typedef enum {Linear
, Square
, Exp
, Exp_cycle
} sweep_t
;
87 double freq
, freq2
, mult
;
90 double p1
, p2
, p3
; /* Use depends on synth type */
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
;
97 size_t buffer_len
, pos
;
102 /* Private data for the synthesizer */
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
;
117 static void create_channel(channel_t
* chan
)
119 memset(chan
, 0, sizeof(*chan
));
120 chan
->freq2
= chan
->freq
= 440;
121 chan
->p3
= chan
->p2
= chan
->p1
= -1;
126 static void set_default_parameters(channel_t
* chan
)
128 switch (chan
->type
) {
129 case synth_square
: /* p1 is pulse width */
131 chan
->p1
= 0.5; /* default to 50% duty cycle */
134 case synth_triangle
: /* p1 is position of maximum */
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
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
;
153 /* symetric is not possible, fall back to asymmetrical triangle */
157 } else if (chan
->p3
< 0)
158 chan
->p3
= 1; /* simple falling slope to the end */
162 if (chan
->p1
< 0) /* p1 is position of maximum */
164 if (chan
->p2
< 0) /* p2 is amplitude */
172 chan
->p2
= .2, chan
->p3
= .9;
180 #undef NUMERIC_PARAMETER
181 #define NUMERIC_PARAMETER(p, min, max) { \
183 double d_np = strtod(argv[argn], &end_ptr_np); \
184 if (end_ptr_np == argv[argn]) \
186 if (d_np < min || d_np > max || *end_ptr_np != '\0') { \
187 lsx_fail("parameter error"); \
190 chan->p = d_np / 100; /* adjust so abs(parameter) <= 1 */\
191 if (++argn == argc) \
197 static int getopts(sox_effect_t
* effp
, int argc
, char **argv
)
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
;
206 if (argc
&& !strcmp(*argv
, "-n")) p
->no_headroom
= sox_true
, ++argv
, --argc
;
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
&&
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');
222 return lsx_usage(effp
);
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)
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
);
240 if (enum_p
== NULL
) {
241 lsx_fail("no type given");
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
;
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
;
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
[] = ":+/-";
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");
270 if (*end_ptr
&& strchr(sweeps
, *end_ptr
)) { /* freq2 given? */
271 if (chan
->type
>= synth_noise
) {
272 lsx_fail("can't sweep this type");
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");
281 if (p
->length_str
== NULL
) {
282 lsx_fail("duration must be given when using freq2");
287 lsx_fail("frequency: invalid trailing character");
290 if (chan
->sweep
>= Exp
&& chan
->freq
* chan
->freq2
== 0) {
291 lsx_fail("invalid frequency for exponential sweep");
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)
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
;
316 if (!effp
->in_signal
.channels
)
317 effp
->in_signal
.channels
= p
->getopts_nchannels
;
324 static int start(sox_effect_t
* effp
)
326 priv_t
* p
= (priv_t
*)effp
->priv
;
332 if (lsx_parsesamples(effp
->in_signal
.rate
, p
->length_str
, &p
->samples_to_do
, 't') == NULL
)
333 return lsx_usage(effp
);
335 p
->samples_to_do
= effp
->in_signal
.length
!= SOX_UNKNOWN_LEN
?
336 effp
->in_signal
.length
/ effp
->in_signal
.channels
: 0;
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
;
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
;
355 /* Single-pole low pass is very rate-dependent: */
356 if (effp
->in_signal
.rate
< 44100 || effp
->in_signal
.rate
> 48000) {
358 "sample rate for pluck must be 44100-48000; use `rate' to resample");
362 chan
->c1
*= exp(-2e4
/ (.05+chan
->p1
)/ chan
->freq
/ effp
->in_signal
.rate
);
364 /* High pass (DC-block): */
365 chan
->c2
= exp(-2 * M_PI
* 10 / effp
->in_signal
.rate
);
366 chan
->c3
= (1 + chan
->c2
) * .5;
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
);
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);
386 chan
->buffer
[j
] = sin(2 * M_PI
* j
/ chan
->buffer_len
);
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
;
398 d2
* chan
->c4
+ chan
->ap_last_in
- chan
->ap_last_out
* chan
->c4
;
399 chan
->ap_last_in
= d2
;
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
]);
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
]);
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
);
416 switch (chan
->sweep
) {
417 case Linear
: chan
->mult
= p
->samples_to_do
?
418 (chan
->freq2
- chan
->freq
) / p
->samples_to_do
/ 2 : 0;
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
;
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
;
429 case Exp_cycle
: chan
->mult
= p
->samples_to_do
?
430 (log(chan
->freq2
) - log(chan
->freq
)) / p
->samples_to_do
: 1;
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
);
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
;
447 #define elapsed_time_s p->samples_done / effp->in_signal.rate
449 static int flow(sox_effect_t
* effp
, const sox_sample_t
* ibuf
, sox_sample_t
* obuf
,
450 size_t * isamp
, size_t * osamp
)
452 priv_t
* p
= (priv_t
*) effp
->priv
;
453 unsigned len
= min(*isamp
, *osamp
) / effp
->in_signal
.channels
;
455 int result
= SOX_SUCCESS
;
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] */
463 if (chan
->type
< synth_noise
) { /* Need to calculate phase: */
464 double phase
; /* [0, 1) */
465 switch (chan
->sweep
) {
467 phase
= (chan
->freq
+ p
->samples_done
* chan
->mult
) *
471 phase
= (chan
->freq
+ sign(chan
->mult
) *
472 sqr(p
->samples_done
* chan
->mult
)) * elapsed_time_s
;
475 phase
= chan
->freq
* exp(chan
->mult
* elapsed_time_s
);
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
;
484 phase
= f
* cycle_elapsed_time_s
;
488 phase
= fmod(phase
+ chan
->phase
, 1.0);
490 switch (chan
->type
) {
492 synth_out
= sin(2 * M_PI
* phase
);
498 * |_______|__________| 0
504 synth_out
= -1 + 2 * (phase
< chan
->p1
);
516 synth_out
= -1 + 2 * phase
;
529 if (phase
< chan
->p1
)
530 synth_out
= -1 + 2 * phase
/ chan
->p1
; /* In rising part of period */
532 synth_out
= 1 - 2 * (phase
- chan
->p1
) / (1 - chan
->p1
); /* In falling part */
535 case synth_trapezium
:
538 * |__/________\___________| 0
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 */
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 */
559 * |____--- ---____ | f(p2)
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
);
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 */
571 default: synth_out
= 0;
573 } else switch (chan
->type
) {
574 case synth_whitenoise
:
578 case synth_tpdfnoise
:
579 synth_out
= .5 * (DRANQD1
+ DRANQD1
);
582 case synth_pinknoise
: { /* "Paul Kellet's refined method" */
583 #define _ .125 / (65536. * 32768.)
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*_
);
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
;
605 double d
= chan
->buffer
[chan
->pos
];
608 (d
- chan
->hp_last_in
) * chan
->c3
+ chan
->hp_last_out
* chan
->c2
;
609 chan
->hp_last_in
= d
;
611 synth_out
= range_limit(chan
->hp_last_out
, -1, 1);
613 chan
->lp_last_out
= d
= d
* chan
->c1
+ chan
->lp_last_out
* chan
->c0
;
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
;
619 chan
->pos
= chan
->pos
+ 1 == chan
->buffer_len
? 0 : chan
->pos
+ 1;
623 default: synth_out
= 0;
626 /* Add offset, but prevent clipping: */
627 synth_out
= synth_out
* (1 - fabs(chan
->offset
)) + chan
->offset
;
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;
635 *obuf
++ = synth_out
< 0? synth_out
* p
->gain
- .5 : synth_out
* p
->gain
+ .5;
637 if (++p
->samples_done
== p
->samples_to_do
)
640 *isamp
= *osamp
= done
* effp
->in_signal
.channels
;
646 static int stop(sox_effect_t
* effp
)
648 priv_t
* p
= (priv_t
*) effp
->priv
;
651 for (i
= 0; i
< p
->number_of_channels
; ++i
)
652 free(p
->channels
[i
].buffer
);
659 static int lsx_kill(sox_effect_t
* effp
)
661 priv_t
* p
= (priv_t
*) effp
->priv
;
662 free(p
->getopts_channels
);
669 const sox_effect_handler_t
*lsx_synth_effect_fn(void)
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
)