Skip to main content

codec_core/utils/
tables.rs

1//! Lookup table utilities for codec optimizations
2
3/// Pre-computed μ-law decoding table (8-bit μ-law to 16-bit linear)
4pub static MULAW_DECODE_TABLE: [i16; 256] = [
5    16004, 14980, 13956, 12932, 11908, 10884, 9860, 8836, 7812, 6788, 5764, 4740, 3716, 2692, 1668,
6    644, 8068, 7556, 7044, 6532, 6020, 5508, 4996, 4484, 3972, 3460, 2948, 2436, 1924, 1412, 900,
7    388, 4100, 3844, 3588, 3332, 3076, 2820, 2564, 2308, 2052, 1796, 1540, 1284, 1028, 772, 516,
8    260, 2116, 1988, 1860, 1732, 1604, 1476, 1348, 1220, 1092, 964, 836, 708, 580, 452, 324, 196,
9    1124, 1060, 996, 932, 868, 804, 740, 676, 612, 548, 484, 420, 356, 292, 228, 164, 628, 596,
10    564, 532, 500, 468, 436, 404, 372, 340, 308, 276, 244, 212, 180, 148, 380, 364, 348, 332, 316,
11    300, 284, 268, 252, 236, 220, 204, 188, 172, 156, 140, 252, 244, 236, 228, 220, 212, 204, 196,
12    188, 180, 172, 164, 156, 148, 140, 132, -16004, -14980, -13956, -12932, -11908, -10884, -9860,
13    -8836, -7812, -6788, -5764, -4740, -3716, -2692, -1668, -644, -8068, -7556, -7044, -6532,
14    -6020, -5508, -4996, -4484, -3972, -3460, -2948, -2436, -1924, -1412, -900, -388, -4100, -3844,
15    -3588, -3332, -3076, -2820, -2564, -2308, -2052, -1796, -1540, -1284, -1028, -772, -516, -260,
16    -2116, -1988, -1860, -1732, -1604, -1476, -1348, -1220, -1092, -964, -836, -708, -580, -452,
17    -324, -196, -1124, -1060, -996, -932, -868, -804, -740, -676, -612, -548, -484, -420, -356,
18    -292, -228, -164, -628, -596, -564, -532, -500, -468, -436, -404, -372, -340, -308, -276, -244,
19    -212, -180, -148, -380, -364, -348, -332, -316, -300, -284, -268, -252, -236, -220, -204, -188,
20    -172, -156, -140, -252, -244, -236, -228, -220, -212, -204, -196, -188, -180, -172, -164, -156,
21    -148, -140, -132,
22];
23
24/// Pre-computed A-law decoding table (8-bit A-law to 16-bit linear)
25pub static ALAW_DECODE_TABLE: [i16; 256] = [
26    15880, 14856, 13832, 12808, 11784, 10760, 9736, 8712, 7688, 6664, 5640, 4616, 3592, 2568, 1544,
27    520, 7944, 7432, 6920, 6408, 5896, 5384, 4872, 4360, 3848, 3336, 2824, 2312, 1800, 1288, 776,
28    264, 3976, 3720, 3464, 3208, 2952, 2696, 2440, 2184, 1928, 1672, 1416, 1160, 904, 648, 392,
29    136, 1992, 1864, 1736, 1608, 1480, 1352, 1224, 1096, 968, 840, 712, 584, 456, 328, 200, 72,
30    1000, 936, 872, 808, 744, 680, 616, 552, 488, 424, 360, 296, 232, 168, 104, 40, 504, 472, 440,
31    408, 376, 344, 312, 280, 248, 216, 184, 152, 120, 88, 56, 24, 256, 240, 224, 208, 192, 176,
32    160, 144, 128, 112, 96, 80, 64, 48, 32, 16, 248, 232, 216, 200, 184, 168, 152, 136, 120, 104,
33    88, 72, 56, 40, 24, 8, -15880, -14856, -13832, -12808, -11784, -10760, -9736, -8712, -7688,
34    -6664, -5640, -4616, -3592, -2568, -1544, -520, -7944, -7432, -6920, -6408, -5896, -5384,
35    -4872, -4360, -3848, -3336, -2824, -2312, -1800, -1288, -776, -264, -3976, -3720, -3464, -3208,
36    -2952, -2696, -2440, -2184, -1928, -1672, -1416, -1160, -904, -648, -392, -136, -1992, -1864,
37    -1736, -1608, -1480, -1352, -1224, -1096, -968, -840, -712, -584, -456, -328, -200, -72, -1000,
38    -936, -872, -808, -744, -680, -616, -552, -488, -424, -360, -296, -232, -168, -104, -40, -504,
39    -472, -440, -408, -376, -344, -312, -280, -248, -216, -184, -152, -120, -88, -56, -24, -256,
40    -240, -224, -208, -192, -176, -160, -144, -128, -112, -96, -80, -64, -48, -32, -16, -248, -232,
41    -216, -200, -184, -168, -152, -136, -120, -104, -88, -72, -56, -40, -24, -8,
42];
43
44/// Fast μ-law encoding using direct computation
45#[must_use]
46pub const fn encode_mulaw_table(sample: i16) -> u8 {
47    crate::utils::simd::linear_to_mulaw_scalar(sample)
48}
49
50/// Fast μ-law decoding using lookup table
51#[must_use]
52pub const fn decode_mulaw_table(encoded: u8) -> i16 {
53    MULAW_DECODE_TABLE[encoded as usize]
54}
55
56/// Fast A-law encoding using direct computation
57#[must_use]
58pub const fn encode_alaw_table(sample: i16) -> u8 {
59    crate::utils::simd::linear_to_alaw_scalar(sample)
60}
61
62/// Fast A-law decoding using lookup table
63#[must_use]
64pub const fn decode_alaw_table(encoded: u8) -> i16 {
65    ALAW_DECODE_TABLE[encoded as usize]
66}
67
68/// Batch μ-law encoding using lookup tables
69pub fn encode_mulaw_batch(samples: &[i16], output: &mut [u8]) {
70    for (i, &sample) in samples.iter().enumerate() {
71        output[i] = encode_mulaw_table(sample);
72    }
73}
74
75/// Batch μ-law decoding using lookup tables
76pub fn decode_mulaw_batch(encoded: &[u8], output: &mut [i16]) {
77    for (i, &byte) in encoded.iter().enumerate() {
78        output[i] = decode_mulaw_table(byte);
79    }
80}
81
82/// Batch A-law encoding using lookup tables
83pub fn encode_alaw_batch(samples: &[i16], output: &mut [u8]) {
84    for (i, &sample) in samples.iter().enumerate() {
85        output[i] = encode_alaw_table(sample);
86    }
87}
88
89/// Batch A-law decoding using lookup tables
90pub fn decode_alaw_batch(encoded: &[u8], output: &mut [i16]) {
91    for (i, &byte) in encoded.iter().enumerate() {
92        output[i] = decode_alaw_table(byte);
93    }
94}
95
96/// Initialize all lookup tables
97pub fn init_tables() {
98    // Static arrays are already initialized at compile time
99    tracing::debug!("Codec lookup tables already initialized (1KB total)");
100}
101
102/// Get memory usage of lookup tables
103#[must_use]
104pub const fn get_table_memory_usage() -> usize {
105    // Only decode tables:
106    // μ-law: 256 * 2 = 512 bytes
107    // A-law: 256 * 2 = 512 bytes
108    // Total: 1024 bytes (1KB)
109    let mulaw_decode_size = std::mem::size_of::<[i16; 256]>();
110    let alaw_decode_size = std::mem::size_of::<[i16; 256]>();
111
112    mulaw_decode_size + alaw_decode_size
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn test_table_initialization() {
121        // Test that static arrays are available
122        assert_eq!(MULAW_DECODE_TABLE.len(), 256);
123        assert_eq!(ALAW_DECODE_TABLE.len(), 256);
124
125        // Test first and last values are reasonable
126        assert_ne!(MULAW_DECODE_TABLE[0], 0);
127        assert_ne!(MULAW_DECODE_TABLE[255], 0);
128        assert_ne!(ALAW_DECODE_TABLE[0], 0);
129        assert_ne!(ALAW_DECODE_TABLE[255], 0);
130    }
131
132    #[test]
133    fn test_table_vs_scalar() {
134        // Test decode tables only (they're small and fast)
135        let test_encoded = vec![0, 127, 128, 255];
136
137        for encoded in test_encoded {
138            // Test μ-law decode
139            let table_result = decode_mulaw_table(encoded);
140            let scalar_result = crate::utils::simd::mulaw_to_linear_scalar(encoded);
141            assert_eq!(
142                table_result, scalar_result,
143                "μ-law decode table mismatch for encoded {encoded}"
144            );
145
146            // Test A-law decode
147            let table_result = decode_alaw_table(encoded);
148            let scalar_result = crate::utils::simd::alaw_to_linear_scalar(encoded);
149            assert_eq!(
150                table_result, scalar_result,
151                "A-law decode table mismatch for encoded {encoded}"
152            );
153        }
154    }
155
156    #[test]
157    fn test_batch_operations() {
158        // Test decode batch operations only (they're fast)
159        let encoded = vec![0u8, 127, 128, 255];
160        let mut decoded = vec![0i16; encoded.len()];
161
162        // Test μ-law batch decode
163        decode_mulaw_batch(&encoded, &mut decoded);
164
165        // Verify we got some non-zero results
166        assert_ne!(decoded[1], 0);
167        assert_ne!(decoded[2], 0);
168        assert_ne!(decoded[3], 0);
169
170        // Test A-law batch decode
171        decode_alaw_batch(&encoded, &mut decoded);
172
173        // Verify we got some non-zero results
174        assert_ne!(decoded[1], 0);
175        assert_ne!(decoded[2], 0);
176        assert_ne!(decoded[3], 0);
177    }
178
179    #[test]
180    fn test_memory_usage() {
181        let usage = get_table_memory_usage();
182
183        // Expected: 2 * 256 * 2 bytes = 1024 bytes
184        assert_eq!(usage, 1024);
185    }
186
187    #[test]
188    fn test_edge_cases() {
189        // Test boundary values for decode operations only
190        let edge_cases = vec![0u8, 127, 128, 255];
191
192        for encoded in edge_cases {
193            // Decoders return `i16`; the value range is guaranteed by
194            // the type. We only need to assert they don't panic.
195            let _ = decode_mulaw_table(encoded);
196            let _ = decode_alaw_table(encoded);
197        }
198    }
199}