#[cfg(not(test))]
use crate::math::Libm;
use crate::chan::{Ch16, Ch24, Ch32, Ch64, Channel};
use crate::frame::Frame;
use crate::{Sink, Stream};
use alloc::boxed::Box;
use alloc::slice::{Iter, IterMut};
use alloc::{vec, vec::Vec};
use core::convert::TryInto;
use core::num::NonZeroU32;
use core::{fmt::Debug, mem::size_of, slice::from_raw_parts_mut};
#[derive(Debug)]
pub struct Audio<Chan: Channel, const CH: usize> {
sample_rate: NonZeroU32,
frames: Box<[Frame<Chan, CH>]>,
}
impl<Chan: Channel, const CH: usize> Audio<Chan, CH> {
#[inline(always)]
pub fn with_silence(hz: u32, len: usize) -> Self {
Self::with_frames(hz, vec![Frame::<Chan, CH>::default(); len])
}
#[inline(always)]
pub fn with_frames<B>(hz: u32, frames: B) -> Self
where
B: Into<Box<[Frame<Chan, CH>]>>,
{
Audio {
sample_rate: hz.try_into().unwrap(),
frames: frames.into(),
}
}
#[inline(always)]
pub fn with_audio<Ch, const N: usize>(hz: u32, audio: &Audio<Ch, N>) -> Self
where
Ch: Channel,
Ch32: From<Ch>,
Chan: From<Ch>,
{
let len =
audio.len() as f64 * hz as f64 / audio.sample_rate().get() as f64;
let mut output = Self::with_silence(hz, len.ceil() as usize);
let mut stream = Stream::new(hz);
let mut sink = crate::SinkTo::<_, Chan, _, CH, N>::new(output.sink());
stream.pipe(audio, &mut sink);
stream.flush(&mut sink);
output
}
#[inline(always)]
pub fn get(&self, index: usize) -> Option<Frame<Chan, CH>> {
self.frames.get(index).cloned()
}
#[inline(always)]
pub fn get_mut(&mut self, index: usize) -> Option<&mut Frame<Chan, CH>> {
self.frames.get_mut(index)
}
#[inline(always)]
pub fn as_slice(&self) -> &[Frame<Chan, CH>] {
&*self.frames
}
#[inline(always)]
pub fn as_mut_slice(&mut self) -> &mut [Frame<Chan, CH>] {
&mut *self.frames
}
#[inline(always)]
pub fn iter(&self) -> Iter<'_, Frame<Chan, CH>> {
self.frames.iter()
}
#[inline(always)]
pub fn iter_mut(&mut self) -> IterMut<'_, Frame<Chan, CH>> {
self.frames.iter_mut()
}
#[inline(always)]
pub fn sample_rate(&self) -> NonZeroU32 {
self.sample_rate
}
#[inline(always)]
pub fn len(&self) -> usize {
self.frames.len()
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline(always)]
pub fn silence(&mut self) {
for f in self.frames.iter_mut() {
*f = Frame::<Chan, CH>::default()
}
}
#[inline(always)]
pub fn sink(&mut self) -> AudioSink<'_, Chan, CH> {
AudioSink {
index: 0,
audio: self,
}
}
}
#[derive(Debug)]
pub struct AudioSink<'a, Chan: Channel, const CH: usize> {
index: usize,
audio: &'a mut Audio<Chan, CH>,
}
#[allow(single_use_lifetimes)]
impl<'a, Chan: Channel, const CH: usize> Sink<Chan, CH>
for AudioSink<'a, Chan, CH>
{
#[inline(always)]
fn sample_rate(&self) -> NonZeroU32 {
self.audio.sample_rate()
}
#[inline(always)]
fn len(&self) -> usize {
self.audio.len()
}
#[inline(always)]
fn sink_with(&mut self, iter: &mut dyn Iterator<Item = Frame<Chan, CH>>) {
let mut this = self;
Sink::<Chan, CH>::sink_with(&mut this, iter)
}
}
impl<Chan: Channel, const CH: usize> Sink<Chan, CH>
for &mut AudioSink<'_, Chan, CH>
{
#[inline(always)]
fn sample_rate(&self) -> NonZeroU32 {
self.audio.sample_rate()
}
#[inline(always)]
fn len(&self) -> usize {
self.audio.len()
}
#[inline(always)]
fn sink_with(&mut self, iter: &mut dyn Iterator<Item = Frame<Chan, CH>>) {
for frame in self.audio.iter_mut().skip(self.index) {
*frame = if let Some(frame) = iter.next() {
frame
} else {
break;
};
self.index += 1;
}
}
}
impl<const CH: usize> Audio<Ch16, CH> {
#[allow(unsafe_code)]
pub fn with_i16_buffer<B>(hz: u32, buffer: B) -> Self
where
B: Into<Box<[i16]>>,
{
let buffer: Box<[i16]> = buffer.into();
let bytes = buffer.len() * size_of::<i16>();
let len = bytes / size_of::<Frame<Ch16, CH>>();
assert_eq!(0, bytes % size_of::<Frame<Ch16, CH>>());
let slice = Box::<[i16]>::into_raw(buffer);
let frames: Box<[Frame<Ch16, CH>]> = unsafe {
let ptr = (*slice).as_mut_ptr() as *mut Frame<Ch16, CH>;
Box::from_raw(from_raw_parts_mut(ptr, len))
};
let frames: Vec<Frame<Ch16, CH>> = frames.into();
Audio::with_frames(hz, frames)
}
#[allow(unsafe_code)]
pub fn as_i16_slice(&mut self) -> &mut [i16] {
let frames = self.as_mut_slice();
unsafe {
let (prefix, v, suffix) = frames.align_to_mut::<i16>();
debug_assert!(prefix.is_empty());
debug_assert!(suffix.is_empty());
v
}
}
}
impl<const CH: usize> Audio<Ch24, CH> {
#[allow(unsafe_code)]
pub fn with_u8_buffer<B>(hz: u32, buffer: B) -> Self
where
B: Into<Box<[u8]>>,
{
let buffer: Box<[u8]> = buffer.into();
let bytes = buffer.len() * size_of::<i16>();
let len = bytes / size_of::<Frame<Ch16, CH>>();
assert_eq!(0, bytes % size_of::<Frame<Ch16, CH>>());
let slice = Box::<[u8]>::into_raw(buffer);
let frames: Box<[Frame<Ch24, CH>]> = unsafe {
let ptr = (*slice).as_mut_ptr() as *mut Frame<Ch24, CH>;
Box::from_raw(from_raw_parts_mut(ptr, len))
};
let frames: Vec<Frame<Ch24, CH>> = frames.into();
Audio::with_frames(hz, frames)
}
#[allow(unsafe_code)]
pub fn as_u8_slice(&mut self) -> &mut [u8] {
let frames = self.as_mut_slice();
unsafe {
let (prefix, v, suffix) = frames.align_to_mut::<u8>();
debug_assert!(prefix.is_empty());
debug_assert!(suffix.is_empty());
v
}
}
}
impl<const CH: usize> Audio<Ch32, CH> {
#[allow(unsafe_code)]
pub fn with_f32_buffer<B>(hz: u32, buffer: B) -> Self
where
B: Into<Box<[f32]>>,
{
let buffer: Box<[f32]> = buffer.into();
let bytes = buffer.len() * size_of::<f32>();
let len = bytes / size_of::<Frame<Ch32, CH>>();
assert_eq!(0, bytes % size_of::<Frame<Ch32, CH>>());
let slice = Box::<[f32]>::into_raw(buffer);
let frames: Box<[Frame<Ch32, CH>]> = unsafe {
let ptr = (*slice).as_mut_ptr() as *mut Frame<Ch32, CH>;
Box::from_raw(from_raw_parts_mut(ptr, len))
};
let frames: Vec<Frame<Ch32, CH>> = frames.into();
Audio::with_frames(hz, frames)
}
#[allow(unsafe_code)]
pub fn as_f32_slice(&mut self) -> &mut [f32] {
let frames = self.as_mut_slice();
unsafe {
let (prefix, v, suffix) = frames.align_to_mut::<f32>();
debug_assert!(prefix.is_empty());
debug_assert!(suffix.is_empty());
v
}
}
}
impl<const CH: usize> Audio<Ch64, CH> {
#[allow(unsafe_code)]
pub fn with_f64_buffer<B>(hz: u32, buffer: B) -> Self
where
B: Into<Box<[f64]>>,
{
let buffer: Box<[f64]> = buffer.into();
let bytes = buffer.len() * size_of::<f64>();
let len = bytes / size_of::<Frame<Ch64, CH>>();
assert_eq!(0, bytes % size_of::<Frame<Ch64, CH>>());
let slice = Box::<[f64]>::into_raw(buffer);
let frames: Box<[Frame<Ch64, CH>]> = unsafe {
let ptr = (*slice).as_mut_ptr() as *mut Frame<Ch64, CH>;
Box::from_raw(from_raw_parts_mut(ptr, len))
};
let frames: Vec<Frame<Ch64, CH>> = frames.into();
Audio::with_frames(hz, frames)
}
#[allow(unsafe_code)]
pub fn as_f64_slice(&mut self) -> &mut [f64] {
let frames = self.as_mut_slice();
unsafe {
let (prefix, v, suffix) = frames.align_to_mut::<f64>();
debug_assert!(prefix.is_empty());
debug_assert!(suffix.is_empty());
v
}
}
}
impl<Chan, const CH: usize> From<Audio<Chan, CH>> for Vec<Frame<Chan, CH>>
where
Chan: Channel,
{
fn from(audio: Audio<Chan, CH>) -> Self {
audio.frames.into()
}
}
impl<Chan: Channel, const CH: usize> From<Audio<Chan, CH>>
for Box<[Frame<Chan, CH>]>
{
fn from(audio: Audio<Chan, CH>) -> Self {
let audio: Vec<Frame<Chan, CH>> = audio.frames.into();
audio.into()
}
}
impl<const CH: usize> From<Audio<Ch16, CH>> for Box<[i16]> {
#[allow(unsafe_code)]
fn from(audio: Audio<Ch16, CH>) -> Self {
let mut frames: Vec<Frame<Ch16, CH>> = audio.frames.into();
let capacity = frames.len() * size_of::<Frame<Ch16, CH>>() / 2;
let buffer: Box<[i16]> = unsafe {
let ptr = frames.as_mut_ptr() as *mut i16;
Box::from_raw(from_raw_parts_mut(ptr, capacity))
};
buffer
}
}
impl<const CH: usize> From<Audio<Ch24, CH>> for Box<[u8]> {
#[allow(unsafe_code)]
fn from(audio: Audio<Ch24, CH>) -> Self {
let mut frames: Vec<Frame<Ch24, CH>> = audio.frames.into();
let capacity = frames.len() * size_of::<Frame<Ch24, CH>>() / 3;
let buffer: Box<[u8]> = unsafe {
let ptr = frames.as_mut_ptr() as *mut u8;
Box::from_raw(from_raw_parts_mut(ptr, capacity))
};
buffer
}
}
impl<const CH: usize> From<Audio<Ch32, CH>> for Box<[f32]> {
#[allow(unsafe_code)]
fn from(audio: Audio<Ch32, CH>) -> Self {
let mut frames: Vec<Frame<Ch32, CH>> = audio.frames.into();
let capacity = frames.len() * size_of::<Frame<Ch32, CH>>() / 4;
let buffer: Box<[f32]> = unsafe {
let ptr = frames.as_mut_ptr() as *mut f32;
Box::from_raw(from_raw_parts_mut(ptr, capacity))
};
buffer
}
}
impl<const CH: usize> From<Audio<Ch64, CH>> for Box<[f64]> {
#[allow(unsafe_code)]
fn from(audio: Audio<Ch64, CH>) -> Self {
let mut frames: Vec<Frame<Ch64, CH>> = audio.frames.into();
let capacity = frames.len() * size_of::<Frame<Ch64, CH>>() / 8;
let buffer: Box<[f64]> = unsafe {
let ptr = frames.as_mut_ptr() as *mut f64;
Box::from_raw(from_raw_parts_mut(ptr, capacity))
};
buffer
}
}