use crate::audio_info::*;
use melodium_core::*;
use melodium_macro::mel_treatment;
use std::sync::Arc;
#[mel_treatment(
input info Block<AudioInfo>
input signal Stream<f32>
output resampled Stream<f32>
)]
pub async fn resample_mono(to_rate: u32) {
let from_rate = match info.recv_one().await {
Ok(value) => {
let arc = GetData::<Arc<dyn Data>>::try_data(value).unwrap();
let audio_info = arc.downcast_arc::<AudioInfo>().unwrap();
audio_info.sample_rate
}
Err(_) => return,
};
if from_rate == to_rate || from_rate == 0 {
while let Ok(batch) = signal
.recv_many()
.await
.map(|values| TryInto::<Vec<f32>>::try_into(values).unwrap())
{
let out: VecDeque<f32> = batch.into_iter().collect();
if resampled.send_many(out.into()).await.is_err() {
return;
}
}
return;
}
let ratio = from_rate as f64 / to_rate as f64;
let mut buf: Vec<f32> = Vec::new();
let mut phase: f64 = 0.0;
while let Ok(batch) = signal
.recv_many()
.await
.map(|values| TryInto::<Vec<f32>>::try_into(values).unwrap())
{
buf.extend_from_slice(&batch);
let mut out: VecDeque<f32> = VecDeque::new();
while phase + 1.0 <= (buf.len() - 1) as f64 + 1.0 {
let i = phase as usize;
if i + 1 >= buf.len() {
break;
}
let frac = (phase - i as f64) as f32;
out.push_back(buf[i] + frac * (buf[i + 1] - buf[i]));
phase += ratio;
}
if !out.is_empty() && resampled.send_many(out.into()).await.is_err() {
return;
}
let consumed = (phase as usize).saturating_sub(1);
if consumed > 0 && consumed < buf.len() {
buf.drain(..consumed);
phase -= consumed as f64;
}
}
if !buf.is_empty() {
let last = *buf.last().unwrap();
let mut out: VecDeque<f32> = VecDeque::new();
while phase < buf.len() as f64 {
let i = phase as usize;
let sample = if i + 1 < buf.len() {
let frac = (phase - i as f64) as f32;
buf[i] + frac * (buf[i + 1] - buf[i])
} else {
last
};
out.push_back(sample);
phase += ratio;
}
if !out.is_empty() {
let _ = resampled.send_many(out.into()).await;
}
}
}