1 /* Effect: phaser Copyright (C) 1998 Juergen Mueller And Sundry Contributors
3 * This source code is freely redistributable and may be used for
4 * any purpose. This copyright notice must be maintained.
5 * Juergen Mueller And Sundry Contributors are not responsible for
6 * the consequences of using this software.
8 * Flow diagram scheme: August 24, 1998
10 * * gain-in +---+ * gain-out
11 * ibuff ----------->| |----------------------------------> obuff
20 * +---------------+ +------------------+
21 * | Delay control |<-----| modulation speed |
22 * +---------------+ +------------------+
24 * The delay is controled by a sine or triangle modulation.
27 * phaser gain-in gain-out delay decay speed [ -s | -t ]
30 * gain-in, decay : 0.0 .. 1.0 volume
31 * gain-out : 0.0 .. volume
32 * delay : 0.0 .. 5.0 msec
33 * speed : 0.1 .. 2.0 Hz modulation speed
34 * -s : modulation by sine (default)
35 * -t : modulation by triangle
38 * When decay is close to 1.0, the samples may begin clipping or the output
40 * in-gain < (1 - decay * decay)
41 * 1 / out-gain > gain-in / (1 - decay)
48 double in_gain
, out_gain
, delay_ms
, decay
, mod_speed
;
60 static int getopts(sox_effect_t
* effp
, int argc
, char * * argv
)
62 priv_t
* p
= (priv_t
*) effp
->priv
;
65 /* Set non-zero defaults: */
73 do { /* break-able block */
74 NUMERIC_PARAMETER(in_gain
, .0, 1)
75 NUMERIC_PARAMETER(out_gain
, .0, 1e9
)
76 NUMERIC_PARAMETER(delay_ms
, .0, 5)
77 NUMERIC_PARAMETER(decay
, .0, .99)
78 NUMERIC_PARAMETER(mod_speed
, .1, 2)
81 if (argc
&& sscanf(*argv
, "-%1[st]%c", chars
, chars
+ 1) == 1) {
82 p
->mod_type
= *chars
== 's'? SOX_WAVE_SINE
: SOX_WAVE_TRIANGLE
;
86 if (p
->in_gain
> (1 - p
->decay
* p
->decay
))
87 lsx_warn("warning: gain-in might cause clipping");
88 if (p
->in_gain
/ (1 - p
->decay
) > 1 / p
->out_gain
)
89 lsx_warn("warning: gain-out might cause clipping");
91 return argc
? lsx_usage(effp
) : SOX_SUCCESS
;
94 static int start(sox_effect_t
* effp
)
96 priv_t
* p
= (priv_t
*) effp
->priv
;
98 p
->delay_buf_len
= p
->delay_ms
* .001 * effp
->in_signal
.rate
+ .5;
99 p
->delay_buf
= lsx_calloc(p
->delay_buf_len
, sizeof(*p
->delay_buf
));
101 p
->mod_buf_len
= effp
->in_signal
.rate
/ p
->mod_speed
+ .5;
102 p
->mod_buf
= lsx_malloc(p
->mod_buf_len
* sizeof(*p
->mod_buf
));
103 lsx_generate_wave_table(p
->mod_type
, SOX_INT
, p
->mod_buf
, p
->mod_buf_len
,
104 1., (double)p
->delay_buf_len
, M_PI_2
);
106 p
->delay_pos
= p
->mod_pos
= 0;
108 effp
->out_signal
.length
= SOX_UNKNOWN_LEN
; /* TODO: calculate actual length */
112 static int flow(sox_effect_t
* effp
, const sox_sample_t
*ibuf
,
113 sox_sample_t
*obuf
, size_t *isamp
, size_t *osamp
)
115 priv_t
* p
= (priv_t
*) effp
->priv
;
116 size_t len
= *isamp
= *osamp
= min(*isamp
, *osamp
);
119 double d
= *ibuf
++ * p
->in_gain
+ p
->delay_buf
[
120 (p
->delay_pos
+ p
->mod_buf
[p
->mod_pos
]) % p
->delay_buf_len
] * p
->decay
;
121 p
->mod_pos
= (p
->mod_pos
+ 1) % p
->mod_buf_len
;
123 p
->delay_pos
= (p
->delay_pos
+ 1) % p
->delay_buf_len
;
124 p
->delay_buf
[p
->delay_pos
] = d
;
126 *obuf
++ = SOX_ROUND_CLIP_COUNT(d
* p
->out_gain
, effp
->clips
);
131 static int stop(sox_effect_t
* effp
)
133 priv_t
* p
= (priv_t
*) effp
->priv
;
140 sox_effect_handler_t
const * lsx_phaser_effect_fn(void)
142 static sox_effect_handler_t handler
= {
143 "phaser", "gain-in gain-out delay decay speed [ -s | -t ]",
144 SOX_EFF_LENGTH
| SOX_EFF_GAIN
, getopts
, start
, flow
, NULL
, stop
, NULL
, sizeof(priv_t
)