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