1#![allow(dead_code)]
6
7use alloc::{vec, vec::Vec};
8
9use super::{
10 fp16_mul, get_cos_from_table, read_u16_be, CodecError, CodecResult, Fp16, FP16_ONE, FP16_SHIFT,
11 FP30_SHIFT,
12};
13
14#[derive(Debug, Clone)]
20pub struct Mp3BitstreamReader<'a> {
21 data: &'a [u8],
22 byte_pos: usize,
23 bit_pos: u8,
24 total_bits: usize,
25 bits_read: usize,
26}
27
28impl<'a> Mp3BitstreamReader<'a> {
29 pub fn new(data: &'a [u8]) -> Self {
31 let total_bits = data.len().saturating_mul(8);
32 Self {
33 data,
34 byte_pos: 0,
35 bit_pos: 0,
36 total_bits,
37 bits_read: 0,
38 }
39 }
40
41 pub fn read_bits(&mut self, count: u8) -> Option<u32> {
43 if count == 0 {
44 return Some(0);
45 }
46 if count > 32 {
47 return None;
48 }
49 if self.bits_read + count as usize > self.total_bits {
50 return None;
51 }
52
53 let mut result: u32 = 0;
54 let mut bits_left = count;
55
56 while bits_left > 0 {
57 if self.byte_pos >= self.data.len() {
58 return None;
59 }
60
61 let byte = self.data[self.byte_pos];
62 let available = 8 - self.bit_pos;
63 let to_read = bits_left.min(available);
64
65 let shift = available - to_read;
67 let mask = (1u32 << to_read) - 1;
68 let bits = ((byte >> shift) as u32) & mask;
69
70 result = (result << to_read) | bits;
71
72 self.bit_pos += to_read;
73 bits_left -= to_read;
74 self.bits_read += to_read as usize;
75
76 if self.bit_pos >= 8 {
77 self.bit_pos = 0;
78 self.byte_pos += 1;
79 }
80 }
81
82 Some(result)
83 }
84
85 pub fn read_bit(&mut self) -> Option<bool> {
87 self.read_bits(1).map(|v| v != 0)
88 }
89
90 pub fn has_bits(&self, count: usize) -> bool {
92 self.bits_read + count <= self.total_bits
93 }
94
95 pub fn position(&self) -> usize {
97 self.bits_read
98 }
99}
100
101const MP3_SYNC_MASK: u16 = 0xFFE0;
107const MP3_SYNC_WORD: u16 = 0xFFE0;
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub enum MpegVersion {
112 Mpeg1,
114 Mpeg2,
116 Mpeg25,
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq)]
122pub enum ChannelMode {
123 Stereo,
125 JointStereo,
127 DualChannel,
129 Mono,
131}
132
133impl ChannelMode {
134 pub fn num_channels(&self) -> u8 {
136 match self {
137 ChannelMode::Mono => 1,
138 _ => 2,
139 }
140 }
141}
142
143const MP3_BITRATE_TABLE: [u16; 15] = [
145 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,
146];
147
148const MP3_SAMPLE_RATE_TABLE: [u32; 3] = [44100, 48000, 32000];
150
151const MP3_SAMPLE_RATE_TABLE_V2: [u32; 3] = [22050, 24000, 16000];
153
154const MP3_SAMPLE_RATE_TABLE_V25: [u32; 3] = [11025, 12000, 8000];
156
157#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159pub struct Mp3FrameHeader {
160 pub version: MpegVersion,
162 pub bitrate: u16,
164 pub sample_rate: u32,
166 pub channel_mode: ChannelMode,
168 pub mode_extension: u8,
170 pub padding: bool,
172 pub crc_protected: bool,
174 pub frame_size: usize,
176 pub samples_per_frame: usize,
178}
179
180impl Mp3FrameHeader {
181 pub fn parse(header_bytes: &[u8]) -> CodecResult<Self> {
183 if header_bytes.len() < 4 {
184 return Err(CodecError::BufferTooShort);
185 }
186
187 let word = read_u16_be(header_bytes, 0).ok_or(CodecError::BufferTooShort)?;
188
189 if word & MP3_SYNC_MASK != MP3_SYNC_WORD {
191 return Err(CodecError::InvalidMagic);
192 }
193
194 let version_bits = (header_bytes[1] >> 3) & 0x03;
196 let version = match version_bits {
197 0 => MpegVersion::Mpeg25,
198 2 => MpegVersion::Mpeg2,
199 3 => MpegVersion::Mpeg1,
200 _ => return Err(CodecError::UnsupportedVersion),
201 };
202
203 let layer_bits = (header_bytes[1] >> 1) & 0x03;
205 if layer_bits != 1 {
206 return Err(CodecError::UnsupportedFeature);
208 }
209
210 let crc_protected = (header_bytes[1] & 0x01) == 0;
212
213 let bitrate_index = (header_bytes[2] >> 4) & 0x0F;
215 if bitrate_index == 0 || bitrate_index == 15 {
216 return Err(CodecError::InvalidHeader);
217 }
218 let bitrate = MP3_BITRATE_TABLE[bitrate_index as usize];
219
220 let sample_rate_index = (header_bytes[2] >> 2) & 0x03;
222 if sample_rate_index >= 3 {
223 return Err(CodecError::UnsupportedSampleRate);
224 }
225 let sample_rate = match version {
226 MpegVersion::Mpeg1 => MP3_SAMPLE_RATE_TABLE[sample_rate_index as usize],
227 MpegVersion::Mpeg2 => MP3_SAMPLE_RATE_TABLE_V2[sample_rate_index as usize],
228 MpegVersion::Mpeg25 => MP3_SAMPLE_RATE_TABLE_V25[sample_rate_index as usize],
229 };
230
231 let padding = (header_bytes[2] >> 1) & 0x01 != 0;
233
234 let channel_bits = (header_bytes[3] >> 6) & 0x03;
236 let channel_mode = match channel_bits {
237 0 => ChannelMode::Stereo,
238 1 => ChannelMode::JointStereo,
239 2 => ChannelMode::DualChannel,
240 3 => ChannelMode::Mono,
241 _ => unreachable!(),
242 };
243
244 let mode_extension = (header_bytes[3] >> 4) & 0x03;
246
247 let samples_per_frame = match version {
249 MpegVersion::Mpeg1 => 1152,
250 _ => 576,
251 };
252
253 let frame_size = if sample_rate > 0 {
256 let base = (144000u64).checked_mul(bitrate as u64).unwrap_or(0) / sample_rate as u64;
257 base as usize + if padding { 1 } else { 0 }
258 } else {
259 return Err(CodecError::UnsupportedSampleRate);
260 };
261
262 Ok(Mp3FrameHeader {
263 version,
264 bitrate,
265 sample_rate,
266 channel_mode,
267 mode_extension,
268 padding,
269 crc_protected,
270 frame_size,
271 samples_per_frame,
272 })
273 }
274}
275
276const SFB_LONG_COUNT: usize = 21;
282
283const SFB_SHORT_COUNT: usize = 12;
285
286#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
288pub struct Mp3Granule {
289 pub part2_3_length: u16,
291 pub big_values: u16,
293 pub global_gain: u16,
295 pub scalefac_compress: u16,
297 pub window_switching: bool,
299 pub block_type: u8,
301 pub mixed_block: bool,
303 pub table_select: [u8; 3],
305 pub subblock_gain: [u8; 3],
307 pub region0_count: u8,
309 pub region1_count: u8,
311 pub preflag: bool,
313 pub scalefac_scale: bool,
315 pub count1table_select: bool,
317}
318
319#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
321pub struct Mp3ChannelSideInfo {
322 pub scfsi: [bool; 4],
324 pub granules: [Mp3Granule; 2],
326}
327
328#[derive(Debug, Clone, PartialEq, Eq)]
330pub struct Mp3SideInfo {
331 pub main_data_begin: u16,
333 pub channels: Vec<Mp3ChannelSideInfo>,
335}
336
337impl Mp3SideInfo {
338 pub fn parse(
340 data: &[u8],
341 offset: usize,
342 channel_mode: ChannelMode,
343 ) -> CodecResult<(Self, usize)> {
344 let num_channels = channel_mode.num_channels() as usize;
345 let mut reader =
346 Mp3BitstreamReader::new(data.get(offset..).ok_or(CodecError::BufferTooShort)?);
347
348 let main_data_begin = reader.read_bits(9).ok_or(CodecError::EndOfStream)? as u16;
349
350 if num_channels == 1 {
352 let _private = reader.read_bits(5);
353 } else {
354 let _private = reader.read_bits(3);
355 }
356
357 let mut channels = Vec::with_capacity(num_channels);
358
359 for _ in 0..num_channels {
361 let mut ch_info = Mp3ChannelSideInfo::default();
362 for band in 0..4 {
363 ch_info.scfsi[band] = reader.read_bit().ok_or(CodecError::EndOfStream)?;
364 }
365 channels.push(ch_info);
366 }
367
368 for gr in 0..2 {
370 for channel in channels.iter_mut().take(num_channels) {
371 let g = &mut channel.granules[gr];
372
373 g.part2_3_length = reader.read_bits(12).ok_or(CodecError::EndOfStream)? as u16;
374 g.big_values = reader.read_bits(9).ok_or(CodecError::EndOfStream)? as u16;
375 g.global_gain = reader.read_bits(8).ok_or(CodecError::EndOfStream)? as u16;
376 g.scalefac_compress = reader.read_bits(4).ok_or(CodecError::EndOfStream)? as u16;
377 g.window_switching = reader.read_bit().ok_or(CodecError::EndOfStream)?;
378
379 if g.window_switching {
380 g.block_type = reader.read_bits(2).ok_or(CodecError::EndOfStream)? as u8;
381 g.mixed_block = reader.read_bit().ok_or(CodecError::EndOfStream)?;
382
383 for i in 0..2 {
384 g.table_select[i] =
385 reader.read_bits(5).ok_or(CodecError::EndOfStream)? as u8;
386 }
387
388 for i in 0..3 {
389 g.subblock_gain[i] =
390 reader.read_bits(3).ok_or(CodecError::EndOfStream)? as u8;
391 }
392
393 if g.block_type == 2 && !g.mixed_block {
395 g.region0_count = 8;
396 } else {
397 g.region0_count = 7;
398 }
399 g.region1_count = 36; } else {
401 for i in 0..3 {
402 g.table_select[i] =
403 reader.read_bits(5).ok_or(CodecError::EndOfStream)? as u8;
404 }
405 g.region0_count = reader.read_bits(4).ok_or(CodecError::EndOfStream)? as u8;
406 g.region1_count = reader.read_bits(3).ok_or(CodecError::EndOfStream)? as u8;
407 }
408
409 g.preflag = reader.read_bit().ok_or(CodecError::EndOfStream)?;
410 g.scalefac_scale = reader.read_bit().ok_or(CodecError::EndOfStream)?;
411 g.count1table_select = reader.read_bit().ok_or(CodecError::EndOfStream)?;
412 }
413 }
414
415 let bytes_consumed = reader.position().div_ceil(8);
416
417 Ok((
418 Mp3SideInfo {
419 main_data_begin,
420 channels,
421 },
422 bytes_consumed,
423 ))
424 }
425}
426
427#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
435pub struct Mp3HuffEntry {
436 pub x: i8,
438 pub y: i8,
440 pub hlen: u8,
442}
443
444#[derive(Debug, Clone, PartialEq, Eq)]
446pub struct Mp3HuffTable {
447 pub table_id: u8,
449 pub max_val: u8,
451 pub linbits: u8,
453 pub entries: Vec<Mp3HuffEntry>,
455}
456
457const MP3_LINBITS_TABLE: [u8; 32] = [
460 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 8, 10, 13, 4, 5, 6, 7, 8, 9, 11, 13, ];
463
464pub fn mp3_huffman_decode_pair(
469 reader: &mut Mp3BitstreamReader<'_>,
470 table_id: u8,
471) -> CodecResult<(i32, i32)> {
472 if table_id == 0 {
473 return Ok((0, 0));
474 }
475
476 let linbits = if (table_id as usize) < MP3_LINBITS_TABLE.len() {
480 MP3_LINBITS_TABLE[table_id as usize]
481 } else {
482 0
483 };
484
485 let mut x = reader.read_bits(4).ok_or(CodecError::EndOfStream)? as i32;
488 let mut y = reader.read_bits(4).ok_or(CodecError::EndOfStream)? as i32;
489
490 if linbits > 0 {
492 if x >= 15 {
493 let ext = reader.read_bits(linbits).ok_or(CodecError::EndOfStream)? as i32;
494 x += ext;
495 }
496 if y >= 15 {
497 let ext = reader.read_bits(linbits).ok_or(CodecError::EndOfStream)? as i32;
498 y += ext;
499 }
500 }
501
502 if x != 0 && reader.read_bit().ok_or(CodecError::EndOfStream)? {
504 x = -x;
505 }
506 if y != 0 && reader.read_bit().ok_or(CodecError::EndOfStream)? {
507 y = -y;
508 }
509
510 Ok((x, y))
511}
512
513pub fn mp3_huffman_decode_quad(
515 reader: &mut Mp3BitstreamReader<'_>,
516 table_b: bool,
517) -> CodecResult<(i32, i32, i32, i32)> {
518 if table_b {
519 let v = if reader.read_bit().ok_or(CodecError::EndOfStream)? {
521 1
522 } else {
523 0
524 };
525 let w = if reader.read_bit().ok_or(CodecError::EndOfStream)? {
526 1
527 } else {
528 0
529 };
530 let x = if reader.read_bit().ok_or(CodecError::EndOfStream)? {
531 1
532 } else {
533 0
534 };
535 let y = if reader.read_bit().ok_or(CodecError::EndOfStream)? {
536 1
537 } else {
538 0
539 };
540
541 let v = if v != 0 && reader.read_bit().ok_or(CodecError::EndOfStream)? {
543 -1
544 } else {
545 v
546 };
547 let w = if w != 0 && reader.read_bit().ok_or(CodecError::EndOfStream)? {
548 -1
549 } else {
550 w
551 };
552 let x = if x != 0 && reader.read_bit().ok_or(CodecError::EndOfStream)? {
553 -1
554 } else {
555 x
556 };
557 let y = if y != 0 && reader.read_bit().ok_or(CodecError::EndOfStream)? {
558 -1
559 } else {
560 y
561 };
562
563 Ok((v, w, x, y))
564 } else {
565 let code = reader.read_bits(4).ok_or(CodecError::EndOfStream)?;
567 let v = ((code >> 3) & 1) as i32;
568 let w = ((code >> 2) & 1) as i32;
569 let x = ((code >> 1) & 1) as i32;
570 let y = (code & 1) as i32;
571 Ok((v, w, x, y))
572 }
573}
574
575const REQUANT_POW43_TABLE: [Fp16; 256] = {
589 let mut table = [0i32; 256];
590 let mut i = 0u32;
594 while i < 256 {
595 if i == 0 {
596 table[0] = 0;
597 } else if i == 1 {
598 table[1] = FP16_ONE;
599 } else {
600 let x = i;
603 let mut guess = x;
604 if x > 27 {
606 guess = x / 3;
607 }
608 if guess == 0 {
609 guess = 1;
610 }
611
612 let mut iter = 0;
614 while iter < 6 {
615 let g2 = match guess.checked_mul(guess) {
616 Some(v) if v > 0 => v,
617 _ => {
618 guess = 1;
619 iter += 1;
620 continue;
621 }
622 };
623 let new_guess = (2 * guess + x / g2) / 3;
624 if new_guess == guess {
625 iter = 6; } else {
627 guess = new_guess;
628 if guess == 0 {
629 guess = 1;
630 }
631 }
632 iter += 1;
633 }
634 let val = match x.checked_mul(guess) {
636 Some(v) => v,
637 None => u32::MAX / 2,
638 };
639 table[i as usize] = (val as i32) << FP16_SHIFT;
640 }
641 i += 1;
642 }
643 table
644};
645
646fn pow2_quarter(exponent: i32) -> Fp16 {
651 const POW2_FRAC: [Fp16; 4] = [
655 0x0001_0000, 0x0001_306F, 0x0001_6A0A, 0x0001_AE8A, ];
660
661 let int_part = exponent >> 2; let frac_part = (exponent & 3) as usize; let base = POW2_FRAC[frac_part];
665
666 if (0..16).contains(&int_part) {
667 base << int_part
668 } else if int_part < 0 && int_part > -16 {
669 base >> (-int_part)
670 } else if int_part >= 16 {
671 i32::MAX } else {
673 0 }
675}
676
677pub fn mp3_requantize(
681 is_val: i32,
682 global_gain: u16,
683 scalefac: u8,
684 scalefac_scale: bool,
685 subblock_gain: u8,
686 preflag: bool,
687 _sfb_index: usize,
688) -> Fp16 {
689 if is_val == 0 {
690 return 0;
691 }
692
693 let sign = if is_val < 0 { -1i32 } else { 1i32 };
694 let abs_val = is_val.unsigned_abs() as usize;
695
696 let pow43 = if abs_val < 256 {
698 REQUANT_POW43_TABLE[abs_val]
699 } else {
700 let base = (abs_val & 0xFF).min(255);
703 let scale_shift = ((abs_val >> 8) as i32).min(15);
704 let base_pow = REQUANT_POW43_TABLE[base];
705 base_pow.saturating_mul(1 + scale_shift)
707 };
708
709 let sf_shift: i32 = if scalefac_scale { 2 } else { 1 };
711 let pretab_val: i32 = if preflag {
712 0
714 } else {
715 0
716 };
717
718 let gain_exp = (global_gain as i32)
719 - 210
720 - sf_shift * (scalefac as i32 + pretab_val)
721 - 8 * subblock_gain as i32;
722
723 let gain = pow2_quarter(gain_exp);
724
725 let result = fp16_mul(pow43, gain);
727 if sign < 0 {
728 -result
729 } else {
730 result
731 }
732}
733
734pub fn mp3_ms_stereo(mid: &mut [Fp16], side: &mut [Fp16]) {
747 const INV_SQRT2_FP16: Fp16 = 46341;
749
750 let len = mid.len().min(side.len());
751 for i in 0..len {
752 let m = mid[i];
753 let s = side[i];
754 let l = fp16_mul(m.saturating_add(s), INV_SQRT2_FP16);
755 let r = fp16_mul(m.saturating_sub(s), INV_SQRT2_FP16);
756 mid[i] = l;
757 side[i] = r;
758 }
759}
760
761pub fn mp3_intensity_stereo(left: &mut [Fp16], right: &mut [Fp16], is_pos: u8) {
766 if is_pos >= 7 {
767 return; }
769
770 const IS_RATIOS: [Fp16; 7] = [
774 0x0000_0000, 0x0000_4B65, 0x0000_93CD, 0x0001_0000, 0x0001_B505, 0x0003_A828, 0x7FFF_FFFF, ];
782
783 let ratio = IS_RATIOS[is_pos as usize];
784
785 let one_plus_ratio = FP16_ONE.saturating_add(ratio);
788 if one_plus_ratio == 0 {
789 return;
790 }
791
792 let len = left.len().min(right.len());
793 for i in 0..len {
794 let source = left[i];
795 let l = ((source as i64) * (FP16_ONE as i64) / (one_plus_ratio as i64)) as Fp16;
797 let r = ((source as i64) * (ratio as i64) / (one_plus_ratio as i64)) as Fp16;
799 left[i] = l;
800 right[i] = r;
801 }
802}
803
804pub fn mp3_imdct_36(input: &[Fp16; 18], output: &mut [Fp16; 36]) {
813 for (n, out) in output.iter_mut().enumerate() {
822 let mut sum: i64 = 0;
823 for (k, &inp) in input.iter().enumerate() {
824 let angle_num = (2 * n as u64 + 19) * (2 * k as u64 + 1);
827 let table_idx = ((angle_num * 128) / 72) as usize;
829
830 let cos_val = get_cos_from_table(table_idx);
832
833 sum += (inp as i64) * (cos_val as i64);
834 }
835
836 *out = (sum >> FP30_SHIFT) as Fp16;
838 }
839}
840
841pub fn mp3_imdct_12(input: &[Fp16; 6], output: &mut [Fp16; 12]) {
845 for (n, out) in output.iter_mut().enumerate() {
846 let mut sum: i64 = 0;
847 for (k, &inp) in input.iter().enumerate() {
848 let angle_num = (2 * n as u64 + 7) * (2 * k as u64 + 1);
851 let table_idx = ((angle_num * 128) / 24) as usize;
852
853 let cos_val = get_cos_from_table(table_idx);
854 sum += (inp as i64) * (cos_val as i64);
855 }
856
857 *out = (sum >> FP30_SHIFT) as Fp16;
858 }
859}
860
861const MP3_NUM_SUBBANDS: usize = 32;
867
868const MP3_SYNTH_WINDOW: [Fp16; 64] = {
874 let mut window = [0i32; 64];
875 let mut i = 0usize;
881 while i < 64 {
882 let x = i as i64;
886 let n = 64i64;
887 let numer = 4 * x * (n - 1 - x);
889 let denom = (n - 1) * (n - 1);
890 let val = (numer * (FP16_ONE as i64)) / denom;
891 window[i] = val as i32;
892 i += 1;
893 }
894 window
895};
896
897#[derive(Debug, Clone)]
899pub struct Mp3SynthesisFilter {
900 v_buffer: Vec<Fp16>,
902 v_offset: usize,
904}
905
906impl Default for Mp3SynthesisFilter {
907 fn default() -> Self {
908 Self::new()
909 }
910}
911
912impl Mp3SynthesisFilter {
913 pub fn new() -> Self {
915 Self {
916 v_buffer: vec![0i32; 1024],
917 v_offset: 0,
918 }
919 }
920
921 pub fn synthesize(&mut self, subband_samples: &[Fp16; 32], output: &mut [i16; 32]) {
926 if self.v_offset < 64 {
928 self.v_offset = 960;
929 } else {
930 self.v_offset -= 64;
931 }
932
933 for i in 0..64 {
936 let mut sum: i64 = 0;
937 for (k, &sample) in subband_samples.iter().enumerate() {
938 let angle_num = ((2 * i + 33) * (2 * k + 1)) as u64;
939 let table_idx = ((angle_num * 128) / 64) as usize;
940 let cos_val = get_cos_from_table(table_idx);
941 sum += (sample as i64) * (cos_val as i64);
942 }
943 let idx = (self.v_offset + i) % 1024;
944 self.v_buffer[idx] = (sum >> FP30_SHIFT) as Fp16;
945 }
946
947 for (j, out) in output.iter_mut().enumerate() {
950 let mut sum: i64 = 0;
951
952 for i in 0..16 {
954 let v_idx = (self.v_offset + 64 * i + j) % 1024;
955 let w_idx = (i * 32 + j) % 64;
956
957 let v_val = self.v_buffer[v_idx] as i64;
958 let w_val = MP3_SYNTH_WINDOW[w_idx] as i64;
959 sum += v_val * w_val;
960 }
961
962 let sample = (sum >> FP16_SHIFT) as i32;
964 *out = if sample > i16::MAX as i32 {
965 i16::MAX
966 } else if sample < i16::MIN as i32 {
967 i16::MIN
968 } else {
969 sample as i16
970 };
971 }
972 }
973}
974
975#[derive(Debug)]
981pub struct Mp3Decoder {
982 filters: Vec<Mp3SynthesisFilter>,
984 pub output_buffer: Vec<i16>,
986 bit_reservoir: Vec<u8>,
988 pub frames_decoded: u64,
990 pub last_header: Option<Mp3FrameHeader>,
992}
993
994impl Default for Mp3Decoder {
995 fn default() -> Self {
996 Self::new()
997 }
998}
999
1000impl Mp3Decoder {
1001 pub fn new() -> Self {
1003 Self {
1004 filters: vec![Mp3SynthesisFilter::new(), Mp3SynthesisFilter::new()],
1005 output_buffer: Vec::new(),
1006 bit_reservoir: Vec::new(),
1007 frames_decoded: 0,
1008 last_header: None,
1009 }
1010 }
1011
1012 pub fn find_sync(data: &[u8], start: usize) -> Option<usize> {
1016 let mut pos = start;
1017 while pos + 1 < data.len() {
1018 if data[pos] == 0xFF && (data[pos + 1] & 0xE0) == 0xE0 {
1019 if pos + 4 <= data.len() && Mp3FrameHeader::parse(&data[pos..pos + 4]).is_ok() {
1021 return Some(pos);
1022 }
1023 }
1024 pos += 1;
1025 }
1026 None
1027 }
1028
1029 pub fn decode_frame(&mut self, data: &[u8]) -> CodecResult<usize> {
1033 if data.len() < 4 {
1034 return Err(CodecError::BufferTooShort);
1035 }
1036
1037 let header = Mp3FrameHeader::parse(data)?;
1038 let num_channels = header.channel_mode.num_channels() as usize;
1039
1040 if header.frame_size > data.len() {
1041 return Err(CodecError::BufferTooShort);
1042 }
1043
1044 let side_info_offset = if header.crc_protected { 6 } else { 4 };
1046
1047 let (_side_info, side_info_size) =
1049 Mp3SideInfo::parse(data, side_info_offset, header.channel_mode)?;
1050
1051 let main_data_start = side_info_offset + side_info_size;
1053
1054 if main_data_start < header.frame_size {
1056 self.bit_reservoir
1057 .extend_from_slice(&data[main_data_start..header.frame_size]);
1058 }
1059
1060 let samples_per_frame = header.samples_per_frame;
1071 let total_samples = samples_per_frame * num_channels;
1072 self.output_buffer.resize(total_samples, 0i16);
1073
1074 let max_reservoir = 511;
1076 if self.bit_reservoir.len() > max_reservoir {
1077 let excess = self.bit_reservoir.len() - max_reservoir;
1078 self.bit_reservoir.drain(..excess);
1079 }
1080
1081 self.last_header = Some(header);
1082 self.frames_decoded += 1;
1083
1084 Ok(header.frame_size)
1085 }
1086
1087 pub fn decode_all(&mut self, data: &[u8]) -> CodecResult<(u32, u8, Vec<i16>)> {
1091 let mut all_pcm = Vec::new();
1092 let mut pos = 0;
1093 let mut sample_rate = 0u32;
1094 let mut channels = 0u8;
1095
1096 if data.len() >= 10 && &data[0..3] == b"ID3" {
1098 let tag_size = ((data[6] as usize & 0x7F) << 21)
1099 | ((data[7] as usize & 0x7F) << 14)
1100 | ((data[8] as usize & 0x7F) << 7)
1101 | (data[9] as usize & 0x7F);
1102 pos = 10 + tag_size;
1103 }
1104
1105 while let Some(sync_pos) = Self::find_sync(data, pos) {
1106 pos = sync_pos;
1107
1108 match self.decode_frame(&data[pos..]) {
1109 Ok(consumed) => {
1110 if let Some(ref hdr) = self.last_header {
1111 sample_rate = hdr.sample_rate;
1112 channels = hdr.channel_mode.num_channels();
1113 }
1114 all_pcm.extend_from_slice(&self.output_buffer);
1115 pos += consumed;
1116 }
1117 Err(CodecError::BufferTooShort) => break,
1118 Err(_) => {
1119 pos += 1; }
1121 }
1122 }
1123
1124 if sample_rate == 0 {
1125 return Err(CodecError::InvalidHeader);
1126 }
1127
1128 Ok((sample_rate, channels, all_pcm))
1129 }
1130
1131 pub fn output(&self) -> &[i16] {
1133 &self.output_buffer
1134 }
1135
1136 pub fn sample_rate(&self) -> Option<u32> {
1138 self.last_header.map(|h| h.sample_rate)
1139 }
1140
1141 pub fn channels(&self) -> Option<u8> {
1143 self.last_header.map(|h| h.channel_mode.num_channels())
1144 }
1145}
1146
1147#[cfg(test)]
1148mod tests {
1149 #[allow(unused_imports)]
1150 use alloc::vec;
1151
1152 use super::*;
1153
1154 #[test]
1155 fn test_mp3_bitstream_reader_msb() {
1156 let data = [0xA5u8];
1157 let mut reader = Mp3BitstreamReader::new(&data);
1158 let val = reader.read_bits(4).unwrap();
1159 assert_eq!(val, 10);
1160 let val2 = reader.read_bits(4).unwrap();
1161 assert_eq!(val2, 5);
1162 }
1163
1164 #[test]
1167 fn test_mp3_frame_header_parse() {
1168 let header = [0xFF, 0xFB, 0x90, 0x00];
1169 let parsed = Mp3FrameHeader::parse(&header).unwrap();
1170 assert_eq!(parsed.version, MpegVersion::Mpeg1);
1171 assert_eq!(parsed.bitrate, 128);
1172 assert_eq!(parsed.sample_rate, 44100);
1173 assert_eq!(parsed.channel_mode, ChannelMode::Stereo);
1174 assert_eq!(parsed.samples_per_frame, 1152);
1175 assert!(!parsed.crc_protected);
1176 }
1177
1178 #[test]
1179 fn test_mp3_frame_header_bad_sync() {
1180 let header = [0x00, 0x00, 0x00, 0x00];
1181 let result = Mp3FrameHeader::parse(&header);
1182 assert_eq!(result.unwrap_err(), CodecError::InvalidMagic);
1183 }
1184
1185 #[test]
1186 fn test_mp3_frame_header_mono() {
1187 let header = [0xFF, 0xFB, 0x50, 0xC0];
1188 let parsed = Mp3FrameHeader::parse(&header).unwrap();
1189 assert_eq!(parsed.channel_mode, ChannelMode::Mono);
1190 assert_eq!(parsed.channel_mode.num_channels(), 1);
1191 }
1192
1193 #[test]
1194 fn test_mp3_frame_size_calculation() {
1195 let header = [0xFF, 0xFB, 0x90, 0x00];
1196 let parsed = Mp3FrameHeader::parse(&header).unwrap();
1197 assert_eq!(parsed.frame_size, 417);
1198 }
1199
1200 #[test]
1203 fn test_mp3_ms_stereo() {
1204 let mut mid = [FP16_ONE, FP16_ONE / 2, 0];
1205 let mut side = [0, FP16_ONE / 2, FP16_ONE];
1206
1207 mp3_ms_stereo(&mut mid, &mut side);
1208
1209 assert!(mid[0] > 0);
1210 assert!(side[0] > 0);
1211 }
1212
1213 #[test]
1216 fn test_imdct_12_zeros() {
1217 let input = [0i32; 6];
1218 let mut output = [0i32; 12];
1219 mp3_imdct_12(&input, &mut output);
1220 for val in &output {
1221 assert_eq!(*val, 0);
1222 }
1223 }
1224
1225 #[test]
1226 fn test_imdct_36_zeros() {
1227 let input = [0i32; 18];
1228 let mut output = [0i32; 36];
1229 mp3_imdct_36(&input, &mut output);
1230 for val in &output {
1231 assert_eq!(*val, 0);
1232 }
1233 }
1234
1235 #[test]
1238 fn test_synthesis_filter_silence() {
1239 let mut filter = Mp3SynthesisFilter::new();
1240 let input = [0i32; 32];
1241 let mut output = [0i16; 32];
1242 filter.synthesize(&input, &mut output);
1243 for val in &output {
1244 assert_eq!(*val, 0);
1245 }
1246 }
1247
1248 #[test]
1251 fn test_pow2_quarter() {
1252 assert_eq!(pow2_quarter(0), FP16_ONE);
1253 assert_eq!(pow2_quarter(4), FP16_ONE * 2);
1254 assert_eq!(pow2_quarter(8), FP16_ONE * 4);
1255 }
1256
1257 #[test]
1258 fn test_requantize_zero() {
1259 let result = mp3_requantize(0, 210, 0, false, 0, false, 0);
1260 assert_eq!(result, 0);
1261 }
1262
1263 #[test]
1266 fn test_mp3_find_sync() {
1267 let mut data = vec![0u8; 100];
1268 data[10] = 0xFF;
1269 data[11] = 0xFB;
1270 data[12] = 0x90;
1271 data[13] = 0x00;
1272
1273 let pos = Mp3Decoder::find_sync(&data, 0);
1274 assert_eq!(pos, Some(10));
1275 }
1276
1277 #[test]
1278 fn test_mp3_find_sync_no_match() {
1279 let data = vec![0u8; 100];
1280 let pos = Mp3Decoder::find_sync(&data, 0);
1281 assert_eq!(pos, None);
1282 }
1283
1284 #[test]
1287 fn test_mp3_decoder_id3_skip() {
1288 let mut decoder = Mp3Decoder::new();
1289 let mut data = vec![0u8; 200];
1290 data[0] = b'I';
1291 data[1] = b'D';
1292 data[2] = b'3';
1293 data[3] = 4;
1294 data[4] = 0;
1295 data[5] = 0;
1296 data[6] = 0;
1297 data[7] = 0;
1298 data[8] = 0;
1299 data[9] = 10;
1300 let result = decoder.decode_all(&data);
1301 assert!(result.is_err());
1302 }
1303}