ref: 8b360a4b6a348b39abee0ec67f014269ba056d7a
parent: 6dc1e9a8f6d2325513083c003a8de04467b09d10
author: robs <robs>
date: Sun Jan 28 14:22:28 EST 2007
Reinstate effects nullification.
--- a/ChangeLog
+++ b/ChangeLog
@@ -91,6 +91,9 @@
o Fixed a bug introduced in 12.18.2 that stopped the draining
of effects from occuring. This had stopped the reverse effect,
among others, from working. (Reuben Thomas)
+ o Several effects are now optimised out in situations where they need
+ do nothing, e.g. changing rate from 8000 to 8000, or changing volume
+ by 0dB [Bug# 1395781]. (robs)
o Fix rounding error when reading command-line time
parameters. (robs)
o Fix nul file hander ignoring other format options if rate
--- a/src/biquads.c
+++ b/src/biquads.c
@@ -227,6 +227,8 @@
break;
case filter_peakingEQ: /* H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) */
+ if (A == 1)
+ return ST_EFF_NULL;
p->b0 = 1 + alpha*A;
p->b1 = -2*cos(w0);
p->b2 = 1 - alpha*A;
@@ -236,6 +238,8 @@
break;
case filter_lowShelf: /* H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) */
+ if (A == 1)
+ return ST_EFF_NULL;
p->b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha );
p->b1 = 2*A*( (A-1) - (A+1)*cos(w0) );
p->b2 = A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha );
@@ -245,6 +249,8 @@
break;
case filter_highShelf: /* H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) */
+ if (!A)
+ return ST_EFF_NULL;
p->b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
p->b1 = -2*A*( (A-1) + (A+1)*cos(w0) );
p->b2 = A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
--- a/src/dcshift.c
+++ b/src/dcshift.c
@@ -76,6 +76,9 @@
{
dcs_t dcs = (dcs_t) effp->priv;
+ if (dcs->dcshift == 0)
+ return ST_EFF_NULL;
+
if (effp->outinfo.channels != effp->ininfo.channels) {
st_fail("DCSHIFT cannot handle different channels (in=%d, out=%d)"
" use avg or pan", effp->ininfo.channels, effp->outinfo.channels);
--- a/src/dither.c
+++ b/src/dither.c
@@ -61,19 +61,10 @@
return ST_SUCCESS;
} else if (effp->outinfo.size == ST_SIZE_16BIT)
return ST_SUCCESS;
- else if (effp->outinfo.size == ST_SIZE_24BIT) {
- dither->amount /= 256;
- return ST_SUCCESS;
- } else if (effp->outinfo.size == ST_SIZE_64BIT) {
- dither->amount /= 16384;
- return ST_SUCCESS;
- }
- st_fail("Invalid size %d", effp->outinfo.size);
- return ST_EOF;
+ return ST_EFF_NULL; /* Dithering not needed at >= 24 bits */
}
-/* FIXME: Scale noise more sensibly for sizes >= 24 bits */
static int flow(eff_t effp, const st_sample_t * ibuf,
st_sample_t * obuf, st_size_t * isamp, st_size_t * osamp)
{
--- a/src/fade.c
+++ b/src/fade.c
@@ -187,6 +187,9 @@
st_debug("fade: in_start = %d in_stop = %d out_start = %d out_stop = %d", fade->in_start, fade->in_stop, fade->out_start, fade->out_stop);
+ if (fade->in_start == fade->in_stop && fade->out_start == fade->out_stop)
+ return ST_EFF_NULL;
+
return ST_SUCCESS;
}
--- a/src/mixer.c
+++ b/src/mixer.c
@@ -206,10 +206,8 @@
/* Handle the special-case flags */
switch (mixer->mix) {
case MIX_CENTER:
- if (ichan == ochan) {
- st_fail("Output must have different number of channels to use mixer effect");
- return(ST_EOF);
- }
+ if (ichan == ochan)
+ return ST_EFF_NULL;
break; /* Code below will handle this case */
case MIX_LEFT:
if (ichan == 2 && ochan == 1)
@@ -500,7 +498,19 @@
return ST_EOF;
}
+#if 0 /* TODO: test the following: */
+ if (effp->ininfo.channels != effp->outinfo.channels)
+ return ST_SUCCESS;
+
+ for (i = 0; i < (int)effp->ininfo.channels; ++i)
+ for (j = 0; j < (int)effp->outinfo.channels; ++j)
+ if (avg->sources[i][j] != (i == j))
+ return ST_SUCCESS;
+
+ return ST_EFF_NULL;
+#else
return ST_SUCCESS;
+#endif
}
/*
--- a/src/pad.c
+++ b/src/pad.c
@@ -72,10 +72,14 @@
static int start(eff_t effp)
{
pad_t p = (pad_t) effp->priv;
+ int i;
parse(effp, 0, effp->ininfo.rate); /* Re-parse now rate is known */
p->in_pos = p->pad_pos = p->pads_pos = 0;
- return ST_SUCCESS;
+ for (i = 0; i < p->npads; ++i)
+ if (p->pads[i].pad)
+ return ST_SUCCESS;
+ return ST_EFF_NULL;
}
static int flow(eff_t effp, const st_sample_t * ibuf, st_sample_t * obuf,
--- a/src/pitch.c
+++ b/src/pitch.c
@@ -433,6 +433,9 @@
return ST_EOF;
}
+ if (pitch->shift == 0)
+ return ST_EFF_NULL;
+
return ST_SUCCESS;
}
--- a/src/polyphas.c
+++ b/src/polyphas.c
@@ -346,6 +346,9 @@
int total, size, uprate;
int k;
+ if (effp->ininfo.rate == effp->outinfo.rate)
+ return ST_EFF_NULL;
+
rate->lcmrate = st_lcm((st_sample_t)effp->ininfo.rate,
(st_sample_t)effp->outinfo.rate);
--- a/src/rabbit.c
+++ b/src/rabbit.c
@@ -92,6 +92,9 @@
double in_rate = floor(effp->ininfo.rate / effp->globalinfo->speed + .5)
* effp->globalinfo->speed;
+ if (in_rate == effp->outinfo.rate)
+ return ST_EFF_NULL;
+
if (effp->ininfo.channels != effp->outinfo.channels) {
st_fail("number of Input and Output channels must be equal to use rabbit effect");
return ST_EOF;
--- a/src/repeat.c
+++ b/src/repeat.c
@@ -59,6 +59,9 @@
{
repeat_t repeat = (repeat_t)effp->priv;
+ if (repeat->repeats == 0)
+ return ST_EFF_NULL;
+
if ((repeat->fp = tmpfile()) == NULL) {
st_fail("repeat: could not create temporary file");
return (ST_EOF);
--- a/src/resample.c
+++ b/src/resample.c
@@ -204,6 +204,9 @@
double in_rate = floor(effp->ininfo.rate / effp->globalinfo->speed + .5)
* effp->globalinfo->speed;
+ if (in_rate == effp->outinfo.rate)
+ return ST_EFF_NULL;
+
r->Factor = (double) effp->outinfo.rate / in_rate;
gcdrate = st_gcd((long) effp->ininfo.rate, (long) effp->outinfo.rate);
--- a/src/sox.c
+++ b/src/sox.c
@@ -1108,10 +1108,6 @@
memcpy(&efftabR[neffects], e, sizeof(*e));
else memset(&efftabR[neffects], 0, sizeof(*e));
- st_report("Effects chain: %-10s %-6s %uHz", e->name,
- e->ininfo.channels < 2? "mono" :
- (e->h->flags & ST_EFF_MCHAN)? "multi" : "stereo", e->ininfo.rate);
-
++neffects;
}
@@ -1198,21 +1194,48 @@
static int start_all_effects(void)
{
- int e, ret = ST_SUCCESS;
+ int i, j, ret = ST_SUCCESS;
- for (e = 1; e < neffects; e++) {
- int (*start)(eff_t effp) =
- efftab[e].h->start? efftab[e].h->start : st_effect_nothing;
- efftab[e].clips = 0;
- if ((ret = start(&efftab[e])) == ST_EOF)
- break;
- if (efftabR[e].name) {
- efftabR[e].clips = 0;
- if ((ret = start(&efftabR[e])) != ST_SUCCESS)
- break;
+ for (i = 1; i < neffects; i++) {
+ struct st_effect * e = &efftab[i];
+ st_bool is_always_null = (e->h->flags & ST_EFF_NULL) != 0;
+ int (*start)(eff_t effp) = e->h->start? e->h->start : st_effect_nothing;
+
+ if (is_always_null)
+ st_report("'%s' has no effect (is a proxy effect)", e->name);
+ else {
+ e->clips = 0;
+ ret = start(e);
+ if (ret == ST_EFF_NULL)
+ st_warn("'%s' has no effect in this configuration", e->name);
+ else if (ret != ST_SUCCESS)
+ return ST_EOF;
}
+ if (is_always_null || ret == ST_EFF_NULL) { /* remove from the chain */
+ int (*delete)(eff_t effp) = e->h->delete? e->h->delete: st_effect_nothing;
+
+ /* No left & right delete as there is no left & right getopts */
+ delete(e);
+ --neffects;
+ for (j = i--; j < neffects; ++j) {
+ efftab[j] = efftab[j + 1];
+ efftabR[j] = efftabR[j + 1];
+ }
+ }
+ /* No null checks here; the left channel looks after this */
+ else if (efftabR[i].name) {
+ efftabR[i].clips = 0;
+ if (start(&efftabR[i]) != ST_SUCCESS)
+ return ST_EOF;
+ }
}
- return ret;
+ for (i = 1; i < neffects; ++i) {
+ struct st_effect * e = &efftab[i];
+ st_report("Effects chain: %-10s %-6s %uHz", e->name,
+ e->ininfo.channels < 2 ? "mono" :
+ (e->h->flags & ST_EFF_MCHAN)? "multi" : "stereo", e->ininfo.rate);
+ }
+ return ST_SUCCESS;
}
static int flow_effect_out(void)
@@ -1545,15 +1568,16 @@
stop(&efftab[e]);
clips = efftab[e].clips;
- delete(&efftab[e]);
if (efftabR[e].name) {
stop(&efftabR[e]);
clips += efftab[e].clips;
- delete(&efftabR[e]);
}
if (clips != 0)
- st_warn("%s clipped %u samples; decrease volume?", efftab[e].name, clips);
+ st_warn("'%s' clipped %u samples; decrease volume?",efftab[e].name,clips);
+
+ /* No left & right delete as there is no left & right getopts */
+ delete(&efftab[e]);
}
}
--- a/src/speed.c
+++ b/src/speed.c
@@ -54,14 +54,6 @@
st_effect_t const *st_speed_effect_fn(void)
{
static st_effect_t driver = {
- "speed", "Usage: speed factor[c]",
- ST_EFF_MCHAN,
- getopts,
- st_effect_nothing,
- st_effect_nothing_flow,
- st_effect_nothing_drain,
- st_effect_nothing,
- st_effect_nothing
- };
+ "speed", "Usage: speed factor[c]", ST_EFF_NULL, getopts, 0, 0, 0, 0, 0};
return &driver;
}
--- a/src/st.h
+++ b/src/st.h
@@ -342,6 +342,7 @@
#define ST_EFF_MCHAN 4 /* Effect can handle multi-channel */
#define ST_EFF_REPORT 8 /* Effect does not affect the audio */
#define ST_EFF_DEPRECATED 16 /* Effect is living on borrowed time */
+#define ST_EFF_NULL 32 /* Effect does nothing */
/*
* Handler structure for each effect.
--- a/src/stretch.c
+++ b/src/stretch.c
@@ -155,6 +155,9 @@
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)"
--- a/src/swap.c
+++ b/src/swap.c
@@ -65,6 +65,7 @@
static int st_swap_start(eff_t effp)
{
swap_t swap = (swap_t) effp->priv;
+ int i;
if (effp->outinfo.channels == 1)
{
@@ -121,7 +122,11 @@
}
- return ST_SUCCESS;
+ for (i = 0; i < (int)effp->outinfo.channels; ++i)
+ if (swap->order[i] != i)
+ return ST_SUCCESS;
+
+ return ST_EFF_NULL;
}
/*
--- a/src/vol.c
+++ b/src/vol.c
@@ -93,6 +93,9 @@
{
vol_t vol = (vol_t) effp->priv;
+ if (vol->gain == 1)
+ return ST_EFF_NULL;
+
if (effp->outinfo.channels != effp->ininfo.channels) {
st_fail("vol cannot handle different channels (in %d, out %d)"
" use avg or pan", effp->ininfo.channels, effp->outinfo.channels);