use std::{ fmt::Debug, iter::repeat_n, num::NonZero, ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}, sync::Arc, }; use crate::{ audio_processing::Frame, file::impulse_format::sample::VibratoWave, project::note_event::Note, }; pub(crate) trait ProcessingFrame: Add + AddAssign + Sub + SubAssign + Mul + MulAssign + Copy { } impl ProcessingFrame for Frame {} impl ProcessingFrame for f32 {} pub(crate) trait ProcessingFunction { fn process(self, data: &[Fr; N]) -> Fr; } #[derive(Clone)] pub struct Sample { mono: bool, data: Arc<[f32]>, } impl Sample { pub const MAX_LENGTH: usize = 16_000_000; pub const MAX_RATE: usize = 192_000; /// this many frames need to be put on the start and the end to ensure that the interpolation algorithms work correctly. pub const PAD_SIZE_EACH: usize = 4; pub fn is_mono(&self) -> bool { self.mono } /// len in Frames pub fn len_with_pad(&self) -> usize { if self.mono { self.data.len() } else { self.data.len() / 2 } } pub(crate) fn compute< const N: usize, // all implementations are generic over the ProcessingFrame type. here both possible ProcessingFrame types // are required, so that it can be decided at runtime which one to call. both are generated by the compiler // from the generic implementation Proc: ProcessingFunction + ProcessingFunction, >( &self, index: usize, proc: Proc, ) -> Frame { if self.is_mono() { let data: &[f32; N] = self.data[index..index + N].try_into().unwrap(); Frame::from(proc.process(data)) } else { let data: &[Frame; N] = Frame::from_interleaved(&self.data[index * 2..(index + N) * 2]) .try_into() .unwrap(); proc.process(data) } } pub fn index(&self, idx: usize) -> Frame { if self.is_mono() { Frame::from(self.data[idx]) } else { Frame::from([self.data[idx * 2], self.data[idx * 2 + 1]]) } } pub(crate) fn strongcount(&self) -> usize { Arc::strong_count(&self.data) } pub fn new_stereo_interpolated>(data: I) -> Self { Self::new_stereo_interpolated_padded( repeat_n(0f32, 2 * Self::PAD_SIZE_EACH) .chain(data) .chain(repeat_n(0f32, 2 * Self::PAD_SIZE_EACH)), ) } pub fn new_stereo_interpolated_padded>(data: I) -> Self { Self { mono: false, data: Arc::from_iter(data), } } pub fn new_mono>(data: I) -> Self { Self::new_mono_padded( repeat_n(0f32, Self::PAD_SIZE_EACH) .chain(data) .chain(repeat_n(0f32, Self::PAD_SIZE_EACH)), ) } pub fn new_mono_padded>(data: I) -> Self { Self { mono: true, data: Arc::from_iter(data), } } } impl Debug for Sample { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Sample") .field("mono", &self.mono) .field("data_len", &self.len_with_pad()) .finish_non_exhaustive() } } #[derive(Clone, Copy, Debug)] pub struct SampleMetaData { pub default_volume: u8, pub global_volume: u8, pub default_pan: Option, pub vibrato_speed: u8, pub vibrato_depth: u8, pub vibrato_rate: u8, pub vibrato_waveform: VibratoWave, pub sample_rate: NonZero, pub base_note: Note, }