use crate::config::*;
use crate::siggen::Siggen;
use anyhow::{bail, Result};
use cpal::{FromSample, Sample};
use itertools::Itertools;
use ndarray::ArcArray2;
use num::{Bounded, FromPrimitive, Num};
use super::*;
use super::*;
use parking_lot::RwLock;
use reinterpret::{reinterpret_slice, reinterpret_vec};
use std::any::TypeId;
use std::sync::{Arc, OnceLock};
use strum_macros::Display;
const UNWRAP_RAW_DATA_ERROR: &str = "No raw data available";
#[derive(Clone, Debug)]
pub enum RawStreamData {
Datai8(Vec<i8>),
Datai16(Vec<i16>),
Datai32(Vec<i32>),
Dataf32(Vec<f32>),
Dataf64(Vec<f64>),
}
impl RawStreamData {
fn new<T, U>(input: T) -> RawStreamData
where
T: Into<Vec<U>> + 'static,
U: num::ToPrimitive + Clone + 'static,
{
let input = input.into();
let i8type: TypeId = TypeId::of::<i8>();
let i16type: TypeId = TypeId::of::<i16>();
let i32type: TypeId = TypeId::of::<i32>();
let f32type: TypeId = TypeId::of::<f32>();
let f64type: TypeId = TypeId::of::<f64>();
let thetype: TypeId = TypeId::of::<U>();
if i8type == thetype {
let v: Vec<i8> = unsafe { reinterpret_vec(input) };
RawStreamData::Datai8(v)
} else if i16type == thetype {
let v: Vec<i16> = unsafe { reinterpret_vec(input) };
RawStreamData::Datai16(v)
} else if i32type == thetype {
let v: Vec<i32> = unsafe { reinterpret_vec(input) };
RawStreamData::Datai32(v)
} else if f32type == thetype {
let v: Vec<f32> = unsafe { reinterpret_vec(input) };
RawStreamData::Dataf32(v)
} else if f64type == thetype {
let v: Vec<f64> = unsafe { reinterpret_vec(input) };
RawStreamData::Dataf64(v)
} else {
panic!("Not implemented sample type! Type: {thetype:?}, i8 = {i8type:?}, i16 = {i16type:?}, i32 = {i32type:?}, f32 = {f32type:?}, f64 = {f64type:?}.")
}
}
pub fn getRef<T>(&self) -> &[T]
where
T: Sample + 'static,
{
let type_requested = TypeId::of::<T>();
macro_rules! ret_ref {
($c:expr,$t:ty) => {{
let type_this = TypeId::of::<$t>();
assert_eq!(type_requested, type_this, "Wrong type requested");
unsafe { reinterpret_slice::<$t, T>(&$c) }
}};
}
use RawStreamData::*;
match &self {
Datai8(v) => {
ret_ref!(v, i8)
}
Datai16(v) => {
ret_ref!(v, i16)
}
Datai32(v) => {
ret_ref!(v, i32)
}
Dataf32(v) => {
ret_ref!(v, f32)
}
Dataf64(v) => {
ret_ref!(v, f64)
}
}
}
}
#[derive(Debug)]
pub struct InStreamData {
pub ctr: usize,
pub meta: Arc<StreamMetaData>,
raw: Option<RawStreamData>,
converted: OnceLock<ArcArray<Flt, Ix2>>,
}
impl InStreamData {
#[inline]
pub fn getRaw(&self) -> Option<&RawStreamData> {
self.raw.as_ref()
}
#[inline]
pub fn nchannels(&self) -> usize {
self.meta.nchannels()
}
pub fn isConverted(&self) -> bool {
self.converted.get().is_some()
}
pub fn iter_channel_raw<'a, T>(&'a self, ch: usize) -> impl Iterator<Item = &'a T> + 'a
where
T: Sample + Copy + 'static,
{
let type_requested: TypeId = TypeId::of::<T>();
macro_rules! create_iter {
($c:expr,$t:ty) => {{
let cur_type: TypeId = TypeId::of::<$t>();
assert!(
type_requested == cur_type,
"BUG: Type mismatch on channel data iterator"
);
let v: &'a [T] = unsafe { reinterpret_slice($c) };
v.iter().skip(ch).step_by(self.meta.nchannels())
}};
}
match self.raw.as_ref().expect(UNWRAP_RAW_DATA_ERROR) {
RawStreamData::Datai8(c) => {
create_iter!(c, i8)
}
RawStreamData::Datai16(c) => {
create_iter!(c, i16)
}
RawStreamData::Datai32(c) => {
create_iter!(c, i32)
}
RawStreamData::Dataf32(c) => {
create_iter!(c, f32)
}
RawStreamData::Dataf64(c) => {
create_iter!(c, f64)
}
}
}
pub fn iter_deinterleaved_raw_allchannels<'a, T>(
&'a self,
) -> Box<dyn Iterator<Item = &'a T> + 'a>
where
T: Sample + Copy + 'static,
{
Box::new((0..self.meta.nchannels()).flat_map(|chi| self.iter_channel_raw(chi)))
}
fn iter_channel_converted<T>(&self, ch: usize) -> impl Iterator<Item = Flt> + '_
where
T: Sample + Copy + 'static,
Flt: FromSample<T>,
{
self.iter_channel_raw(ch)
.copied()
.map(move |v: T| Flt::from_sample(v) / self.meta.channelInfo[ch].sensitivity)
}
pub fn iter_deinterleaved_converted<'a, T>(&'a self) -> Box<dyn Iterator<Item = Flt> + 'a>
where
T: Sample + Copy + 'static,
Flt: FromSample<T>,
{
Box::new((0..self.meta.nchannels()).flat_map(move |chi| self.iter_channel_converted(chi)))
}
pub fn newFromRaw<T, U>(ctr: usize, meta: Arc<StreamMetaData>, raw: T) -> InStreamData
where
T: Into<Vec<U>> + 'static,
U: Sample + num::ToPrimitive + Clone + 'static,
{
InStreamData {
ctr,
meta,
raw: Some(RawStreamData::new(raw)),
converted: OnceLock::new(),
}
}
pub fn newFromConverted(
ctr: usize,
meta: Arc<StreamMetaData>,
data: Array2<Flt>,
) -> InStreamData {
let data: ArcArray2<Flt> = data.into();
let conv = OnceLock::new();
conv.set(data).expect("Cannot set data");
InStreamData {
ctr,
meta,
raw: None,
converted: conv,
}
}
pub fn nframes(&self) -> usize {
if self.isConverted() {
return self
.converted
.get()
.expect("isConverted not converted?")
.nrows();
}
let nch = self.meta.nchannels();
match self.raw.as_ref().expect(UNWRAP_RAW_DATA_ERROR) {
RawStreamData::Datai8(c) => c.len() / nch,
RawStreamData::Datai16(c) => c.len() / nch,
RawStreamData::Datai32(c) => c.len() / nch,
RawStreamData::Dataf32(c) => c.len() / nch,
RawStreamData::Dataf64(c) => c.len() / nch,
}
}
pub fn getFloatData(&self) -> ArcArray2<Flt> {
let errmsg = "Data cannot be converted to floating point";
macro_rules! convert_data {
($t:ty) => {
Dmat::from_shape_vec(
(self.nframes(), self.nchannels()).f(),
self.iter_deinterleaved_converted::<$t>().collect(),
)
.expect(errmsg)
};
}
self.converted
.get_or_init(|| {
let converted_data = match self.raw.as_ref().expect(UNWRAP_RAW_DATA_ERROR) {
RawStreamData::Datai8(_) => convert_data!(i8),
RawStreamData::Datai16(_) => convert_data!(i16),
RawStreamData::Datai32(_) => convert_data!(i32),
RawStreamData::Dataf32(_) => convert_data!(f32),
RawStreamData::Dataf64(_) => convert_data!(f64),
};
let converted_data: ArcArray2<Flt> = converted_data.into();
converted_data
})
.clone()
}
}
#[cfg(test)]
mod test {
use cpal::Sample;
use num::traits::sign;
use super::*;
use crate::siggen::Siggen;
#[test]
fn test() {
const fs: Flt = 20.;
const Nframes: usize = 20;
const Nch: usize = 2;
let mut signal = [0.; Nch * Nframes];
let mut siggen = Siggen::newSine(fs, Nch, 1.).unwrap();
siggen.reset(fs);
siggen.setMute(&[false, true]);
siggen.genSignal(&mut signal);
let raw: Vec<i16> = Vec::from_iter(signal.iter().map(|o| o.to_sample::<i16>()));
let ms1 = raw
.iter()
.step_by(2)
.map(|s1| *s1 as f64 * *s1 as f64)
.sum::<f64>()
/ Nframes as f64;
let i16maxsq = (i16::MAX as f64).powf(2.);
assert!(f64::abs(ms1 - i16maxsq / 2.) / i16maxsq < 1e-3);
}
}