1 /* libSoX effect: Overdrive            (c) 2008 robs@users.sourceforge.net
2  *
3  * This library is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2.1 of the License, or (at
6  * your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation,
15  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
16  */
17 
18 #include "sox_i.h"
19 
20 typedef struct {
21   double gain, colour, last_in, last_out, b0, b1, a1;
22 } priv_t;
23 
create(sox_effect_t * effp,int argc,char ** argv)24 static int create(sox_effect_t * effp, int argc, char * * argv)
25 {
26   priv_t * p = (priv_t *)effp->priv;
27   --argc, ++argv;
28   p->gain = p->colour = 20;
29   do {
30     NUMERIC_PARAMETER(gain, 0, 100)
31     NUMERIC_PARAMETER(colour, 0, 100)
32   } while (0);
33   p->gain = dB_to_linear(p->gain);
34   p->colour /= 200;
35   return argc? lsx_usage(effp) : SOX_SUCCESS;
36 }
37 
start(sox_effect_t * effp)38 static int start(sox_effect_t * effp)
39 {
40   priv_t * p = (priv_t *)effp->priv;
41 
42   if (p->gain == 1)
43     return SOX_EFF_NULL;
44 
45   return SOX_SUCCESS;
46 }
47 
flow(sox_effect_t * effp,const sox_sample_t * ibuf,sox_sample_t * obuf,size_t * isamp,size_t * osamp)48 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
49     sox_sample_t * obuf, size_t * isamp, size_t * osamp)
50 {
51   priv_t * p = (priv_t *)effp->priv;
52   size_t dummy = 0, len = *isamp = *osamp = min(*isamp, *osamp);
53   while (len--) {
54     SOX_SAMPLE_LOCALS;
55     double d = SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf++, dummy), d0 = d;
56     d *= p->gain;
57     d += p->colour;
58     d = d < -1? -2./3 : d > 1? 2./3 : d - d * d * d * (1./3);
59     p->last_out = d - p->last_in + .995 * p->last_out;
60     p->last_in = d;
61     *obuf++ = SOX_FLOAT_64BIT_TO_SAMPLE(d0 * .5 + p->last_out * .75, dummy);
62   }
63   return SOX_SUCCESS;
64 }
65 
lsx_overdrive_effect_fn(void)66 sox_effect_handler_t const * lsx_overdrive_effect_fn(void)
67 {
68   static sox_effect_handler_t handler = {"overdrive", "[gain [colour]]",
69     SOX_EFF_GAIN, create, start, flow, NULL, NULL, NULL, sizeof(priv_t)};
70   return &handler;
71 }
72