use std::sync::LazyLock;
use crate::core::Core;
static RAND_TABLE: LazyLock<[[f32; 48000]; 2]> = LazyLock::new(|| {
let mut rand: [[f32; 48000]; 2] = [[0.0; 48000]; 2];
for c in rand.iter_mut() {
let mut dp = 0.0;
for i in c.iter_mut().take(48000 - 1) {
let r: i32 = rand::random();
let d = r as f32 / 2147483647.0 - 0.5;
*i = d - dp;
dp = d;
}
c[48000 - 1] = 0.0 - dp;
}
rand
});
#[derive(Default)]
pub(crate) struct I16OutputState {
dither_index: usize,
}
#[inline]
pub fn write_i16(
synth: &mut Core,
len: usize,
loff: usize,
lincr: usize,
roff: usize,
rincr: usize,
mut cb: impl FnMut((usize, i16), (usize, i16)),
) {
let mut di = synth.output.i16_output.dither_index;
let mut cur = synth.output.cur;
let mut i = 0;
let mut j = loff;
let mut k = roff;
while i < len {
if cur == 64 {
synth.one_block(false);
cur = 0;
}
let mut left_sample =
f32::round(synth.output.left_buf[0][cur] * 32766.0 + RAND_TABLE[0][di]);
let mut right_sample =
f32::round(synth.output.right_buf[0][cur] * 32766.0 + RAND_TABLE[1][di]);
di += 1;
if di >= 48000 {
di = 0;
}
left_sample = left_sample.clamp(-32768.0, 32767.0);
right_sample = right_sample.clamp(-32768.0, 32767.0);
cb(
(j, left_sample as i16),
(k, right_sample as i16),
);
i += 1;
cur += 1;
j += lincr;
k += rincr
}
synth.output.cur = cur;
synth.output.i16_output.dither_index = di;
}