Skip to main content

rill_sampler/
player.rs

1use crate::buffer::SampleBuffer;
2use rill_core::traits::algorithm::{Algorithm, AlgorithmCategory, AlgorithmMetadata};
3use rill_core::traits::ProcessResult;
4use rill_core::Transcendental;
5use rill_core_dsp::generators::{LoopMode, SamplePlayer};
6use std::marker::PhantomData;
7
8/// Sample playback node with stereo support, looping, and playback rate control.
9pub struct SamplePlayerNode<T: Transcendental, const BUF_SIZE: usize> {
10    left: SamplePlayer<T>,
11    right: Option<SamplePlayer<T>>,
12    gate: bool,
13    amplitude: T,
14    rate: f64,
15    loop_mode: LoopMode,
16    loop_start: f64,
17    loop_end: f64,
18    cubic: bool,
19    _phantom: PhantomData<[T; BUF_SIZE]>,
20}
21
22impl<T: Transcendental, const BUF_SIZE: usize> SamplePlayerNode<T, BUF_SIZE> {
23    /// Creates a new sample player node.
24    pub fn new() -> Self {
25        Self {
26            left: SamplePlayer::new(Vec::new()),
27            right: None,
28            gate: false,
29            amplitude: T::from_f32(1.0),
30            rate: 1.0,
31            loop_mode: LoopMode::OneShot,
32            loop_start: 0.0,
33            loop_end: 0.0,
34            cubic: false,
35            _phantom: PhantomData,
36        }
37    }
38    /// Loads a sample buffer for playback.
39    pub fn load(&mut self, sample: SampleBuffer<T>) {
40        let len = sample.len() as f64;
41        self.loop_end = len;
42        self.loop_start = 0.0;
43        self.left.set_buffer(sample.data);
44        self.left.set_loop_start(self.loop_start);
45        self.left.set_loop_end(self.loop_end);
46        self.left.set_loop_mode(self.loop_mode);
47        self.left.set_playback_rate(self.rate);
48        self.left.set_cubic(self.cubic);
49        if let Some(right_data) = sample.right {
50            let mut rp = SamplePlayer::new(right_data);
51            rp.set_loop_start(self.loop_start);
52            rp.set_loop_end(self.loop_end);
53            rp.set_loop_mode(self.loop_mode);
54            rp.set_playback_rate(self.rate);
55            rp.set_cubic(self.cubic);
56            self.right = Some(rp);
57        } else {
58            self.right = None;
59        }
60    }
61    /// Starts playback (opens the gate).
62    pub fn play(&mut self) {
63        self.gate = true;
64        self.left.set_gate(true);
65        if let Some(ref mut r) = self.right {
66            r.set_gate(true);
67        }
68    }
69    /// Stops playback (closes the gate).
70    pub fn stop(&mut self) {
71        self.gate = false;
72        self.left.set_gate(false);
73        if let Some(ref mut r) = self.right {
74            r.set_gate(false);
75        }
76    }
77    /// Sets output amplitude (clamped to 0.0–1.0).
78    pub fn set_amplitude(&mut self, amp: T) {
79        self.amplitude = amp.clamp(T::ZERO, T::from_f32(1.0));
80    }
81}
82
83impl<T: Transcendental, const BUF_SIZE: usize> Algorithm<T> for SamplePlayerNode<T, BUF_SIZE> {
84    fn process(&mut self, _input: Option<&[T]>, output: &mut [T]) -> ProcessResult<()> {
85        let mut buf = vec![T::ZERO; output.len()];
86        self.left.process(None, &mut buf)?;
87        for (out, s) in output.iter_mut().zip(&buf) {
88            *out = s.mul(self.amplitude);
89        }
90        Ok(())
91    }
92    fn reset(&mut self) {
93        self.left.reset();
94        if let Some(ref mut r) = self.right {
95            r.reset();
96        }
97    }
98    fn metadata(&self) -> AlgorithmMetadata {
99        AlgorithmMetadata {
100            name: "SamplePlayer",
101            category: AlgorithmCategory::Generator,
102            description: "Sample playback with stereo support and looping",
103            author: "Rill",
104            version: env!("CARGO_PKG_VERSION"),
105        }
106    }
107}
108
109impl<T: Transcendental, const BUF_SIZE: usize> Default for SamplePlayerNode<T, BUF_SIZE> {
110    fn default() -> Self {
111        Self::new()
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118    #[test]
119    fn test_sample_player_creation() {
120        let player = SamplePlayerNode::<f32, 64>::new();
121        assert!(!player.gate);
122    }
123    #[test]
124    fn test_sample_player_play_stop() {
125        let mut player = SamplePlayerNode::<f32, 64>::new();
126        player.play();
127        assert!(player.gate);
128        player.stop();
129        assert!(!player.gate);
130    }
131}