servo_media_audio/
stereo_panner.rs1use std::f32::consts::PI;
6
7use crate::block::{Chunk, FRAMES_PER_BLOCK, Tick};
8use crate::node::{AudioNodeEngine, AudioNodeType, BlockInfo, ChannelInfo};
9use crate::param::{Param, ParamType};
10
11#[derive(Copy, Clone, Debug)]
12pub struct StereoPannerOptions {
13 pub pan: f32,
14}
15
16impl Default for StereoPannerOptions {
17 fn default() -> Self {
18 StereoPannerOptions { pan: 0. }
19 }
20}
21
22#[derive(AudioNodeCommon)]
23pub(crate) struct StereoPannerNode {
24 channel_info: ChannelInfo,
25 pan: Param,
26}
27
28impl StereoPannerNode {
29 pub fn new(options: StereoPannerOptions, channel_info: ChannelInfo) -> Self {
30 Self {
31 channel_info,
32 pan: Param::new(options.pan),
33 }
34 }
35
36 pub fn update_parameters(&mut self, info: &BlockInfo, tick: Tick) -> bool {
37 self.pan.update(info, tick)
38 }
39}
40
41impl AudioNodeEngine for StereoPannerNode {
42 fn node_type(&self) -> AudioNodeType {
43 AudioNodeType::StereoPannerNode
44 }
45
46 fn process(&mut self, mut inputs: Chunk, info: &BlockInfo) -> Chunk {
47 debug_assert!(inputs.len() == 1);
48
49 {
50 let block = &mut inputs.blocks[0];
51
52 block.explicit_repeat();
53
54 let mono = if block.chan_count() == 1 {
55 block.resize_silence(2);
56 true
57 } else {
58 debug_assert!(block.chan_count() == 2);
59 false
60 };
61
62 let (l, r) = block.data_mut().split_at_mut(FRAMES_PER_BLOCK.0 as usize);
63 let mut pan = self.pan.value();
64 for frame in 0..FRAMES_PER_BLOCK.0 {
65 let frame = Tick(frame);
66 if self.update_parameters(info, frame) {
67 pan = self.pan.value();
68 }
69
70 pan = pan.clamp(-1., 1.);
74
75 let x = if mono {
76 (pan + 1.) / 2.
77 } else if pan <= 0. {
78 pan + 1.
79 } else {
80 pan
81 };
82 let x = x * PI / 2.;
83
84 let mut gain_l = x.cos();
85 let mut gain_r = x.sin();
86 if gain_l <= 0. {
88 gain_l = 0.
89 }
90 if gain_r <= 0. {
91 gain_r = 0.;
92 }
93
94 let index = frame.0 as usize;
95 if mono {
96 let input = l[index];
97 l[index] = input * gain_l;
98 r[index] = input * gain_r;
99 } else if pan <= 0. {
100 l[index] += r[index] * gain_l;
101 r[index] *= gain_r;
102 } else {
103 r[index] += l[index] * gain_r;
104 l[index] *= gain_l;
105 }
106 }
107 }
108
109 inputs
110 }
111
112 fn input_count(&self) -> u32 {
113 1
114 }
115
116 fn get_param(&mut self, id: ParamType) -> &mut Param {
117 match id {
118 ParamType::Pan => &mut self.pan,
119 _ => panic!("Unknown param {:?} for PannerNode", id),
120 }
121 }
122}