1 /* libSoX Effect: Adjust the audio speed (pitch and tempo together)
2  * (c) 2006,8 robs@users.sourceforge.net
3  *
4  * This library is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation; either version 2.1 of the License, or (at
7  * your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  *
19  * Adjustment is given as the ratio of the new speed to the old speed, or as
20  * a number of cents (100ths of a semitone) to change.  Speed change is
21  * actually performed by whichever resampling effect is in effect.
22  */
23 
24 #include "sox_i.h"
25 #include <string.h>
26 
27 typedef struct {
28   double factor;
29 } priv_t;
30 
getopts(sox_effect_t * effp,int argc,char ** argv)31 static int getopts(sox_effect_t * effp, int argc, char * * argv)
32 {
33   priv_t * p = (priv_t *) effp->priv;
34   sox_bool is_cents = sox_false;
35 
36   --argc, ++argv;
37   if (argc == 1) {
38     char c, dummy;
39     int scanned = sscanf(*argv, "%lf%c %c", &p->factor, &c, &dummy);
40     if (scanned == 1 || (scanned == 2 && c == 'c')) {
41       is_cents |= scanned == 2;
42       if (is_cents || p->factor > 0) {
43         p->factor = is_cents? pow(2., p->factor / 1200) : p->factor;
44         return SOX_SUCCESS;
45       }
46     }
47   }
48   return lsx_usage(effp);
49 }
50 
start(sox_effect_t * effp)51 static int start(sox_effect_t * effp)
52 {
53   priv_t * p = (priv_t *) effp->priv;
54 
55   if (p->factor == 1)
56     return SOX_EFF_NULL;
57 
58   effp->out_signal.rate = effp->in_signal.rate * p->factor;
59 
60   effp->out_signal.length = effp->in_signal.length;
61     /* audio length if measured in samples doesn't change */
62 
63   return SOX_SUCCESS;
64 }
65 
lsx_speed_effect_fn(void)66 sox_effect_handler_t const * lsx_speed_effect_fn(void)
67 {
68   static sox_effect_handler_t handler = {
69     "speed", "factor[c]",
70     SOX_EFF_MCHAN | SOX_EFF_RATE | SOX_EFF_LENGTH | SOX_EFF_MODIFY,
71     getopts, start, lsx_flow_copy, 0, 0, 0, sizeof(priv_t)};
72   return &handler;
73 }
74