use alloc::vec::Vec;
use core::mem;
use core::num::NonZeroU32;
use crate::chan::{Ch32, Channel};
use crate::frame::Frame;
use crate::{Audio, Sink};
mod speex;
use speex::ResamplerState;
const WINDOW_FN_KAISER_TABLE: &[f64] = &[
0.99537781, 1.0, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
0.56155915, 0.5011968, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
0.23636152, 0.19515633, 0.15859932, 0.1267028, 0.09935205, 0.07632451,
0.05731132, 0.0419398, 0.02979584, 0.0204451, 0.01345224, 0.00839739,
0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.0, 0.0,
];
const WINDOW_FN_OVERSAMPLE: usize = 32;
#[derive(Debug)]
pub struct Stream<const CH: usize> {
output_sample_rate: u32,
input_sample_rate: Option<NonZeroU32>,
ratio: (u32, u32),
channels: [Resampler32; 8],
input_latency: u32,
}
impl<const CH: usize> Stream<CH> {
pub fn new(target_hz: u32) -> Self {
assert_ne!(target_hz, 0);
Self {
output_sample_rate: target_hz,
input_sample_rate: None,
ratio: (0, 1),
channels: [
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
],
input_latency: 0,
}
}
fn source_hz(&mut self, hz: NonZeroU32) {
let ratio = simplify(hz.get(), self.output_sample_rate);
let (num, den) = ratio;
if NonZeroU32::new(hz.get()) != self.input_sample_rate {
for ch in self.channels.iter_mut() {
let v = ch.state.samp_frac_num;
ch.state.samp_frac_num = speex::_muldiv(v, den, self.ratio.1);
if ch.state.samp_frac_num >= den {
ch.state.samp_frac_num = den - 1;
}
ch.state.update_filter(num, den);
self.input_latency = ch.state.filt_len / 2;
}
self.ratio = ratio;
self.input_sample_rate = Some(hz);
}
}
pub fn flush<Ch, S>(mut self, sink: S)
where
Ch: Channel,
S: Sink<Ch, CH>,
{
if self.channels[0].state.started == 0 {
return;
}
for chan in 0..CH {
self.channels[chan].input.clear();
}
for _ in 0..self.input_latency {
for chan in 0..CH {
self.channels[chan].input.push(0.0);
}
}
self.resample_audio(sink);
}
pub fn pipe<Chan, Ch, S>(&mut self, audio: &Audio<Chan, CH>, mut sink: S)
where
Chan: Channel,
Ch: Channel + From<Chan>,
S: Sink<Ch, CH>,
Ch32: From<Chan>,
{
assert_eq!(sink.sample_rate().get(), self.output_sample_rate);
if self.channels[0].state.started == 0
&& sink.sample_rate() == audio.sample_rate()
{
sink.sink_with(&mut audio.iter().cloned().map(|x| x.to()));
return;
}
if NonZeroU32::new(audio.sample_rate().get()) != self.input_sample_rate
{
self.source_hz(audio.sample_rate());
}
let converted = Audio::<Ch32, CH>::with_frames(
audio.sample_rate().get(),
audio
.as_slice()
.iter()
.map(|frame| frame.to())
.collect::<Vec<_>>(),
);
for chan in 0..CH {
self.channels[chan].input.clear();
}
for frame in converted.iter() {
for chan in 0..CH {
self.channels[chan]
.input
.push(frame.channels()[chan].to_f32());
}
}
self.resample_audio(sink);
}
fn resample_audio<Ch, S>(&mut self, mut sink: S)
where
Ch: Channel,
S: Sink<Ch, CH>,
{
if self.channels[0].input.is_empty() {
return;
}
let mut out = u32::MAX;
for chan in 0..CH {
self.channels[chan].output.resize(sink.len(), 0.0);
self.channels[chan].state.process_float(
self.channels[chan].input.as_slice(),
&mut (self.channels[chan].input.len() as u32),
self.channels[chan].output.as_mut_slice(),
&mut out,
self.ratio.1,
);
}
sink.sink_with(&mut (0..out as usize).into_iter().map(|i| {
let mut out_frame = Frame::<Ch, CH>::default();
for chan in 0..CH {
out_frame.channels_mut()[chan] =
Ch::from(self.channels[chan].output[i]);
}
out_frame
}));
}
}
#[derive(Default, Clone, Debug)]
struct Resampler32 {
state: ResamplerState,
input: Vec<f32>,
output: Vec<f32>,
}
#[inline(always)]
fn simplify(num: u32, den: u32) -> (u32, u32) {
debug_assert_ne!(num, 0);
debug_assert_ne!(den, 0);
let factor = gcd(num, den);
(num / factor, den / factor)
}
#[inline(always)]
fn gcd(mut a: u32, mut b: u32) -> u32 {
if b == 0 {
return a;
}
while a != 0 {
mem::swap(&mut a, &mut b);
a %= b;
}
b
}