servo_media_audio/
listener.rs

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