1use std::fmt;
11
12use crate::util::clamp::{clamp_f32, clamp_f64, clamp_i24, clamp_u24};
13
14#[derive(Copy, Clone, Debug)]
16pub enum SampleFormat {
17 U8,
19 U16,
21 U24,
23 U32,
25 S8,
27 S16,
29 S24,
31 S32,
33 F32,
35 F64,
37}
38
39pub trait Sample:
44 Copy
45 + Clone
46 + core::ops::Add<Output = Self>
47 + core::ops::Sub<Output = Self>
48 + Default
49 + PartialOrd
50 + PartialEq
51 + Sized
52{
53 const FORMAT: SampleFormat;
56
57 const EFF_BITS: u32;
60
61 const MID: Self;
64
65 fn clamped(self) -> Self;
68}
69
70#[allow(non_camel_case_types)]
75#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
76pub struct u24(pub u32);
77
78#[allow(non_camel_case_types)]
83#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
84pub struct i24(pub i32);
85
86impl Sample for u8 {
87 const FORMAT: SampleFormat = SampleFormat::U8;
88 const EFF_BITS: u32 = 8;
89 const MID: u8 = 128;
90
91 #[inline(always)]
92 fn clamped(self) -> Self {
93 self
94 }
95}
96
97impl Sample for i8 {
98 const FORMAT: SampleFormat = SampleFormat::S8;
99 const EFF_BITS: u32 = 8;
100 const MID: i8 = 0;
101
102 #[inline(always)]
103 fn clamped(self) -> Self {
104 self
105 }
106}
107
108impl Sample for u16 {
109 const FORMAT: SampleFormat = SampleFormat::U16;
110 const EFF_BITS: u32 = 16;
111 const MID: u16 = 32_768;
112
113 #[inline(always)]
114 fn clamped(self) -> Self {
115 self
116 }
117}
118
119impl Sample for i16 {
120 const FORMAT: SampleFormat = SampleFormat::S16;
121 const EFF_BITS: u32 = 16;
122 const MID: i16 = 0;
123
124 #[inline(always)]
125 fn clamped(self) -> Self {
126 self
127 }
128}
129
130impl Sample for u24 {
131 const FORMAT: SampleFormat = SampleFormat::U24;
132 const EFF_BITS: u32 = 24;
133 const MID: u24 = u24(8_388_608);
134
135 #[inline(always)]
136 fn clamped(self) -> Self {
137 u24(clamp_u24(self.0))
138 }
139}
140
141impl Sample for i24 {
142 const FORMAT: SampleFormat = SampleFormat::S24;
143 const EFF_BITS: u32 = 24;
144 const MID: i24 = i24(0);
145
146 #[inline(always)]
147 fn clamped(self) -> Self {
148 i24(clamp_i24(self.0))
149 }
150}
151
152impl Sample for u32 {
153 const FORMAT: SampleFormat = SampleFormat::U32;
154 const EFF_BITS: u32 = 32;
155 const MID: u32 = 2_147_483_648;
156
157 #[inline(always)]
158 fn clamped(self) -> Self {
159 self
160 }
161}
162
163impl Sample for i32 {
164 const FORMAT: SampleFormat = SampleFormat::S32;
165 const EFF_BITS: u32 = 32;
166 const MID: i32 = 0;
167
168 #[inline(always)]
169 fn clamped(self) -> Self {
170 self
171 }
172}
173
174impl Sample for f32 {
175 const FORMAT: SampleFormat = SampleFormat::F32;
176 const EFF_BITS: u32 = 24;
177 const MID: f32 = 0.0;
178
179 #[inline(always)]
180 fn clamped(self) -> Self {
181 clamp_f32(self)
182 }
183}
184
185impl Sample for f64 {
186 const FORMAT: SampleFormat = SampleFormat::F64;
187 const EFF_BITS: u32 = 53;
188 const MID: f64 = 0.0;
189
190 #[inline(always)]
191 fn clamped(self) -> Self {
192 clamp_f64(self)
193 }
194}
195
196macro_rules! shl_impl {
199 ($t:ident, $f:ty) => {
200 impl core::ops::Shl<$f> for $t {
201 type Output = $t;
202
203 #[inline]
204 fn shl(self, other: $f) -> $t {
205 $t(self.0 << other)
206 }
207 }
208 };
209}
210
211macro_rules! shr_impl {
212 ($t:ident, $f:ty) => {
213 impl core::ops::Shr<$f> for $t {
214 type Output = $t;
215
216 #[inline]
217 fn shr(self, other: $f) -> $t {
218 $t(self.0 >> other)
219 }
220 }
221 };
222}
223
224macro_rules! impl_shifts {
225 ($t:ident, $f:ty) => {
226 shl_impl! { $t, $f }
227 shr_impl! { $t, $f }
228 };
229}
230
231impl i24 {
234 pub const MAX: i24 = i24(8_388_607);
236 pub const MIN: i24 = i24(-8_388_608);
238
239 #[inline(always)]
241 #[deprecated = "Superseded by `inner`."]
242 pub fn into_i32(self) -> i32 {
243 self.0
244 }
245
246 #[inline(always)]
248 pub fn inner(self) -> i32 {
249 self.0
250 }
251
252 #[inline]
254 pub fn to_ne_bytes(self) -> [u8; 3] {
255 let b = self.0.to_ne_bytes();
256
257 if cfg!(target_endian = "little") {
258 [b[0], b[1], b[2]]
260 }
261 else {
262 [b[1], b[2], b[3]]
264 }
265 }
266}
267
268impl fmt::Display for i24 {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 write!(f, "{}", self.0)
271 }
272}
273
274impl From<i32> for i24 {
275 fn from(val: i32) -> Self {
276 i24(clamp_i24(val))
277 }
278}
279
280impl From<i16> for i24 {
281 fn from(val: i16) -> Self {
282 i24(i32::from(val))
283 }
284}
285
286impl From<i8> for i24 {
287 fn from(val: i8) -> Self {
288 i24(i32::from(val))
289 }
290}
291
292impl core::ops::Add<i24> for i24 {
293 type Output = i24;
294
295 #[inline]
296 fn add(self, other: Self) -> Self {
297 i24(self.0 + other.0)
298 }
299}
300
301impl core::ops::Sub<i24> for i24 {
302 type Output = i24;
303
304 #[inline]
305 fn sub(self, other: Self) -> Self {
306 i24(self.0 - other.0)
307 }
308}
309
310impl core::ops::Mul<i24> for i24 {
311 type Output = i24;
312
313 #[inline]
314 fn mul(self, other: Self) -> Self {
315 i24(self.0 * other.0)
316 }
317}
318
319impl core::ops::Div<i24> for i24 {
320 type Output = i24;
321
322 #[inline]
323 fn div(self, other: Self) -> Self {
324 i24(self.0 / other.0)
325 }
326}
327
328impl core::ops::Not for i24 {
329 type Output = i24;
330
331 #[inline]
332 fn not(self) -> Self {
333 i24(!self.0)
334 }
335}
336
337impl core::ops::Rem<i24> for i24 {
338 type Output = i24;
339
340 #[inline]
341 fn rem(self, other: Self) -> Self {
342 i24(self.0 % other.0)
343 }
344}
345
346impl core::ops::Shl<i24> for i24 {
347 type Output = i24;
348
349 #[inline]
350 fn shl(self, other: Self) -> Self {
351 i24(self.0 << other.0)
352 }
353}
354
355impl core::ops::Shr<i24> for i24 {
356 type Output = i24;
357
358 #[inline]
359 fn shr(self, other: Self) -> Self {
360 i24(self.0 >> other.0)
361 }
362}
363
364impl_shifts! { i24, u8 }
365impl_shifts! { i24, u16 }
366impl_shifts! { i24, u32 }
367impl_shifts! { i24, u64 }
368impl_shifts! { i24, u128 }
369impl_shifts! { i24, usize }
370
371impl_shifts! { i24, i8 }
372impl_shifts! { i24, i16 }
373impl_shifts! { i24, i32 }
374impl_shifts! { i24, i64 }
375impl_shifts! { i24, i128 }
376impl_shifts! { i24, isize }
377
378impl core::ops::BitAnd<i24> for i24 {
379 type Output = i24;
380
381 #[inline]
382 fn bitand(self, other: Self) -> Self {
383 i24(self.0 & other.0)
384 }
385}
386
387impl core::ops::BitOr<i24> for i24 {
388 type Output = i24;
389
390 #[inline]
391 fn bitor(self, other: Self) -> Self {
392 i24(self.0 | other.0)
393 }
394}
395
396impl core::ops::BitXor<i24> for i24 {
397 type Output = i24;
398
399 #[inline]
400 fn bitxor(self, other: Self) -> Self {
401 i24(self.0 ^ other.0)
402 }
403}
404
405impl u24 {
408 pub const MAX: u24 = u24(16_777_215);
410 pub const MIN: u24 = u24(0);
412
413 #[inline(always)]
415 #[deprecated = "Superseded by `inner`."]
416 pub fn into_u32(self) -> u32 {
417 self.0
418 }
419
420 #[inline(always)]
422 pub fn inner(self) -> u32 {
423 self.0
424 }
425
426 #[inline]
428 pub fn to_ne_bytes(self) -> [u8; 3] {
429 let b = self.0.to_ne_bytes();
430
431 if cfg!(target_endian = "little") {
432 [b[0], b[1], b[2]]
434 }
435 else {
436 [b[1], b[2], b[3]]
438 }
439 }
440}
441
442impl fmt::Display for u24 {
443 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
444 write!(f, "{}", self.0)
445 }
446}
447
448impl From<u32> for u24 {
449 fn from(val: u32) -> Self {
450 u24(clamp_u24(val))
451 }
452}
453
454impl From<u16> for u24 {
455 fn from(val: u16) -> Self {
456 u24(u32::from(val))
457 }
458}
459
460impl From<u8> for u24 {
461 fn from(val: u8) -> Self {
462 u24(u32::from(val))
463 }
464}
465
466impl core::ops::Add<u24> for u24 {
467 type Output = u24;
468
469 #[inline]
470 fn add(self, other: Self) -> Self {
471 u24(self.0 + other.0)
472 }
473}
474
475impl core::ops::Sub<u24> for u24 {
476 type Output = u24;
477
478 #[inline]
479 fn sub(self, other: Self) -> Self {
480 u24(self.0 - other.0)
481 }
482}
483
484impl core::ops::Mul<u24> for u24 {
485 type Output = u24;
486
487 #[inline]
488 fn mul(self, other: Self) -> Self {
489 u24(self.0 * other.0)
490 }
491}
492
493impl core::ops::Div<u24> for u24 {
494 type Output = u24;
495
496 #[inline]
497 fn div(self, other: Self) -> Self {
498 u24(self.0 / other.0)
499 }
500}
501
502impl core::ops::Not for u24 {
503 type Output = u24;
504
505 #[inline]
506 fn not(self) -> Self {
507 u24(!self.0)
508 }
509}
510
511impl core::ops::Rem<u24> for u24 {
512 type Output = u24;
513
514 #[inline]
515 fn rem(self, other: Self) -> Self {
516 u24(self.0 % other.0)
517 }
518}
519
520impl core::ops::Shl<u24> for u24 {
521 type Output = u24;
522
523 #[inline]
524 fn shl(self, other: Self) -> Self {
525 u24(self.0 << other.0)
526 }
527}
528
529impl core::ops::Shr<u24> for u24 {
530 type Output = u24;
531
532 #[inline]
533 fn shr(self, other: Self) -> Self {
534 u24(self.0 >> other.0)
535 }
536}
537
538impl_shifts! { u24, u8 }
539impl_shifts! { u24, u16 }
540impl_shifts! { u24, u32 }
541impl_shifts! { u24, u64 }
542impl_shifts! { u24, u128 }
543impl_shifts! { u24, usize }
544
545impl_shifts! { u24, i8 }
546impl_shifts! { u24, i16 }
547impl_shifts! { u24, i32 }
548impl_shifts! { u24, i64 }
549impl_shifts! { u24, i128 }
550impl_shifts! { u24, isize }
551
552impl core::ops::BitAnd<u24> for u24 {
553 type Output = u24;
554
555 #[inline]
556 fn bitand(self, other: Self) -> Self {
557 u24(self.0 & other.0)
558 }
559}
560
561impl core::ops::BitOr<u24> for u24 {
562 type Output = u24;
563
564 #[inline]
565 fn bitor(self, other: Self) -> Self {
566 u24(self.0 | other.0)
567 }
568}
569
570impl core::ops::BitXor<u24> for u24 {
571 type Output = u24;
572
573 #[inline]
574 fn bitxor(self, other: Self) -> Self {
575 u24(self.0 ^ other.0)
576 }
577}