use crate::channel::{LinearChannel, LinearChannelMut};
use audio_core::{Buf, BufMut, ExactSizeBuf, ResizableBuf, Sample};
use std::cmp;
use std::fmt;
use std::hash;
use std::mem;
use std::ops;
use std::ptr;
use std::slice;
mod iter;
pub use self::iter::{IterChannels, IterChannelsMut};
pub struct Dynamic<T> {
data: RawSlice<RawSlice<T>>,
channels: usize,
channels_cap: usize,
frames: usize,
frames_cap: usize,
}
impl<T> Dynamic<T> {
pub fn new() -> Self {
Self {
data: RawSlice::empty(),
channels: 0,
channels_cap: 0,
frames: 0,
frames_cap: 0,
}
}
pub fn with_topology(channels: usize, frames: usize) -> Self
where
T: Sample,
{
let mut data = RawSlice::uninit(channels);
for n in 0..channels {
unsafe {
data.write(n, RawSlice::zeroed(frames));
}
}
Self {
data,
channels,
channels_cap: channels,
frames,
frames_cap: frames,
}
}
pub fn from_array<const F: usize, const C: usize>(channels: [[T; F]; C]) -> Self
where
T: Copy,
{
return Self {
data: unsafe { data_from_array(channels) },
channels: C,
channels_cap: C,
frames: F,
frames_cap: F,
};
#[inline]
unsafe fn data_from_array<T, const F: usize, const C: usize>(
values: [[T; F]; C],
) -> RawSlice<RawSlice<T>>
where
T: Copy,
{
let mut data = Vec::with_capacity(C);
for frames in values {
let slice = Box::<[T]>::from(frames);
let slice = ptr::NonNull::new_unchecked(Box::into_raw(slice) as *mut T);
data.push(RawSlice { data: slice });
}
RawSlice {
data: ptr::NonNull::new_unchecked(mem::ManuallyDrop::new(data).as_mut_ptr()),
}
}
}
pub fn from_frames<const N: usize>(frames: [T; N], channels: usize) -> Self
where
T: Copy,
{
return Self {
data: data_from_frames(frames, channels),
channels,
channels_cap: channels,
frames: N,
frames_cap: N,
};
fn data_from_frames<T, const N: usize>(
frames: [T; N],
channels: usize,
) -> RawSlice<RawSlice<T>>
where
T: Copy,
{
unsafe {
let mut data = RawSlice::uninit(channels);
for c in 0..channels {
let mut slice = RawSlice::uninit(N);
ptr::copy_nonoverlapping(frames.as_ptr(), slice.as_ptr(), N);
data.write(c, slice);
}
data
}
}
}
pub fn frames(&self) -> usize {
self.frames
}
pub fn channels(&self) -> usize {
self.channels
}
pub fn iter_channels(&self) -> IterChannels<'_, T> {
unsafe { IterChannels::new(self.data.as_ref(self.channels), self.frames) }
}
pub fn iter_channels_mut(&mut self) -> IterChannelsMut<'_, T> {
unsafe { IterChannelsMut::new(self.data.as_mut(self.channels), self.frames) }
}
pub fn resize_frames(&mut self, frames: usize)
where
T: Sample,
{
if self.frames_cap < frames {
let from = self.frames_cap;
let to = <RawSlice<T>>::next_cap(from, frames);
if self.channels_cap > 0 {
let additional = to - from;
for n in 0..self.channels_cap {
unsafe {
self.data
.get_unchecked_mut(n)
.reserve_zeroed(from, additional)
};
}
}
self.frames_cap = to;
}
self.frames = frames;
}
pub fn resize_channels(&mut self, channels: usize)
where
T: Sample,
{
if channels == self.channels {
return;
}
if channels > self.channels_cap {
let old_cap = self.channels_cap;
let new_cap = <RawSlice<RawSlice<T>>>::next_cap(old_cap, channels);
let additional = new_cap - old_cap;
unsafe {
self.data.reserve_uninit(old_cap, additional);
}
for n in old_cap..new_cap {
let slice = RawSlice::zeroed(self.frames_cap);
unsafe {
self.data.write(n, slice);
}
}
self.channels_cap = new_cap;
}
debug_assert!(channels <= self.channels_cap);
self.channels = channels;
}
pub fn get_channel(&self, channel: usize) -> Option<LinearChannel<'_, T>> {
if channel < self.channels {
let data = unsafe { self.data.get_unchecked(channel).as_ref(self.frames) };
Some(LinearChannel::new(data))
} else {
None
}
}
pub fn get_or_default(&mut self, channel: usize) -> &[T]
where
T: Sample,
{
self.resize_channels(channel + 1);
unsafe { self.data.get_unchecked(channel).as_ref(self.frames) }
}
pub fn get_mut(&mut self, channel: usize) -> Option<LinearChannelMut<'_, T>> {
if channel < self.channels {
let data = unsafe { self.data.get_unchecked_mut(channel).as_mut(self.frames) };
Some(LinearChannelMut::new(data))
} else {
None
}
}
pub fn get_or_default_mut(&mut self, channel: usize) -> &mut [T]
where
T: Sample,
{
self.resize_channels(channel + 1);
unsafe { self.data.get_unchecked_mut(channel).as_mut(self.frames) }
}
pub fn into_vectors(self) -> Vec<Vec<T>> {
self.into_vectors_if(|_| true)
}
pub fn into_vectors_if(self, mut condition: impl FnMut(usize) -> bool) -> Vec<Vec<T>> {
let mut this = mem::ManuallyDrop::new(self);
let mut vecs = Vec::with_capacity(this.channels);
let frames_cap = this.frames_cap;
for n in 0..this.channels {
unsafe {
let mut slice = this.data.read(n);
if condition(n) {
vecs.push(slice.into_vec(this.frames, frames_cap));
} else {
slice.drop_in_place(frames_cap);
vecs.push(Vec::new());
}
}
}
for n in this.channels..this.channels_cap {
unsafe {
this.data.get_unchecked_mut(n).drop_in_place(frames_cap);
}
}
unsafe {
let cap = this.channels_cap;
this.data.drop_in_place(cap);
}
vecs
}
}
impl<T> Default for Dynamic<T> {
fn default() -> Self {
Self::new()
}
}
unsafe impl<T> Send for Dynamic<T> where T: Send {}
unsafe impl<T> Sync for Dynamic<T> where T: Sync {}
impl<T, const F: usize, const C: usize> From<[[T; F]; C]> for Dynamic<T>
where
T: Copy,
{
#[inline]
fn from(channels: [[T; F]; C]) -> Self {
Self::from_array(channels)
}
}
impl<T> fmt::Debug for Dynamic<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter_channels()).finish()
}
}
impl<T> cmp::PartialEq for Dynamic<T>
where
T: cmp::PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.iter_channels().eq(other.iter_channels())
}
}
impl<T> cmp::Eq for Dynamic<T> where T: cmp::Eq {}
impl<T> cmp::PartialOrd for Dynamic<T>
where
T: cmp::PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.iter_channels().partial_cmp(other.iter_channels())
}
}
impl<T> cmp::Ord for Dynamic<T>
where
T: cmp::Ord,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.iter_channels().cmp(other.iter_channels())
}
}
impl<T> hash::Hash for Dynamic<T>
where
T: hash::Hash,
{
fn hash<H: hash::Hasher>(&self, state: &mut H) {
for channel in self.iter_channels() {
channel.hash(state);
}
}
}
impl<'a, T> IntoIterator for &'a Dynamic<T> {
type IntoIter = IterChannels<'a, T>;
type Item = <Self::IntoIter as Iterator>::Item;
fn into_iter(self) -> Self::IntoIter {
(*self).iter_channels()
}
}
impl<'a, T> IntoIterator for &'a mut Dynamic<T> {
type IntoIter = IterChannelsMut<'a, T>;
type Item = <Self::IntoIter as Iterator>::Item;
fn into_iter(self) -> Self::IntoIter {
self.iter_channels_mut()
}
}
impl<T> ops::Index<usize> for Dynamic<T> {
type Output = [T];
fn index(&self, index: usize) -> &Self::Output {
match self.get_channel(index) {
Some(slice) => slice.into_ref(),
None => panic!("index `{}` is not a channel", index),
}
}
}
impl<T> ops::IndexMut<usize> for Dynamic<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match self.get_mut(index) {
Some(slice) => slice.into_mut(),
None => panic!("index `{}` is not a channel", index,),
}
}
}
impl<T> Drop for Dynamic<T> {
fn drop(&mut self) {
for n in 0..self.channels_cap {
unsafe {
self.data
.get_unchecked_mut(n)
.drop_in_place(self.frames_cap);
}
}
unsafe {
self.data.drop_in_place(self.channels_cap);
}
}
}
impl<T> ExactSizeBuf for Dynamic<T>
where
T: Copy,
{
fn frames(&self) -> usize {
(*self).frames()
}
}
impl<T> Buf for Dynamic<T>
where
T: Copy,
{
type Sample = T;
type Channel<'this>
= LinearChannel<'this, Self::Sample>
where
Self::Sample: 'this;
type IterChannels<'this>
= IterChannels<'this, T>
where
Self::Sample: 'this;
#[inline]
fn frames_hint(&self) -> Option<usize> {
Some(self.frames)
}
#[inline]
fn channels(&self) -> usize {
(*self).channels()
}
#[inline]
fn get_channel(&self, channel: usize) -> Option<Self::Channel<'_>> {
(*self).get_channel(channel)
}
#[inline]
fn iter_channels(&self) -> Self::IterChannels<'_> {
(*self).iter_channels()
}
}
impl<T> ResizableBuf for Dynamic<T>
where
T: Sample,
{
fn try_reserve(&mut self, _capacity: usize) -> bool {
false
}
fn resize_frames(&mut self, frames: usize) {
Self::resize_frames(self, frames);
}
fn resize_topology(&mut self, channels: usize, frames: usize) {
Self::resize_frames(self, frames);
Self::resize_channels(self, channels);
}
}
impl<T> BufMut for Dynamic<T>
where
T: Copy,
{
type ChannelMut<'this>
= LinearChannelMut<'this, Self::Sample>
where
Self: 'this;
type IterChannelsMut<'this>
= IterChannelsMut<'this, T>
where
Self: 'this;
fn get_channel_mut(&mut self, channel: usize) -> Option<Self::ChannelMut<'_>> {
(*self).get_mut(channel)
}
fn copy_channel(&mut self, from: usize, to: usize) {
assert! {
from < self.channels,
"copy from channel {} is out of bounds 0-{}",
from,
self.channels
};
assert! {
to < self.channels,
"copy to channel {} which is out of bounds 0-{}",
to,
self.channels
};
if from != to {
unsafe {
let from = self.data.get_unchecked(from).as_ref(self.frames);
let to = self.data.get_unchecked_mut(to).as_mut(self.frames);
to.copy_from_slice(from);
}
}
}
fn iter_channels_mut(&mut self) -> Self::IterChannelsMut<'_> {
(*self).iter_channels_mut()
}
}
#[repr(transparent)]
struct RawSlice<T> {
data: ptr::NonNull<T>,
}
impl<T> RawSlice<T> {
const MIN_NON_ZERO_CAP: usize = if mem::size_of::<T>() == 1 {
8
} else if mem::size_of::<T>() <= 256 {
4
} else {
1
};
fn next_cap(from: usize, to: usize) -> usize {
let to = usize::max(from * 2, to);
usize::max(Self::MIN_NON_ZERO_CAP, to)
}
fn empty() -> Self {
Self {
data: unsafe { ptr::NonNull::new_unchecked(Vec::new().as_mut_ptr()) },
}
}
fn uninit(cap: usize) -> Self {
unsafe {
let data = Vec::with_capacity(cap);
let data = ptr::NonNull::new_unchecked(mem::ManuallyDrop::new(data).as_mut_ptr());
Self { data }
}
}
fn zeroed(cap: usize) -> Self
where
T: Sample,
{
unsafe {
let mut data = Vec::with_capacity(cap);
ptr::write_bytes(data.as_mut_ptr(), 0, cap);
let data = ptr::NonNull::new_unchecked(mem::ManuallyDrop::new(data).as_mut_ptr());
Self { data }
}
}
unsafe fn reserve_zeroed(&mut self, len: usize, additional: usize)
where
T: Sample,
{
let mut channel = Vec::from_raw_parts(self.data.as_ptr(), len, len);
channel.reserve_exact(additional);
ptr::write_bytes(channel.as_mut_ptr().add(len), 0, additional);
self.data = ptr::NonNull::new_unchecked(mem::ManuallyDrop::new(channel).as_mut_ptr());
}
unsafe fn reserve_uninit(&mut self, len: usize, additional: usize) {
let mut channel = Vec::from_raw_parts(self.data.as_ptr(), len, len);
channel.reserve_exact(additional);
self.data = ptr::NonNull::new_unchecked(mem::ManuallyDrop::new(channel).as_mut_ptr());
}
unsafe fn get_unchecked<'a>(&self, n: usize) -> &'a T {
&*self.data.as_ptr().add(n)
}
unsafe fn get_unchecked_mut<'a>(&mut self, n: usize) -> &'a mut T {
&mut *self.data.as_ptr().add(n)
}
unsafe fn read(&self, n: usize) -> T {
ptr::read(self.data.as_ptr().add(n))
}
unsafe fn write(&mut self, n: usize, value: T) {
ptr::write(self.data.as_ptr().add(n), value)
}
fn as_ptr(&mut self) -> *mut T {
self.data.as_ptr()
}
unsafe fn as_ref(&self, len: usize) -> &[T] {
slice::from_raw_parts(self.data.as_ptr() as *const _, len)
}
unsafe fn as_linear_channel(&self, len: usize) -> LinearChannel<'_, T> {
LinearChannel::new(self.as_ref(len))
}
unsafe fn as_mut(&mut self, len: usize) -> &mut [T] {
slice::from_raw_parts_mut(self.data.as_ptr(), len)
}
unsafe fn as_linear_channel_mut(&mut self, len: usize) -> LinearChannelMut<'_, T> {
LinearChannelMut::new(self.as_mut(len))
}
unsafe fn drop_in_place(&mut self, len: usize) {
let _ = Vec::from_raw_parts(self.data.as_ptr(), 0, len);
}
pub(crate) unsafe fn into_vec(self, len: usize, cap: usize) -> Vec<T> {
Vec::from_raw_parts(self.data.as_ptr(), len, cap)
}
}