aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2015-02-10 22:34:07 +0100
committerGravatar wm4 <wm4@nowhere>2015-02-10 22:34:07 +0100
commit81d8c5d519828b1d5de9a30d23ceeb6c4c9a1d15 (patch)
tree2464a5259a9db73ef66e91449285daa182f2a029
parent2a3d19a9dffc2613d491fc4dcd49e1e239e663c9 (diff)
af_scaletempo: allow changing speed at runtime without reinit
Staring at the code a bit, it turns out that changing speed without losing state is quite easy. The initialization code is big and complicated, but most of it is specific only to the configured audio format, not the speed. Refactor the code so that changing speed at runtime could work. (It's not actually used yet - the player code still does a complete reinit. This will be fixed in the next commit.) The "if (s->speed_tempo == s->speed_pitch)" looks a bit strange, but does the same thing as the code did before: speed can be changed only if exactly one flag is set. If both are set or none, speed can't be changed.
-rw-r--r--audio/filter/af_scaletempo.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/audio/filter/af_scaletempo.c b/audio/filter/af_scaletempo.c
index 449ad02dc2..707060578f 100644
--- a/audio/filter/af_scaletempo.c
+++ b/audio/filter/af_scaletempo.c
@@ -276,6 +276,22 @@ static int filter(struct af_instance *af, struct mp_audio *data)
return 0;
}
+static void update_speed(struct af_instance *af, float speed)
+{
+ af_scaletempo_t *s = af->priv;
+
+ s->speed = speed;
+
+ double factor = s->speed_pitch ? 1.0 / s->speed : s->speed;
+ s->scale = factor * s->scale_nominal;
+
+ s->frames_stride_scaled = s->scale * s->frames_stride;
+ s->frames_stride_error = MPMIN(s->frames_stride_error, s->frames_stride_scaled);
+
+ MP_VERBOSE(af, "%.3f speed * %.3f scale_nominal = %.3f\n",
+ s->speed, s->scale_nominal, s->scale);
+}
+
// Initialization and runtime control
static int control(struct af_instance *af, int cmd, void *arg)
{
@@ -292,9 +308,6 @@ static int control(struct af_instance *af, int cmd, void *arg)
return AF_DETACH;
}
- MP_VERBOSE(af, "%.3f speed * %.3f scale_nominal = %.3f\n",
- s->speed, s->scale_nominal, s->scale);
-
mp_audio_force_interleaved_format(data);
mp_audio_copy_config(af->data, data);
@@ -307,10 +320,10 @@ static int control(struct af_instance *af, int cmd, void *arg)
s->frames_stride = srate * s->ms_stride;
s->bytes_stride = s->frames_stride * bps * nch;
- s->frames_stride_scaled = s->scale * s->frames_stride;
- s->frames_stride_error = 0;
af->delay = 0;
+ update_speed(af, s->speed);
+
int frames_overlap = s->frames_stride * s->percent_overlap;
if (frames_overlap <= 0) {
s->bytes_standing = s->bytes_stride;
@@ -420,18 +433,9 @@ static int control(struct af_instance *af, int cmd, void *arg)
return af_test_output(af, (struct mp_audio *)arg);
}
case AF_CONTROL_SET_PLAYBACK_SPEED: {
- if (s->speed_tempo) {
- if (s->speed_pitch)
- break;
- s->speed = *(double *)arg;
- s->scale = s->speed * s->scale_nominal;
- } else {
- if (s->speed_pitch) {
- s->speed = 1 / *(double *)arg;
- s->scale = s->speed * s->scale_nominal;
- break;
- }
- }
+ if (s->speed_tempo == s->speed_pitch)
+ break; // doesn't change speed
+ update_speed(af, *(double *)arg);
return AF_OK;
}
case AF_CONTROL_RESET:
@@ -469,7 +473,6 @@ static int af_open(struct af_instance *af)
s->speed_tempo = !!(s->speed_opt & SCALE_TEMPO);
s->speed_pitch = !!(s->speed_opt & SCALE_PITCH);
- s->scale = s->speed * s->scale_nominal;
return AF_OK;
}