ref: 7c691371778b480154fb5c9f66c9541d3a62d807
parent: 30112cdfaca3ffe9d8869322e0ee07c96a59152c
author: rrt <rrt>
date: Wed Dec 27 17:45:30 EST 2006
stretch of 1.0 works. Tidy code, fix typos in comments.
--- a/src/stretch.c
+++ b/src/stretch.c
@@ -2,9 +2,9 @@
* (c) march/april 2000 Fabien COELHO <fabien@coelho.net> for sox.
*
* Basic time stretcher.
- * cross fade samples so as to go slower of faster.
+ * cross fade samples so as to go slower or faster.
*
- * The automaton is based on 6 parameters:
+ * The filter is based on 6 parameters:
* - stretch factor f
* - window size w
* - input step i
@@ -43,117 +43,108 @@
typedef struct
{
- /* options
- * Q: maybe shift could be allowed > 1.0 with factor < 1.0 ???
- */
- double factor; /* strech factor. 1.0 means copy. */
- double window; /* window in ms */
- st_fading_t fade; /* type of fading */
- double shift; /* shift ratio wrt window. <1.0 */
- double fading; /* fading ratio wrt window. <0.5 */
+ /* options
+ * FIXME: maybe shift could be allowed > 1.0 with factor < 1.0 ???
+ */
+ double factor; /* strech factor. 1.0 means copy. */
+ double window; /* window in ms */
+ st_fading_t fade; /* type of fading */
+ double shift; /* shift ratio wrt window. <1.0 */
+ double fading; /* fading ratio wrt window. <0.5 */
- /* internal stuff
- */
- stretch_status_t state; /* automaton status */
+ /* internal stuff */
+ stretch_status_t state; /* automaton status */
- st_size_t size; /* buffer size */
- st_size_t index; /* next available element */
- st_sample_t *ibuf; /* input buffer */
- st_size_t ishift; /* input shift */
+ st_size_t size; /* buffer size */
+ st_size_t index; /* next available element */
+ st_sample_t *ibuf; /* input buffer */
+ st_size_t ishift; /* input shift */
+
+ st_size_t oindex; /* next evailable element */
+ double * obuf; /* output buffer */
+ st_size_t oshift; /* output shift */
+
+ st_size_t fsize; /* fading size */
+ double * fbuf; /* fading, 1.0 -> 0.0 */
+
+} *stretch_t;
- st_size_t oindex; /* next evailable element */
- double * obuf; /* output buffer */
- st_size_t oshift; /* output shift */
-
- st_size_t fsize; /* fading size */
- double * fbuf; /* fading, 1.0 -> 0.0 */
-
-} * stretch_t;
-
/*
* Process options
*/
static int st_stretch_getopts(eff_t effp, int n, char **argv)
{
- char usage[1024];
- stretch_t stretch = (stretch_t) effp->priv;
+ char usage[1024];
+ stretch_t stretch = (stretch_t) effp->priv;
- /* default options */
- stretch->factor = 1.0; /* default is no change */
- stretch->window = DEFAULT_STRETCH_WINDOW;
- stretch->fade = st_linear_fading;
+ /* default options */
+ stretch->factor = 1.0; /* default is no change */
+ stretch->window = DEFAULT_STRETCH_WINDOW;
+ stretch->fade = st_linear_fading;
- if (n>0 && !sscanf(argv[0], "%lf", &stretch->factor))
- {
- sprintf (usage, "%s\n\terror while parsing factor", st_stretch_effect.usage);
- st_fail(usage);
- return ST_EOF;
- }
+ if (n > 0 && !sscanf(argv[0], "%lf", &stretch->factor)) {
+ sprintf(usage, "%s\n\terror while parsing factor", st_stretch_effect.usage);
+ st_fail(usage);
+ return ST_EOF;
+ }
- if (n>1 && !sscanf(argv[1], "%lf", &stretch->window))
- {
- sprintf (usage, "%s\n\terror while parsing window size", st_stretch_effect.usage);
- st_fail(usage);
- return ST_EOF;
- }
+ if (n > 1 && !sscanf(argv[1], "%lf", &stretch->window)) {
+ sprintf(usage, "%s\n\terror while parsing window size", st_stretch_effect.usage);
+ st_fail(usage);
+ return ST_EOF;
+ }
- if (n>2)
- {
- switch (argv[2][0])
- {
- case 'l':
- case 'L':
- stretch->fade = st_linear_fading;
- break;
- default:
- sprintf (usage, "%s\n\terror while parsing fade type", st_stretch_effect.usage);
- st_fail(usage);
- return ST_EOF;
- }
+ if (n > 2) {
+ switch (argv[2][0]) {
+ case 'l':
+ case 'L':
+ stretch->fade = st_linear_fading;
+ break;
+ default:
+ sprintf (usage, "%s\n\terror while parsing fade type", st_stretch_effect.usage);
+ st_fail(usage);
+ return ST_EOF;
}
+ }
- /* default shift depends whether we go slower or faster */
- stretch->shift = (stretch->factor <= 1.0) ?
- DEFAULT_FAST_SHIFT_RATIO: DEFAULT_SLOW_SHIFT_RATIO;
+ /* default shift depends whether we go slower or faster */
+ stretch->shift = (stretch->factor <= 1.0) ?
+ DEFAULT_FAST_SHIFT_RATIO: DEFAULT_SLOW_SHIFT_RATIO;
- if (n>3 && !sscanf(argv[3], "%lf", &stretch->shift))
- {
- sprintf (usage, "%s\n\terror while parsing shift ratio", st_stretch_effect.usage);
- st_fail(usage);
- return ST_EOF;
- }
+ if (n > 3 && !sscanf(argv[3], "%lf", &stretch->shift)) {
+ sprintf (usage, "%s\n\terror while parsing shift ratio", st_stretch_effect.usage);
+ st_fail(usage);
+ return ST_EOF;
+ }
- if (stretch->shift > 1.0 || stretch->shift <= 0.0)
- {
- sprintf (usage, "%s\n\terror with shift ratio value", st_stretch_effect.usage);
- st_fail(usage);
- return ST_EOF;
- }
+ if (stretch->shift > 1.0 || stretch->shift <= 0.0) {
+ sprintf(usage, "%s\n\terror with shift ratio value", st_stretch_effect.usage);
+ st_fail(usage);
+ return ST_EOF;
+ }
- /* default fading stuff...
- it makes sense for factor >= 0.5
- */
- if (stretch->factor<1.0)
- stretch->fading = 1.0 - (stretch->factor*stretch->shift);
- else
- stretch->fading = 1.0 - stretch->shift;
- if (stretch->fading > 0.5) stretch->fading = 0.5;
+ /* default fading stuff...
+ it makes sense for factor >= 0.5 */
+ if (stretch->factor < 1.0)
+ stretch->fading = 1.0 - (stretch->factor * stretch->shift);
+ else
+ stretch->fading = 1.0 - stretch->shift;
+ if (stretch->fading > 0.5)
+ stretch->fading = 0.5;
+
+ if (n > 4 && !sscanf(argv[4], "%lf", &stretch->fading)) {
+ sprintf(usage, "%s\n\terror while parsing fading ratio", st_stretch_effect.usage);
+ st_fail(usage);
+ return ST_EOF;
+ }
- if (n>4 && !sscanf(argv[4], "%lf", &stretch->fading))
- {
- sprintf (usage, "%s\n\terror while parsing fading ratio", st_stretch_effect.usage);
- st_fail(usage);
- return ST_EOF;
- }
-
- if (stretch->fading > 0.5 || stretch->fading < 0.0)
- {
- sprintf (usage, "%s\n\terror with fading ratio value", st_stretch_effect.usage);
- st_fail(usage);
- return ST_EOF;
- }
-
- return ST_SUCCESS;
+ if (stretch->fading > 0.5 || stretch->fading < 0.0) {
+ sprintf(usage, "%s\n\terror with fading ratio value", st_stretch_effect.usage);
+ st_fail(usage);
+ return ST_EOF;
+ }
+
+ return ST_SUCCESS;
}
/*
@@ -161,100 +152,90 @@
*/
static int st_stretch_start(eff_t effp)
{
- stretch_t stretch = (stretch_t) effp->priv;
- st_size_t i;
+ stretch_t stretch = (stretch_t)effp->priv;
+ st_size_t i;
- if (stretch->factor == 1)
- return ST_EFF_NULL;
+ /* FIXME: not necessary. taken care by effect processing? */
+ if (effp->outinfo.channels != effp->ininfo.channels) {
+ st_fail("stretch cannot handle different channels (in=%d, out=%d)"
+ " use avg or pan", effp->ininfo.channels, effp->outinfo.channels);
+ return ST_EOF;
+ }
- /* not necessary. taken care by effect processing? */
- if (effp->outinfo.channels != effp->ininfo.channels)
- {
- st_fail("STRETCH cannot handle different channels (in=%d, out=%d)"
- " use avg or pan", effp->ininfo.channels, effp->outinfo.channels);
- return ST_EOF;
- }
+ if (effp->outinfo.rate != effp->ininfo.rate) {
+ st_fail("stretch cannot handle different rates (in=%ld, out=%ld)"
+ " use resample or rate", effp->ininfo.rate, effp->outinfo.rate);
+ return ST_EOF;
+ }
- if (effp->outinfo.rate != effp->ininfo.rate)
- {
- st_fail("STRETCH cannot handle different rates (in=%ld, out=%ld)"
- " use resample or rate", effp->ininfo.rate, effp->outinfo.rate);
- return ST_EOF;
- }
+ stretch->state = input_state;
- stretch->state = input_state;
+ stretch->size = (int)(effp->outinfo.rate * 0.001 * stretch->window);
+ /* start in the middle of an input to avoid initial fading... */
+ stretch->index = stretch->size / 2;
+ stretch->ibuf = (st_sample_t *)xmalloc(stretch->size * sizeof(st_sample_t));
- stretch->size = (int)(effp->outinfo.rate * 0.001 * stretch->window);
- /* start in the middle of an input to avoid initial fading... */
- stretch->index = stretch->size/2;
- stretch->ibuf = (st_sample_t *) xmalloc(stretch->size * sizeof(st_sample_t));
+ /* the shift ratio deal with the longest of ishift/oshift
+ hence ishift<=size and oshift<=size. */
+ if (stretch->factor < 1.0) {
+ stretch->ishift = stretch->shift * stretch->size;
+ stretch->oshift = stretch->factor * stretch->ishift;
+ } else {
+ stretch->oshift = stretch->shift * stretch->size;
+ stretch->ishift = stretch->oshift / stretch->factor;
+ }
+ assert(stretch->ishift <= stretch->size);
+ assert(stretch->oshift <= stretch->size);
- /* the shift ratio deal with the longest of ishift/oshift
- hence ishift<=size and oshift<=size.
- */
- if (stretch->factor < 1.0) {
- stretch->ishift = stretch->shift * stretch->size;
- stretch->oshift = stretch->factor * stretch->ishift;
- } else {
- stretch->oshift = stretch->shift * stretch->size;
- stretch->ishift = stretch->oshift / stretch->factor;
- }
- assert(stretch->ishift <= stretch->size);
- assert(stretch->oshift <= stretch->size);
-
- stretch->oindex = stretch->index; /* start as synchronized */
- stretch->obuf = (double *)xmalloc(stretch->size * sizeof(double));
- stretch->fsize = (int) (stretch->fading * stretch->size);
- stretch->fbuf = (double *)xmalloc(stretch->fsize * sizeof(double));
+ stretch->oindex = stretch->index; /* start as synchronized */
+ stretch->obuf = (double *)xmalloc(stretch->size * sizeof(double));
+ stretch->fsize = (int)(stretch->fading * stretch->size);
+ stretch->fbuf = (double *)xmalloc(stretch->fsize * sizeof(double));
- /* initialize buffers
- */
- for (i=0; i<stretch->size; i++)
- stretch->ibuf[i] = 0;
+ /* initialize buffers */
+ for (i = 0; i<stretch->size; i++)
+ stretch->ibuf[i] = 0;
- for (i=0; i<stretch->size; i++)
- stretch->obuf[i] = 0.0;
+ for (i = 0; i<stretch->size; i++)
+ stretch->obuf[i] = 0.0;
- if (stretch->fsize>1)
- {
- register double slope = 1.0 / (stretch->fsize - 1);
-
- stretch->fbuf[0] = 1.0;
- for (i=1; i<stretch->fsize-1; i++)
- stretch->fbuf[i] = slope * (stretch->fsize-i-1);
- stretch->fbuf[stretch->fsize-1] = 0.0;
- } else if (stretch->fsize==1)
- stretch->fbuf[0] = 1.0;
+ if (stretch->fsize>1) {
+ double slope = 1.0 / (stretch->fsize - 1);
+ stretch->fbuf[0] = 1.0;
+ for (i = 1; i < stretch->fsize - 1; i++)
+ stretch->fbuf[i] = slope * (stretch->fsize - i - 1);
+ stretch->fbuf[stretch->fsize - 1] = 0.0;
+ } else if (stretch->fsize == 1)
+ stretch->fbuf[0] = 1.0;
- st_debug("start: (f=%.2f w=%.2f r=%.2f f=%.2f)"
- " st=%d s=%d ii=%d is=%d oi=%d os=%d fs=%d\n",
- stretch->factor, stretch->window, stretch->shift, stretch->fading,
- stretch->state, stretch->size, stretch->index, stretch->ishift,
- stretch->oindex, stretch->oshift, stretch->fsize);
+ st_debug("start: (f=%.2f w=%.2f r=%.2f f=%.2f)"
+ " st=%d s=%d ii=%d is=%d oi=%d os=%d fs=%d\n",
+ stretch->factor, stretch->window, stretch->shift, stretch->fading,
+ stretch->state, stretch->size, stretch->index, stretch->ishift,
+ stretch->oindex, stretch->oshift, stretch->fsize);
- return ST_SUCCESS;
+ return ST_SUCCESS;
}
-/* accumulates input ibuf to output obuf with fading fbuf
- */
+/* accumulates input ibuf to output obuf with fading fbuf */
static void combine(stretch_t stretch)
{
- register int i, size, fsize;
+ int i, size, fsize;
- size = stretch->size;
- fsize = stretch->fsize;
+ size = stretch->size;
+ fsize = stretch->fsize;
- /* fade in */
- for (i=0; i<fsize; i++)
- stretch->obuf[i] += stretch->fbuf[fsize-i-1]*stretch->ibuf[i];
+ /* fade in */
+ for (i = 0; i < fsize; i++)
+ stretch->obuf[i] += stretch->fbuf[fsize - i - 1] * stretch->ibuf[i];
- /* steady state */
- for (; i<size-fsize; i++)
- stretch->obuf[i] += stretch->ibuf[i];
+ /* steady state */
+ for (; i < size - fsize; i++)
+ stretch->obuf[i] += stretch->ibuf[i];
- /* fade out */
- for (; i<size; i++)
- stretch->obuf[i] += stretch->fbuf[i-size+fsize]*stretch->ibuf[i];
+ /* fade out */
+ for (; i<size; i++)
+ stretch->obuf[i] += stretch->fbuf[i - size + fsize] * stretch->ibuf[i];
}
/*
@@ -263,73 +244,63 @@
static int st_stretch_flow(eff_t effp, const st_sample_t *ibuf, st_sample_t *obuf,
st_size_t *isamp, st_size_t *osamp)
{
- stretch_t stretch = (stretch_t) effp->priv;
- st_size_t iindex, oindex;
- st_size_t i;
+ stretch_t stretch = (stretch_t) effp->priv;
+ st_size_t iindex = 0, oindex = 0;
+ st_size_t i;
- iindex = 0;
- oindex = 0;
+ while (iindex<*isamp && oindex<*osamp) {
+ if (stretch->state == input_state) {
+ st_size_t tocopy = min(*isamp-iindex,
+ stretch->size-stretch->index);
- while (iindex<*isamp && oindex<*osamp)
- {
- if (stretch->state == input_state)
- {
- st_size_t tocopy = min(*isamp-iindex,
- stretch->size-stretch->index);
+ memcpy(stretch->ibuf + stretch->index, ibuf + iindex, tocopy * sizeof(st_sample_t));
+
+ iindex += tocopy;
+ stretch->index += tocopy;
- memcpy(stretch->ibuf+stretch->index,
- ibuf+iindex, tocopy*sizeof(st_sample_t));
+ if (stretch->index == stretch->size) {
+ /* compute */
+ combine(stretch);
- iindex += tocopy;
- stretch->index += tocopy;
+ /* shift input */
+ for (i = 0; i + stretch->ishift < stretch->size; i++)
+ stretch->ibuf[i] = stretch->ibuf[i+stretch->ishift];
- if (stretch->index == stretch->size)
- {
- /* compute */
- combine(stretch);
+ stretch->index -= stretch->ishift;
+
+ /* switch to output state */
+ stretch->state = output_state;
+ }
+ }
- /* shift input */
- for (i=0; i+stretch->ishift<stretch->size; i++)
- stretch->ibuf[i] = stretch->ibuf[i+stretch->ishift];
+ if (stretch->state == output_state) {
+ while (stretch->oindex < stretch->oshift && oindex < *osamp) {
+ float f;
+ f = stretch->obuf[stretch->oindex++];
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
+ obuf[oindex++] = f;
+ }
- stretch->index -= stretch->ishift;
+ if (stretch->oindex >= stretch->oshift && oindex<*osamp) {
+ stretch->oindex -= stretch->oshift;
- /* switch to output state */
- stretch->state = output_state;
- }
- }
+ /* shift internal output buffer */
+ for (i = 0; i + stretch->oshift < stretch->size; i++)
+ stretch->obuf[i] = stretch->obuf[i + stretch->oshift];
- if (stretch->state == output_state)
- {
- while (stretch->oindex<stretch->oshift && oindex<*osamp)
- {
- float f;
- f = stretch->obuf[stretch->oindex++];
- ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
- obuf[oindex++] = f;
- }
-
- if (stretch->oindex >= stretch->oshift && oindex<*osamp)
- {
- stretch->oindex -= stretch->oshift;
-
- /* shift internal output buffer */
- for (i=0; i+stretch->oshift<stretch->size; i++)
- stretch->obuf[i] = stretch->obuf[i+stretch->oshift];
-
- /* pad with 0 */
- for (; i<stretch->size; i++)
- stretch->obuf[i] = 0.0;
+ /* pad with 0 */
+ for (; i < stretch->size; i++)
+ stretch->obuf[i] = 0.0;
- stretch->state = input_state;
- }
- }
+ stretch->state = input_state;
+ }
}
+ }
- *isamp = iindex;
- *osamp = oindex;
+ *isamp = iindex;
+ *osamp = oindex;
- return ST_SUCCESS;
+ return ST_SUCCESS;
}
@@ -339,37 +310,31 @@
*/
static int st_stretch_drain(eff_t effp, st_sample_t *obuf, st_size_t *osamp)
{
- stretch_t stretch = (stretch_t) effp->priv;
- st_size_t i;
- st_size_t oindex;
-
- oindex = 0;
-
- if (stretch->state == input_state)
- {
- for (i=stretch->index; i<stretch->size; i++)
- stretch->ibuf[i] = 0;
-
- combine(stretch);
-
- stretch->state = output_state;
- }
-
- for (; oindex<*osamp && stretch->oindex<stretch->index;)
- {
- float f;
-
- f = stretch->obuf[stretch->oindex++];
- ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
- obuf[oindex++] = f;
- }
+ stretch_t stretch = (stretch_t) effp->priv;
+ st_size_t i;
+ st_size_t oindex = 0;
+
+ if (stretch->state == input_state) {
+ for (i=stretch->index; i<stretch->size; i++)
+ stretch->ibuf[i] = 0;
- *osamp = oindex;
+ combine(stretch);
+
+ stretch->state = output_state;
+ }
+
+ while (oindex<*osamp && stretch->oindex<stretch->index) {
+ float f = stretch->obuf[stretch->oindex++];
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
+ obuf[oindex++] = f;
+ }
+
+ *osamp = oindex;
- if (stretch->oindex == stretch->index)
- return ST_EOF;
- else
- return ST_SUCCESS;
+ if (stretch->oindex == stretch->index)
+ return ST_EOF;
+ else
+ return ST_SUCCESS;
}
@@ -379,13 +344,13 @@
*/
static int st_stretch_stop(eff_t effp)
{
- stretch_t stretch = (stretch_t) effp->priv;
+ stretch_t stretch = (stretch_t) effp->priv;
- free(stretch->ibuf);
- free(stretch->obuf);
- free(stretch->fbuf);
+ free(stretch->ibuf);
+ free(stretch->obuf);
+ free(stretch->fbuf);
- return ST_SUCCESS;
+ return ST_SUCCESS;
}
static st_effect_t st_stretch_effect = {
@@ -404,5 +369,5 @@
const st_effect_t *st_stretch_effect_fn(void)
{
- return &st_stretch_effect;
+ return &st_stretch_effect;
}