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}