servo_media_audio/
listener.rs

1use crate::block::{Block, Chunk};
2use crate::node::{AudioNodeEngine, BlockInfo};
3use crate::node::{AudioNodeType, ChannelInfo};
4use crate::param::{Param, ParamDir, ParamType};
5
6/// AudioListeners are fake nodes; from the user's point of view they're
7/// a non-node entity with zero inputs and outputs, but with AudioParams
8/// that can be manipulated.
9///
10/// Internally, PannerNodes all have an implicit PortIndex::Listener connection
11/// from a hidden output port on AudioListeners that contains all the position data.
12///
13/// This encodes the otherwise implicit dependency between AudioListeners and PannerNodes
14/// so that if there is a cycle involving panner nodes and the audio params on the listener,
15/// the cycle breaking algorithm can deal with it.
16#[derive(AudioNodeCommon)]
17pub(crate) struct AudioListenerNode {
18    channel_info: ChannelInfo,
19    position_x: Param,
20    position_y: Param,
21    position_z: Param,
22    forward_x: Param,
23    forward_y: Param,
24    forward_z: Param,
25    up_x: Param,
26    up_y: Param,
27    up_z: Param,
28}
29
30impl AudioListenerNode {
31    pub fn new() -> Self {
32        Self {
33            channel_info: Default::default(),
34            position_x: Param::new(0.),
35            position_y: Param::new(0.),
36            position_z: Param::new(0.),
37            forward_x: Param::new(0.),
38            forward_y: Param::new(0.),
39            forward_z: Param::new(-1.),
40            up_x: Param::new(0.),
41            up_y: Param::new(1.),
42            up_z: Param::new(0.),
43        }
44    }
45}
46
47impl AudioNodeEngine for AudioListenerNode {
48    fn node_type(&self) -> AudioNodeType {
49        AudioNodeType::AudioListenerNode
50    }
51
52    fn process(&mut self, mut inputs: Chunk, info: &BlockInfo) -> Chunk {
53        debug_assert!(inputs.len() == 0);
54
55        // XXXManishearth in the common case when all of these are constant,
56        // it would be nice to instead send just the constant values down
57        let mut block = Block::for_channels_explicit(9);
58        self.position_x.flush_to_block(info, block.data_chan_mut(0));
59        self.position_y.flush_to_block(info, block.data_chan_mut(1));
60        self.position_z.flush_to_block(info, block.data_chan_mut(2));
61        self.forward_x.flush_to_block(info, block.data_chan_mut(3));
62        self.forward_y.flush_to_block(info, block.data_chan_mut(4));
63        self.forward_z.flush_to_block(info, block.data_chan_mut(5));
64        self.up_x.flush_to_block(info, block.data_chan_mut(6));
65        self.up_y.flush_to_block(info, block.data_chan_mut(7));
66        self.up_z.flush_to_block(info, block.data_chan_mut(8));
67
68        inputs.blocks.push(block);
69        inputs
70    }
71
72    fn input_count(&self) -> u32 {
73        0
74    }
75
76    fn get_param(&mut self, id: ParamType) -> &mut Param {
77        match id {
78            ParamType::Position(ParamDir::X) => &mut self.position_x,
79            ParamType::Position(ParamDir::Y) => &mut self.position_y,
80            ParamType::Position(ParamDir::Z) => &mut self.position_z,
81            ParamType::Forward(ParamDir::X) => &mut self.forward_x,
82            ParamType::Forward(ParamDir::Y) => &mut self.forward_y,
83            ParamType::Forward(ParamDir::Z) => &mut self.forward_z,
84            ParamType::Up(ParamDir::X) => &mut self.up_x,
85            ParamType::Up(ParamDir::Y) => &mut self.up_y,
86            ParamType::Up(ParamDir::Z) => &mut self.up_z,
87            _ => panic!("Unknown param {:?} for AudioListenerNode", id),
88        }
89    }
90}