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
8pub 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 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 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 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 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 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}