firewheel_nodes/
stereo_to_mono.rs1use firewheel_core::{
2 channel_config::{ChannelConfig, ChannelCount},
3 event::NodeEventList,
4 node::{
5 AudioNode, AudioNodeInfo, AudioNodeProcessor, ConstructProcessorContext, EmptyConfig,
6 ProcBuffers, ProcInfo, ProcessStatus,
7 },
8};
9
10#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
11#[cfg_attr(feature = "bevy", derive(bevy_ecs::prelude::Component))]
12pub struct StereoToMonoNode;
13
14impl AudioNode for StereoToMonoNode {
15 type Configuration = EmptyConfig;
16
17 fn info(&self, _config: &Self::Configuration) -> AudioNodeInfo {
18 AudioNodeInfo::new()
19 .debug_name("stereo_to_mono")
20 .channel_config(ChannelConfig {
21 num_inputs: ChannelCount::STEREO,
22 num_outputs: ChannelCount::MONO,
23 })
24 .uses_events(false)
25 }
26
27 fn construct_processor(
28 &self,
29 _config: &Self::Configuration,
30 _cx: ConstructProcessorContext,
31 ) -> impl AudioNodeProcessor {
32 StereoToMonoProcessor
33 }
34}
35
36struct StereoToMonoProcessor;
37
38impl AudioNodeProcessor for StereoToMonoProcessor {
39 fn process(
40 &mut self,
41 buffers: ProcBuffers,
42 proc_info: &ProcInfo,
43 _events: NodeEventList,
44 ) -> ProcessStatus {
45 if proc_info.in_silence_mask.all_channels_silent(2)
46 || buffers.inputs.len() < 2
47 || buffers.outputs.is_empty()
48 {
49 return ProcessStatus::ClearAllOutputs;
50 }
51
52 for (out_s, (&in1, &in2)) in buffers.outputs[0]
53 .iter_mut()
54 .zip(buffers.inputs[0].iter().zip(buffers.inputs[1].iter()))
55 {
56 *out_s = (in1 + in2) * 0.5;
57 }
58
59 ProcessStatus::outputs_not_silent()
60 }
61}