mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-29 04:56:46 -06:00
Integration: AudioSuite speed ramp: Fit To plays the first two thirds for Slow Down and the last for Speed Up
This commit is contained in:
@@ -465,7 +465,8 @@ pub enum SpeedRampChange {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SpeedRampSelection {
|
||||
/// The result is as long as the input. Two thirds of the input are played: the first two
|
||||
/// thirds for Speed Up, the last two thirds for Slow Down.
|
||||
/// thirds for Slow Down, the last two thirds for Speed Up, so each joins its neighbour
|
||||
/// without a jump.
|
||||
FitTo,
|
||||
/// All of the input is played, and the result is 150 % of its length.
|
||||
Extend,
|
||||
@@ -482,7 +483,7 @@ pub fn speed_ramp(ch: &[Vec<f32>], change: SpeedRampChange, selection: SpeedRamp
|
||||
SpeedRampSelection::Extend => ((len * 1.5).round(), 0.0, len),
|
||||
SpeedRampSelection::FitTo => {
|
||||
let played = len * 2.0 / 3.0;
|
||||
(len, if change == SpeedRampChange::SlowDown { len - played } else { 0.0 }, played)
|
||||
(len, if change == SpeedRampChange::SlowDown { 0.0 } else { len - played }, played)
|
||||
}
|
||||
};
|
||||
let out_len = (total as usize).min(MAX_OFFLINE_SAMPLES);
|
||||
|
||||
@@ -24,21 +24,22 @@ fn speed_ramp_fit_to_keeps_the_length_and_plays_two_thirds() {
|
||||
let x = vec![ramp(len)];
|
||||
let slow = offline::speed_ramp(&x, SpeedRampChange::SlowDown, SpeedRampSelection::FitTo, false);
|
||||
assert_eq!(slow[0].len(), len);
|
||||
// Slow Down plays the last two thirds: it starts at normal speed one third in and stops at the end.
|
||||
// Slow Down plays the first two thirds: it starts at normal speed at the start and stops at the end.
|
||||
for u in [0.0, 0.25, 0.5, 0.75, 0.9] {
|
||||
let n = (u * len as f64) as usize;
|
||||
near(slow[0][n], 1.0 / 3.0 + 2.0 / 3.0 * slow_down_pos(u), &format!("slow down at {u}"));
|
||||
near(slow[0][n], 2.0 / 3.0 * slow_down_pos(u), &format!("slow down at {u}"));
|
||||
}
|
||||
let step = |a: &[f32], n: usize| f64::from(a[n + 1] - a[n]) * len as f64;
|
||||
// The speed over 50 samples: a one-sample step inside the input also shows the interpolation's ripple.
|
||||
let step = |a: &[f32], n: usize| f64::from(a[n + 50] - a[n]) * len as f64 / 50.0;
|
||||
assert!((step(&slow[0], 100) - 1.0).abs() < 0.01, "slow down starts at normal speed: {}", step(&slow[0], 100));
|
||||
assert!(step(&slow[0], len - 200) < 0.02, "slow down ends near a stop: {}", step(&slow[0], len - 200));
|
||||
|
||||
// Speed Up plays the first two thirds: it starts from a stop and reaches normal speed at the end.
|
||||
// Speed Up plays the last two thirds: it starts from a stop and reaches normal speed at the end.
|
||||
let fast = offline::speed_ramp(&x, SpeedRampChange::SpeedUp, SpeedRampSelection::FitTo, false);
|
||||
assert_eq!(fast[0].len(), len);
|
||||
for u in [0.1, 0.25, 0.5, 0.75, 0.99] {
|
||||
let n = (u * len as f64) as usize;
|
||||
near(fast[0][n], 2.0 / 3.0 * speed_up_pos(u), &format!("speed up at {u}"));
|
||||
near(fast[0][n], 1.0 / 3.0 + 2.0 / 3.0 * speed_up_pos(u), &format!("speed up at {u}"));
|
||||
}
|
||||
assert!(step(&fast[0], 200) < 0.02, "speed up starts near a stop: {}", step(&fast[0], 200));
|
||||
assert!((step(&fast[0], len - 100) - 1.0).abs() < 0.01, "speed up ends at normal speed: {}", step(&fast[0], len - 100));
|
||||
|
||||
@@ -274,10 +274,10 @@ mod tests {
|
||||
(c.start, c.length, c.name, audio)
|
||||
};
|
||||
// The defaults: Slow Down, Fit To, Fades On. Halfway through, the read position is 11/16 of the
|
||||
// way through the last two thirds, and the gain is the speed there, 3/4.
|
||||
// way through the first two thirds, and the gain is the speed there, 3/4.
|
||||
let (start, length, name, audio) = run(json!({}));
|
||||
assert_eq!((start, length, name.as_str()), (480, 4800, "ramp-speeramp"));
|
||||
let want = (1.0 / 3.0 + 2.0 / 3.0 * 11.0 / 16.0) * 0.75;
|
||||
let want = (2.0 / 3.0 * 11.0 / 16.0) * 0.75;
|
||||
assert!((audio[2400] - want).abs() < 2e-3, "slow down halfway: got {}, want {want}", audio[2400]);
|
||||
assert!(audio[4790].abs() < 0.01, "the fade-out ends near silence, got {}", audio[4790]);
|
||||
// Speed Up with Extend and no fades: all of the clip is played over 150 % of its length, and the
|
||||
|
||||
Reference in New Issue
Block a user