ref: 4efd7465a94b4a10cc3a283ed32668e228b62f95
parent: bc8d4ef63433f5649e5ce30ec34d58dd43394623
author: Ulrich Klauer <ulrich@chirlu.de>
date: Sun Jan 1 18:54:01 EST 2012
Let some effects calculate expected output length For certain effects (see below) that change audio length (SOX_EFF_LENGTH), calculate the expected output length for propagation down the effects chain. This makes it possible, e.g., to use a fade-out later without specifying an explicit end position. This commit takes care of the following effects: delay, fade, pad, repeat, speed, synth, trim. It would probably be possible to do the same for more effects: chorus, echo, echos, noisered, phaser, stretch, tempo. For these three effects, however, calculating the output length beforehand is impossible as it depends on the input audio: silence, splice, vad.
--- a/src/delay.c
+++ b/src/delay.c
@@ -84,8 +84,11 @@
p->buffer_size = temp;
}
lsx_parsesamples(effp->in_signal.rate, p->max_arg, &max_delay, 't');
- if (effp->flow == 0)
+ if (effp->flow == 0) {
+ effp->out_signal.length = effp->in_signal.length ?
+ effp->in_signal.length + max_delay * effp->in_signal.channels : 0;
lsx_debug("extending audio by %" PRIu64 " 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));
--- a/src/fade.c
+++ b/src/fade.c
@@ -187,6 +187,9 @@
fade->out_start == fade->out_stop)
return SOX_EFF_NULL;
+ effp->out_signal.length = truncate ?
+ fade->out_stop * effp->in_signal.channels : effp->in_signal.length;
+
return SOX_SUCCESS;
}
--- a/src/pad.c
+++ b/src/pad.c
@@ -76,7 +76,29 @@
priv_t * p = (priv_t *)effp->priv;
unsigned i;
- parse(effp, 0, effp->in_signal.rate); /* Re-parse now rate is known */
+ /* Re-parse now rate is known */
+ if (parse(effp, 0, effp->in_signal.rate) != SOX_SUCCESS)
+ return SOX_EOF;
+
+ if ((effp->out_signal.length = effp->in_signal.length) != 0) {
+ for (i = 0; i < p->npads; ++i)
+ effp->out_signal.length +=
+ p->pads[i].pad * effp->in_signal.channels;
+
+ /* Check that the last pad position (except for "at the end")
+ is within bounds. */
+ i = p->npads;
+ if (i > 0 && p->pads[i-1].start == UINT64_MAX)
+ i--;
+ if (i > 0 &&
+ p->pads[i-1].start * effp->in_signal.channels
+ > effp->in_signal.length)
+ {
+ lsx_fail("pad position after end of audio");
+ return SOX_EOF;
+ }
+ }
+
p->in_pos = p->pad_pos = p->pads_pos = 0;
for (i = 0; i < p->npads; ++i)
if (p->pads[i].pad)
--- a/src/repeat.c
+++ b/src/repeat.c
@@ -45,6 +45,7 @@
}
p->num_samples = p->remaining_samples = 0;
p->remaining_repeats = p->num_repeats;
+ effp->out_signal.length = effp->in_signal.length * (p->num_repeats + 1);
return SOX_SUCCESS;
}
--- a/src/speed.c
+++ b/src/speed.c
@@ -56,6 +56,10 @@
return SOX_EFF_NULL;
effp->out_signal.rate = effp->in_signal.rate * p->factor;
+
+ effp->out_signal.length = effp->in_signal.length;
+ /* audio length if measured in samples doesn't change */
+
return SOX_SUCCESS;
}
--- a/src/synth.c
+++ b/src/synth.c
@@ -415,9 +415,11 @@
p->samples_done = 0;
- if (p->length_str)
+ if (p->length_str) {
if (lsx_parsesamples(effp->in_signal.rate, p->length_str, &p->samples_to_do, 't') == NULL)
return lsx_usage(effp);
+ } else
+ p->samples_to_do = effp->in_signal.length / effp->in_signal.channels;
p->number_of_channels = effp->in_signal.channels;
p->channels = lsx_calloc(p->number_of_channels, sizeof(*p->channels));
@@ -523,6 +525,7 @@
}
p->gain = 1;
effp->out_signal.mult = p->no_headroom? NULL : &p->gain;
+ effp->out_signal.length = p->samples_to_do * effp->out_signal.channels;
return SOX_SUCCESS;
}
--- a/src/trim.c
+++ b/src/trim.c
@@ -107,7 +107,20 @@
trim->index = 0;
trim->trimmed = 0;
+ if (effp->in_signal.length) {
+ if (trim->start >= effp->in_signal.length) {
+ lsx_fail("start position after end of file");
+ return SOX_EOF;
+ } else if (trim->start + trim->length >= effp->in_signal.length) {
+ lsx_fail("end position after end of file");
+ return SOX_EOF;
+ }
+ }
+
effp->out_signal.length = trim->length;
+ if (!effp->out_signal.length && effp->in_signal.length > trim->start)
+ effp->out_signal.length = effp->in_signal.length - trim->start;
+
return (SOX_SUCCESS);
}