ref: 2dd8e848393dff0a4be2f4b54e242995f036c7d7
parent: 1338952d0f41fb87ff45d313cdc08fb22f267ea5
author: robs <robs>
date: Sun Jun 17 17:12:01 EDT 2007
Can now run an effects chain with e.g. upsample, filter, downsample, dither. Cleaned up speed hack so as not to affect resampling effects.
--- a/src/biquad.c
+++ b/src/biquad.c
@@ -67,10 +67,10 @@
if (effp->global_info->plot == sox_plot_octave) {
printf(
"%% GNU Octave file (may also work with MATLAB(R) )\n"
- "title('SoX effect: %s gain=%g frequency=%g %s=%g (rate=%u)')\n"
+ "title('SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)')\n"
"xlabel('Frequency (Hz)')\n"
"ylabel('Amplitude Response (dB)')\n"
- "Fs=%u;minF=10;maxF=Fs/2;\n"
+ "Fs=%g;minF=10;maxF=Fs/2;\n"
"axis([minF maxF -35 25])\n"
"sweepF=logspace(log10(minF),log10(maxF),200);\n"
"grid on\n"
@@ -87,10 +87,10 @@
if (effp->global_info->plot == sox_plot_gnuplot) {
printf(
"# gnuplot file\n"
- "set title 'SoX effect: %s gain=%g frequency=%g %s=%g (rate=%u)'\n"
+ "set title 'SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)'\n"
"set xlabel 'Frequency (Hz)'\n"
"set ylabel 'Amplitude Response (dB)'\n"
- "Fs=%u.\n"
+ "Fs=%g\n"
"b0=%g; b1=%g; b2=%g; a1=%g; a2=%g\n"
"o=2*pi/Fs\n"
"H(f)=sqrt((b0*b0+b1*b1+b2*b2+2.*(b0*b1+b1*b2)*cos(f*o)+2.*(b0*b2)*cos(2.*f*o))/(1.+a1*a1+a2*a2+2.*(a1+a1*a2)*cos(f*o)+2.*a2*cos(2.*f*o)))\n"
--- a/src/echo.c
+++ b/src/echo.c
@@ -141,7 +141,7 @@
if ( echo->samples[i] > (sox_ssize_t)DELAY_BUFSIZ )
{
sox_fail("echo: delay must be less than %g seconds!",
- DELAY_BUFSIZ / (float) effp->ininfo.rate );
+ DELAY_BUFSIZ / effp->ininfo.rate );
return (SOX_EOF);
}
if ( echo->decay[i] < 0.0 )
--- a/src/echos.c
+++ b/src/echos.c
@@ -134,7 +134,7 @@
if ( echos->samples[i] > (sox_ssize_t)DELAY_BUFSIZ )
{
sox_fail("echos: delay must be less than %g seconds!",
- DELAY_BUFSIZ / (float) effp->ininfo.rate );
+ DELAY_BUFSIZ / effp->ininfo.rate );
return (SOX_EOF);
}
if ( echos->decay[i] < 0.0 )
--- a/src/hcom.c
+++ b/src/hcom.c
@@ -244,7 +244,7 @@
{
register struct writepriv *p = (struct writepriv *) ft->priv;
- switch (ft->signal.rate) {
+ switch ((int)ft->signal.rate) {
case 22050:
case 22050/2:
case 22050/3:
--- a/src/ladspa.c
+++ b/src/ladspa.c
@@ -198,8 +198,8 @@
unsigned long i;
/* Instantiate the plugin */
- sox_debug("rate for plugin is %d", effp->ininfo.rate);
- l_st->handle = l_st->desc->instantiate(l_st->desc, effp->ininfo.rate);
+ sox_debug("rate for plugin is %g", effp->ininfo.rate);
+ l_st->handle = l_st->desc->instantiate(l_st->desc, (unsigned long)effp->ininfo.rate);
if (l_st->handle == NULL) {
sox_fail("could not instantiate plugin");
return SOX_EOF;
--- a/src/polyphas.c
+++ b/src/polyphas.c
@@ -351,6 +351,8 @@
if (effp->ininfo.rate == effp->outinfo.rate)
return SOX_EFF_NULL;
+ effp->outinfo.channels = effp->ininfo.channels;
+
rate->lcmrate = sox_lcm((sox_ssample_t)effp->ininfo.rate,
(sox_ssample_t)effp->outinfo.rate);
@@ -359,8 +361,8 @@
* 16 bits x 16 bits = 32 bits, which we can handle.
*/
- rate->inskip = rate->lcmrate / effp->ininfo.rate;
- rate->outskip = rate->lcmrate / effp->outinfo.rate;
+ rate->inskip = rate->lcmrate / (sox_ssample_t)effp->ininfo.rate;
+ rate->outskip = rate->lcmrate / (sox_ssample_t)effp->outinfo.rate;
rate->Factor = (double)rate->inskip / (double)rate->outskip;
rate->inpipe = 0;
{
@@ -374,7 +376,7 @@
rate->total = total;
/* l1 and l2 are now lists of the up/down factors for conversion */
- sox_debug("Poly: input rate %d, output rate %d. %d stages.",
+ sox_debug("Poly: input rate %g, output rate %g. %d stages.",
effp->ininfo.rate, effp->outinfo.rate,total);
sox_debug("Poly: window: %s size: %d cutoff: %f.",
(rate->win_type == 0) ? ("nut") : ("ham"), rate->win_width, rate->cutoff);
--- a/src/rabbit.c
+++ b/src/rabbit.c
@@ -28,6 +28,7 @@
/* Private data for resampling */
typedef struct {
int converter_type; /* SRC converter type */
+ double out_rate;
SRC_STATE *state; /* SRC state struct */
SRC_DATA *data; /* SRC_DATA control struct */
sox_size_t i_alloc, o_alloc; /* Samples allocated in data->data_{in,out} */
@@ -36,35 +37,40 @@
/*
* Process options
*/
-static int getopts(sox_effect_t * effp, int n, char **argv)
+static int getopts(sox_effect_t * effp, int argc, char **argv)
{
rabbit_t r = (rabbit_t) effp->priv;
+ char dummy; /* To check for extraneous chars. */
r->converter_type = SRC_SINC_BEST_QUALITY;
- if (n >= 1) {
+ if (argc) {
if (!strcmp(argv[0], "-c0")) {
r->converter_type = SRC_SINC_BEST_QUALITY;
- n--; argv++;
+ argc--; argv++;
} else if (!strcmp(argv[0], "-c1")) {
r->converter_type = SRC_SINC_MEDIUM_QUALITY;
- n--; argv++;
+ argc--; argv++;
} else if (!strcmp(argv[0], "-c2")) {
r->converter_type = SRC_SINC_FASTEST;
- n--; argv++;
+ argc--; argv++;
} else if (!strcmp(argv[0], "-c3")) {
r->converter_type = SRC_ZERO_ORDER_HOLD;
- n--; argv++;
+ argc--; argv++;
} else if (!strcmp(argv[0], "-c4")) {
r->converter_type = SRC_LINEAR;
- n--; argv++;
+ argc--; argv++;
}
}
- if (n >= 1)
- return sox_usage(effp);
+ r->out_rate = HUGE_VAL;
+ if (argc) {
+ if (sscanf(*argv, "%lf %c", &r->out_rate, &dummy) != 1 || r->out_rate <= 0)
+ return sox_usage(effp);
+ argc--; argv++;
+ }
- return SOX_SUCCESS;
+ return argc? sox_usage(effp) : SOX_SUCCESS;
}
/*
@@ -74,23 +80,16 @@
{
rabbit_t r = (rabbit_t) effp->priv;
int err = 0;
+ double out_rate = r->out_rate != HUGE_VAL? r->out_rate : effp->outinfo.rate;
- /* The next line makes the "speed" effect accurate; it's needed because
- * ininfo.rate (sox_rate_t) isn't floating point (but it's probably not worth
- * changing sox_rate_t just because of this): */
- double in_rate = floor(effp->ininfo.rate / effp->global_info->speed + .5)
- * effp->global_info->speed;
-
- if (in_rate == effp->outinfo.rate)
+ if (effp->ininfo.rate == out_rate)
return SOX_EFF_NULL;
- if (effp->ininfo.channels != effp->outinfo.channels) {
- sox_fail("number of Input and Output channels must be equal to use rabbit effect");
- return SOX_EOF;
- }
+ effp->outinfo.channels = effp->ininfo.channels;
+ effp->outinfo.rate = out_rate;
r->data = (SRC_DATA *)xcalloc(1, sizeof(SRC_DATA));
- r->data->src_ratio = (double)effp->outinfo.rate / in_rate;
+ r->data->src_ratio = out_rate / effp->ininfo.rate;
r->i_alloc = r->o_alloc = 0;
r->state = src_new(r->converter_type, effp->ininfo.channels, &err);
if (err) {
@@ -112,34 +111,31 @@
SRC_DATA *d = r->data;
unsigned int channels = effp->ininfo.channels;
sox_size_t i;
+ sox_size_t isamples0 = d->input_frames * channels;
+ sox_size_t isamples = isamples0 + *isamp;
+ sox_size_t osamples = isamples * (d->src_ratio + 0.01) + 8;
- if (isamp && *isamp > 0) {
- sox_size_t isamples0 = d->input_frames * channels;
- sox_size_t isamples = isamples0 + *isamp;
- sox_size_t osamples = isamples * (d->src_ratio + 0.01) + 8;
+ if (osamples > *osamp) {
+ osamples = *osamp;
+ isamples = (osamples - 8) / (d->src_ratio + 0.01);
+ }
- if (osamples > sox_bufsiz) {
- osamples = sox_bufsiz;
- isamples = (osamples - 8) / (d->src_ratio + 0.01);
- }
+ if (r->i_alloc < isamples) {
+ d->data_in = xrealloc(d->data_in, isamples * sizeof(float));
+ r->i_alloc = isamples;
+ }
+ if (r->o_alloc < osamples) {
+ d->data_out = xrealloc(d->data_out, osamples * sizeof(float));
+ r->o_alloc = osamples;
+ d->output_frames = osamples / channels;
+ }
- if (r->i_alloc < isamples) {
- d->data_in = xrealloc(d->data_in, isamples * sizeof(float));
- r->i_alloc = isamples;
- }
- if (r->o_alloc < osamples) {
- d->data_out = xrealloc(d->data_out, osamples * sizeof(float));
- r->o_alloc = osamples;
- d->output_frames = osamples / channels;
- }
+ for (i = 0; i < isamples - isamples0; i++)
+ d->data_in[isamples0 + i] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[i], effp->clips);
+ *isamp = i;
- for (i = 0; i < isamples - isamples0; i++)
- d->data_in[isamples0 + i] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[i], effp->clips);
+ d->input_frames = isamples / channels;
- *isamp = isamples - isamples0;
- d->input_frames = isamples / channels;
- }
-
*osamp = 0;
while (d->input_frames > 0 || d->end_of_input != 0) {
if (src_process(r->state, r->data) != 0) {
@@ -146,22 +142,16 @@
sox_fail("%s", src_strerror(src_error(r->state)));
return SOX_EOF;
}
- if (d->input_frames_used) {
- d->input_frames -= d->input_frames_used;
- if (d->input_frames)
- memcpy(d->data_in,
- d->data_in + d->input_frames_used * sizeof(float),
- d->input_frames * sizeof(float));
- }
+ d->input_frames -= d->input_frames_used;
+ if (d->input_frames)
+ memmove(d->data_in, d->data_in + d->input_frames_used * sizeof(float),
+ d->input_frames * sizeof(float));
- *osamp = d->output_frames_gen * channels;
- if (! *osamp)
- break;
-
for (i = 0; i < (sox_size_t)d->output_frames_gen * channels; i++)
obuf[i] = SOX_FLOAT_32BIT_TO_SAMPLE(d->data_out[i], effp->clips);
+ *osamp += i;
- if (d->end_of_input)
+ if (!d->output_frames_gen || d->end_of_input)
break;
}
@@ -174,8 +164,9 @@
static int drain(sox_effect_t * effp, sox_ssample_t *obuf, sox_size_t *osamp)
{
rabbit_t r = (rabbit_t) effp->priv;
+ static sox_size_t isamp = 0;
r->data->end_of_input = 1;
- return flow(effp, NULL, obuf, NULL, osamp);
+ return flow(effp, NULL, obuf, &isamp, osamp);
}
/*
@@ -193,7 +184,7 @@
const sox_effect_handler_t *sox_rabbit_effect_fn(void)
{
static sox_effect_handler_t handler = {
- "rabbit", "[-c0|-c1|-c2|-c3|-c4]",
+ "rabbit", "[-c0|-c1|-c2|-c3|-c4] [rate]",
SOX_EFF_RATE | SOX_EFF_MCHAN,
getopts, start, flow, drain, stop, NULL
};
--- a/src/resample.c
+++ b/src/resample.c
@@ -195,16 +195,12 @@
long Xoff, gcdrate;
int i;
- /* The next line makes the "speed" effect accurate; it's needed because
- * ininfo.rate (sox_rate_t) isn't floating point (but it's probably not worth
- * changing sox_rate_t just because of this): */
- double in_rate = floor(effp->ininfo.rate / effp->global_info->speed + .5)
- * effp->global_info->speed;
-
- if (in_rate == effp->outinfo.rate)
+ if (effp->ininfo.rate == effp->outinfo.rate)
return SOX_EFF_NULL;
- r->Factor = (double) effp->outinfo.rate / in_rate;
+ effp->outinfo.channels = effp->ininfo.channels;
+
+ r->Factor = effp->outinfo.rate / effp->ininfo.rate;
gcdrate = sox_gcd((long) effp->ininfo.rate, (long) effp->outinfo.rate);
r->a = effp->ininfo.rate / gcdrate;
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -174,7 +174,7 @@
if ( reverb->samples[i] > DELAY_BUFSIZ )
{
sox_fail("reverb: delay must be less than %g seconds!",
- DELAY_BUFSIZ / (float) effp->ininfo.rate );
+ DELAY_BUFSIZ / effp->ininfo.rate );
return(SOX_EOF);
}
/* Compute a realistic decay */
--- a/src/sox.c
+++ b/src/sox.c
@@ -214,6 +214,7 @@
f->signal.size = -1;
f->signal.encoding = SOX_ENCODING_UNKNOWN;
f->signal.channels = 0;
+ f->signal.rate = 0;
f->signal.reverse_bytes = SOX_OPTION_DEFAULT;
f->signal.reverse_nibbles = SOX_OPTION_DEFAULT;
f->signal.reverse_bits = SOX_OPTION_DEFAULT;
@@ -836,11 +837,10 @@
break;
case 'r':
- if (sscanf(optarg, "%i %c", &i, &dummy) != 1 || i <= 0) {
- sox_fail("Rate value `%s' is not a positive integer", optarg);
+ if (sscanf(optarg, "%lf %c", &f->signal.rate, &dummy) != 1 || f->signal.rate <= 0) {
+ sox_fail("Rate value `%s' is not a positive number", optarg);
exit(1);
}
- f->signal.rate = i;
break;
case 'v':
@@ -950,7 +950,7 @@
fprintf(stderr,
"Channels : %u\n"
- "Sample Rate : %u\n",
+ "Sample Rate : %g\n",
f->ft->signal.channels,
f->ft->signal.rate);
@@ -1244,7 +1244,7 @@
for (i = 0; i < sox_neffects; ++i) {
sox_effect_t * effp = &sox_effects[i][0];
- sox_report("effects chain: %-10s %uHz %u channels %u bits %s",
+ sox_report("effects chain: %-10s %gHz %u channels %u bits %s",
effp->handler.name, effp->ininfo.rate, effp->ininfo.channels, effp->ininfo.size * 8,
(effp->handler.flags & SOX_EFF_MCHAN)? "(multi)" : "");
}
@@ -1403,7 +1403,7 @@
if (ofile->signal.channels == 0)
ofile->signal.channels = combiner.channels;
- combiner.rate = combiner.rate * effects_global_info.speed + .5;
+ combiner.rate = combiner.rate * effects_global_info.speed;
for (i = 0; i < nuser_effects; i++)
known_length = known_length && !(user_efftab[i].handler.flags & SOX_EFF_LENGTH);
--- a/src/sox.h
+++ b/src/sox.h
@@ -155,12 +155,14 @@
((d) < 0? (d) <= SOX_SAMPLE_MIN - 0.5? ++(clips), SOX_SAMPLE_MIN: (d) - 0.5 \
: (d) >= SOX_SAMPLE_MAX + 0.5? ++(clips), SOX_SAMPLE_MAX: (d) + 0.5)
-/* Rvalue MACRO to clip a sox_sample_t to 24 bits,
+/* Rvalue MACRO to clip an integer to a given number of bits
* and increment a counter if clipping occurs.
*/
-#define SOX_24BIT_CLIP_COUNT(l, clips) \
- ((l) >= ((sox_ssample_t)1 << 23)? ++(clips), ((sox_ssample_t)1 << 23) - 1 : \
- (l) <=-((sox_ssample_t)1 << 23)? ++(clips),-((sox_ssample_t)1 << 23) + 1 : (l))
+#define SOX_INTEGER_CLIP_COUNT(bits,i,clips) ( \
+ (i) >(1 << ((bits)-1))- 1? ++(clips),(1 << ((bits)-1))- 1 : \
+ (i) <-1 << ((bits)-1) ? ++(clips),-1 << ((bits)-1) : (i))
+#define SOX_16BIT_CLIP_COUNT(i,clips) SOX_INTEGER_CLIP_COUNT(16,i,clips)
+#define SOX_24BIT_CLIP_COUNT(i,clips) SOX_INTEGER_CLIP_COUNT(24,i,clips)
@@ -174,7 +176,7 @@
#define SOX_SSIZE_MAX 0x7fffffff
#define SOX_SSIZE_MIN (-SOX_SSIZE_MAX - 1)
-typedef unsigned sox_rate_t;
+typedef double sox_rate_t;
/* Warning, this is a MAX value used in the library. Each format and
* effect may have its own limitations of rate.
*/
--- a/src/stat.c
+++ b/src/stat.c
@@ -146,7 +146,7 @@
if (stat->fft_offset >= stat->fft_size) {
stat->fft_offset = 0;
- print_power_spectrum(stat->fft_size, (double)effp->ininfo.rate, stat->re_in, stat->re_out);
+ print_power_spectrum(stat->fft_size, effp->ininfo.rate, stat->re_in, stat->re_out);
}
}
@@ -215,7 +215,7 @@
for (x = stat->fft_offset; x < stat->fft_size; x++)
stat->re_in[x] = 0;
- print_power_spectrum(stat->fft_size, (double)effp->ininfo.rate, stat->re_in, stat->re_out);
+ print_power_spectrum(stat->fft_size, effp->ininfo.rate, stat->re_in, stat->re_out);
}
*osamp = 0;