use super::audio_effect_state::AudioEffectState;
use super::equalizer::Equalizer;
use super::error::{ImpulseResponseSizeExceedsMaxError, NumChannelsExceedsMaxError};
use super::EffectError;
use crate::audio_buffer::{AudioBuffer, Sample};
use crate::audio_settings::AudioSettings;
use crate::context::Context;
use crate::device::true_audio_next::TrueAudioNextDevice;
use crate::error::{to_option_error, SteamAudioError};
use crate::ffi_wrapper::FFIWrapper;
use crate::Sealed;
use crate::{ChannelPointers, ChannelRequirement};
use std::marker::PhantomData;
#[derive(Debug)]
pub struct Convolution;
#[derive(Debug)]
pub struct Parametric;
#[derive(Debug)]
pub struct Hybrid;
#[derive(Debug)]
pub struct TrueAudioNext;
impl Sealed for Convolution {}
impl Sealed for Parametric {}
impl Sealed for Hybrid {}
impl Sealed for TrueAudioNext {}
pub trait CanApplyDirectly: Sealed {}
impl CanApplyDirectly for Convolution {}
impl CanApplyDirectly for Parametric {}
impl CanApplyDirectly for Hybrid {}
pub trait CanUseReflectionMixer: Sealed {}
impl CanUseReflectionMixer for Convolution {}
impl CanUseReflectionMixer for TrueAudioNext {}
pub trait ReflectionEffectType: Sealed {
fn to_ffi_type() -> audionimbus_sys::IPLReflectionEffectType;
fn ffi_settings(
settings: &ReflectionEffectSettings,
) -> audionimbus_sys::IPLReflectionEffectSettings {
audionimbus_sys::IPLReflectionEffectSettings {
type_: Self::to_ffi_type(),
irSize: settings.impulse_response_size as i32,
numChannels: settings.num_channels as i32,
}
}
fn num_output_channels(settings: &ReflectionEffectSettings) -> ChannelRequirement;
}
impl ReflectionEffectType for Convolution {
fn to_ffi_type() -> audionimbus_sys::IPLReflectionEffectType {
audionimbus_sys::IPLReflectionEffectType::IPL_REFLECTIONEFFECTTYPE_CONVOLUTION
}
fn num_output_channels(settings: &ReflectionEffectSettings) -> ChannelRequirement {
ChannelRequirement::Exactly(settings.num_channels)
}
}
impl ReflectionEffectType for Parametric {
fn to_ffi_type() -> audionimbus_sys::IPLReflectionEffectType {
audionimbus_sys::IPLReflectionEffectType::IPL_REFLECTIONEFFECTTYPE_PARAMETRIC
}
fn ffi_settings(
settings: &ReflectionEffectSettings,
) -> audionimbus_sys::IPLReflectionEffectSettings {
audionimbus_sys::IPLReflectionEffectSettings {
type_: Self::to_ffi_type(),
irSize: settings.impulse_response_size as i32,
numChannels: settings.num_channels as i32,
}
}
fn num_output_channels(_settings: &ReflectionEffectSettings) -> ChannelRequirement {
ChannelRequirement::AtLeast(1)
}
}
impl ReflectionEffectType for Hybrid {
fn to_ffi_type() -> audionimbus_sys::IPLReflectionEffectType {
audionimbus_sys::IPLReflectionEffectType::IPL_REFLECTIONEFFECTTYPE_HYBRID
}
fn num_output_channels(settings: &ReflectionEffectSettings) -> ChannelRequirement {
ChannelRequirement::Exactly(settings.num_channels)
}
}
impl ReflectionEffectType for TrueAudioNext {
fn to_ffi_type() -> audionimbus_sys::IPLReflectionEffectType {
audionimbus_sys::IPLReflectionEffectType::IPL_REFLECTIONEFFECTTYPE_TAN
}
fn num_output_channels(settings: &ReflectionEffectSettings) -> ChannelRequirement {
ChannelRequirement::Exactly(settings.num_channels)
}
}
#[cfg(doc)]
use super::AmbisonicsDecodeEffect;
#[cfg(doc)]
use crate::geometry::Scene;
#[cfg(doc)]
use crate::simulation::{SimulationOutputs, Simulator, Source};
#[derive(Debug)]
pub struct ReflectionEffect<T: ReflectionEffectType> {
inner: audionimbus_sys::IPLReflectionEffect,
num_output_channels: ChannelRequirement,
_marker: PhantomData<T>,
}
impl<T: ReflectionEffectType> ReflectionEffect<T> {
pub fn try_new(
context: &Context,
audio_settings: &AudioSettings,
reflection_effect_settings: &ReflectionEffectSettings,
) -> Result<Self, SteamAudioError> {
let mut inner = std::ptr::null_mut();
let status = unsafe {
audionimbus_sys::iplReflectionEffectCreate(
context.raw_ptr(),
&mut audionimbus_sys::IPLAudioSettings::from(audio_settings),
&mut T::ffi_settings(reflection_effect_settings),
&raw mut inner,
)
};
if let Some(error) = to_option_error(status) {
return Err(error);
}
let num_output_channels = T::num_output_channels(reflection_effect_settings);
let reflection_effect = Self {
inner,
num_output_channels,
_marker: PhantomData,
};
Ok(reflection_effect)
}
pub fn tail_size(&self) -> usize {
unsafe { audionimbus_sys::iplReflectionEffectGetTailSize(self.raw_ptr()) as usize }
}
pub fn reset(&mut self) {
unsafe { audionimbus_sys::iplReflectionEffectReset(self.raw_ptr()) };
}
pub const fn raw_ptr(&self) -> audionimbus_sys::IPLReflectionEffect {
self.inner
}
pub const fn raw_ptr_mut(&mut self) -> &mut audionimbus_sys::IPLReflectionEffect {
&mut self.inner
}
}
impl<T: ReflectionEffectType + CanApplyDirectly> ReflectionEffect<T> {
pub fn apply<I, O, PI: ChannelPointers, PO: ChannelPointers>(
&mut self,
reflection_effect_params: &ReflectionEffectParams<T>,
input_buffer: &AudioBuffer<I, PI>,
output_buffer: &AudioBuffer<O, PO>,
) -> Result<AudioEffectState, EffectError>
where
I: AsRef<[Sample]>,
O: AsRef<[Sample]> + AsMut<[Sample]>,
{
let num_input_channels = input_buffer.num_channels();
if num_input_channels != 1 {
return Err(EffectError::InvalidInputChannels {
expected: ChannelRequirement::Exactly(1),
actual: num_input_channels,
});
}
let num_output_channels = output_buffer.num_channels();
if !self
.num_output_channels
.is_satisfied_by(num_output_channels)
{
return Err(EffectError::InvalidOutputChannels {
expected: self.num_output_channels,
actual: num_output_channels,
});
}
let state = unsafe {
audionimbus_sys::iplReflectionEffectApply(
self.raw_ptr(),
&raw mut *reflection_effect_params.as_ffi(),
&raw mut *input_buffer.as_ffi(),
&raw mut *output_buffer.as_ffi(),
std::ptr::null_mut(),
)
}
.into();
Ok(state)
}
pub fn tail<O>(&self, output_buffer: &AudioBuffer<O>) -> Result<AudioEffectState, EffectError>
where
O: AsRef<[Sample]> + AsMut<[Sample]>,
{
let num_output_channels = output_buffer.num_channels();
if !self
.num_output_channels
.is_satisfied_by(num_output_channels)
{
return Err(EffectError::InvalidOutputChannels {
expected: self.num_output_channels,
actual: num_output_channels,
});
}
let state = unsafe {
audionimbus_sys::iplReflectionEffectGetTail(
self.raw_ptr(),
&raw mut *output_buffer.as_ffi(),
std::ptr::null_mut(),
)
}
.into();
Ok(state)
}
}
impl<T: ReflectionEffectType + CanUseReflectionMixer> ReflectionEffect<T> {
pub fn apply_into_mixer<I, O, PI: ChannelPointers, PO: ChannelPointers>(
&mut self,
reflection_effect_params: &ReflectionEffectParams<T>,
input_buffer: &AudioBuffer<I, PI>,
output_buffer: &AudioBuffer<O, PO>,
mixer: &ReflectionMixer<T>,
) -> Result<AudioEffectState, EffectError>
where
I: AsRef<[Sample]>,
O: AsRef<[Sample]> + AsMut<[Sample]>,
{
let num_input_channels = input_buffer.num_channels();
if num_input_channels != 1 {
return Err(EffectError::InvalidInputChannels {
expected: ChannelRequirement::Exactly(1),
actual: num_input_channels,
});
}
let num_output_channels = output_buffer.num_channels();
if !self
.num_output_channels
.is_satisfied_by(num_output_channels)
{
return Err(EffectError::InvalidOutputChannels {
expected: self.num_output_channels,
actual: num_output_channels,
});
}
let state = unsafe {
audionimbus_sys::iplReflectionEffectApply(
self.raw_ptr(),
&mut *reflection_effect_params.as_ffi(),
&mut *input_buffer.as_ffi(),
&mut *output_buffer.as_ffi(),
mixer.raw_ptr(),
)
}
.into();
Ok(state)
}
pub fn tail_into_mixer<O>(
&self,
output_buffer: &AudioBuffer<O>,
mixer: &ReflectionMixer<T>,
) -> Result<AudioEffectState, EffectError>
where
O: AsRef<[Sample]> + AsMut<[Sample]>,
{
let num_output_channels = output_buffer.num_channels();
if !self
.num_output_channels
.is_satisfied_by(num_output_channels)
{
return Err(EffectError::InvalidOutputChannels {
expected: self.num_output_channels,
actual: num_output_channels,
});
}
let state = unsafe {
audionimbus_sys::iplReflectionEffectGetTail(
self.raw_ptr(),
&raw mut *output_buffer.as_ffi(),
mixer.raw_ptr(),
)
}
.into();
Ok(state)
}
}
impl<T: ReflectionEffectType> Drop for ReflectionEffect<T> {
fn drop(&mut self) {
unsafe { audionimbus_sys::iplReflectionEffectRelease(&raw mut self.inner) }
}
}
unsafe impl<T: ReflectionEffectType> Send for ReflectionEffect<T> {}
unsafe impl<T: ReflectionEffectType> Sync for ReflectionEffect<T> {}
impl<T: ReflectionEffectType> Clone for ReflectionEffect<T> {
fn clone(&self) -> Self {
Self {
inner: unsafe { audionimbus_sys::iplReflectionEffectRetain(self.inner) },
num_output_channels: self.num_output_channels,
_marker: PhantomData,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct ReflectionEffectSettings {
pub impulse_response_size: u32,
pub num_channels: u32,
}
#[derive(Debug, PartialEq)]
pub struct ReflectionEffectParams<'a, T: ReflectionEffectType> {
impulse_response: ReflectionEffectIR,
reverb_times: [f32; 3],
equalizer: Equalizer<3>,
delay: u32,
num_channels: u32,
impulse_response_size: u32,
max_num_channels: u32,
max_impulse_response_size: u32,
true_audio_next_device: Option<&'a TrueAudioNextDevice>,
true_audio_next_slot: u32,
_marker: PhantomData<T>,
}
impl ReflectionEffectParams<'_, Convolution> {
pub fn new(
impulse_response: audionimbus_sys::IPLReflectionEffectIR,
num_channels: u32,
impulse_response_size: u32,
) -> Self {
Self {
impulse_response: ReflectionEffectIR(impulse_response),
reverb_times: <[f32; 3]>::default(),
equalizer: Equalizer::default(),
delay: 0,
num_channels,
impulse_response_size,
max_num_channels: num_channels,
max_impulse_response_size: impulse_response_size,
true_audio_next_device: None,
true_audio_next_slot: 0,
_marker: PhantomData,
}
}
}
impl ReflectionEffectParams<'_, Parametric> {
pub fn new(reverb_times: [f32; 3], num_channels: u32, impulse_response_size: u32) -> Self {
Self {
impulse_response: ReflectionEffectIR(std::ptr::null_mut()),
reverb_times,
equalizer: Equalizer::default(),
delay: 0,
num_channels,
impulse_response_size,
max_num_channels: num_channels,
max_impulse_response_size: impulse_response_size,
true_audio_next_device: None,
true_audio_next_slot: 0,
_marker: PhantomData,
}
}
}
impl ReflectionEffectParams<'_, Hybrid> {
pub const fn new(
impulse_response: audionimbus_sys::IPLReflectionEffectIR,
reverb_times: [f32; 3],
equalizer: Equalizer<3>,
delay: u32,
num_channels: u32,
impulse_response_size: u32,
) -> Self {
Self {
impulse_response: ReflectionEffectIR(impulse_response),
reverb_times,
equalizer,
delay,
num_channels,
impulse_response_size,
max_num_channels: num_channels,
max_impulse_response_size: impulse_response_size,
true_audio_next_device: None,
true_audio_next_slot: 0,
_marker: PhantomData,
}
}
}
impl<'a> ReflectionEffectParams<'a, TrueAudioNext> {
pub fn new(
num_channels: u32,
impulse_response_size: u32,
device: &'a TrueAudioNextDevice,
slot: u32,
) -> Self {
Self {
impulse_response: ReflectionEffectIR(std::ptr::null_mut()),
reverb_times: <[f32; 3]>::default(),
equalizer: Equalizer::default(),
delay: 0,
num_channels,
impulse_response_size,
max_num_channels: num_channels,
max_impulse_response_size: impulse_response_size,
true_audio_next_device: Some(device),
true_audio_next_slot: slot,
_marker: PhantomData,
}
}
}
impl<T: ReflectionEffectType> ReflectionEffectParams<'_, T> {
pub fn set_num_channels(
&mut self,
num_channels: u32,
) -> Result<(), NumChannelsExceedsMaxError> {
if num_channels > self.max_num_channels {
return Err(NumChannelsExceedsMaxError {
requested: num_channels,
max: self.max_num_channels,
});
}
self.num_channels = num_channels;
Ok(())
}
pub fn set_impulse_response_size(
&mut self,
impulse_response_size: u32,
) -> Result<(), ImpulseResponseSizeExceedsMaxError> {
if impulse_response_size > self.max_impulse_response_size {
return Err(ImpulseResponseSizeExceedsMaxError {
requested: impulse_response_size,
max: self.max_impulse_response_size,
});
}
self.impulse_response_size = impulse_response_size;
Ok(())
}
pub(crate) unsafe fn from_ffi_unchecked(
params: audionimbus_sys::IPLReflectionEffectParams,
) -> Self {
let device = if params.tanDevice.is_null() {
None
} else {
Some(&*(params.tanDevice as *const TrueAudioNextDevice))
};
let num_channels = params.numChannels as u32;
let impulse_response_size = params.irSize as u32;
Self {
impulse_response: ReflectionEffectIR(params.ir),
reverb_times: params.reverbTimes,
equalizer: Equalizer(params.eq),
delay: params.delay as u32,
num_channels,
impulse_response_size,
max_num_channels: num_channels,
max_impulse_response_size: impulse_response_size,
true_audio_next_device: device,
true_audio_next_slot: params.tanSlot as u32,
_marker: PhantomData,
}
}
}
unsafe impl<T: ReflectionEffectType> Send for ReflectionEffectParams<'_, T> {}
#[derive(Debug, Eq, PartialEq)]
pub struct ReflectionEffectIR(pub audionimbus_sys::IPLReflectionEffectIR);
unsafe impl Send for ReflectionEffectIR {}
impl<'a, T: ReflectionEffectType> ReflectionEffectParams<'a, T> {
pub(crate) fn as_ffi(
&self,
) -> FFIWrapper<'_, audionimbus_sys::IPLReflectionEffectParams, Self> {
let device_ptr = self
.true_audio_next_device
.map(|d| d.raw_ptr())
.unwrap_or(std::ptr::null_mut());
let reflection_effect_params = audionimbus_sys::IPLReflectionEffectParams {
type_: T::to_ffi_type(),
ir: self.impulse_response.0,
reverbTimes: self.reverb_times,
eq: *self.equalizer,
delay: self.delay as i32,
numChannels: self.num_channels as i32,
irSize: self.impulse_response_size as i32,
tanDevice: device_ptr,
tanSlot: self.true_audio_next_slot as i32,
};
FFIWrapper::new(reflection_effect_params)
}
}
#[derive(Debug)]
pub struct ReflectionMixer<T: ReflectionEffectType> {
inner: audionimbus_sys::IPLReflectionMixer,
num_output_channels: ChannelRequirement,
_marker: PhantomData<T>,
}
impl<T: ReflectionEffectType> ReflectionMixer<T> {
pub fn try_new(
context: &Context,
audio_settings: &AudioSettings,
reflection_effect_settings: &ReflectionEffectSettings,
) -> Result<Self, SteamAudioError> {
let mut inner = std::ptr::null_mut();
let status = unsafe {
audionimbus_sys::iplReflectionMixerCreate(
context.raw_ptr(),
&mut audionimbus_sys::IPLAudioSettings::from(audio_settings),
&mut T::ffi_settings(reflection_effect_settings),
&raw mut inner,
)
};
if let Some(error) = to_option_error(status) {
return Err(error);
}
let num_output_channels = T::num_output_channels(reflection_effect_settings);
let reflection_mixer = Self {
inner,
num_output_channels,
_marker: PhantomData,
};
Ok(reflection_mixer)
}
pub fn apply<O, PO: ChannelPointers>(
&mut self,
reflection_effect_params: &mut ReflectionEffectParams<T>,
output_buffer: &AudioBuffer<O, PO>,
) -> Result<AudioEffectState, EffectError>
where
O: AsRef<[Sample]> + AsMut<[Sample]>,
{
let num_output_channels = output_buffer.num_channels();
if !self
.num_output_channels
.is_satisfied_by(num_output_channels)
{
return Err(EffectError::InvalidOutputChannels {
expected: self.num_output_channels,
actual: num_output_channels,
});
}
let audio_effect_state = unsafe {
audionimbus_sys::iplReflectionMixerApply(
self.raw_ptr(),
&raw mut *reflection_effect_params.as_ffi(),
&raw mut *output_buffer.as_ffi(),
)
};
let state = audio_effect_state.into();
Ok(state)
}
pub fn reset(&mut self) {
unsafe { audionimbus_sys::iplReflectionMixerReset(self.raw_ptr()) };
}
pub const fn raw_ptr(&self) -> audionimbus_sys::IPLReflectionMixer {
self.inner
}
pub const fn raw_ptr_mut(&mut self) -> &mut audionimbus_sys::IPLReflectionMixer {
&mut self.inner
}
}
impl<T: ReflectionEffectType> Drop for ReflectionMixer<T> {
fn drop(&mut self) {
unsafe { audionimbus_sys::iplReflectionMixerRelease(&raw mut self.inner) }
}
}
unsafe impl<T: ReflectionEffectType> Send for ReflectionMixer<T> {}
unsafe impl<T: ReflectionEffectType> Sync for ReflectionMixer<T> {}
impl<T: ReflectionEffectType> Clone for ReflectionMixer<T> {
fn clone(&self) -> Self {
Self {
inner: unsafe { audionimbus_sys::iplReflectionMixerRetain(self.inner) },
num_output_channels: self.num_output_channels,
_marker: PhantomData,
}
}
}
#[cfg(test)]
mod tests {
use crate::*;
mod reflection_effect {
use super::*;
mod apply {
use super::*;
#[test]
fn test_valid() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Convolution {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let input_container = vec![0.5; FRAME_SIZE as usize];
let input_buffer = AudioBuffer::try_with_data(&input_container).unwrap();
let mut output_container =
vec![0.0; (num_output_channels * input_buffer.num_samples()) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(4),
)
.unwrap();
let reflection_effect_params = simulation_outputs.reflections();
assert!(reflection_effect
.apply(&reflection_effect_params, &input_buffer, &output_buffer)
.is_ok());
}
#[test]
fn test_invalid_input_num_channels() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Convolution {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut input_container = vec![0.5; 2 * FRAME_SIZE as usize];
let input_buffer = AudioBuffer::try_with_data_and_settings(
&mut input_container,
AudioBufferSettings::with_num_channels(2),
)
.unwrap();
let mut output_container =
vec![0.0; (num_output_channels * input_buffer.num_samples()) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(4),
)
.unwrap();
let reflection_effect_params = simulation_outputs.reflections();
assert_eq!(
reflection_effect.apply(
&reflection_effect_params,
&input_buffer,
&output_buffer
),
Err(EffectError::InvalidInputChannels {
expected: ChannelRequirement::Exactly(1),
actual: 2
})
);
}
#[test]
fn test_invalid_output_num_channels() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Convolution {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let input_container = vec![0.5; FRAME_SIZE as usize];
let input_buffer = AudioBuffer::try_with_data(&input_container).unwrap();
let mut output_container = vec![0.0; (2 * input_buffer.num_samples()) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(2),
)
.unwrap();
let reflection_effect_params = simulation_outputs.reflections();
assert_eq!(
reflection_effect.apply(
&reflection_effect_params,
&input_buffer,
&output_buffer
),
Err(EffectError::InvalidOutputChannels {
expected: ChannelRequirement::Exactly(4),
actual: 2
})
);
}
}
mod apply_into_mixer {
use super::*;
#[test]
fn test_valid() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Convolution {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let input_container = vec![0.5; FRAME_SIZE as usize];
let input_buffer = AudioBuffer::try_with_data(&input_container).unwrap();
let mut output_container =
vec![0.0; (num_output_channels * input_buffer.num_samples()) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(4),
)
.unwrap();
let mixer = ReflectionMixer::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let reflection_effect_params = simulation_outputs.reflections();
assert!(reflection_effect
.apply_into_mixer(
&reflection_effect_params,
&input_buffer,
&output_buffer,
&mixer
)
.is_ok());
}
#[test]
fn test_invalid_input_num_channels() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Convolution {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut input_container = vec![0.5; 2 * FRAME_SIZE as usize];
let input_buffer = AudioBuffer::try_with_data_and_settings(
&mut input_container,
AudioBufferSettings::with_num_channels(2),
)
.unwrap();
let mut output_container =
vec![0.0; (num_output_channels * input_buffer.num_samples()) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(4),
)
.unwrap();
let mixer = ReflectionMixer::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let reflection_effect_params = simulation_outputs.reflections();
assert_eq!(
reflection_effect.apply_into_mixer(
&reflection_effect_params,
&input_buffer,
&output_buffer,
&mixer
),
Err(EffectError::InvalidInputChannels {
expected: ChannelRequirement::Exactly(1),
actual: 2
})
);
}
#[test]
fn test_invalid_output_num_channels() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Convolution {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut input_container = vec![0.5; FRAME_SIZE as usize];
let input_buffer = AudioBuffer::try_with_data(&mut input_container).unwrap();
let mut output_container = vec![0.0; (2 * input_buffer.num_samples()) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(2),
)
.unwrap();
let mixer = ReflectionMixer::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let reflection_effect_params = simulation_outputs.reflections();
assert_eq!(
reflection_effect.apply_into_mixer(
&reflection_effect_params,
&input_buffer,
&output_buffer,
&mixer
),
Err(EffectError::InvalidOutputChannels {
expected: ChannelRequirement::Exactly(4),
actual: 2
})
);
}
}
mod tail {
use super::*;
#[test]
fn test_valid() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
let context = Context::default();
let audio_settings = AudioSettings::default();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut output_container = vec![0.0; (num_output_channels * FRAME_SIZE) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(num_output_channels),
)
.unwrap();
assert!(reflection_effect.tail(&output_buffer).is_ok());
}
#[test]
fn test_invalid_output_num_channels() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
let context = Context::default();
let audio_settings = AudioSettings::default();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut output_container = vec![0.0; FRAME_SIZE as usize];
let output_buffer = AudioBuffer::try_with_data(&mut output_container).unwrap();
assert_eq!(
reflection_effect.tail(&output_buffer),
Err(EffectError::InvalidOutputChannels {
expected: ChannelRequirement::Exactly(4),
actual: 1
})
);
}
}
mod tail_into_mixer {
use super::*;
#[test]
fn test_valid() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
let context = Context::default();
let audio_settings = AudioSettings::default();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut output_container = vec![0.0; (num_output_channels * FRAME_SIZE) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(num_output_channels),
)
.unwrap();
let mixer = ReflectionMixer::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
assert!(reflection_effect
.tail_into_mixer(&output_buffer, &mixer)
.is_ok());
}
#[test]
fn test_invalid_output_num_channels() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
let context = Context::default();
let audio_settings = AudioSettings::default();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let reflection_effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut output_container = vec![0.0; FRAME_SIZE as usize];
let output_buffer = AudioBuffer::try_with_data(&mut output_container).unwrap();
let mixer = ReflectionMixer::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
assert_eq!(
reflection_effect.tail_into_mixer(&output_buffer, &mixer),
Err(EffectError::InvalidOutputChannels {
expected: ChannelRequirement::Exactly(4),
actual: 1
})
);
}
}
mod clone {
use super::*;
#[test]
fn test_clone() {
const SAMPLING_RATE: u32 = 48000;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
let context = Context::default();
let audio_settings = AudioSettings::default();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let effect = ReflectionEffect::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let clone = effect.clone();
assert_eq!(effect.raw_ptr(), clone.raw_ptr());
drop(effect);
assert!(!clone.raw_ptr().is_null());
}
}
}
mod reflection_mixer {
use super::*;
mod apply {
use super::*;
#[test]
fn test_valid() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Convolution {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut mixer = ReflectionMixer::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut output_container = vec![0.0; (num_output_channels * FRAME_SIZE) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(num_output_channels),
)
.unwrap();
let mut reflection_effect_params = simulation_outputs.reflections();
assert!(mixer
.apply(&mut reflection_effect_params, &output_buffer)
.is_ok());
}
#[test]
fn test_invalid_output_num_channels() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Convolution {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut mixer = ReflectionMixer::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut output_container = vec![0.0; (2 * FRAME_SIZE) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(2),
)
.unwrap();
let mut reflection_effect_params = simulation_outputs.reflections();
assert_eq!(
mixer.apply(&mut reflection_effect_params, &output_buffer),
Err(EffectError::InvalidOutputChannels {
expected: ChannelRequirement::Exactly(4),
actual: 2
})
);
}
#[test]
fn test_parametric_valid() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Parametric {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut mixer = ReflectionMixer::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut output_container = vec![0.0; (num_output_channels * FRAME_SIZE) as usize];
let output_buffer = AudioBuffer::try_with_data_and_settings(
&mut output_container,
AudioBufferSettings::with_num_channels(num_output_channels),
)
.unwrap();
let mut reflection_effect_params = simulation_outputs.reflections();
assert!(mixer
.apply(&mut reflection_effect_params, &output_buffer)
.is_ok());
}
#[test]
fn test_parametric_at_least_one_channel() {
const SAMPLING_RATE: u32 = 48000;
const FRAME_SIZE: u32 = 1024;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
const MAX_ORDER: u32 = 1;
let context = Context::default();
let audio_settings = AudioSettings::default();
let simulation_settings =
SimulationSettings::new(SAMPLING_RATE, FRAME_SIZE, MAX_ORDER).with_reflections(
ReflectionsSimulationSettings::Parametric {
max_num_rays: 4096,
num_diffuse_samples: 32,
max_duration: 2.0,
max_num_sources: 8,
num_threads: 1,
},
);
let mut simulator = Simulator::try_new(&context, &simulation_settings).unwrap();
let scene = Scene::try_new(&context).unwrap();
simulator.set_scene(&scene);
let source_settings = SourceSettings {
flags: SimulationFlags::REFLECTIONS,
};
let mut source =
Source::<(), Reflections, ()>::try_new(&simulator, &source_settings).unwrap();
simulator.add_source(&source);
let simulation_shared_inputs = SimulationSharedInputs::new(
CoordinateSystem::default(),
)
.with_reflections(ReflectionsSharedInputs {
num_rays: 4096,
num_bounces: 16,
duration: 2.0,
order: 1,
irradiance_min_distance: 1.0,
});
simulator
.set_shared_inputs(SimulationFlags::REFLECTIONS, &simulation_shared_inputs)
.unwrap();
simulator.commit();
assert!(simulator.run_reflections().is_ok());
let simulation_outputs = source.get_outputs(SimulationFlags::REFLECTIONS).unwrap();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut mixer = ReflectionMixer::<Parametric>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let mut output_container = vec![0.0; FRAME_SIZE as usize];
let output_buffer = AudioBuffer::try_with_data(&mut output_container).unwrap();
let mut reflection_effect_params = simulation_outputs.reflections();
assert!(mixer
.apply(&mut reflection_effect_params, &output_buffer)
.is_ok());
}
}
mod reset {
use super::*;
#[test]
fn test_reset() {
const SAMPLING_RATE: u32 = 48000;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
let context = Context::default();
let audio_settings = AudioSettings::default();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mut mixer = ReflectionMixer::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
mixer.reset();
}
}
mod clone {
use super::*;
#[test]
fn test_clone() {
const SAMPLING_RATE: u32 = 48000;
const IR_SIZE: u32 = 2 * SAMPLING_RATE;
let context = Context::default();
let audio_settings = AudioSettings::default();
let num_output_channels = num_ambisonics_channels(1);
let reflection_effect_settings = ReflectionEffectSettings {
impulse_response_size: IR_SIZE,
num_channels: num_output_channels,
};
let mixer = ReflectionMixer::<Convolution>::try_new(
&context,
&audio_settings,
&reflection_effect_settings,
)
.unwrap();
let clone = mixer.clone();
assert_eq!(mixer.raw_ptr(), clone.raw_ptr());
drop(mixer);
assert!(!clone.raw_ptr().is_null());
}
}
}
}