use core::{
num::{NonZeroU32, NonZeroUsize},
ops::Range,
};
use firewheel_core::{
collector::{ArcGc, OwnedGcUnsized},
sample_resource::{SampleResource, SampleResourceInfo},
};
#[cfg(not(feature = "std"))]
use bevy_platform::prelude::Box;
pub enum SamplerNodeResource {
InMemory(ArcGc<dyn SampleResource + Send + Sync + 'static>),
Streamed(OwnedGcUnsized<dyn StreamedSample>),
}
impl SamplerNodeResource {
pub fn from_sample<T: SampleResource + Send + Sync + 'static>(sample: T) -> Self {
Self::InMemory(sample.into())
}
pub fn from_streamed<T: StreamedSample>(sample: T) -> Self {
Self::Streamed(OwnedGcUnsized::new_unsized(Box::new(sample)))
}
pub fn num_channels(&self) -> NonZeroUsize {
match self {
Self::InMemory(s) => s.num_channels(),
Self::Streamed(s) => s.num_channels(),
}
}
pub fn len_frames(&self) -> u64 {
match self {
Self::InMemory(s) => s.len_frames(),
Self::Streamed(s) => s.len_frames(),
}
}
pub fn sample_rate(&self) -> Option<NonZeroU32> {
match self {
Self::InMemory(s) => s.sample_rate(),
Self::Streamed(s) => s.sample_rate(),
}
}
pub fn fill_buffers(
&mut self,
out_buffer: &mut [&mut [f32]],
out_buffer_range: Range<usize>,
start_frame: u64,
speed: f64,
is_playing_backwards: bool,
) -> usize {
match self {
SamplerNodeResource::InMemory(s) => {
s.fill_buffers(out_buffer, out_buffer_range.clone(), start_frame)
}
SamplerNodeResource::Streamed(s) => s.fill_buffers(
out_buffer,
out_buffer_range,
start_frame,
speed,
is_playing_backwards,
),
}
}
pub fn range_is_ready(&mut self, range: Range<u64>) -> bool {
if let SamplerNodeResource::Streamed(s) = self {
s.range_is_ready(range)
} else {
true
}
}
pub fn cache_new_starting_frame(&mut self, frame: u64, speed: f64, will_play_backwards: bool) {
if let SamplerNodeResource::Streamed(s) = self {
s.cache_new_starting_frame(frame, speed, will_play_backwards);
}
}
}
impl From<ArcGc<dyn SampleResource + Send + Sync + 'static>> for SamplerNodeResource {
fn from(value: ArcGc<dyn SampleResource + Send + Sync + 'static>) -> Self {
Self::InMemory(value)
}
}
impl From<OwnedGcUnsized<dyn StreamedSample>> for SamplerNodeResource {
fn from(value: OwnedGcUnsized<dyn StreamedSample>) -> Self {
Self::Streamed(value)
}
}
pub trait StreamedSample: SampleResourceInfo + Send + Sync + 'static {
fn fill_buffers(
&mut self,
out_buffer: &mut [&mut [f32]],
out_buffer_range: Range<usize>,
start_frame: u64,
speed: f64,
is_playing_backwards: bool,
) -> usize;
fn range_is_ready(&mut self, range: Range<u64>) -> bool;
fn cache_new_starting_frame(&mut self, frame: u64, speed: f64, will_play_backwards: bool);
}