@@ -7,9 +7,6 @@ use zerocopy::AsBytes;
7
7
#[ repr( transparent) ]
8
8
pub struct i24 ( [ u8 ; 3 ] ) ;
9
9
impl i24 {
10
- pub const MIN : i32 = -8388608 ;
11
- pub const MAX : i32 = 8388607 ;
12
-
13
10
fn from_s24 ( sample : i32 ) -> Self {
14
11
// trim the padding in the most significant byte
15
12
let [ a, b, c, _d] = sample. to_le_bytes ( ) ;
@@ -35,13 +32,10 @@ impl Converter {
35
32
}
36
33
37
34
// Denormalize, dither and shape noise
38
- pub fn scale ( & mut self , sample : f32 , max : i32 ) -> f32 {
39
- // Losslessly represent [-1.0..1.0] as some signed integer value while
40
- // maintaining DC linearity. There is nothing to be gained by doing
41
- // this in f64, as the significand of a f32 is 24 bits, just like the
42
- // maximum bit depth we are converting to. Taken from:
43
- // http://blog.bjornroche.com/2009/12/int-float-int-its-jungle-out-there.html
44
- let int_value = sample * ( max as f32 + 0.5 ) - 0.5 ;
35
+ pub fn scale ( & mut self , sample : f32 , factor : i64 ) -> f32 {
36
+ // From the many float to int conversion methods available, match what
37
+ // the reference Vorbis implementation uses: sample * 32768 (for 16 bit)
38
+ let int_value = sample * factor as f32 ;
45
39
self . shaped_dither ( int_value)
46
40
}
47
41
@@ -50,11 +44,13 @@ impl Converter {
50
44
// byte is zero. Otherwise, dithering may cause an overflow. This is not
51
45
// necessary for other formats, because casting to integer will saturate
52
46
// to the bounds of the primitive.
53
- pub fn clamping_scale ( & mut self , sample : f32 , min : i32 , max : i32 ) -> f32 {
54
- let int_value = self . scale ( sample, max) ;
47
+ pub fn clamping_scale ( & mut self , sample : f32 , factor : i64 ) -> f32 {
48
+ let int_value = self . scale ( sample, factor) ;
49
+
50
+ // In two's complement, there are more negative than positive values.
51
+ let min = -factor as f32 ;
52
+ let max = ( factor - 1 ) as f32 ;
55
53
56
- let min = min as f32 ;
57
- let max = max as f32 ;
58
54
if int_value < min {
59
55
return min;
60
56
} else if int_value > max {
@@ -75,15 +71,15 @@ impl Converter {
75
71
pub fn f32_to_s32 ( & mut self , samples : & [ f32 ] ) -> Vec < i32 > {
76
72
samples
77
73
. iter ( )
78
- . map ( |sample| self . scale ( * sample, std :: i32 :: MAX ) as i32 )
74
+ . map ( |sample| self . scale ( * sample, 0x80000000 ) as i32 )
79
75
. collect ( )
80
76
}
81
77
82
78
// S24 is 24-bit PCM packed in an upper 32-bit word
83
79
pub fn f32_to_s24 ( & mut self , samples : & [ f32 ] ) -> Vec < i32 > {
84
80
samples
85
81
. iter ( )
86
- . map ( |sample| self . clamping_scale ( * sample, i24 :: MIN , i24 :: MAX ) as i32 )
82
+ . map ( |sample| self . clamping_scale ( * sample, 0x800000 ) as i32 )
87
83
. collect ( )
88
84
}
89
85
@@ -94,7 +90,7 @@ impl Converter {
94
90
. map ( |sample| {
95
91
// Not as DRY as calling f32_to_s24 first, but this saves iterating
96
92
// over all samples twice.
97
- let int_value = self . clamping_scale ( * sample, i24 :: MIN , i24 :: MAX ) as i32 ;
93
+ let int_value = self . clamping_scale ( * sample, 0x800000 ) as i32 ;
98
94
i24:: from_s24 ( int_value)
99
95
} )
100
96
. collect ( )
@@ -103,7 +99,7 @@ impl Converter {
103
99
pub fn f32_to_s16 ( & mut self , samples : & [ f32 ] ) -> Vec < i16 > {
104
100
samples
105
101
. iter ( )
106
- . map ( |sample| self . scale ( * sample, std :: i16 :: MAX as i32 ) as i16 )
102
+ . map ( |sample| self . scale ( * sample, 0x8000 ) as i16 )
107
103
. collect ( )
108
104
}
109
105
}
0 commit comments