id3: fix COMM frame handling
[sox.git] / src / phaser.c
blob0455f1bf02c4817943ac515da850c040874e5759
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
12 * | + | * decay
13 * | |<------------+
14 * +---+ _______ |
15 * | | | |
16 * +---| delay |---+
17 * |_______|
18 * /|\
19 * |
20 * +---------------+ +------------------+
21 * | Delay control |<-----| modulation speed |
22 * +---------------+ +------------------+
24 * The delay is controled by a sine or triangle modulation.
26 * Usage:
27 * phaser gain-in gain-out delay decay speed [ -s | -t ]
29 * Where:
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
37 * Note:
38 * When decay is close to 1.0, the samples may begin clipping or the output
39 * can saturate! Hint:
40 * in-gain < (1 - decay * decay)
41 * 1 / out-gain > gain-in / (1 - decay)
44 #include "sox_i.h"
45 #include <string.h>
47 typedef struct {
48 double in_gain, out_gain, delay_ms, decay, mod_speed;
49 lsx_wave_t mod_type;
51 int * mod_buf;
52 size_t mod_buf_len;
53 int mod_pos;
55 double * delay_buf;
56 size_t delay_buf_len;
57 int delay_pos;
58 } priv_t;
60 static int getopts(sox_effect_t * effp, int argc, char * * argv)
62 priv_t * p = (priv_t *) effp->priv;
63 char chars[2];
65 /* Set non-zero defaults: */
66 p->in_gain = .4;
67 p->out_gain = .74;
68 p->delay_ms = 3.;
69 p->decay = .4;
70 p->mod_speed = .5;
72 --argc, ++argv;
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)
79 } while (0);
81 if (argc && sscanf(*argv, "-%1[st]%c", chars, chars + 1) == 1) {
82 p->mod_type = *chars == 's'? SOX_WAVE_SINE : SOX_WAVE_TRIANGLE;
83 --argc, ++argv;
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 */
109 return SOX_SUCCESS;
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);
118 while (len--) {
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);
128 return SOX_SUCCESS;
131 static int stop(sox_effect_t * effp)
133 priv_t * p = (priv_t *) effp->priv;
135 free(p->delay_buf);
136 free(p->mod_buf);
137 return SOX_SUCCESS;
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)
146 return &handler;