use crate::internal_utils::{slice_from_external_parts, slice_from_external_parts_mut};
use crate::process::Audio;
use crate::process::audio::pair::ChannelPair::*;
use crate::process::audio::{BufferError, InputPort, OutputPort, SampleType};
use clack_common::process::{AudioPortProcessingInfo, ConstantMask};
use clap_sys::audio_buffer::clap_audio_buffer;
use std::slice::{Iter, IterMut};
pub struct PortPair<'a> {
input: Option<&'a clap_audio_buffer>,
output: Option<&'a mut clap_audio_buffer>,
frames_count: u32,
}
impl<'a> PortPair<'a> {
#[inline]
pub(crate) unsafe fn from_raw(
input: Option<&'a clap_audio_buffer>,
output: Option<&'a mut clap_audio_buffer>,
frames_count: u32,
) -> Option<Self> {
match (input, output) {
(None, None) => None,
(input, output) => Some(PortPair {
input,
output,
frames_count,
}),
}
}
#[inline]
pub fn input(&self) -> Option<InputPort<'_>> {
self.input
.map(|i| unsafe { InputPort::from_raw(i, self.frames_count) })
}
#[inline]
pub fn output(&mut self) -> Option<OutputPort<'_>> {
self.output
.as_mut()
.map(|i| unsafe { OutputPort::from_raw(i, self.frames_count) })
}
#[inline]
pub fn input_info(&self) -> Option<AudioPortProcessingInfo> {
self.input
.as_ref()
.map(|buf| AudioPortProcessingInfo::from_raw(buf))
}
#[inline]
pub fn output_info(&self) -> Option<AudioPortProcessingInfo> {
self.output
.as_ref()
.map(|buf| AudioPortProcessingInfo::from_raw(buf))
}
#[inline]
pub fn channels(
&mut self,
) -> Result<SampleType<PairedChannels<'a, f32>, PairedChannels<'a, f64>>, BufferError> {
let input = match self.input {
None => SampleType::Both([].as_slice(), [].as_slice()),
Some(buffer) => unsafe { SampleType::from_raw_buffer(buffer)? },
};
let output = match self.output.as_mut() {
None => SampleType::Both([].as_mut_slice(), [].as_mut_slice()),
Some(buffer) => unsafe { SampleType::from_raw_buffer_mut(buffer)? },
};
Ok(input.try_match_with(output)?.map(
|(i, o)| PairedChannels {
input_data: i,
output_data: o,
frames_count: self.frames_count,
},
|(i, o)| PairedChannels {
input_data: i,
output_data: o,
frames_count: self.frames_count,
},
))
}
#[inline]
pub fn channel_pair_count(&self) -> usize {
let in_channels = self.input.map(|b| b.channel_count).unwrap_or(0);
let out_channels = self.output.as_ref().map(|b| b.channel_count).unwrap_or(0);
in_channels.max(out_channels) as usize
}
#[inline]
pub fn frames_count(&self) -> u32 {
self.frames_count
}
#[inline]
pub fn latencies(&self) -> (Option<u32>, Option<u32>) {
(
self.input.map(|i| i.latency),
self.output.as_ref().map(|o| o.latency),
)
}
#[inline]
pub fn constant_masks(&self) -> (ConstantMask, ConstantMask) {
(
self.input
.map(|i| ConstantMask::from_bits(i.constant_mask))
.unwrap_or(ConstantMask::FULLY_CONSTANT),
self.output
.as_ref()
.map(|o| ConstantMask::from_bits(o.constant_mask))
.unwrap_or(ConstantMask::FULLY_CONSTANT),
)
}
}
pub struct PairedChannels<'a, S> {
input_data: &'a [*mut S],
output_data: &'a mut [*mut S],
frames_count: u32,
}
impl<'a, S> PairedChannels<'a, S> {
#[inline]
pub fn frames_count(&self) -> u32 {
self.frames_count
}
#[inline]
pub fn input_channel_count(&self) -> usize {
self.input_data.len()
}
#[inline]
pub fn output_channel_count(&self) -> usize {
self.output_data.len()
}
#[inline]
pub fn channel_pair_count(&self) -> usize {
self.input_channel_count().max(self.output_channel_count())
}
#[inline]
pub fn channel_pair(&mut self, index: usize) -> Option<ChannelPair<'a, S>> {
let input = self
.input_data
.get(index)
.map(|ptr| unsafe { slice_from_external_parts(*ptr, self.frames_count as usize) });
let output = self
.output_data
.get(index)
.map(|ptr| unsafe { slice_from_external_parts_mut(*ptr, self.frames_count as usize) });
ChannelPair::from_optional_io(input, output)
}
#[inline]
pub fn iter_mut(&mut self) -> PairedChannelsIter<'_, S> {
PairedChannelsIter {
input_iter: self.input_data.iter(),
output_iter: self.output_data.iter_mut(),
frames_count: self.frames_count,
}
}
}
impl<'a, S> IntoIterator for PairedChannels<'a, S> {
type Item = ChannelPair<'a, S>;
type IntoIter = PairedChannelsIter<'a, S>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
PairedChannelsIter {
input_iter: self.input_data.iter(),
output_iter: self.output_data.iter_mut(),
frames_count: self.frames_count,
}
}
}
pub struct PairedChannelsIter<'a, S> {
input_iter: Iter<'a, *mut S>,
output_iter: IterMut<'a, *mut S>,
frames_count: u32,
}
impl<'a, S> Iterator for PairedChannelsIter<'a, S> {
type Item = ChannelPair<'a, S>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let input = self
.input_iter
.next()
.map(|ptr| unsafe { slice_from_external_parts(*ptr, self.frames_count as usize) });
let output = self.output_iter.next().map(|ptr| unsafe {
slice_from_external_parts_mut((*ptr) as *mut _, self.frames_count as usize)
});
ChannelPair::from_optional_io(input, output)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<S> ExactSizeIterator for PairedChannelsIter<'_, S> {
#[inline]
fn len(&self) -> usize {
self.input_iter.len().max(self.output_iter.len())
}
}
pub struct PortPairsIter<'a> {
inputs: Iter<'a, clap_audio_buffer>,
outputs: IterMut<'a, clap_audio_buffer>,
frames_count: u32,
}
impl<'a> PortPairsIter<'a> {
#[inline]
pub(crate) fn new(audio: &'a mut Audio<'_>) -> Self {
Self {
inputs: audio.inputs.iter(),
outputs: audio.outputs.iter_mut(),
frames_count: audio.frames_count,
}
}
}
impl<'a> Iterator for PortPairsIter<'a> {
type Item = PortPair<'a>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
unsafe { PortPair::from_raw(self.inputs.next(), self.outputs.next(), self.frames_count) }
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl ExactSizeIterator for PortPairsIter<'_> {
#[inline]
fn len(&self) -> usize {
self.inputs.len().max(self.outputs.len())
}
}
pub enum ChannelPair<'a, S> {
InputOnly(&'a [S]),
OutputOnly(&'a mut [S]),
InputOutput(&'a [S], &'a mut [S]),
InPlace(&'a mut [S]),
}
impl<'a, S> ChannelPair<'a, S> {
#[inline]
pub(crate) fn from_optional_io(
input: Option<&'a [S]>,
output: Option<&'a mut [S]>,
) -> Option<ChannelPair<'a, S>> {
match (input, output) {
(None, None) => None,
(Some(input), None) => Some(InputOnly(input)),
(None, Some(output)) => Some(OutputOnly(output)),
(Some(input), Some(output)) => Some(if input.as_ptr() == output.as_ptr() {
InPlace(output)
} else {
InputOutput(input, output)
}),
}
}
#[inline]
pub fn input(&'a self) -> Option<&'a [S]> {
match self {
InputOnly(i) | InputOutput(i, _) => Some(i),
OutputOnly(_) => None,
InPlace(io) => Some(io),
}
}
#[inline]
pub fn output(&'a self) -> Option<&'a [S]> {
match self {
OutputOnly(o) | InputOutput(_, o) | InPlace(o) => Some(o),
InputOnly(_) => None,
}
}
#[inline]
pub fn output_mut(&'a mut self) -> Option<&'a mut [S]> {
match self {
OutputOnly(o) | InputOutput(_, o) | InPlace(o) => Some(o),
InputOnly(_) => None,
}
}
}