ref: dc35efc0cb561002610c82a8f357eb812f396355
parent: 3ae511f8292579ff4aa0ec3a23ea9c18fd0f0994
author: robs <robs>
date: Sun Oct 26 05:34:06 EDT 2008
Improved handling of speed changes in the effects chain. Fixes e.g. 'play -n synth speed 100' not working properly.
--- a/ChangeLog
+++ b/ChangeLog
@@ -38,7 +38,7 @@
File formats:
- o New unfiltered CVSD; supports any bit-rate. (robs)
+ o New `.cvu' unfiltered CVSD; supports any bit-rate. (robs)
o New `.sox' native format intended for intermediate files. (robs)
o Fix WAV write on 64-bit arch. (robs)
o Fix writing PRC ADPCM files. (Silas Brown)
@@ -65,6 +65,7 @@
o Fix rare crash with `rate' effect. (robs)
o Fix [2190767] `norm' under-amplifying in some cases. (George Yohng)
o Trim will now skip past 2G point correctly. (cbagwell)
+ o Improved handling of speed changes in the effects chain. (robs)
Other new features:
--- a/sox.1
+++ b/sox.1
@@ -29,7 +29,7 @@
.SP
.fi
..
-.TH SoX 1 "September 22, 2008" "sox" "Sound eXchange"
+.TH SoX 1 "October 28, 2008" "sox" "Sound eXchange"
.SH NAME
SoX \- Sound eXchange, the Swiss Army knife of audio manipulation
.SH SYNOPSIS
--- a/soxformat.7
+++ b/soxformat.7
@@ -29,7 +29,7 @@
.SP
.fi
..
-.TH SoX 7 "July 27, 2008" "soxformat" "Sound eXchange"
+.TH SoX 7 "October 28, 2008" "soxformat" "Sound eXchange"
.SH NAME
SoX \- Sound eXchange, the Swiss Army knife of audio manipulation
.SH DESCRIPTION
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -13,7 +13,7 @@
else(${ver} LESS 403)
add_definitions(-Wtraditional-conversion)
endif(${ver} LESS 403)
- #add_definitions(-Werror)
+ add_definitions(-Werror)
endif(CMAKE_COMPILER_IS_GNUCC)
if (NOT EXTERNAL_GSM)
@@ -28,16 +28,16 @@
# Format with: !xargs echo|tr ' ' '\n'|sort|column|expand|sed 's/^/ /'
set(effects_srcs
- bend earwax mixer rate stat
- biquad echo noiseprof remix stretch
- biquads echos noisered repeat swap
- chorus fade normalise resample synth
- compand fft4g output reverb tempo
- compandt filter pad reverse tremolo
- contrast flanger pan silence trim
- dcshift input phaser skeleff vol
- delay loudness pitch speed
- dither mcompand polyphas splice
+ bend earwax mixer remix stretch
+ biquad echo noiseprof repeat swap
+ biquads echos noisered resample synth
+ chorus fade normalise reverb tempo
+ compand fft4g output reverse tremolo
+ compandt filter pad silence trim
+ contrast flanger pan skeleff vol
+ dcshift input phaser speed
+ delay loudness polyphas splice
+ dither mcompand rate stat
)
set(formats_srcs
8svx dat ima-fmt s3-fmt u3-fmt
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -267,7 +267,7 @@
echo.c echos.c effects.c effects.h effects_i.c fade.c fft4g.c fft4g.h \
fifo.h filter.c flanger.c input.c ladspa.c loudness.c mcompand.c \
mixer.c noiseprof.c noisered.c noisered.h normalise.c output.c pad.c \
- pan.c phaser.c pitch.c polyphas.c rabbit.c rate.c \
+ pan.c phaser.c polyphas.c rabbit.c rate.c \
rate_filters.h rate_half_fir.h rate_poly_fir0.h rate_poly_fir.h \
remix.c repeat.c resample.c reverb.c reverse.c silence.c skeleff.c \
speed.c splice.c stat.c swap.c stretch.c synth.c tempo.c tremolo.c \
--- a/src/effects.c
+++ b/src/effects.c
@@ -33,7 +33,7 @@
/* FIXME: Not thread safe using globals */
sox_effects_globals_t sox_effects_globals =
- {sox_plot_off, 1, &sox_globals};
+ {sox_plot_off, &sox_globals};
/* Default effect handler functions for do-nothing situations: */
@@ -137,10 +137,6 @@
unsigned f;
sox_effect_t eff0; /* Copy of effect for flow 0 before calling start */
- if (effp->handler.flags & SOX_EFF_NULL) {
- lsx_report("has no effect (is a proxy effect)");
- return SOX_SUCCESS;
- }
effp->global_info = &chain->global_info;
effp->in_signal = *in;
effp->out_signal = *out;
--- a/src/pitch.c
+++ /dev/null
@@ -1,63 +1,0 @@
-/* libSoX effect: change the audio pitch (i.e. change pitch but not tempo)
- * Copyright (c) 2007 robs@users.sourceforge.net
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- *
- * Adjustment is given as a number of cents (100ths of a semitone) to
- * change. Implementation comprises a tempo change (performed by tempo)
- * and a speed change performed by whichever resampling effect is in effect.
- */
-
-#include "sox_i.h"
-#include <string.h>
-
-static int getopts(sox_effect_t * effp, int argc, char **argv)
-{
- double d;
- char dummy, arg[100], **argv2 = malloc(argc * sizeof(*argv2));
- int ret, pos = (argc > 1 && !strcmp(argv[1], "-q"))? 2 : 1;
-
- if (argc <= pos || sscanf(argv[pos], "%lf %c", &d, &dummy) != 1)
- return lsx_usage(effp);
-
- effp->global_info->speed *= d = pow(2., d / 1200); /* cents --> factor */
- sprintf(arg, "%g", 1 / d);
- memcpy(argv2, argv, argc * sizeof(*argv2));
- argv2[pos] = arg;
- ret = sox_tempo_effect_fn()->getopts(effp, argc, argv2);
- free(argv2);
- return ret;
-}
-
-sox_effect_handler_t const * sox_pitch_effect_fn(void)
-{
- static sox_effect_handler_t handler;
- handler = *sox_tempo_effect_fn();
- handler.name = "pitch";
- handler.usage = "[-q] shift-in-cents [segment-ms [search-ms [overlap-ms]]]",
- handler.getopts = getopts;
- handler.flags &= ~SOX_EFF_LENGTH;
- return &handler;
-}
-
-sox_effect_handler_t const * sox_key_effect_fn(void) /* old name for pitch */
-{
- static sox_effect_handler_t handler;
- handler = *sox_pitch_effect_fn();
- handler.name = "key";
- handler.flags |= SOX_EFF_DEPRECATED;
- return &handler;
-}
--- a/src/sox.c
+++ b/src/sox.c
@@ -1456,13 +1456,6 @@
calculate_combiner_signal_parameters();
set_combiner_and_output_encoding_parameters();
calculate_output_signal_parameters();
-
- /* Now take account of any net speed change specified by user effects by
- * adjusting the nominal sample rate at the output of the combiner. This
- * cannot be done inside calculate_combiner_signal_parameters since
- * it must be done after calculate_output_signal_parameters. */
- combiner_signal.rate *= sox_effects_globals.speed;
-
open_output_file();
if (!effects_chain)
--- a/src/sox.h
+++ b/src/sox.h
@@ -448,7 +448,6 @@
typedef struct sox_effect sox_effect_t;
struct sox_effects_globals { /* Global parameters (for effects) */
sox_plot_t plot; /* To help the user choose effect & options */
- double speed; /* Gather up all speed changes here, then resample */
sox_globals_t * global_info;
};
typedef struct sox_effects_globals sox_effects_globals_t;
--- a/src/speed.c
+++ b/src/speed.c
@@ -1,5 +1,5 @@
/* libSoX Effect: Adjust the audio speed (pitch and tempo together)
- * (c) 2006 robs@users.sourceforge.net
+ * (c) 2006,8 robs@users.sourceforge.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -24,22 +24,22 @@
#include "sox_i.h"
#include <string.h>
+typedef struct {
+ double factor;
+} priv_t;
+
static int getopts(sox_effect_t * effp, int n, char * * argv)
{
+ priv_t * p = (priv_t *) effp->priv;
sox_bool is_cents = sox_false;
- double speed;
- /* Be quietly compatible with the old speed effect: */
- if (n != 0 && strcmp(*argv, "-c") == 0)
- is_cents = sox_true, ++argv, --n;
-
if (n == 1) {
char c, dummy;
- int scanned = sscanf(*argv, "%lf%c %c", &speed, &c, &dummy);
+ int scanned = sscanf(*argv, "%lf%c %c", &p->factor, &c, &dummy);
if (scanned == 1 || (scanned == 2 && c == 'c')) {
is_cents |= scanned == 2;
- if (is_cents || speed > 0) {
- effp->global_info->speed *= is_cents? pow(2., speed/1200) : speed;
+ if (is_cents || p->factor > 0) {
+ p->factor = is_cents? pow(2., p->factor / 1200) : p->factor;
return SOX_SUCCESS;
}
}
@@ -47,10 +47,30 @@
return lsx_usage(effp);
}
+static int start(sox_effect_t * effp)
+{
+ priv_t * p = (priv_t *) effp->priv;
+
+ if (p->factor == 1)
+ return SOX_EFF_NULL;
+
+ effp->out_signal.rate = effp->in_signal.rate * p->factor;
+ return SOX_SUCCESS;
+}
+
+static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
+ sox_sample_t * obuf, size_t * isamp, size_t * osamp)
+{
+ size_t len = *isamp = *osamp = min(*isamp, *osamp);
+ memcpy(obuf, ibuf, len * sizeof(*osamp));
+ (void)effp;
+ return SOX_SUCCESS;
+}
+
sox_effect_handler_t const * sox_speed_effect_fn(void)
{
static sox_effect_handler_t handler = {
- "speed", "factor[c]", SOX_EFF_NULL | SOX_EFF_LENGTH,
- getopts, 0, 0, 0, 0, 0, 0};
+ "speed", "factor[c]",SOX_EFF_NULL|SOX_EFF_MCHAN|SOX_EFF_RATE|SOX_EFF_LENGTH,
+ getopts, start, flow, 0, 0, 0, sizeof(priv_t)};
return &handler;
}
--- a/src/tempo.c
+++ b/src/tempo.c
@@ -1,5 +1,5 @@
-/* libSoX effect: change tempo (alter duration, maintain pitch)
- * Copyright (c) 2007 robs@users.sourceforge.net
+/* libSoX effect: change tempo (and duration) or pitch (maintain duration)
+ * Copyright (c) 2007,8 robs@users.sourceforge.net
* Based on ideas from Olli Parviainen's SoundTouch Library.
*
* This library is free software; you can redistribute it and/or modify it
@@ -302,5 +302,57 @@
SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_GETOPT,
getopts, start, flow, drain, stop, NULL, sizeof(priv_t)
};
+ return &handler;
+}
+
+/*---------------------------------- pitch -----------------------------------*/
+
+static int pitch_getopts(sox_effect_t * effp, int argc, char **argv)
+{
+ double d;
+ char dummy, arg[100], **argv2 = malloc(argc * sizeof(*argv2));
+ int result, pos = (argc > 1 && !strcmp(argv[1], "-q"))? 2 : 1;
+
+ if (argc <= pos || sscanf(argv[pos], "%lf %c", &d, &dummy) != 1)
+ return lsx_usage(effp);
+
+ d = pow(2., d / 1200); /* cents --> factor */
+ sprintf(arg, "%g", 1 / d);
+ memcpy(argv2, argv, argc * sizeof(*argv2));
+ argv2[pos] = arg;
+ result = getopts(effp, argc, argv2);
+ free(argv2);
+ return result;
+}
+
+static int pitch_start(sox_effect_t * effp)
+{
+ priv_t * p = (priv_t *) effp->priv;
+ int result = start(effp);
+
+ effp->out_signal.rate = effp->in_signal.rate / p->factor;
+ return result;
+}
+
+sox_effect_handler_t const * sox_pitch_effect_fn(void)
+{
+ static sox_effect_handler_t handler;
+ handler = *sox_tempo_effect_fn();
+ handler.name = "pitch";
+ handler.usage = "[-q] shift-in-cents [segment-ms [search-ms [overlap-ms]]]",
+ handler.getopts = pitch_getopts;
+ handler.start = pitch_start;
+ handler.flags &= ~SOX_EFF_LENGTH;
+ return &handler;
+}
+
+/*------------------------- key (old name for pitch) -------------------------*/
+
+sox_effect_handler_t const * sox_key_effect_fn(void)
+{
+ static sox_effect_handler_t handler;
+ handler = *sox_pitch_effect_fn();
+ handler.name = "key";
+ handler.flags |= SOX_EFF_DEPRECATED;
return &handler;
}