use std::sync::Arc;
use super::error::SampleSourceError;
use super::traits::SampleSource;
#[allow(dead_code)]
pub struct LoopingSampleSource {
samples: Arc<Vec<f32>>,
current_index: usize,
channel_count: u16,
sample_rate: u32,
volume: f32,
}
impl LoopingSampleSource {
#[allow(dead_code)]
pub fn from_shared(
samples: Arc<Vec<f32>>,
channel_count: u16,
sample_rate: u32,
volume: f32,
) -> Self {
Self {
samples,
current_index: 0,
channel_count,
sample_rate,
volume,
}
}
}
impl SampleSource for LoopingSampleSource {
fn next_sample(&mut self) -> Result<Option<f32>, SampleSourceError> {
if self.samples.is_empty() {
return Ok(None);
}
let sample = self.samples[self.current_index] * self.volume;
self.current_index += 1;
if self.current_index >= self.samples.len() {
self.current_index = 0;
}
Ok(Some(sample))
}
fn channel_count(&self) -> u16 {
self.channel_count
}
fn sample_rate(&self) -> u32 {
self.sample_rate
}
fn bits_per_sample(&self) -> u16 {
32
}
fn sample_format(&self) -> crate::audio::SampleFormat {
crate::audio::SampleFormat::Float
}
fn duration(&self) -> Option<std::time::Duration> {
None }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_looping_wraps_around() {
let samples = Arc::new(vec![0.1, 0.2, 0.3, 0.4]);
let mut source = LoopingSampleSource::from_shared(samples, 2, 44100, 1.0);
assert_eq!(source.next_sample().unwrap(), Some(0.1));
assert_eq!(source.next_sample().unwrap(), Some(0.2));
assert_eq!(source.next_sample().unwrap(), Some(0.3));
assert_eq!(source.next_sample().unwrap(), Some(0.4));
assert_eq!(source.next_sample().unwrap(), Some(0.1));
assert_eq!(source.next_sample().unwrap(), Some(0.2));
}
#[test]
fn test_looping_volume_scaling() {
let samples = Arc::new(vec![1.0, -1.0]);
let mut source = LoopingSampleSource::from_shared(samples, 1, 44100, 0.5);
assert_eq!(source.next_sample().unwrap(), Some(0.5));
assert_eq!(source.next_sample().unwrap(), Some(-0.5));
assert_eq!(source.next_sample().unwrap(), Some(0.5));
}
#[test]
fn test_looping_empty_samples() {
let samples = Arc::new(vec![]);
let mut source = LoopingSampleSource::from_shared(samples, 1, 44100, 1.0);
assert_eq!(source.next_sample().unwrap(), None);
}
#[test]
fn test_looping_metadata() {
let samples = Arc::new(vec![0.0; 100]);
let source = LoopingSampleSource::from_shared(samples, 2, 48000, 0.8);
assert_eq!(source.channel_count(), 2);
assert_eq!(source.sample_rate(), 48000);
assert_eq!(source.bits_per_sample(), 32);
assert_eq!(source.sample_format(), crate::audio::SampleFormat::Float);
assert!(source.duration().is_none());
}
#[test]
fn test_looping_many_cycles() {
let samples = Arc::new(vec![0.5, -0.5]);
let mut source = LoopingSampleSource::from_shared(samples, 1, 44100, 1.0);
for i in 0..10000 {
let expected = if i % 2 == 0 { 0.5 } else { -0.5 };
assert_eq!(
source.next_sample().unwrap(),
Some(expected),
"Mismatch at sample {}",
i
);
}
}
}