ref: 5469291fcec13d4482730caed009d8577472090e
parent: 4cc26362506d3bf8cfd66a15b9229ee54fe1fcd5
author: Ulrich Klauer <ulrich@chirlu.de>
date: Mon Oct 10 23:20:49 EDT 2011
delay effect: Allow a delay to be more than the input length The delay effect would fail ("drained asymmetrically!") when a specified delay was more than the input length, e.g. play stereo.wav trim 0 1 delay 0 2 In this special case, drain() will now output additional silence such that the specified delay is reached and all channels end simultaneously. This resolves bug #3055399.
--- a/ChangeLog
+++ b/ChangeLog
@@ -41,6 +41,8 @@
o Effect chain can now be unlimitted in length. (Ulrich Klauer)
o Fix newfile/restart effects when merging or mixing files. (Ulrich Klauer)
o Fix crashes in compand and mcompand effects. [3420893] (Ulrich Klauer)
+ o Let the delay effect gracefully handle the special case that a delay can
+ be more than the input length. [3055399] (Ulrich Klauer)
Misc:
--- a/src/delay.c
+++ b/src/delay.c
@@ -21,8 +21,9 @@
typedef struct {
size_t argc;
char * * argv, * max_arg;
- size_t delay, pad, buffer_size, buffer_index;
+ size_t delay, pre_pad, pad, buffer_size, buffer_index;
sox_sample_t * buffer;
+ sox_bool drain_started;
} priv_t;
static int lsx_kill(sox_effect_t * effp)
@@ -43,7 +44,8 @@
unsigned i;
--argc, ++argv;
- p->argv = lsx_calloc(p->argc = argc, sizeof(*p->argv));
+ p->argc = argc;
+ p->argv = lsx_calloc(p->argc, sizeof(*p->argv));
for (i = 0; i < p->argc; ++i) {
char const * next = lsx_parsesamples(1e5, p->argv[i] = lsx_strdup(argv[i]), &delay, 't');
if (!next || *next) {
@@ -75,9 +77,12 @@
if (effp->flow < p->argc)
lsx_parsesamples(effp->in_signal.rate, p->argv[effp->flow], &p->buffer_size, 't');
lsx_parsesamples(effp->in_signal.rate, p->max_arg, &max_delay, 't');
- p->buffer_index = p->delay = 0;
+ if (effp->flow == 0)
+ lsx_debug("extending audio by %" FMT_size_t " samples", max_delay);
+ p->buffer_index = p->delay = p->pre_pad = 0;
p->pad = max_delay - p->buffer_size;
p->buffer = lsx_malloc(p->buffer_size * sizeof(*p->buffer));
+ p->drain_started = sox_false;
return SOX_SUCCESS;
}
@@ -105,8 +110,18 @@
static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
- size_t len = *osamp = min(p->delay + p->pad, *osamp);
+ size_t len;
+ if (! p->drain_started) {
+ p->drain_started = sox_true;
+ p->pre_pad = p->buffer_size - p->delay;
+ /* If the input was too short to fill the buffer completely,
+ flow() has not yet output enough silence to reach the
+ desired delay. */
+ }
+ len = *osamp = min(p->pre_pad + p->delay + p->pad, *osamp);
+ for (; p->pre_pad && len; --p->pre_pad, --len)
+ *obuf++ = 0;
for (; p->delay && len; --p->delay, --len) {
*obuf++ = p->buffer[p->buffer_index++];
p->buffer_index %= p->buffer_size;