mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-14 14:26:46 -04:00
Merge pull request #301 from marcoarnulfo/fix/seek-flushes-state
Locate clears plugin and delay-compensation state
This commit is contained in:
2 files changed
+71
No files matched your search
@@ -251,6 +251,9 @@ impl DelayLine {
|
||||
}
|
||||
self.idx = (start + frames) % self.len.max(1);
|
||||
}
|
||||
fn clear(&mut self) {
|
||||
self.bufs.iter_mut().for_each(|b| b.fill(0.0));
|
||||
}
|
||||
}
|
||||
|
||||
/// Clip Effects: an EQ and a compressor per clip, configured from `edit.values`
|
||||
@@ -481,6 +484,9 @@ impl MixEngine {
|
||||
i.plugin.reset();
|
||||
}
|
||||
s.held.clear();
|
||||
s.align.clear();
|
||||
s.align_pre.clear();
|
||||
s.out_extra.clear();
|
||||
}
|
||||
self.meters.clear();
|
||||
self.main_meter = StripMeter::default();
|
||||
@@ -2363,6 +2369,27 @@ mod tests {
|
||||
assert_ne!(argmax(&out[0]), argmax(&out[1]));
|
||||
}
|
||||
|
||||
/// A reset (stop, locate) must not leave the previous position's audio in the alignment delay.
|
||||
#[test]
|
||||
fn reset_clears_delay_compensation_history() {
|
||||
let (mut s, t) = session_with_dc(0.5, 4800);
|
||||
s.edit.click = false;
|
||||
s.track_mut(t).unwrap().mixer.pan = vec![1.0];
|
||||
let latent = s.add_track(TrackKind::Audio, ChannelFormat::Mono, None);
|
||||
let mut comp = Insert::new("compressor");
|
||||
comp.params.insert("lookahead".into(), 5.0);
|
||||
s.track_mut(latent).unwrap().mixer.inserts[0] = Some(comp);
|
||||
let mut eng = MixEngine::new(48_000.0, 512);
|
||||
let mut out = vec![vec![0.0f32; 512]; 2];
|
||||
for b in 0..9 {
|
||||
eng.render(&s, b * 512, 512, &mut out);
|
||||
}
|
||||
assert!(eng.latency > 0 && out[1][500] > 0.3, "the fixture plays through the alignment delay");
|
||||
eng.reset();
|
||||
eng.render(&s, 1_000_000, 512, &mut out);
|
||||
assert!(out.iter().flatten().all(|x| *x == 0.0), "old aligned audio after a reset");
|
||||
}
|
||||
|
||||
fn impulse_at(ch: &[f32]) -> Vec<usize> {
|
||||
ch.iter().enumerate().filter(|(_, v)| v.abs() > 1e-4).map(|(i, _)| i).collect()
|
||||
}
|
||||
|
||||
@@ -176,6 +176,7 @@ impl AudioState {
|
||||
self.pos = at;
|
||||
self.pending_len = 0;
|
||||
self.read = 0.0;
|
||||
self.mix.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -953,6 +954,49 @@ mod tests {
|
||||
assert!(shared.playing.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn locate_while_playing_drops_the_old_position_audio() {
|
||||
use soundcraft_model::{ChannelFormat, Clip, Insert, SourceAudio, SourceId, TrackKind};
|
||||
for (plugin, params) in [("compressor", &[("lookahead", 5.0), ("ratio", 1.0)][..]), ("room_reverb", &[][..])] {
|
||||
let mut s = soundcraft_model::Session::default();
|
||||
s.edit.click = false;
|
||||
let t = s.add_track(TrackKind::Audio, ChannelFormat::Mono, None);
|
||||
s.pool.insert(
|
||||
SourceId(5),
|
||||
Arc::new(SourceAudio::new(soundcraft_audio_io::AudioBuffer { sample_rate: 48_000, channels: vec![vec![0.5; 4800]] })),
|
||||
);
|
||||
let id = s.new_clip_id();
|
||||
let tr = s.track_mut(t).unwrap();
|
||||
tr.playlist_mut().unwrap().clips.push(Clip::audio(id, "x", SourceId(5), 0, 0, 4800));
|
||||
let mut ins = Insert::new(plugin);
|
||||
for (k, v) in params {
|
||||
ins.params.insert((*k).into(), *v);
|
||||
}
|
||||
tr.mixer.inserts[0] = Some(ins);
|
||||
let shared = Arc::new(Shared {
|
||||
position: AtomicI64::new(0),
|
||||
playing: AtomicBool::new(false),
|
||||
speed: AtomicU32::new(1000),
|
||||
meters: Mutex::new(MeterSnapshot::default()),
|
||||
});
|
||||
let (tx, rx) = channel();
|
||||
let mut st = AudioState::new(rx, Arc::clone(&shared), Arc::new(s), 48_000.0, channel().0);
|
||||
tx.send(Cmd::Play { from: 0, end: None, looped: None }).unwrap();
|
||||
let mut out = vec![0.0f32; 2 * 512];
|
||||
let mut before = 0.0f32;
|
||||
for _ in 0..9 {
|
||||
st.fill(&mut out, 2);
|
||||
before = out.iter().fold(before, |m, x| m.max(x.abs()));
|
||||
}
|
||||
assert!(before > 0.1, "{plugin}: the clip plays before the locate");
|
||||
tx.send(Cmd::Locate(1_000_000)).unwrap();
|
||||
for _ in 0..8 {
|
||||
st.fill(&mut out, 2);
|
||||
assert!(out.iter().all(|x| x.abs() < 1e-6), "{plugin}: audio from before the locate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn armed_tracks_are_heard_and_metered_after_playback_stops() {
|
||||
use soundcraft_model::{ChannelFormat, TrackKind};
|
||||
|
||||
Reference in new issue
Block a user