mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-24 02:26:46 -06:00
Merge pull request #573 from DCubix/fix/resampler-block-edge
Fix stale sample read at the end of each mix block when device and session rates differ
This commit is contained in:
@@ -362,7 +362,8 @@ impl AudioState {
|
||||
let sample = |c: usize| {
|
||||
let ch = self.pending.get(c);
|
||||
let a = ch.and_then(|v| v.get(i0)).copied().unwrap_or(0.0);
|
||||
let b = ch.and_then(|v| v.get(i0 + 1)).copied().unwrap_or(a);
|
||||
// `pending` is BLOCK long; only `pending_len` frames are valid. Hold the last one at the edge.
|
||||
let b = if i0 + 1 < self.pending_len { ch.and_then(|v| v.get(i0 + 1)).copied().unwrap_or(a) } else { a };
|
||||
a + (b - a) * fr
|
||||
};
|
||||
if channels < nch {
|
||||
@@ -1223,6 +1224,26 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resampling_at_a_short_block_edge_does_not_mix_in_stale_frames() {
|
||||
use soundcraft_model::ChannelFormat;
|
||||
// DC for the first long block, then silence. The device runs slower than the session, so
|
||||
// reads land between frames; a short block leaves the long block's DC past `pending_len`.
|
||||
let mut st = audio_output_state(ChannelFormat::Stereo, vec![vec![0.8; BLOCK]; 2]);
|
||||
st.device_rate = 44_100.0;
|
||||
let mut long = vec![0.0; 2 * 470];
|
||||
st.fill(&mut long, 2);
|
||||
assert_eq!(st.pending_len, BLOCK);
|
||||
let mut short = [0.0; 2 * 8];
|
||||
for call in 0..20 {
|
||||
st.fill(&mut short, 2);
|
||||
assert!(st.pending_len < BLOCK);
|
||||
// The first frame of the first short call still reads the DC block's last frame.
|
||||
let from = if call == 0 { 2 } else { 0 };
|
||||
assert!(short[from..].iter().all(|x| x.abs() < 1e-6), "call {call}: {short:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mono_device_preserves_centered_mono_level_and_includes_surround_right_channels() {
|
||||
use soundcraft_model::ChannelFormat;
|
||||
|
||||
Reference in New Issue
Block a user