Skip to main content

shine_rs/
types.rs

1//! Type definitions for MP3 encoding
2//!
3//! This module contains all the type definitions that correspond exactly
4//! to shine's types.h, maintaining binary compatibility and data layout.
5
6use crate::bitstream::BitstreamWriter;
7
8/// Constants from shine (matches types.h exactly)
9pub const GRANULE_SIZE: usize = 576;
10pub const PI: f64 = std::f64::consts::PI;
11pub const PI4: f64 = std::f64::consts::FRAC_PI_4;
12pub const PI12: f64 = 0.26179938779915;
13pub const PI36: f64 = 0.087266462599717;
14pub const PI64: f64 = 0.049087385212;
15pub const SQRT2: f64 = std::f64::consts::SQRT_2;
16pub const LN2: f64 = std::f64::consts::LN_2;
17pub const LN_TO_LOG10: f64 = 0.2302585093;
18pub const BLKSIZE: usize = 1024;
19pub const HAN_SIZE: usize = 512; // for loop unrolling, require that HAN_SIZE%8==0
20pub const SCALE_BLOCK: i32 = 12;
21pub const SCALE_RANGE: i32 = 64;
22pub const SCALE: i32 = 32768;
23pub const SBLIMIT: usize = 32;
24pub const MAX_CHANNELS: usize = 2;
25pub const MAX_GRANULES: usize = 2;
26
27/// SWAB32 macro implementation (matches shine's SWAB32)
28#[inline]
29pub fn swab32(x: u32) -> u32 {
30    (x >> 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8) | (x << 24)
31}
32
33/// Private shine wave configuration (matches priv_shine_wave_t)
34/// (ref/shine/src/lib/types.h:60-63)
35#[repr(C)]
36#[derive(Debug, Clone)]
37pub struct PrivShineWave {
38    pub channels: i32,
39    pub samplerate: i32,
40}
41
42/// Private shine MPEG configuration (matches priv_shine_mpeg_t)
43/// (ref/shine/src/lib/types.h:65-87)
44#[repr(C)]
45#[derive(Debug, Clone)]
46pub struct PrivShineMpeg {
47    pub version: i32,
48    pub layer: i32,
49    pub granules_per_frame: i32,
50    pub mode: i32, // Stereo mode
51    pub bitr: i32, // Must conform to known bitrate
52    pub emph: i32, // De-emphasis
53    pub padding: i32,
54    pub bits_per_frame: i32,
55    pub bits_per_slot: i32,
56    pub frac_slots_per_frame: f64,
57    pub slot_lag: f64,
58    pub whole_slots_per_frame: i32,
59    pub bitrate_index: i32,    // See Main.c and Layer3.c
60    pub samplerate_index: i32, // See Main.c and Layer3.c
61    pub crc: i32,
62    pub ext: i32,
63    pub mode_ext: i32,
64    pub copyright: i32,
65    pub original: i32,
66}
67/// L3 loop structure (matches l3loop_t)
68/// (ref/shine/src/lib/types.h:89-101)
69#[repr(C)]
70#[derive(Debug)]
71pub struct L3Loop {
72    /// Magnitudes of the spectral values
73    pub xr: *mut i32,
74    /// xr squared
75    pub xrsq: Box<[i32; GRANULE_SIZE]>, // Move to heap
76    /// xr absolute
77    pub xrabs: Box<[i32; GRANULE_SIZE]>, // Move to heap
78    /// Maximum of xrabs array
79    pub xrmax: i32,
80    /// Total energy per granule
81    pub en_tot: [i32; MAX_GRANULES],
82    /// Energy per scalefactor band [granule][sfb]
83    pub en: [[i32; 21]; MAX_GRANULES],
84    /// Masking threshold per scalefactor band [granule][sfb]
85    pub xm: [[i32; 21]; MAX_GRANULES],
86    /// Maximum per granule
87    pub xrmaxl: [i32; MAX_GRANULES],
88    /// 2**(-x/4) for x = -127..0
89    pub steptab: [f64; 128],
90    /// 2**(-x/4) for x = -127..0 (integer version)
91    pub steptabi: [i32; 128],
92    /// x**(3/4) for x = 0..9999
93    pub int2idx: Box<[i32; 10000]>, // Move to heap
94}
95
96impl Default for L3Loop {
97    fn default() -> Self {
98        Self {
99            xr: std::ptr::null_mut(),
100            xrsq: Box::new([0; GRANULE_SIZE]),
101            xrabs: Box::new([0; GRANULE_SIZE]),
102            xrmax: 0,
103            en_tot: [0; MAX_GRANULES],
104            en: [[0; 21]; MAX_GRANULES],
105            xm: [[0; 21]; MAX_GRANULES],
106            xrmaxl: [0; MAX_GRANULES],
107            steptab: [0.0; 128],
108            steptabi: [0; 128],
109            int2idx: Box::new([0; 10000]),
110        }
111    }
112}
113
114/// MDCT structure (matches mdct_t)
115/// (ref/shine/src/lib/types.h:103-105)
116#[repr(C)]
117#[derive(Debug)]
118pub struct Mdct {
119    pub cos_l: [[i32; 36]; 18],
120}
121
122impl Default for Mdct {
123    fn default() -> Self {
124        Self {
125            cos_l: [[0; 36]; 18],
126        }
127    }
128}
129
130/// Subband structure (matches subband_t)
131/// (ref/shine/src/lib/types.h:107-111)
132#[repr(C)]
133#[derive(Debug)]
134pub struct Subband {
135    pub off: [i32; MAX_CHANNELS],
136    pub fl: [[i32; 64]; SBLIMIT],
137    pub x: Box<[[i32; HAN_SIZE]; MAX_CHANNELS]>, // Move to heap
138}
139
140impl Default for Subband {
141    fn default() -> Self {
142        Self {
143            off: [0; MAX_CHANNELS],
144            fl: [[0; 64]; SBLIMIT],
145            x: Box::new([[0; HAN_SIZE]; MAX_CHANNELS]),
146        }
147    }
148}
149/// Granule information (matches gr_info)
150/// (ref/shine/src/lib/types.h:114-133)
151#[repr(C)]
152#[derive(Debug, Clone)]
153pub struct GrInfo {
154    pub part2_3_length: u32,
155    pub big_values: u32,
156    pub count1: u32,
157    pub global_gain: u32,
158    pub scalefac_compress: u32,
159    pub table_select: [u32; 3],
160    pub region0_count: u32,
161    pub region1_count: u32,
162    pub preflag: u32,
163    pub scalefac_scale: u32,
164    pub count1table_select: u32,
165    pub part2_length: u32,
166    pub sfb_lmax: u32,
167    pub address1: u32,
168    pub address2: u32,
169    pub address3: u32,
170    pub quantizer_step_size: i32,
171    pub slen: [u32; 4],
172}
173
174impl Default for GrInfo {
175    fn default() -> Self {
176        Self {
177            part2_3_length: 0,
178            big_values: 0,
179            count1: 0,
180            global_gain: 210,
181            scalefac_compress: 0,
182            table_select: [0, 0, 0],
183            region0_count: 0,
184            region1_count: 0,
185            preflag: 0,
186            scalefac_scale: 0,
187            count1table_select: 0,
188            part2_length: 0,
189            sfb_lmax: 21,
190            address1: 0,
191            address2: 0,
192            address3: 0,
193            quantizer_step_size: 0,
194            slen: [0, 0, 0, 0],
195        }
196    }
197}
198
199/// Channel information within a granule
200#[repr(C)]
201#[derive(Debug, Clone, Default)]
202pub struct GranuleChannel {
203    pub tt: GrInfo,
204}
205
206/// Granule structure
207#[repr(C)]
208#[derive(Debug, Clone, Default)]
209pub struct Granule {
210    pub ch: [GranuleChannel; MAX_CHANNELS],
211}
212/// Side information structure (matches shine_side_info_t)
213/// (ref/shine/src/lib/types.h:135-144)
214#[repr(C)]
215#[derive(Debug, Clone)]
216pub struct ShineSideInfo {
217    pub private_bits: u32,
218    pub resv_drain: i32, // matches resvDrain in shine
219    pub scfsi: [[u32; 4]; MAX_CHANNELS],
220    pub gr: [Granule; MAX_GRANULES],
221}
222
223impl Default for ShineSideInfo {
224    fn default() -> Self {
225        Self {
226            private_bits: 0,
227            resv_drain: 0,
228            scfsi: [[0; 4]; MAX_CHANNELS],
229            gr: [Granule::default(), Granule::default()],
230        }
231    }
232}
233
234/// Psychoacoustic ratio structure (matches shine_psy_ratio_t)
235/// (ref/shine/src/lib/types.h:146-148)
236#[repr(C)]
237#[derive(Debug)]
238pub struct ShinePsyRatio {
239    pub l: Box<[[[f64; 21]; MAX_CHANNELS]; MAX_GRANULES]>, // Move to heap
240}
241
242impl Default for ShinePsyRatio {
243    fn default() -> Self {
244        Self {
245            l: Box::new([[[0.0; 21]; MAX_CHANNELS]; MAX_GRANULES]),
246        }
247    }
248}
249
250/// Psychoacoustic minimum structure (matches shine_psy_xmin_t)
251/// (ref/shine/src/lib/types.h:150-152)
252#[repr(C)]
253#[derive(Debug)]
254pub struct ShinePsyXmin {
255    pub l: Box<[[[f64; 21]; MAX_CHANNELS]; MAX_GRANULES]>, // Move to heap
256}
257
258impl Default for ShinePsyXmin {
259    fn default() -> Self {
260        Self {
261            l: Box::new([[[0.0; 21]; MAX_CHANNELS]; MAX_GRANULES]),
262        }
263    }
264}
265
266/// Scale factor structure (matches shine_scalefac_t)
267/// (ref/shine/src/lib/types.h:154-157)
268#[repr(C)]
269#[derive(Debug)]
270pub struct ShineScalefac {
271    /// Long block scale factors [granule][channel][scalefactor_band]
272    pub l: Box<[[[i32; 22]; MAX_CHANNELS]; MAX_GRANULES]>, // Move to heap
273    /// Short block scale factors [granule][channel][scalefactor_band][window]
274    pub s: Box<[[[[i32; 3]; 13]; MAX_CHANNELS]; MAX_GRANULES]>, // Move to heap
275}
276
277impl Default for ShineScalefac {
278    fn default() -> Self {
279        Self {
280            l: Box::new([[[0; 22]; MAX_CHANNELS]; MAX_GRANULES]),
281            s: Box::new([[[[0; 3]; 13]; MAX_CHANNELS]; MAX_GRANULES]),
282        }
283    }
284}
285/// Global configuration structure (matches shine_global_config)
286/// (ref/shine/src/lib/types.h:159-180)
287#[repr(C)]
288#[derive(Debug)]
289pub struct ShineGlobalConfig {
290    pub wave: PrivShineWave,
291    pub mpeg: PrivShineMpeg,
292    pub bs: BitstreamWriter,
293    pub side_info: ShineSideInfo,
294    pub sideinfo_len: i32,
295    pub mean_bits: i32,
296    pub ratio: ShinePsyRatio,
297    pub scalefactor: Box<ShineScalefac>, // Move to heap
298    pub buffer: [*mut i16; MAX_CHANNELS],
299    pub pe: Box<[[f64; MAX_GRANULES]; MAX_CHANNELS]>, // Move to heap
300    pub l3_enc: Box<[[[i32; GRANULE_SIZE]; MAX_GRANULES]; MAX_CHANNELS]>, // Move to heap
301    pub l3_sb_sample: Box<[[[[i32; SBLIMIT]; 18]; MAX_GRANULES + 1]; MAX_CHANNELS]>, // Move to heap
302    pub mdct_freq: Box<[[[i32; GRANULE_SIZE]; MAX_GRANULES]; MAX_CHANNELS]>, // Move to heap
303    pub resv_size: i32,
304    pub resv_max: i32,
305    pub l3loop: L3Loop,
306    pub mdct: Mdct,
307    pub subband: Subband,
308}
309
310impl ShineGlobalConfig {
311    /// Create a new global configuration
312    pub fn new() -> Self {
313        Self {
314            wave: PrivShineWave {
315                channels: 2,
316                samplerate: 44100,
317            },
318            mpeg: PrivShineMpeg {
319                version: 3, // MPEG_I = 3
320                layer: 1,   // LAYER_III = 1
321                granules_per_frame: 2,
322                mode: 1,
323                bitr: 128,
324                emph: 0,
325                padding: 0,
326                bits_per_frame: 0,
327                bits_per_slot: 8,
328                frac_slots_per_frame: 0.0,
329                slot_lag: 0.0,
330                whole_slots_per_frame: 0,
331                bitrate_index: 9,
332                samplerate_index: 0,
333                crc: 0,
334                ext: 0,
335                mode_ext: 0,
336                copyright: 0,
337                original: 1,
338            },
339            bs: BitstreamWriter::default(),
340            side_info: ShineSideInfo::default(),
341            sideinfo_len: 0,
342            mean_bits: 0,
343            ratio: ShinePsyRatio::default(),
344            scalefactor: Box::new(ShineScalefac::default()), // Allocate on heap
345            buffer: [std::ptr::null_mut(); MAX_CHANNELS],
346            pe: Box::new([[0.0; MAX_GRANULES]; MAX_CHANNELS]), // Allocate on heap
347            l3_enc: Box::new([[[0; GRANULE_SIZE]; MAX_GRANULES]; MAX_CHANNELS]), // Allocate on heap
348            l3_sb_sample: Box::new([[[[0; SBLIMIT]; 18]; MAX_GRANULES + 1]; MAX_CHANNELS]), // Allocate on heap
349            mdct_freq: Box::new([[[0; GRANULE_SIZE]; MAX_GRANULES]; MAX_CHANNELS]), // Allocate on heap
350            resv_size: 0,
351            resv_max: 0,
352            l3loop: L3Loop::default(),
353            mdct: Mdct::default(),
354            subband: Subband::default(),
355        }
356    }
357}
358
359impl Default for ShineGlobalConfig {
360    fn default() -> Self {
361        Self::new()
362    }
363}