1use core::{
2 num::{NonZeroU32, NonZeroUsize},
3 ops::Range,
4};
5
6#[cfg(not(feature = "std"))]
7use bevy_platform::prelude::Vec;
8
9pub trait SampleResourceInfo: Send + Sync + 'static {
11 fn num_channels(&self) -> NonZeroUsize;
13
14 fn len_frames(&self) -> u64;
18
19 fn sample_rate(&self) -> Option<NonZeroU32> {
23 None
24 }
25}
26
27pub trait SampleResource: SampleResourceInfo {
29 fn fill_buffers(
41 &self,
42 buffers: &mut [&mut [f32]],
43 buffer_range: Range<usize>,
44 start_frame: u64,
45 );
46}
47
48pub trait SampleResourceF32: SampleResourceInfo {
50 fn channel(&self, i: usize) -> Option<&[f32]>;
52}
53
54#[derive(Clone)]
55pub struct InterleavedResourceI16 {
56 pub data: Vec<i16>,
57 pub channels: NonZeroUsize,
58 pub sample_rate: Option<NonZeroU32>,
59}
60
61impl SampleResourceInfo for InterleavedResourceI16 {
62 fn num_channels(&self) -> NonZeroUsize {
63 self.channels
64 }
65
66 fn len_frames(&self) -> u64 {
67 (self.data.len() / self.channels.get()) as u64
68 }
69
70 fn sample_rate(&self) -> Option<NonZeroU32> {
71 self.sample_rate
72 }
73}
74
75impl SampleResource for InterleavedResourceI16 {
76 fn fill_buffers(
77 &self,
78 buffers: &mut [&mut [f32]],
79 buffer_range: Range<usize>,
80 start_frame: u64,
81 ) {
82 fill_buffers_interleaved(
83 buffers,
84 buffer_range,
85 start_frame as usize,
86 self.channels,
87 &self.data,
88 pcm_i16_to_f32,
89 );
90 }
91}
92
93impl core::fmt::Debug for InterleavedResourceI16 {
94 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
95 write!(
96 f,
97 "InterleavedResourceI16 {{ channels: {}, frames: {} }}",
98 self.channels.get(),
99 self.data.len() / self.channels.get(),
100 )
101 }
102}
103
104#[derive(Clone)]
105pub struct InterleavedResourceU16 {
106 pub data: Vec<u16>,
107 pub channels: NonZeroUsize,
108 pub sample_rate: Option<NonZeroU32>,
109}
110
111impl SampleResourceInfo for InterleavedResourceU16 {
112 fn num_channels(&self) -> NonZeroUsize {
113 self.channels
114 }
115
116 fn len_frames(&self) -> u64 {
117 (self.data.len() / self.channels.get()) as u64
118 }
119
120 fn sample_rate(&self) -> Option<NonZeroU32> {
121 self.sample_rate
122 }
123}
124
125impl SampleResource for InterleavedResourceU16 {
126 fn fill_buffers(
127 &self,
128 buffers: &mut [&mut [f32]],
129 buffer_range: Range<usize>,
130 start_frame: u64,
131 ) {
132 fill_buffers_interleaved(
133 buffers,
134 buffer_range,
135 start_frame as usize,
136 self.channels,
137 &self.data,
138 pcm_u16_to_f32,
139 );
140 }
141}
142
143impl core::fmt::Debug for InterleavedResourceU16 {
144 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
145 write!(
146 f,
147 "InterleavedResourceU16 {{ channels: {}, frames: {} }}",
148 self.channels.get(),
149 self.data.len() / self.channels.get(),
150 )
151 }
152}
153
154#[derive(Clone)]
155pub struct InterleavedResourceF32 {
156 pub data: Vec<f32>,
157 pub channels: NonZeroUsize,
158 pub sample_rate: Option<NonZeroU32>,
159}
160
161impl SampleResourceInfo for InterleavedResourceF32 {
162 fn num_channels(&self) -> NonZeroUsize {
163 self.channels
164 }
165
166 fn len_frames(&self) -> u64 {
167 (self.data.len() / self.channels.get()) as u64
168 }
169
170 fn sample_rate(&self) -> Option<NonZeroU32> {
171 self.sample_rate
172 }
173}
174
175impl SampleResource for InterleavedResourceF32 {
176 fn fill_buffers(
177 &self,
178 buffers: &mut [&mut [f32]],
179 buffer_range: Range<usize>,
180 start_frame: u64,
181 ) {
182 fill_buffers_interleaved(
183 buffers,
184 buffer_range,
185 start_frame as usize,
186 self.channels,
187 &self.data,
188 |s| s,
189 );
190 }
191}
192
193impl core::fmt::Debug for InterleavedResourceF32 {
194 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
195 write!(
196 f,
197 "InterleavedResourceF32 {{ channels: {}, frames: {} }}",
198 self.channels.get(),
199 self.data.len() / self.channels.get(),
200 )
201 }
202}
203
204impl SampleResourceInfo for Vec<Vec<i16>> {
205 fn num_channels(&self) -> NonZeroUsize {
206 NonZeroUsize::new(self.len()).unwrap()
207 }
208
209 fn len_frames(&self) -> u64 {
210 self[0].len() as u64
211 }
212}
213
214impl SampleResource for Vec<Vec<i16>> {
215 fn fill_buffers(
216 &self,
217 buffers: &mut [&mut [f32]],
218 buffer_range: Range<usize>,
219 start_frame: u64,
220 ) {
221 fill_buffers_deinterleaved(
222 buffers,
223 buffer_range,
224 start_frame as usize,
225 self.as_slice(),
226 pcm_i16_to_f32,
227 );
228 }
229}
230
231impl SampleResourceInfo for Vec<Vec<u16>> {
232 fn num_channels(&self) -> NonZeroUsize {
233 NonZeroUsize::new(self.len()).unwrap()
234 }
235
236 fn len_frames(&self) -> u64 {
237 self[0].len() as u64
238 }
239}
240
241impl SampleResource for Vec<Vec<u16>> {
242 fn fill_buffers(
243 &self,
244 buffers: &mut [&mut [f32]],
245 buffer_range: Range<usize>,
246 start_frame: u64,
247 ) {
248 fill_buffers_deinterleaved(
249 buffers,
250 buffer_range,
251 start_frame as usize,
252 self.as_slice(),
253 pcm_u16_to_f32,
254 );
255 }
256}
257
258impl SampleResourceInfo for Vec<Vec<f32>> {
259 fn num_channels(&self) -> NonZeroUsize {
260 NonZeroUsize::new(self.len()).unwrap()
261 }
262
263 fn len_frames(&self) -> u64 {
264 self[0].len() as u64
265 }
266}
267
268impl SampleResource for Vec<Vec<f32>> {
269 fn fill_buffers(
270 &self,
271 buffers: &mut [&mut [f32]],
272 buffer_range: Range<usize>,
273 start_frame: u64,
274 ) {
275 fill_buffers_deinterleaved_f32(buffers, buffer_range, start_frame as usize, self);
276 }
277}
278
279impl SampleResourceF32 for Vec<Vec<f32>> {
280 fn channel(&self, i: usize) -> Option<&[f32]> {
281 self.get(i).map(|data| data.as_slice())
282 }
283}
284
285#[inline]
286pub fn pcm_i16_to_f32(s: i16) -> f32 {
287 f32::from(s) * (1.0 / core::i16::MAX as f32)
288}
289
290#[inline]
291pub fn pcm_u16_to_f32(s: u16) -> f32 {
292 ((f32::from(s)) * (2.0 / core::u16::MAX as f32)) - 1.0
293}
294
295pub fn fill_buffers_interleaved<T: Clone + Copy>(
297 buffers: &mut [&mut [f32]],
298 buffer_range: Range<usize>,
299 start_frame: usize,
300 channels: NonZeroUsize,
301 data: &[T],
302 convert: impl Fn(T) -> f32,
303) {
304 let start_frame = start_frame as usize;
305 let channels = channels.get();
306
307 let frames = buffer_range.end - buffer_range.start;
308
309 if channels == 1 {
310 for (buf_s, &src_s) in buffers[0][buffer_range.clone()]
312 .iter_mut()
313 .zip(&data[start_frame..start_frame + frames])
314 {
315 *buf_s = convert(src_s);
316 }
317 return;
318 }
319
320 if channels == 2 && buffers.len() >= 2 {
321 let (buf0, buf1) = buffers.split_first_mut().unwrap();
323 let buf0 = &mut buf0[buffer_range.clone()];
324 let buf1 = &mut buf1[0][buffer_range.clone()];
325
326 let src_slice = &data[start_frame * 2..(start_frame + frames) * 2];
327
328 for (src_chunk, (buf0_s, buf1_s)) in src_slice
329 .chunks_exact(2)
330 .zip(buf0.iter_mut().zip(buf1.iter_mut()))
331 {
332 *buf0_s = convert(src_chunk[0]);
333 *buf1_s = convert(src_chunk[1]);
334 }
335
336 return;
337 }
338
339 let src_slice = &data[start_frame * channels..(start_frame + frames) * channels];
340 for (ch_i, buf_ch) in (0..channels).zip(buffers.iter_mut()) {
341 for (src_chunk, buf_s) in src_slice
342 .chunks_exact(channels)
343 .zip(buf_ch[buffer_range.clone()].iter_mut())
344 {
345 *buf_s = convert(src_chunk[ch_i]);
346 }
347 }
348}
349
350pub fn fill_buffers_deinterleaved<T: Clone + Copy, V: AsRef<[T]>>(
352 buffers: &mut [&mut [f32]],
353 buffer_range: Range<usize>,
354 start_frame: usize,
355 data: &[V],
356 convert: impl Fn(T) -> f32,
357) {
358 let start_frame = start_frame as usize;
359 let frames = buffer_range.end - buffer_range.start;
360
361 if data.len() == 2 && buffers.len() >= 2 {
362 let (buf0, buf1) = buffers.split_first_mut().unwrap();
364 let buf0 = &mut buf0[buffer_range.clone()];
365 let buf1 = &mut buf1[0][buffer_range.clone()];
366 let s0 = &data[0].as_ref()[start_frame..start_frame + frames];
367 let s1 = &data[1].as_ref()[start_frame..start_frame + frames];
368
369 for i in 0..frames {
370 buf0[i] = convert(s0[i]);
371 buf1[i] = convert(s1[i]);
372 }
373
374 return;
375 }
376
377 for (buf, ch) in buffers.iter_mut().zip(data.iter()) {
378 for (buf_s, &ch_s) in buf[buffer_range.clone()]
379 .iter_mut()
380 .zip(ch.as_ref()[start_frame..start_frame + frames].iter())
381 {
382 *buf_s = convert(ch_s);
383 }
384 }
385}
386
387pub fn fill_buffers_deinterleaved_f32<V: AsRef<[f32]>>(
389 buffers: &mut [&mut [f32]],
390 buffer_range: Range<usize>,
391 start_frame: usize,
392 data: &[V],
393) {
394 let start_frame = start_frame as usize;
395
396 for (buf, ch) in buffers.iter_mut().zip(data.iter()) {
397 buf[buffer_range.clone()].copy_from_slice(
398 &ch.as_ref()[start_frame..start_frame + buffer_range.end - buffer_range.start],
399 );
400 }
401}