#![allow(missing_docs)]
#![allow(clippy::module_inception)]
use bevy::prelude::Component;
use firewheel::{
channel_config::{ChannelConfig, ChannelCount},
core::node::ProcInfo,
diff::{Diff, Patch},
event::NodeEventList,
node::{
AudioNode, AudioNodeInfo, AudioNodeProcessor, ConstructProcessorContext, EmptyConfig,
ProcBuffers, ProcessStatus,
},
};
mod all_pass;
mod comb;
mod delay_line;
mod freeverb;
#[derive(Diff, Patch, Clone, Debug, Component)]
pub struct FreeverbNode {
pub room_size: f32,
pub damping: f32,
pub width: f32,
}
impl Default for FreeverbNode {
fn default() -> Self {
FreeverbNode {
room_size: 0.5,
damping: 0.5,
width: 0.5,
}
}
}
impl AudioNode for FreeverbNode {
type Configuration = EmptyConfig;
fn info(&self, _: &Self::Configuration) -> AudioNodeInfo {
AudioNodeInfo::new()
.debug_name("freeverb")
.channel_config(ChannelConfig {
num_inputs: ChannelCount::STEREO,
num_outputs: ChannelCount::STEREO,
})
}
fn construct_processor(
&self,
_: &Self::Configuration,
cx: ConstructProcessorContext,
) -> impl AudioNodeProcessor {
let mut freeverb = freeverb::Freeverb::new(cx.stream_info.sample_rate.get() as usize);
self.apply_params(&mut freeverb);
FreeverbProcessor {
params: self.clone(),
freeverb,
}
}
}
impl FreeverbNode {
fn apply_params(&self, verb: &mut freeverb::Freeverb) {
verb.set_dampening(self.damping as f64);
verb.set_width(self.width as f64);
verb.set_room_size(self.room_size as f64);
}
}
struct FreeverbProcessor {
params: FreeverbNode,
freeverb: freeverb::Freeverb,
}
impl AudioNodeProcessor for FreeverbProcessor {
fn process(
&mut self,
ProcBuffers {
inputs, outputs, ..
}: ProcBuffers,
proc_info: &ProcInfo,
mut events: NodeEventList,
) -> ProcessStatus {
let mut changed = false;
events.for_each_patch::<FreeverbNode>(|p| {
changed = true;
self.params.apply(p);
});
if changed {
self.params.apply_params(&mut self.freeverb);
}
for frame in 0..proc_info.frames {
let (left, right) = self
.freeverb
.tick((inputs[0][frame] as f64, inputs[1][frame] as f64));
outputs[0][frame] = left as f32;
outputs[1][frame] = right as f32;
}
ProcessStatus::outputs_not_silent()
}
fn new_stream(&mut self, stream_info: &firewheel::StreamInfo) {
self.freeverb = freeverb::Freeverb::new(stream_info.sample_rate.get() as usize);
self.params.apply_params(&mut self.freeverb);
}
}