1use std::fmt;
12
13use crate::util::clamp::{clamp_f32, clamp_f64, clamp_i24, clamp_u24};
14
15#[derive(Copy, Clone, Debug)]
17pub enum SampleFormat {
18 U8,
20 U16,
22 U24,
24 U32,
26 S8,
28 S16,
30 S24,
32 S32,
34 F32,
36 F64,
38}
39
40pub trait Sample:
43 Copy
44 + Clone
45 + core::ops::Add<Output = Self>
46 + core::ops::Sub<Output = Self>
47 + Default
48 + PartialOrd
49 + PartialEq
50 + Sized
51{
52 const EFF_BITS: u32;
55
56 const MID: Self;
59
60 fn clamped(self) -> Self;
63}
64
65#[allow(non_camel_case_types)]
70#[repr(transparent)]
71#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
72pub struct u24(pub u32);
73
74#[allow(non_camel_case_types)]
79#[repr(transparent)]
80#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
81pub struct i24(pub i32);
82
83impl Sample for u8 {
84 const EFF_BITS: u32 = 8;
85 const MID: u8 = 128;
86
87 #[inline(always)]
88 fn clamped(self) -> Self {
89 self
90 }
91}
92
93impl Sample for i8 {
94 const EFF_BITS: u32 = 8;
95 const MID: i8 = 0;
96
97 #[inline(always)]
98 fn clamped(self) -> Self {
99 self
100 }
101}
102
103impl Sample for u16 {
104 const EFF_BITS: u32 = 16;
105 const MID: u16 = 32_768;
106
107 #[inline(always)]
108 fn clamped(self) -> Self {
109 self
110 }
111}
112
113impl Sample for i16 {
114 const EFF_BITS: u32 = 16;
115 const MID: i16 = 0;
116
117 #[inline(always)]
118 fn clamped(self) -> Self {
119 self
120 }
121}
122
123impl Sample for u24 {
124 const EFF_BITS: u32 = 24;
125 const MID: u24 = u24(8_388_608);
126
127 #[inline(always)]
128 fn clamped(self) -> Self {
129 u24(clamp_u24(self.0))
130 }
131}
132
133impl Sample for i24 {
134 const EFF_BITS: u32 = 24;
135 const MID: i24 = i24(0);
136
137 #[inline(always)]
138 fn clamped(self) -> Self {
139 i24(clamp_i24(self.0))
140 }
141}
142
143impl Sample for u32 {
144 const EFF_BITS: u32 = 32;
145 const MID: u32 = 2_147_483_648;
146
147 #[inline(always)]
148 fn clamped(self) -> Self {
149 self
150 }
151}
152
153impl Sample for i32 {
154 const EFF_BITS: u32 = 32;
155 const MID: i32 = 0;
156
157 #[inline(always)]
158 fn clamped(self) -> Self {
159 self
160 }
161}
162
163impl Sample for f32 {
164 const EFF_BITS: u32 = 24;
165 const MID: f32 = 0.0;
166
167 #[inline(always)]
168 fn clamped(self) -> Self {
169 clamp_f32(self)
170 }
171}
172
173impl Sample for f64 {
174 const EFF_BITS: u32 = 53;
175 const MID: f64 = 0.0;
176
177 #[inline(always)]
178 fn clamped(self) -> Self {
179 clamp_f64(self)
180 }
181}
182
183macro_rules! shl_impl {
186 ($t:ident, $f:ty) => {
187 impl core::ops::Shl<$f> for $t {
188 type Output = $t;
189
190 #[inline]
191 fn shl(self, other: $f) -> $t {
192 $t(self.0 << other)
193 }
194 }
195 };
196}
197
198macro_rules! shr_impl {
199 ($t:ident, $f:ty) => {
200 impl core::ops::Shr<$f> for $t {
201 type Output = $t;
202
203 #[inline]
204 fn shr(self, other: $f) -> $t {
205 $t(self.0 >> other)
206 }
207 }
208 };
209}
210
211macro_rules! impl_shifts {
212 ($t:ident, $f:ty) => {
213 shl_impl! { $t, $f }
214 shr_impl! { $t, $f }
215 };
216}
217
218impl i24 {
221 pub const MAX: i24 = i24(8_388_607);
223 pub const MIN: i24 = i24(-8_388_608);
225
226 #[inline(always)]
228 pub fn inner(self) -> i32 {
229 self.0
230 }
231
232 #[inline(always)]
234 pub fn to_le_bytes(self) -> [u8; 3] {
235 let b = self.0.to_le_bytes();
236
237 [b[0], b[1], b[2]]
239 }
240
241 #[inline(always)]
243 pub fn to_be_bytes(self) -> [u8; 3] {
244 let b = self.0.to_be_bytes();
245
246 [b[1], b[2], b[3]]
248 }
249
250 #[inline(always)]
252 pub fn to_ne_bytes(self) -> [u8; 3] {
253 let b = self.0.to_ne_bytes();
254
255 if cfg!(target_endian = "little") {
256 [b[0], b[1], b[2]]
258 }
259 else {
260 [b[1], b[2], b[3]]
262 }
263 }
264}
265
266impl fmt::Display for i24 {
267 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268 write!(f, "{}", self.0)
269 }
270}
271
272impl From<i32> for i24 {
273 fn from(val: i32) -> Self {
274 i24(clamp_i24(val))
275 }
276}
277
278impl From<i16> for i24 {
279 fn from(val: i16) -> Self {
280 i24(i32::from(val))
281 }
282}
283
284impl From<i8> for i24 {
285 fn from(val: i8) -> Self {
286 i24(i32::from(val))
287 }
288}
289
290impl core::ops::Add<i24> for i24 {
291 type Output = i24;
292
293 #[inline]
294 fn add(self, other: Self) -> Self {
295 i24(self.0 + other.0)
296 }
297}
298
299impl core::ops::Sub<i24> for i24 {
300 type Output = i24;
301
302 #[inline]
303 fn sub(self, other: Self) -> Self {
304 i24(self.0 - other.0)
305 }
306}
307
308impl core::ops::Mul<i24> for i24 {
309 type Output = i24;
310
311 #[inline]
312 fn mul(self, other: Self) -> Self {
313 i24(self.0 * other.0)
314 }
315}
316
317impl core::ops::Div<i24> for i24 {
318 type Output = i24;
319
320 #[inline]
321 fn div(self, other: Self) -> Self {
322 i24(self.0 / other.0)
323 }
324}
325
326impl core::ops::Not for i24 {
327 type Output = i24;
328
329 #[inline]
330 fn not(self) -> Self {
331 i24(!self.0)
332 }
333}
334
335impl core::ops::Rem<i24> for i24 {
336 type Output = i24;
337
338 #[inline]
339 fn rem(self, other: Self) -> Self {
340 i24(self.0 % other.0)
341 }
342}
343
344impl core::ops::Shl<i24> for i24 {
345 type Output = i24;
346
347 #[inline]
348 fn shl(self, other: Self) -> Self {
349 i24(self.0 << other.0)
350 }
351}
352
353impl core::ops::Shr<i24> for i24 {
354 type Output = i24;
355
356 #[inline]
357 fn shr(self, other: Self) -> Self {
358 i24(self.0 >> other.0)
359 }
360}
361
362impl_shifts! { i24, u8 }
363impl_shifts! { i24, u16 }
364impl_shifts! { i24, u32 }
365impl_shifts! { i24, u64 }
366impl_shifts! { i24, u128 }
367impl_shifts! { i24, usize }
368
369impl_shifts! { i24, i8 }
370impl_shifts! { i24, i16 }
371impl_shifts! { i24, i32 }
372impl_shifts! { i24, i64 }
373impl_shifts! { i24, i128 }
374impl_shifts! { i24, isize }
375
376impl core::ops::BitAnd<i24> for i24 {
377 type Output = i24;
378
379 #[inline]
380 fn bitand(self, other: Self) -> Self {
381 i24(self.0 & other.0)
382 }
383}
384
385impl core::ops::BitOr<i24> for i24 {
386 type Output = i24;
387
388 #[inline]
389 fn bitor(self, other: Self) -> Self {
390 i24(self.0 | other.0)
391 }
392}
393
394impl core::ops::BitXor<i24> for i24 {
395 type Output = i24;
396
397 #[inline]
398 fn bitxor(self, other: Self) -> Self {
399 i24(self.0 ^ other.0)
400 }
401}
402
403impl u24 {
406 pub const MAX: u24 = u24(16_777_215);
408 pub const MIN: u24 = u24(0);
410
411 #[inline(always)]
413 pub fn inner(self) -> u32 {
414 self.0
415 }
416
417 #[inline(always)]
419 pub fn to_le_bytes(self) -> [u8; 3] {
420 let b = self.0.to_le_bytes();
421
422 [b[0], b[1], b[2]]
424 }
425
426 #[inline(always)]
428 pub fn to_be_bytes(self) -> [u8; 3] {
429 let b = self.0.to_be_bytes();
430
431 [b[1], b[2], b[3]]
433 }
434
435 #[inline(always)]
437 pub fn to_ne_bytes(self) -> [u8; 3] {
438 let b = self.0.to_ne_bytes();
439
440 if cfg!(target_endian = "little") {
441 [b[0], b[1], b[2]]
443 }
444 else {
445 [b[1], b[2], b[3]]
447 }
448 }
449}
450
451impl fmt::Display for u24 {
452 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
453 write!(f, "{}", self.0)
454 }
455}
456
457impl From<u32> for u24 {
458 fn from(val: u32) -> Self {
459 u24(clamp_u24(val))
460 }
461}
462
463impl From<u16> for u24 {
464 fn from(val: u16) -> Self {
465 u24(u32::from(val))
466 }
467}
468
469impl From<u8> for u24 {
470 fn from(val: u8) -> Self {
471 u24(u32::from(val))
472 }
473}
474
475impl core::ops::Add<u24> for u24 {
476 type Output = u24;
477
478 #[inline]
479 fn add(self, other: Self) -> Self {
480 u24(self.0 + other.0)
481 }
482}
483
484impl core::ops::Sub<u24> for u24 {
485 type Output = u24;
486
487 #[inline]
488 fn sub(self, other: Self) -> Self {
489 u24(self.0 - other.0)
490 }
491}
492
493impl core::ops::Mul<u24> for u24 {
494 type Output = u24;
495
496 #[inline]
497 fn mul(self, other: Self) -> Self {
498 u24(self.0 * other.0)
499 }
500}
501
502impl core::ops::Div<u24> for u24 {
503 type Output = u24;
504
505 #[inline]
506 fn div(self, other: Self) -> Self {
507 u24(self.0 / other.0)
508 }
509}
510
511impl core::ops::Not for u24 {
512 type Output = u24;
513
514 #[inline]
515 fn not(self) -> Self {
516 u24(!self.0)
517 }
518}
519
520impl core::ops::Rem<u24> for u24 {
521 type Output = u24;
522
523 #[inline]
524 fn rem(self, other: Self) -> Self {
525 u24(self.0 % other.0)
526 }
527}
528
529impl core::ops::Shl<u24> for u24 {
530 type Output = u24;
531
532 #[inline]
533 fn shl(self, other: Self) -> Self {
534 u24(self.0 << other.0)
535 }
536}
537
538impl core::ops::Shr<u24> for u24 {
539 type Output = u24;
540
541 #[inline]
542 fn shr(self, other: Self) -> Self {
543 u24(self.0 >> other.0)
544 }
545}
546
547impl_shifts! { u24, u8 }
548impl_shifts! { u24, u16 }
549impl_shifts! { u24, u32 }
550impl_shifts! { u24, u64 }
551impl_shifts! { u24, u128 }
552impl_shifts! { u24, usize }
553
554impl_shifts! { u24, i8 }
555impl_shifts! { u24, i16 }
556impl_shifts! { u24, i32 }
557impl_shifts! { u24, i64 }
558impl_shifts! { u24, i128 }
559impl_shifts! { u24, isize }
560
561impl core::ops::BitAnd<u24> for u24 {
562 type Output = u24;
563
564 #[inline]
565 fn bitand(self, other: Self) -> Self {
566 u24(self.0 & other.0)
567 }
568}
569
570impl core::ops::BitOr<u24> for u24 {
571 type Output = u24;
572
573 #[inline]
574 fn bitor(self, other: Self) -> Self {
575 u24(self.0 | other.0)
576 }
577}
578
579impl core::ops::BitXor<u24> for u24 {
580 type Output = u24;
581
582 #[inline]
583 fn bitxor(self, other: Self) -> Self {
584 u24(self.0 ^ other.0)
585 }
586}
587
588mod sealed {
589 pub trait ByteAligned: bytemuck::Pod {}
592}
593
594impl sealed::ByteAligned for [u8; 1] {}
595impl sealed::ByteAligned for [u8; 2] {}
596impl sealed::ByteAligned for [u8; 3] {}
597impl sealed::ByteAligned for [u8; 4] {}
598impl sealed::ByteAligned for [u8; 5] {}
599impl sealed::ByteAligned for [u8; 6] {}
600impl sealed::ByteAligned for [u8; 7] {}
601impl sealed::ByteAligned for [u8; 8] {}
602impl sealed::ByteAligned for [u8; 9] {}
603impl sealed::ByteAligned for [u8; 10] {}
604impl sealed::ByteAligned for [u8; 11] {}
605impl sealed::ByteAligned for [u8; 12] {}
606impl sealed::ByteAligned for [u8; 13] {}
607impl sealed::ByteAligned for [u8; 14] {}
608impl sealed::ByteAligned for [u8; 15] {}
609impl sealed::ByteAligned for [u8; 16] {}
610pub trait SampleBytes: Sample {
617 type RawType: sealed::ByteAligned;
622
623 fn to_ne_sample_bytes(self) -> Self::RawType;
625
626 fn to_le_sample_bytes(self) -> Self::RawType;
628
629 fn to_be_sample_bytes(self) -> Self::RawType;
631}
632
633impl SampleBytes for u8 {
634 type RawType = [u8; 1];
635
636 #[inline(always)]
637 fn to_ne_sample_bytes(self) -> Self::RawType {
638 self.to_ne_bytes()
639 }
640
641 #[inline(always)]
642 fn to_le_sample_bytes(self) -> Self::RawType {
643 self.to_le_bytes()
644 }
645
646 #[inline(always)]
647 fn to_be_sample_bytes(self) -> Self::RawType {
648 self.to_be_bytes()
649 }
650}
651
652impl SampleBytes for u16 {
653 type RawType = [u8; 2];
654
655 #[inline(always)]
656 fn to_ne_sample_bytes(self) -> Self::RawType {
657 self.to_ne_bytes()
658 }
659
660 #[inline(always)]
661 fn to_le_sample_bytes(self) -> Self::RawType {
662 self.to_le_bytes()
663 }
664
665 #[inline(always)]
666 fn to_be_sample_bytes(self) -> Self::RawType {
667 self.to_be_bytes()
668 }
669}
670
671impl SampleBytes for u24 {
672 type RawType = [u8; 3];
673
674 #[inline(always)]
675 fn to_ne_sample_bytes(self) -> Self::RawType {
676 self.to_ne_bytes()
677 }
678
679 #[inline(always)]
680 fn to_le_sample_bytes(self) -> Self::RawType {
681 self.to_le_bytes()
682 }
683
684 #[inline(always)]
685 fn to_be_sample_bytes(self) -> Self::RawType {
686 self.to_be_bytes()
687 }
688}
689
690impl SampleBytes for u32 {
691 type RawType = [u8; 4];
692
693 #[inline(always)]
694 fn to_ne_sample_bytes(self) -> Self::RawType {
695 self.to_ne_bytes()
696 }
697
698 #[inline(always)]
699 fn to_le_sample_bytes(self) -> Self::RawType {
700 self.to_le_bytes()
701 }
702
703 #[inline(always)]
704 fn to_be_sample_bytes(self) -> Self::RawType {
705 self.to_be_bytes()
706 }
707}
708
709impl SampleBytes for i8 {
710 type RawType = [u8; 1];
711
712 #[inline(always)]
713 fn to_ne_sample_bytes(self) -> Self::RawType {
714 self.to_ne_bytes()
715 }
716
717 #[inline(always)]
718 fn to_le_sample_bytes(self) -> Self::RawType {
719 self.to_le_bytes()
720 }
721
722 #[inline(always)]
723 fn to_be_sample_bytes(self) -> Self::RawType {
724 self.to_be_bytes()
725 }
726}
727
728impl SampleBytes for i16 {
729 type RawType = [u8; 2];
730
731 #[inline(always)]
732 fn to_ne_sample_bytes(self) -> Self::RawType {
733 self.to_ne_bytes()
734 }
735
736 #[inline(always)]
737 fn to_le_sample_bytes(self) -> Self::RawType {
738 self.to_le_bytes()
739 }
740
741 #[inline(always)]
742 fn to_be_sample_bytes(self) -> Self::RawType {
743 self.to_be_bytes()
744 }
745}
746
747impl SampleBytes for i24 {
748 type RawType = [u8; 3];
749
750 #[inline(always)]
751 fn to_ne_sample_bytes(self) -> Self::RawType {
752 self.to_ne_bytes()
753 }
754
755 #[inline(always)]
756 fn to_le_sample_bytes(self) -> Self::RawType {
757 self.to_le_bytes()
758 }
759
760 #[inline(always)]
761 fn to_be_sample_bytes(self) -> Self::RawType {
762 self.to_be_bytes()
763 }
764}
765
766impl SampleBytes for i32 {
767 type RawType = [u8; 4];
768
769 #[inline(always)]
770 fn to_ne_sample_bytes(self) -> Self::RawType {
771 self.to_ne_bytes()
772 }
773
774 #[inline(always)]
775 fn to_le_sample_bytes(self) -> Self::RawType {
776 self.to_le_bytes()
777 }
778
779 #[inline(always)]
780 fn to_be_sample_bytes(self) -> Self::RawType {
781 self.to_be_bytes()
782 }
783}
784
785impl SampleBytes for f32 {
786 type RawType = [u8; 4];
787
788 #[inline(always)]
789 fn to_ne_sample_bytes(self) -> Self::RawType {
790 self.to_ne_bytes()
791 }
792
793 #[inline(always)]
794 fn to_le_sample_bytes(self) -> Self::RawType {
795 self.to_le_bytes()
796 }
797
798 #[inline(always)]
799 fn to_be_sample_bytes(self) -> Self::RawType {
800 self.to_be_bytes()
801 }
802}
803
804impl SampleBytes for f64 {
805 type RawType = [u8; 8];
806
807 #[inline(always)]
808 fn to_ne_sample_bytes(self) -> Self::RawType {
809 self.to_ne_bytes()
810 }
811
812 #[inline(always)]
813 fn to_le_sample_bytes(self) -> Self::RawType {
814 self.to_le_bytes()
815 }
816
817 #[inline(always)]
818 fn to_be_sample_bytes(self) -> Self::RawType {
819 self.to_be_bytes()
820 }
821}