servo_media_audio/
constant_source_node.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::{Chunk, Tick};
6use crate::node::{
7    AudioNodeEngine, AudioNodeType, AudioScheduledSourceNodeMessage, BlockInfo, ChannelInfo,
8    OnEndedCallback, ShouldPlay,
9};
10use crate::param::{Param, ParamType};
11
12#[derive(Copy, Clone, Debug)]
13pub struct ConstantSourceNodeOptions {
14    pub offset: f32,
15}
16
17impl Default for ConstantSourceNodeOptions {
18    fn default() -> Self {
19        ConstantSourceNodeOptions { offset: 1. }
20    }
21}
22
23#[derive(AudioScheduledSourceNode, AudioNodeCommon)]
24pub(crate) struct ConstantSourceNode {
25    channel_info: ChannelInfo,
26    offset: Param,
27    start_at: Option<Tick>,
28    stop_at: Option<Tick>,
29    onended_callback: Option<OnEndedCallback>,
30}
31
32impl ConstantSourceNode {
33    pub fn new(options: ConstantSourceNodeOptions, channel_info: ChannelInfo) -> Self {
34        Self {
35            channel_info,
36            offset: Param::new(options.offset),
37            start_at: None,
38            stop_at: None,
39            onended_callback: None,
40        }
41    }
42
43    pub fn update_parameters(&mut self, info: &BlockInfo, tick: Tick) -> bool {
44        self.offset.update(info, tick)
45    }
46}
47
48impl AudioNodeEngine for ConstantSourceNode {
49    fn node_type(&self) -> AudioNodeType {
50        AudioNodeType::ConstantSourceNode
51    }
52
53    fn process(&mut self, mut inputs: Chunk, info: &BlockInfo) -> Chunk {
54        debug_assert!(inputs.is_empty());
55
56        inputs.blocks.push(Default::default());
57
58        let (start_at, stop_at) = match self.should_play_at(info.frame) {
59            ShouldPlay::No => {
60                return inputs;
61            },
62            ShouldPlay::Between(start, end) => (start, end),
63        };
64
65        {
66            inputs.blocks[0].explicit_silence();
67
68            let mut iter = inputs.blocks[0].iter();
69            let mut offset = self.offset.value();
70            while let Some(mut frame) = iter.next() {
71                let tick = frame.tick();
72                if tick < start_at {
73                    continue;
74                } else if tick > stop_at {
75                    break;
76                }
77                if self.update_parameters(info, frame.tick()) {
78                    offset = self.offset.value();
79                }
80                frame.mutate_with(|sample, _| *sample = offset);
81            }
82        }
83        inputs
84    }
85    fn input_count(&self) -> u32 {
86        0
87    }
88
89    fn get_param(&mut self, id: ParamType) -> &mut Param {
90        match id {
91            ParamType::Offset => &mut self.offset,
92            _ => panic!("Unknown param {:?} for the offset", id),
93        }
94    }
95    make_message_handler!(AudioScheduledSourceNode: handle_source_node_message);
96}