Skip to main content

firewheel_pool/
sampler.rs

1use firewheel_core::{
2    channel_config::NonZeroChannelCount,
3    diff::{Diff, PathBuilder},
4    node::NodeID,
5};
6use firewheel_graph::{backend::AudioBackend, ContextQueue, FirewheelCtx};
7use firewheel_nodes::sampler::{SamplerConfig, SamplerNode, SamplerState};
8
9use crate::{PoolError, PoolableNode};
10
11/// A struct which uses a [`SamplerNode`] as the first node in an
12/// [`AudioNodePool`](crate::AudioNodePool).
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct SamplerPool;
15
16impl PoolableNode for SamplerPool {
17    type AudioNode = SamplerNode;
18
19    /// Return the number of output channels for the given configuration.
20    fn num_output_channels(config: Option<&SamplerConfig>) -> NonZeroChannelCount {
21        config
22            .map(|c| c.channels)
23            .unwrap_or(SamplerConfig::default().channels)
24    }
25
26    /// Return `true` if the given parameters signify that the sequence is stopped,
27    /// `false` otherwise.
28    fn params_stopped(params: &SamplerNode) -> bool {
29        params.stop_requested()
30    }
31
32    /// Return `true` if the node state of the given node is stopped.
33    ///
34    /// Return an error if the given `node_id` is invalid.
35    fn node_is_stopped<B: AudioBackend>(
36        node_id: NodeID,
37        cx: &FirewheelCtx<B>,
38    ) -> Result<bool, PoolError> {
39        cx.node_state::<SamplerState>(node_id)
40            .map(|s| s.stopped())
41            .ok_or(PoolError::InvalidNodeID(node_id))
42    }
43
44    /// Return a score of how ready this node is to accept new work.
45    ///
46    /// The worker with the highest worker score will be chosen for the new work.
47    ///
48    /// Return an error if the given `node_id` is invalid.
49    fn worker_score<B: AudioBackend>(
50        params: &SamplerNode,
51        node_id: NodeID,
52        cx: &mut FirewheelCtx<B>,
53    ) -> Result<u64, PoolError> {
54        cx.node_state::<SamplerState>(node_id)
55            .map(|s| s.worker_score(params))
56            .ok_or(PoolError::InvalidNodeID(node_id))
57    }
58
59    /// Diff the new parameters and push the changes into the event queue.
60    fn diff<B: AudioBackend>(
61        baseline: &SamplerNode,
62        new: &SamplerNode,
63        event_queue: &mut ContextQueue<B>,
64    ) {
65        new.diff(baseline, PathBuilder::default(), event_queue);
66    }
67
68    /// Notify the node state that a sequence is playing.
69    ///
70    /// This is used to account for the delay between sending an event to the node
71    /// and the node receiving the event.
72    ///
73    /// Return an error if the given `node_id` is invalid.
74    fn mark_playing<B: AudioBackend>(
75        node_id: NodeID,
76        cx: &mut FirewheelCtx<B>,
77    ) -> Result<(), PoolError> {
78        cx.node_state_mut::<SamplerState>(node_id)
79            .map(|s| s.mark_playing())
80            .ok_or(PoolError::InvalidNodeID(node_id))
81    }
82
83    /// Pause the sequence in the node parameters
84    fn pause(params: &mut SamplerNode) {
85        params.pause();
86    }
87    /// Resume the sequence in the node parameters
88    fn resume(params: &mut SamplerNode) {
89        params.resume();
90    }
91    /// Stop the sequence in the node parameters
92    fn stop(params: &mut SamplerNode) {
93        params.stop();
94    }
95}