|
5 | 5 |
|
6 | 6 | #![cfg_attr(not(feature = "std"), no_std)]
|
7 | 7 |
|
8 |
| -use core::iter::DoubleEndedIterator; |
| 8 | +use core::{iter::DoubleEndedIterator, mem::MaybeUninit}; |
9 | 9 |
|
10 | 10 | use dasp_sample::Sample;
|
11 | 11 |
|
@@ -295,198 +295,133 @@ pub struct ChannelsRef<'a, F: Frame>(core::slice::Iter<'a, F::Sample>);
|
295 | 295 | /// Like [`ChannelsRef`], but yields mutable references instead.
|
296 | 296 | pub struct ChannelsMut<'a, F: Frame>(core::slice::IterMut<'a, F::Sample>);
|
297 | 297 |
|
298 |
| -macro_rules! impl_frame_for_fixed_size_array { |
299 |
| - ($($NChan:ident $N:expr, [$($idx:expr)*],)*) => { |
300 |
| - $( |
301 |
| - /// A typified version of a number of channels. |
302 |
| - pub struct $NChan; |
303 |
| - impl NumChannels for $NChan {} |
304 |
| - |
305 |
| - impl<S> Frame for [S; $N] |
306 |
| - where |
307 |
| - S: Sample, |
308 |
| - { |
309 |
| - type Sample = S; |
310 |
| - type NumChannels = $NChan; |
311 |
| - type Channels = Channels<Self>; |
312 |
| - type Float = [S::Float; $N]; |
313 |
| - type Signed = [S::Signed; $N]; |
314 |
| - |
315 |
| - const EQUILIBRIUM: Self = [S::EQUILIBRIUM; $N]; |
316 |
| - const CHANNELS: usize = $N; |
| 298 | +pub struct NChannels<const N: usize> {} |
| 299 | +impl<const N: usize> NumChannels for NChannels<N> {} |
317 | 300 |
|
318 |
| - #[inline] |
319 |
| - fn channels(self) -> Self::Channels { |
320 |
| - Channels { |
321 |
| - next_idx: 0, |
322 |
| - frame: self, |
323 |
| - } |
324 |
| - } |
325 |
| - |
326 |
| - #[inline] |
327 |
| - fn channels_ref(&self) -> ChannelsRef<'_, Self> { |
328 |
| - ChannelsRef(self.iter()) |
329 |
| - } |
330 |
| - |
331 |
| - #[inline] |
332 |
| - fn channels_mut(&mut self) -> ChannelsMut<'_, Self> { |
333 |
| - ChannelsMut(self.iter_mut()) |
334 |
| - } |
| 301 | +impl<S, const N: usize> Frame for [S; N] |
| 302 | +where |
| 303 | + S: Sample, |
| 304 | +{ |
| 305 | + type Sample = S; |
| 306 | + type NumChannels = NChannels<N>; |
| 307 | + type Channels = Channels<Self>; |
| 308 | + type Float = [S::Float; N]; |
| 309 | + type Signed = [S::Signed; N]; |
335 | 310 |
|
336 |
| - #[inline] |
337 |
| - fn channel(&self, idx: usize) -> Option<&Self::Sample> { |
338 |
| - self.get(idx) |
339 |
| - } |
| 311 | + const EQUILIBRIUM: Self = [S::EQUILIBRIUM; N]; |
| 312 | + const CHANNELS: usize = N; |
340 | 313 |
|
341 |
| - #[inline] |
342 |
| - fn channel_mut(&mut self, idx: usize) -> Option<&mut Self::Sample> { |
343 |
| - self.get_mut(idx) |
344 |
| - } |
| 314 | + #[inline] |
| 315 | + fn channels(self) -> Self::Channels { |
| 316 | + Channels { |
| 317 | + next_idx: 0, |
| 318 | + frame: self, |
| 319 | + } |
| 320 | + } |
345 | 321 |
|
346 |
| - #[inline] |
347 |
| - fn from_fn<F>(mut from: F) -> Self |
348 |
| - where |
349 |
| - F: FnMut(usize) -> S, |
350 |
| - { |
351 |
| - [$(from($idx), )*] |
352 |
| - } |
| 322 | + #[inline] |
| 323 | + fn channels_ref(&self) -> ChannelsRef<'_, Self> { |
| 324 | + ChannelsRef(self.iter()) |
| 325 | + } |
353 | 326 |
|
354 |
| - #[inline] |
355 |
| - fn from_samples<I>(samples: &mut I) -> Option<Self> |
356 |
| - where |
357 |
| - I: Iterator<Item=Self::Sample> |
358 |
| - { |
359 |
| - Some([$( { |
360 |
| - $idx; |
361 |
| - match samples.next() { |
362 |
| - Some(sample) => sample, |
363 |
| - None => return None, |
364 |
| - } |
365 |
| - }, )*]) |
366 |
| - } |
| 327 | + #[inline] |
| 328 | + fn channels_mut(&mut self) -> ChannelsMut<'_, Self> { |
| 329 | + ChannelsMut(self.iter_mut()) |
| 330 | + } |
367 | 331 |
|
368 |
| - #[inline(always)] |
369 |
| - unsafe fn channel_unchecked(&self, idx: usize) -> &Self::Sample { |
370 |
| - self.get_unchecked(idx) |
371 |
| - } |
| 332 | + #[inline] |
| 333 | + fn channel(&self, idx: usize) -> Option<&Self::Sample> { |
| 334 | + self.get(idx) |
| 335 | + } |
372 | 336 |
|
373 |
| - #[inline(always)] |
374 |
| - unsafe fn channel_unchecked_mut(&mut self, idx: usize) -> &mut Self::Sample { |
375 |
| - self.get_unchecked_mut(idx) |
376 |
| - } |
| 337 | + #[inline] |
| 338 | + fn channel_mut(&mut self, idx: usize) -> Option<&mut Self::Sample> { |
| 339 | + self.get_mut(idx) |
| 340 | + } |
377 | 341 |
|
378 |
| - #[inline] |
379 |
| - fn to_signed_frame(self) -> Self::Signed { |
380 |
| - self.map(|s| s.to_sample()) |
381 |
| - } |
| 342 | + #[inline] |
| 343 | + fn from_fn<F>(from: F) -> Self |
| 344 | + where |
| 345 | + F: FnMut(usize) -> S, |
| 346 | + { |
| 347 | + core::array::from_fn(from) |
| 348 | + } |
382 | 349 |
|
383 |
| - #[inline] |
384 |
| - fn to_float_frame(self) -> Self::Float { |
385 |
| - self.map(|s| s.to_sample()) |
386 |
| - } |
| 350 | + #[inline] |
| 351 | + fn from_samples<I>(samples: &mut I) -> Option<Self> |
| 352 | + where |
| 353 | + I: Iterator<Item = Self::Sample>, |
| 354 | + { |
| 355 | + array_from_iter(samples) |
| 356 | + } |
387 | 357 |
|
388 |
| - #[inline] |
389 |
| - fn map<F, M>(self, mut map: M) -> F |
390 |
| - where |
391 |
| - F: Frame<NumChannels=Self::NumChannels>, |
392 |
| - M: FnMut(Self::Sample) -> F::Sample, |
393 |
| - { |
394 |
| - F::from_fn(|channel_idx| { |
| 358 | + #[inline(always)] |
| 359 | + unsafe fn channel_unchecked(&self, idx: usize) -> &Self::Sample { |
| 360 | + self.get_unchecked(idx) |
| 361 | + } |
395 | 362 |
|
396 |
| - // Here we do not require run-time bounds checking as we have asserted that |
397 |
| - // the two arrays have the same number of channels at compile time with our |
398 |
| - // where clause, i.e. |
399 |
| - // |
400 |
| - // `F: Frame<NumChannels=Self::NumChannels>` |
401 |
| - unsafe { map(*self.channel_unchecked(channel_idx)) } |
402 |
| - }) |
403 |
| - } |
| 363 | + #[inline(always)] |
| 364 | + unsafe fn channel_unchecked_mut(&mut self, idx: usize) -> &mut Self::Sample { |
| 365 | + self.get_unchecked_mut(idx) |
| 366 | + } |
404 | 367 |
|
405 |
| - #[inline] |
406 |
| - fn zip_map<O, F, M>(self, other: O, mut zip_map: M) -> F |
407 |
| - where |
408 |
| - O: Frame<NumChannels=Self::NumChannels>, |
409 |
| - F: Frame<NumChannels=Self::NumChannels>, |
410 |
| - M: FnMut(Self::Sample, O::Sample) -> F::Sample |
411 |
| - { |
412 |
| - F::from_fn(|channel_idx| { |
| 368 | + #[inline] |
| 369 | + fn to_signed_frame(self) -> Self::Signed { |
| 370 | + self.map(|s| s.to_sample()) |
| 371 | + } |
413 | 372 |
|
414 |
| - // Here we do not require run-time bounds checking as we have asserted that the two |
415 |
| - // arrays have the same number of channels at compile time with our where clause, i.e. |
416 |
| - // |
417 |
| - // ``` |
418 |
| - // O: Frame<NumChannels=Self::NumChannels> |
419 |
| - // F: Frame<NumChannels=Self::NumChannels> |
420 |
| - // ``` |
421 |
| - unsafe { |
422 |
| - zip_map(*self.channel_unchecked(channel_idx), |
423 |
| - *other.channel_unchecked(channel_idx)) |
424 |
| - } |
425 |
| - }) |
426 |
| - } |
| 373 | + #[inline] |
| 374 | + fn to_float_frame(self) -> Self::Float { |
| 375 | + self.map(|s| s.to_sample()) |
| 376 | + } |
427 | 377 |
|
428 |
| - #[inline] |
429 |
| - fn scale_amp(self, amp: S::Float) -> Self { |
430 |
| - [$(self[$idx].mul_amp(amp), )*] |
431 |
| - } |
| 378 | + #[inline] |
| 379 | + fn map<F, M>(self, mut map: M) -> F |
| 380 | + where |
| 381 | + F: Frame<NumChannels = Self::NumChannels>, |
| 382 | + M: FnMut(Self::Sample) -> F::Sample, |
| 383 | + { |
| 384 | + F::from_fn(|channel_idx| { |
| 385 | + // Here we do not require run-time bounds checking as we have asserted that |
| 386 | + // the two arrays have the same number of channels at compile time with our |
| 387 | + // where clause, i.e. |
| 388 | + // |
| 389 | + // `F: Frame<NumChannels=Self::NumChannels>` |
| 390 | + unsafe { map(*self.channel_unchecked(channel_idx)) } |
| 391 | + }) |
| 392 | + } |
432 | 393 |
|
433 |
| - #[inline] |
434 |
| - fn add_amp<F>(self, other: F) -> Self |
435 |
| - where |
436 |
| - F: Frame<Sample=S::Signed, NumChannels=$NChan>, |
437 |
| - { |
438 |
| - // Here we do not require run-time bounds checking as we have asserted that the two |
439 |
| - // arrays have the same number of channels at compile time with our where clause, i.e. |
440 |
| - unsafe { |
441 |
| - [$(self[$idx].add_amp(*other.channel_unchecked($idx)), )*] |
442 |
| - } |
443 |
| - } |
| 394 | + #[inline] |
| 395 | + fn zip_map<O, F, M>(self, other: O, mut zip_map: M) -> F |
| 396 | + where |
| 397 | + O: Frame<NumChannels = Self::NumChannels>, |
| 398 | + F: Frame<NumChannels = Self::NumChannels>, |
| 399 | + M: FnMut(Self::Sample, O::Sample) -> F::Sample, |
| 400 | + { |
| 401 | + F::from_fn(|channel_idx| { |
| 402 | + // Here we do not require run-time bounds checking as we have asserted that the two |
| 403 | + // arrays have the same number of channels at compile time with our where clause, i.e. |
| 404 | + // |
| 405 | + // ``` |
| 406 | + // O: Frame<NumChannels=Self::NumChannels> |
| 407 | + // F: Frame<NumChannels=Self::NumChannels> |
| 408 | + // ``` |
| 409 | + unsafe { |
| 410 | + zip_map( |
| 411 | + *self.channel_unchecked(channel_idx), |
| 412 | + *other.channel_unchecked(channel_idx), |
| 413 | + ) |
444 | 414 | }
|
445 |
| - )* |
446 |
| - }; |
447 |
| -} |
448 |
| - |
449 |
| -impl_frame_for_fixed_size_array! { |
450 |
| - N1 1, [0], |
451 |
| - N2 2, [0 1], |
452 |
| - N3 3, [0 1 2], |
453 |
| - N4 4, [0 1 2 3], |
454 |
| - N5 5, [0 1 2 3 4], |
455 |
| - N6 6, [0 1 2 3 4 5], |
456 |
| - N7 7, [0 1 2 3 4 5 6], |
457 |
| - N8 8, [0 1 2 3 4 5 6 7], |
458 |
| - N9 9, [0 1 2 3 4 5 6 7 8], |
459 |
| - N10 10, [0 1 2 3 4 5 6 7 8 9], |
460 |
| - N11 11, [0 1 2 3 4 5 6 7 8 9 10], |
461 |
| - N12 12, [0 1 2 3 4 5 6 7 8 9 10 11], |
462 |
| - N13 13, [0 1 2 3 4 5 6 7 8 9 10 11 12], |
463 |
| - N14 14, [0 1 2 3 4 5 6 7 8 9 10 11 12 13], |
464 |
| - N15 15, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14], |
465 |
| - N16 16, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15], |
466 |
| - N17 17, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16], |
467 |
| - N18 18, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17], |
468 |
| - N19 19, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18], |
469 |
| - N20 20, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19], |
470 |
| - N21 21, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20], |
471 |
| - N22 22, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21], |
472 |
| - N23 23, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22], |
473 |
| - N24 24, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23], |
474 |
| - N25 25, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24], |
475 |
| - N26 26, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25], |
476 |
| - N27 27, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26], |
477 |
| - N28 28, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27], |
478 |
| - N29 29, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28], |
479 |
| - N30 30, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29], |
480 |
| - N31 31, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30], |
481 |
| - N32 32, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31], |
| 415 | + }) |
| 416 | + } |
482 | 417 | }
|
483 | 418 |
|
484 | 419 | macro_rules! impl_frame_for_sample {
|
485 | 420 | ($($T:ty)*) => {
|
486 | 421 | $(
|
487 | 422 | impl Frame for $T {
|
488 | 423 | type Sample = $T;
|
489 |
| - type NumChannels = N1; |
| 424 | + type NumChannels = NChannels<1>; |
490 | 425 | type Channels = Channels<Self>;
|
491 | 426 | type Float = <$T as Sample>::Float;
|
492 | 427 | type Signed = <$T as Sample>::Signed;
|
@@ -612,7 +547,7 @@ macro_rules! impl_frame_for_sample {
|
612 | 547 | #[inline]
|
613 | 548 | fn add_amp<F>(self, other: F) -> Self
|
614 | 549 | where
|
615 |
| - F: Frame<Sample=<$T as Sample>::Signed, NumChannels=N1>, |
| 550 | + F: Frame<Sample=<$T as Sample>::Signed, NumChannels=NChannels<1>>, |
616 | 551 | {
|
617 | 552 | // Here we do not require run-time bounds checking as we have asserted that the two
|
618 | 553 | // arrays have the same number of channels at compile time with our where clause, i.e.
|
@@ -714,3 +649,24 @@ impl<'a, F: Frame> DoubleEndedIterator for ChannelsMut<'a, F> {
|
714 | 649 | self.0.next_back()
|
715 | 650 | }
|
716 | 651 | }
|
| 652 | + |
| 653 | +fn array_from_iter<T, const N: usize>(mut iter: impl Iterator<Item = T>) -> Option<[T; N]> { |
| 654 | + // Hopefully something equivalent will be in stdlib some day |
| 655 | + |
| 656 | + unsafe { |
| 657 | + let mut result: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init(); |
| 658 | + |
| 659 | + for i in 0..N { |
| 660 | + if let Some(sample) = iter.next() { |
| 661 | + result[i].write(sample); |
| 662 | + } else { |
| 663 | + for i in 0..i { |
| 664 | + result[i].assume_init_drop() |
| 665 | + } |
| 666 | + return None; |
| 667 | + } |
| 668 | + } |
| 669 | + |
| 670 | + Some(result.map(|v| v.assume_init())) |
| 671 | + } |
| 672 | +} |
0 commit comments