use super::super::simulation::SourceWithInputs;
use super::{SimulationStep, SimulationStepError, SourceEntries};
use crate::effect::{ReflectionEffectParams, ReflectionEffectType};
use crate::ray_tracing::RayTracer;
use crate::simulation::{
DirectCompatible, PathingCompatible, ReflectionEffectCompatible, Reflections,
SimulationFlagsProvider, SimulationSharedInputs, Simulator,
};
use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
pub struct ReflectionsReverbStep<SourceId, T, D, P, RE>
where
T: RayTracer,
{
simulator: Simulator<T, D, Reflections, P, RE>,
_source_id: PhantomData<fn() -> SourceId>,
}
impl<T, D, P, RE> ReflectionsReverbStep<(), T, D, P, RE>
where
T: RayTracer,
{
pub fn new<SourceId>(
simulator: Simulator<T, D, Reflections, P, RE>,
) -> ReflectionsReverbStep<SourceId, T, D, P, RE> {
ReflectionsReverbStep {
simulator,
_source_id: PhantomData,
}
}
}
impl<SourceId, T, D, P, RE, I> SimulationStep<I> for ReflectionsReverbStep<SourceId, T, D, P, RE>
where
T: 'static + RayTracer,
D: 'static + Send + Sync + DirectCompatible<D> + SimulationFlagsProvider,
P: 'static + Send + Sync + PathingCompatible<P> + SimulationFlagsProvider,
RE: 'static + Send + Sync + ReflectionEffectCompatible<Reflections, RE> + ReflectionEffectType,
(): DirectCompatible<D>
+ PathingCompatible<P>
+ DirectCompatible<I::LD>
+ PathingCompatible<I::LP>,
SourceId: 'static + Clone + Send + Sync + Hash + Eq,
I: AsReflectionsReverbInput<SourceId, D, Reflections, P, RE>,
I::LD: 'static + Send + Sync + DirectCompatible<I::LD> + SimulationFlagsProvider,
I::LP: 'static + Send + Sync + PathingCompatible<I::LP> + SimulationFlagsProvider,
{
type Output = ReflectionsReverbOutput<SourceId, RE>;
type Error = SimulationStepError;
fn run(&mut self, frame: &I, output: &mut Self::Output) -> Result<(), Self::Error> {
let input = frame.as_reflections_reverb_input();
self.simulator
.set_shared_reflections_inputs(input.shared_inputs)?;
for (
_,
SourceWithInputs {
source,
simulation_inputs,
},
) in input.sources
{
source.set_reflections_inputs(simulation_inputs)?;
}
if let Some(listener) = input.listener {
listener
.source
.set_reflections_inputs(&listener.simulation_inputs)?;
}
self.simulator.run_reflections()?;
for (id, SourceWithInputs { source, .. }) in input.sources.iter() {
output
.sources
.insert(id.clone(), source.get_reflections_outputs()?);
}
if let Some(listener) = input.listener {
output.listener = Some(listener.source.get_reflections_outputs()?);
}
Ok(())
}
}
#[derive(Debug)]
pub struct ReflectionsReverbInput<'a, SourceId, D, R, P, RE, LD = D, LP = P>
where
RE: ReflectionEffectCompatible<R, RE>,
{
pub sources: &'a SourceEntries<SourceId, D, R, P, RE>,
pub listener: Option<&'a SourceWithInputs<LD, R, LP, RE>>,
pub shared_inputs: &'a SimulationSharedInputs<D, R, P>,
}
pub trait AsReflectionsReverbInput<SourceId, D, R, P, RE>
where
RE: ReflectionEffectCompatible<R, RE>,
{
type LD;
type LP;
fn as_reflections_reverb_input(
&self,
) -> ReflectionsReverbInput<'_, SourceId, D, R, P, RE, Self::LD, Self::LP>;
}
pub struct ReflectionsReverbInputOwned<SourceId, D, R, P, RE, LD = D, LP = P>
where
RE: ReflectionEffectCompatible<R, RE>,
{
pub sources: Vec<(SourceId, SourceWithInputs<D, R, P, RE>)>,
pub listener: Option<SourceWithInputs<LD, R, LP, RE>>,
pub shared_inputs: SimulationSharedInputs<D, R, P>,
}
impl<SourceId, D, R, P, RE, LD, LP> AsReflectionsReverbInput<SourceId, D, R, P, RE>
for ReflectionsReverbInputOwned<SourceId, D, R, P, RE, LD, LP>
where
RE: ReflectionEffectCompatible<R, RE>,
{
type LD = LD;
type LP = LP;
fn as_reflections_reverb_input(
&self,
) -> ReflectionsReverbInput<'_, SourceId, D, R, P, RE, LD, LP> {
ReflectionsReverbInput {
sources: self.sources.as_slice(),
listener: self.listener.as_ref(),
shared_inputs: &self.shared_inputs,
}
}
}
#[derive(Debug)]
pub struct ReflectionsReverbOutput<SourceId, RE>
where
SourceId: Hash + Eq,
RE: ReflectionEffectType,
{
pub sources: HashMap<SourceId, ReflectionEffectParams<RE>>,
pub listener: Option<ReflectionEffectParams<RE>>,
}
impl<SourceId, RE> Default for ReflectionsReverbOutput<SourceId, RE>
where
SourceId: Hash + Eq,
RE: ReflectionEffectType,
{
fn default() -> Self {
Self {
sources: HashMap::new(),
listener: None,
}
}
}
unsafe impl<SourceId, RE> Send for ReflectionsReverbOutput<SourceId, RE>
where
SourceId: Send + Hash + Eq,
RE: ReflectionEffectType,
{
}
unsafe impl<SourceId, RE> Sync for ReflectionsReverbOutput<SourceId, RE>
where
SourceId: Sync + Hash + Eq,
RE: ReflectionEffectType,
{
}