2 * (c) 2000.04.15 Chris Ausbrooks <weed@bucket.pp.ualr.edu>
4 * based on vol.c which is
5 * (c) 20/03/2000 Fabien COELHO <fabien@coelho.net> for sox.
7 * DC shift a sound file, with basic linear amplitude formula.
8 * Beware of saturations! clipping is checked and reported.
9 * Cannot handle different number of channels.
10 * Cannot handle rate change.
16 double dcshift
; /* DC shift. */
17 int uselimiter
; /* boolean: are we using the limiter? */
18 double limiterthreshhold
;
19 double limitergain
; /* limiter gain. */
20 uint64_t limited
; /* number of limited values to report. */
21 uint64_t totalprocessed
;
25 * Process options: dcshift (double) type (amplitude, power, dB)
27 static int sox_dcshift_getopts(sox_effect_t
* effp
, int argc
, char **argv
)
29 priv_t
* dcs
= (priv_t
*) effp
->priv
;
30 dcs
->dcshift
= 1.0; /* default is no change */
31 dcs
->uselimiter
= 0; /* default is no limiter */
35 return lsx_usage(effp
);
37 if (argc
&& (!sscanf(argv
[0], "%lf", &dcs
->dcshift
)))
38 return lsx_usage(effp
);
42 if (!sscanf(argv
[1], "%lf", &dcs
->limitergain
))
43 return lsx_usage(effp
);
45 dcs
->uselimiter
= 1; /* ok, we'll use it */
46 /* The following equation is derived so that there is no
47 * discontinuity in output amplitudes */
48 /* and a SOX_SAMPLE_MAX input always maps to a SOX_SAMPLE_MAX output
49 * when the limiter is activated. */
50 /* (NOTE: There **WILL** be a discontinuity in the slope of the
51 * output amplitudes when using the limiter.) */
52 dcs
->limiterthreshhold
= SOX_SAMPLE_MAX
* (1.0 - (fabs(dcs
->dcshift
) - dcs
->limitergain
));
61 static int sox_dcshift_start(sox_effect_t
* effp
)
63 priv_t
* dcs
= (priv_t
*) effp
->priv
;
65 if (dcs
->dcshift
== 0)
69 dcs
->totalprocessed
= 0;
77 static int sox_dcshift_flow(sox_effect_t
* effp
, const sox_sample_t
*ibuf
, sox_sample_t
*obuf
,
78 size_t *isamp
, size_t *osamp
)
80 priv_t
* dcs
= (priv_t
*) effp
->priv
;
81 double dcshift
= dcs
->dcshift
;
82 double limitergain
= dcs
->limitergain
;
83 double limiterthreshhold
= dcs
->limiterthreshhold
;
87 len
= min(*osamp
, *isamp
);
89 /* report back dealt with amount. */
90 *isamp
= len
; *osamp
= len
;
94 dcs
->totalprocessed
+= len
;
100 if (sample
> limiterthreshhold
&& dcshift
> 0)
102 sample
= (sample
- limiterthreshhold
) * limitergain
/ (SOX_SAMPLE_MAX
- limiterthreshhold
) + limiterthreshhold
+ dcshift
;
105 else if (sample
< -limiterthreshhold
&& dcshift
< 0)
107 /* Note this should really be SOX_SAMPLE_MIN but
108 * the clip() below will take care of the overflow.
110 sample
= (sample
+ limiterthreshhold
) * limitergain
/ (SOX_SAMPLE_MAX
- limiterthreshhold
) - limiterthreshhold
+ dcshift
;
115 /* Note this should consider SOX_SAMPLE_MIN but
116 * the clip() below will take care of the overflow.
118 sample
= dcshift
* SOX_SAMPLE_MAX
+ sample
;
121 SOX_SAMPLE_CLIP_COUNT(sample
, effp
->clips
);
125 else for (; len
> 0; --len
) { /* quite basic, with clipping */
126 double d
= dcshift
* (SOX_SAMPLE_MAX
+ 1.) + *ibuf
++;
127 *obuf
++ = SOX_ROUND_CLIP_COUNT(d
, effp
->clips
);
133 * Do anything required when you stop reading samples.
134 * Don't close input file!
136 static int sox_dcshift_stop(sox_effect_t
* effp
)
138 priv_t
* dcs
= (priv_t
*) effp
->priv
;
142 lsx_warn("DCSHIFT limited %" PRIu64
" values (%d percent).",
143 dcs
->limited
, (int) (dcs
->limited
* 100.0 / dcs
->totalprocessed
));
148 static sox_effect_handler_t sox_dcshift_effect
= {
150 "shift [ limitergain ]\n"
151 "\tThe peak limiter has a gain much less than 1.0 (ie 0.05 or 0.02) which\n"
152 "\tis only used on peaks to prevent clipping. (default is no limiter)",
153 SOX_EFF_MCHAN
| SOX_EFF_GAIN
,
162 const sox_effect_handler_t
*lsx_dcshift_effect_fn(void)
164 return &sox_dcshift_effect
;