use std::sync::Arc;
use super::error::SampleSourceError;
use super::traits::SampleSource;
#[cfg(test)]
use super::traits::SampleSourceTestExt;
pub struct MemorySampleSource {
samples: Arc<Vec<f32>>,
current_index: usize,
channel_count: u16,
sample_rate: u32,
volume: f32,
}
impl MemorySampleSource {
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,
}
}
}
#[cfg(test)]
impl MemorySampleSource {
pub fn new(samples: Vec<f32>, channel_count: u16, sample_rate: u32) -> Self {
Self {
samples: Arc::new(samples),
current_index: 0,
channel_count,
sample_rate,
volume: 1.0,
}
}
}
impl SampleSource for MemorySampleSource {
fn next_sample(&mut self) -> Result<Option<f32>, SampleSourceError> {
if self.current_index >= self.samples.len() {
Ok(None)
} else {
let sample = self.samples[self.current_index] * self.volume;
self.current_index += 1;
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> {
let total_samples = self.samples.len() as f64;
let samples_per_channel = total_samples / self.channel_count as f64;
let duration_secs = samples_per_channel / self.sample_rate as f64;
Some(std::time::Duration::from_secs_f64(duration_secs))
}
}
impl Clone for MemorySampleSource {
fn clone(&self) -> Self {
Self {
samples: self.samples.clone(),
current_index: 0, channel_count: self.channel_count,
sample_rate: self.sample_rate,
volume: self.volume,
}
}
}
#[cfg(test)]
impl SampleSourceTestExt for MemorySampleSource {
fn is_finished(&self) -> bool {
self.current_index >= self.samples.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[test]
fn new_basic() {
let src = MemorySampleSource::new(vec![1.0, 2.0, 3.0, 4.0], 2, 44100);
assert_eq!(src.channel_count(), 2);
assert_eq!(src.sample_rate(), 44100);
assert_eq!(src.bits_per_sample(), 32);
assert_eq!(src.sample_format(), crate::audio::SampleFormat::Float);
}
#[test]
fn next_sample_sequential() {
let mut src = MemorySampleSource::new(vec![0.5, 1.0, -0.5], 1, 44100);
assert_eq!(src.next_sample().unwrap(), Some(0.5));
assert_eq!(src.next_sample().unwrap(), Some(1.0));
assert_eq!(src.next_sample().unwrap(), Some(-0.5));
assert_eq!(src.next_sample().unwrap(), None); }
#[test]
fn next_sample_empty() {
let mut src = MemorySampleSource::new(vec![], 1, 44100);
assert_eq!(src.next_sample().unwrap(), None);
}
#[test]
fn next_sample_eof_repeatable() {
let mut src = MemorySampleSource::new(vec![1.0], 1, 44100);
assert_eq!(src.next_sample().unwrap(), Some(1.0));
assert_eq!(src.next_sample().unwrap(), None);
assert_eq!(src.next_sample().unwrap(), None); }
#[test]
fn volume_scaling() {
let samples = Arc::new(vec![1.0, 0.5, -1.0]);
let mut src = MemorySampleSource::from_shared(samples, 1, 44100, 0.5);
assert_eq!(src.next_sample().unwrap(), Some(0.5));
assert_eq!(src.next_sample().unwrap(), Some(0.25));
assert_eq!(src.next_sample().unwrap(), Some(-0.5));
}
#[test]
fn duration_mono() {
let samples = vec![0.0; 44100];
let src = MemorySampleSource::new(samples, 1, 44100);
let dur = src.duration().unwrap();
assert!((dur.as_secs_f64() - 1.0).abs() < 1e-6);
}
#[test]
fn duration_stereo() {
let samples = vec![0.0; 88200];
let src = MemorySampleSource::new(samples, 2, 44100);
let dur = src.duration().unwrap();
assert!((dur.as_secs_f64() - 1.0).abs() < 1e-6);
}
#[test]
fn clone_resets_position() {
let mut src = MemorySampleSource::new(vec![1.0, 2.0, 3.0], 1, 44100);
src.next_sample().unwrap(); src.next_sample().unwrap();
let mut cloned = src.clone();
assert_eq!(cloned.next_sample().unwrap(), Some(1.0));
}
#[test]
fn is_finished_tracking() {
let mut src = MemorySampleSource::new(vec![1.0], 1, 44100);
assert!(!src.is_finished());
src.next_sample().unwrap();
assert!(src.is_finished());
}
#[test]
fn from_shared_arc() {
let data = Arc::new(vec![0.1, 0.2, 0.3]);
let mut src = MemorySampleSource::from_shared(data.clone(), 1, 48000, 1.0);
assert_eq!(src.sample_rate(), 48000);
assert_eq!(src.next_sample().unwrap(), Some(0.1));
assert_eq!(Arc::strong_count(&data), 2);
}
}