Skip to main content

rust_audio_api/nodes/
gain.rs

1use crate::types::AudioUnit;
2
3/// A node that adjusts the volume (gain) of the input signal.
4///
5/// Supports dynamic gain updates via [`ControlMessage::SetParameter`](crate::graph::ControlMessage::SetParameter).
6///
7/// # Example
8/// ```no_run
9/// use rust_audio_api::nodes::{GainNode, NodeType};
10/// use rust_audio_api::{AudioContext, NodeParameter};
11///
12/// let mut ctx = AudioContext::new().unwrap();
13///
14/// let mut gain_id = None;
15/// let dest_id = ctx.build_graph(|builder| {
16///     let gain = builder.add_node(NodeType::Gain(GainNode::new(0.5)));
17///     gain_id = Some(gain);
18///     gain
19/// });
20///
21/// // Dynamically change the gain to 1.0 (full volume)
22/// ctx.control_sender().send(
23///     rust_audio_api::graph::ControlMessage::SetParameter(
24///         gain_id.unwrap(),
25///         NodeParameter::Gain(1.0)
26///     )
27/// ).unwrap();
28/// ```
29pub struct GainNode {
30    gain: f32,
31}
32
33impl GainNode {
34    /// Creates a new `GainNode` with the specified gain factor.
35    ///
36    /// # Parameters
37    /// - `gain`: The multiplier for the audio signal (e.g., 1.0 for unity gain, 0.5 for half volume).
38    pub fn new(gain: f32) -> Self {
39        Self { gain }
40    }
41
42    /// Sets the gain factor for this node.
43    pub fn set_gain(&mut self, gain: f32) {
44        self.gain = gain;
45    }
46
47    /// GainNode is a passive node; it requires input to function.
48    /// It doesn't manage a ringbuf; it simply applies gain to each incoming frame.
49    #[inline(always)]
50    pub fn process(&mut self, input: Option<&AudioUnit>, output: &mut AudioUnit) {
51        if let Some(in_unit) = input {
52            output.copy_from_slice(in_unit);
53            dasp::slice::map_in_place(&mut output[..], |f| [f[0] * self.gain, f[1] * self.gain]);
54        } else {
55            // If no upstream input, output silence
56            dasp::slice::equilibrium(&mut output[..]);
57        }
58    }
59}