mirror of
https://github.com/storytold/soundcraft.git
synced 2026-11-02 06:56:53 -06:00
Merge pull request #284 from marcoarnulfo/fix/elastic-properties-ratio
fix(clip): Elastic Properties stretches the clip by the requested ratio (#227)
This commit is contained in:
@@ -199,9 +199,7 @@ fn elastic(e: &mut Engine, p: &Value) -> Result<Value> {
|
||||
continue;
|
||||
}
|
||||
let out_len = soundcraft_time::to_samples(base.length as f64 * ratio).max(1);
|
||||
let mut warp = base.clone();
|
||||
warp.stretch = ratio;
|
||||
let Some(src) = super::more_util::render_stretched(s, "clip.elastic_properties", &warp, out_len)? else { continue };
|
||||
let Some(src) = super::more_util::render_stretched(s, "clip.elastic_properties", &base, out_len)? else { continue };
|
||||
if orig.is_none()
|
||||
&& let soundcraft_model::ClipContent::Audio { source, offset } = base.content
|
||||
{
|
||||
@@ -378,6 +376,45 @@ mod tests {
|
||||
assert_eq!(e.session().find_clip(ClipId(cid)).unwrap().1.length, len0);
|
||||
}
|
||||
|
||||
/// A clip on an Elastic track playing `clip_len` samples of a source that is silent before `tone_at`.
|
||||
fn elastic_clip(source_len: usize, tone_at: usize, clip_len: i64) -> (crate::Engine, TrackId, ClipId) {
|
||||
use soundcraft_model::{ChannelFormat, Clip, Session, TrackKind};
|
||||
let mut s = Session::default();
|
||||
let t = s.add_track(TrackKind::Audio, ChannelFormat::Mono, Some("Elastic"));
|
||||
let samples = (0..source_len).map(|i| if i >= tone_at { (i as f32 * 0.2).sin() * 0.4 } else { 0.0 }).collect();
|
||||
let buf = soundcraft_audio_io::AudioBuffer { sample_rate: 48_000, channels: vec![samples] };
|
||||
let src = crate::io::add_source(&mut s, "Tone", buf, None, soundcraft_audio_io::FileFormat::Wav);
|
||||
let cid = s.new_clip_id();
|
||||
crate::edit::place_clip(&mut s, t, Clip::audio(cid, "Clip", src, 0, 0, clip_len));
|
||||
let mut e = crate::Engine::new(s);
|
||||
e.execute("track.elastic", &json!({"track": t.0, "algorithm": "polyphonic"})).unwrap();
|
||||
(e, t, cid)
|
||||
}
|
||||
|
||||
fn rendered_peak(e: &crate::Engine, t: TrackId, cid: ClipId) -> f32 {
|
||||
let range = e.session().find_clip(cid).unwrap().1.range();
|
||||
soundcraft_mix::render_clips(e.session(), t, range).iter().flatten().fold(0.0, |m, x| m.max(x.abs()))
|
||||
}
|
||||
|
||||
/// Elastic Properties stretches the material the clip plays, by the requested ratio (#227).
|
||||
#[test]
|
||||
fn elastic_properties_stretches_the_clip_material() {
|
||||
let (mut e, t, cid) = elastic_clip(20_000, 10_000, 20_000);
|
||||
e.execute("clip.elastic_properties", &json!({"clips": [cid.0], "ratio": 2.0})).unwrap();
|
||||
assert_eq!(e.session().find_clip(cid).unwrap().1.length, 40_000);
|
||||
assert!(rendered_peak(&e, t, cid) > 0.3, "the tone in the second half was lost");
|
||||
|
||||
let (mut e, t, cid) = elastic_clip(60_000, 20_000, 20_000);
|
||||
e.execute("clip.elastic_properties", &json!({"clips": [cid.0], "ratio": 0.5})).unwrap();
|
||||
assert_eq!(rendered_peak(&e, t, cid), 0.0, "audio from past the clip end leaked in");
|
||||
|
||||
for (ratio, len) in [(4.0, 80_000), (0.2, 4_000)] {
|
||||
let (mut e, _, cid) = elastic_clip(20_000, 10_000, 20_000);
|
||||
e.execute("clip.elastic_properties", &json!({"clips": [cid.0], "ratio": ratio})).unwrap();
|
||||
assert_eq!(e.session().find_clip(cid).unwrap().1.length, len, "ratio {ratio}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_warp_keeps_the_audio_when_the_original_file_is_gone() {
|
||||
let mut e = crate::demo::demo_engine();
|
||||
|
||||
Reference in New Issue
Block a user