1#![allow(dead_code)]
6
7use alloc::{string::String, vec, vec::Vec};
8
9use super::{
10 fp16_from_i32, fp16_mul, fp30_mul, fp30_to_fp16, ilog, read_u32_le, read_u64_le, CodecError,
11 CodecResult, Fp16, Fp30, FP16_SHIFT, FP30_ONE, FP30_SHIFT, MDCT_COS_TABLE_64,
12};
13
14const OGG_CAPTURE_PATTERN: [u8; 4] = [b'O', b'g', b'g', b'S'];
20
21const OGG_VERSION: u8 = 0;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub struct OggHeaderType(u8);
27
28impl OggHeaderType {
29 pub const CONTINUATION: u8 = 0x01;
31 pub const BOS: u8 = 0x02;
33 pub const EOS: u8 = 0x04;
35
36 pub fn new(val: u8) -> Self {
38 Self(val)
39 }
40
41 pub fn is_continuation(&self) -> bool {
43 self.0 & Self::CONTINUATION != 0
44 }
45
46 pub fn is_bos(&self) -> bool {
48 self.0 & Self::BOS != 0
49 }
50
51 pub fn is_eos(&self) -> bool {
53 self.0 & Self::EOS != 0
54 }
55}
56
57#[derive(Debug, Clone)]
59pub struct OggPage {
60 pub version: u8,
62 pub header_type: OggHeaderType,
64 pub granule_position: u64,
66 pub serial_number: u32,
68 pub page_sequence: u32,
70 pub crc_checksum: u32,
72 pub num_segments: u8,
74 pub segment_table: Vec<u8>,
76 pub data_size: usize,
78 pub data_offset: usize,
80 pub total_size: usize,
82}
83
84const OGG_CRC_TABLE: [u32; 256] = {
86 let mut table = [0u32; 256];
87 let mut i = 0u32;
88 while i < 256 {
89 let mut crc = i << 24;
90 let mut j = 0;
91 while j < 8 {
92 if crc & 0x80000000 != 0 {
93 crc = (crc << 1) ^ 0x04C11DB7;
94 } else {
95 crc <<= 1;
96 }
97 j += 1;
98 }
99 table[i as usize] = crc;
100 i += 1;
101 }
102 table
103};
104
105fn ogg_crc32(data: &[u8]) -> u32 {
107 let mut crc: u32 = 0;
108 for &byte in data {
109 let index = ((crc >> 24) ^ (byte as u32)) & 0xFF;
110 crc = (crc << 8) ^ OGG_CRC_TABLE[index as usize];
111 }
112 crc
113}
114
115impl OggPage {
116 const MIN_HEADER_SIZE: usize = 27;
118
119 pub fn parse(data: &[u8], offset: usize) -> CodecResult<OggPage> {
121 if offset + Self::MIN_HEADER_SIZE > data.len() {
122 return Err(CodecError::BufferTooShort);
123 }
124
125 if data[offset..offset + 4] != OGG_CAPTURE_PATTERN {
127 return Err(CodecError::InvalidMagic);
128 }
129
130 let version = data[offset + 4];
131 if version != OGG_VERSION {
132 return Err(CodecError::UnsupportedVersion);
133 }
134
135 let header_type = OggHeaderType::new(data[offset + 5]);
136 let granule_position = read_u64_le(data, offset + 6).ok_or(CodecError::BufferTooShort)?;
137 let serial_number = read_u32_le(data, offset + 14).ok_or(CodecError::BufferTooShort)?;
138 let page_sequence = read_u32_le(data, offset + 18).ok_or(CodecError::BufferTooShort)?;
139 let crc_checksum = read_u32_le(data, offset + 22).ok_or(CodecError::BufferTooShort)?;
140 let num_segments = data[offset + 26];
141
142 let seg_table_offset = offset + Self::MIN_HEADER_SIZE;
143 let seg_table_end = seg_table_offset + num_segments as usize;
144 if seg_table_end > data.len() {
145 return Err(CodecError::BufferTooShort);
146 }
147
148 let segment_table = data[seg_table_offset..seg_table_end].to_vec();
149 let data_size: usize = segment_table.iter().map(|&s| s as usize).sum();
150 let data_offset = seg_table_end;
151 let total_size = Self::MIN_HEADER_SIZE + num_segments as usize + data_size;
152
153 if offset + total_size > data.len() {
154 return Err(CodecError::BufferTooShort);
155 }
156
157 Ok(OggPage {
158 version,
159 header_type,
160 granule_position,
161 serial_number,
162 page_sequence,
163 crc_checksum,
164 num_segments,
165 segment_table,
166 data_size,
167 data_offset,
168 total_size,
169 })
170 }
171
172 pub fn verify_crc(&self, data: &[u8], page_offset: usize) -> bool {
174 if page_offset + self.total_size > data.len() {
175 return false;
176 }
177
178 let page_data = &data[page_offset..page_offset + self.total_size];
180 let mut check_buf = Vec::from(page_data);
181 check_buf[22] = 0;
183 check_buf[23] = 0;
184 check_buf[24] = 0;
185 check_buf[25] = 0;
186
187 let computed = ogg_crc32(&check_buf);
188 computed == self.crc_checksum
189 }
190
191 pub fn extract_packets(&self, data: &[u8], _page_offset: usize) -> Vec<Vec<u8>> {
193 let mut packets = Vec::new();
194 let mut current_packet = Vec::new();
195 let mut seg_data_pos = self.data_offset;
196
197 for &seg_size in &self.segment_table {
198 let end = (seg_data_pos + seg_size as usize).min(data.len());
199 if seg_data_pos < data.len() {
200 current_packet.extend_from_slice(&data[seg_data_pos..end]);
201 }
202 seg_data_pos = end;
203
204 if seg_size < 255 && (!current_packet.is_empty() || seg_size == 0) {
206 packets.push(core::mem::take(&mut current_packet));
207 }
208 }
209
210 if !current_packet.is_empty() {
213 packets.push(current_packet);
214 }
215
216 packets
217 }
218}
219
220#[derive(Debug, Clone)]
222pub struct OggDemuxer {
223 pub serial_numbers: Vec<u32>,
225 pub position: usize,
227}
228
229impl Default for OggDemuxer {
230 fn default() -> Self {
231 Self::new()
232 }
233}
234
235impl OggDemuxer {
236 pub fn new() -> Self {
238 Self {
239 serial_numbers: Vec::new(),
240 position: 0,
241 }
242 }
243
244 pub fn next_page(&mut self, data: &[u8]) -> CodecResult<OggPage> {
246 let page = OggPage::parse(data, self.position)?;
247
248 if page.header_type.is_bos() && !self.serial_numbers.contains(&page.serial_number) {
250 self.serial_numbers.push(page.serial_number);
251 }
252
253 self.position += page.total_size;
254 Ok(page)
255 }
256
257 pub fn reset(&mut self) {
259 self.position = 0;
260 self.serial_numbers.clear();
261 }
262
263 pub fn find_sync(&mut self, data: &[u8]) -> Option<usize> {
265 while self.position + 4 <= data.len() {
266 if data[self.position..self.position + 4] == OGG_CAPTURE_PATTERN {
267 return Some(self.position);
268 }
269 self.position += 1;
270 }
271 None
272 }
273}
274
275const VORBIS_IDENTIFICATION_HEADER: u8 = 1;
281const VORBIS_COMMENT_HEADER: u8 = 3;
282const VORBIS_SETUP_HEADER: u8 = 5;
283
284const VORBIS_MAGIC: [u8; 6] = [b'v', b'o', b'r', b'b', b'i', b's'];
286
287#[derive(Debug, Clone, PartialEq, Eq)]
289pub struct VorbisIdentHeader {
290 pub version: u32,
292 pub channels: u8,
294 pub sample_rate: u32,
296 pub bitrate_max: i32,
298 pub bitrate_nominal: i32,
300 pub bitrate_min: i32,
302 pub blocksize_0: u8,
304 pub blocksize_1: u8,
306}
307
308impl VorbisIdentHeader {
309 pub fn parse(packet: &[u8]) -> CodecResult<Self> {
311 if packet.len() < 30 {
314 return Err(CodecError::BufferTooShort);
315 }
316
317 if packet[0] != VORBIS_IDENTIFICATION_HEADER {
318 return Err(CodecError::InvalidHeader);
319 }
320
321 if packet[1..7] != VORBIS_MAGIC {
322 return Err(CodecError::InvalidMagic);
323 }
324
325 let version = read_u32_le(packet, 7).ok_or(CodecError::BufferTooShort)?;
326 if version != 0 {
327 return Err(CodecError::UnsupportedVersion);
328 }
329
330 let channels = packet[11];
331 if channels == 0 {
332 return Err(CodecError::UnsupportedChannels);
333 }
334
335 let sample_rate = read_u32_le(packet, 12).ok_or(CodecError::BufferTooShort)?;
336 if sample_rate == 0 {
337 return Err(CodecError::UnsupportedSampleRate);
338 }
339
340 let bitrate_max = read_u32_le(packet, 16).ok_or(CodecError::BufferTooShort)? as i32;
341 let bitrate_nominal = read_u32_le(packet, 20).ok_or(CodecError::BufferTooShort)? as i32;
342 let bitrate_min = read_u32_le(packet, 24).ok_or(CodecError::BufferTooShort)? as i32;
343
344 let blocksizes_byte = packet[28];
345 let blocksize_0 = blocksizes_byte & 0x0F;
346 let blocksize_1 = (blocksizes_byte >> 4) & 0x0F;
347
348 if !(6..=13).contains(&blocksize_0) || !(6..=13).contains(&blocksize_1) {
350 return Err(CodecError::InvalidHeader);
351 }
352
353 if blocksize_0 > blocksize_1 {
355 return Err(CodecError::InvalidHeader);
356 }
357
358 if packet.len() > 29 && packet[29] & 0x01 == 0 {
360 return Err(CodecError::InvalidHeader);
361 }
362
363 Ok(VorbisIdentHeader {
364 version,
365 channels,
366 sample_rate,
367 bitrate_max,
368 bitrate_nominal,
369 bitrate_min,
370 blocksize_0,
371 blocksize_1,
372 })
373 }
374
375 pub fn short_blocksize(&self) -> usize {
377 1usize << (self.blocksize_0 as usize)
378 }
379
380 pub fn long_blocksize(&self) -> usize {
382 1usize << (self.blocksize_1 as usize)
383 }
384}
385
386#[derive(Debug, Clone, PartialEq, Eq)]
388pub struct VorbisCommentHeader {
389 pub vendor: String,
391 pub comments: Vec<String>,
393}
394
395impl VorbisCommentHeader {
396 pub fn parse(packet: &[u8]) -> CodecResult<Self> {
398 if packet.len() < 7 {
399 return Err(CodecError::BufferTooShort);
400 }
401
402 if packet[0] != VORBIS_COMMENT_HEADER {
403 return Err(CodecError::InvalidHeader);
404 }
405
406 if packet[1..7] != VORBIS_MAGIC {
407 return Err(CodecError::InvalidMagic);
408 }
409
410 let mut pos = 7;
411
412 let vendor_len = read_u32_le(packet, pos).ok_or(CodecError::BufferTooShort)? as usize;
414 pos += 4;
415 if pos + vendor_len > packet.len() {
416 return Err(CodecError::BufferTooShort);
417 }
418 let vendor = String::from_utf8_lossy(&packet[pos..pos + vendor_len]).into_owned();
419 pos += vendor_len;
420
421 let comment_count = read_u32_le(packet, pos).ok_or(CodecError::BufferTooShort)? as usize;
423 pos += 4;
424
425 let mut comments = Vec::with_capacity(comment_count.min(256));
426 for _ in 0..comment_count.min(256) {
427 let comment_len = read_u32_le(packet, pos).ok_or(CodecError::BufferTooShort)? as usize;
428 pos += 4;
429 if pos + comment_len > packet.len() {
430 return Err(CodecError::BufferTooShort);
431 }
432 let comment = String::from_utf8_lossy(&packet[pos..pos + comment_len]).into_owned();
433 comments.push(comment);
434 pos += comment_len;
435 }
436
437 Ok(VorbisCommentHeader { vendor, comments })
438 }
439}
440
441const MAX_CODEBOOK_ENTRIES: usize = 8192;
447
448const MAX_CODEWORD_LENGTH: u8 = 32;
450
451#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
453pub struct CodebookEntry {
454 pub length: u8,
456 pub symbol: u16,
458}
459
460#[derive(Debug, Clone)]
462pub struct VorbisCodebook {
463 pub entries: Vec<CodebookEntry>,
465 pub num_entries: usize,
467 pub dimensions: u16,
469 pub lookup_type: u8,
472}
473
474impl VorbisCodebook {
475 pub fn from_lengths(lengths: &[u8], dimensions: u16) -> CodecResult<Self> {
477 if lengths.len() > MAX_CODEBOOK_ENTRIES {
478 return Err(CodecError::InternalOverflow);
479 }
480
481 let mut entries: Vec<CodebookEntry> = Vec::with_capacity(lengths.len());
482 let mut num_valid = 0usize;
483
484 for (i, &len) in lengths.iter().enumerate() {
485 if len > 0 && len <= MAX_CODEWORD_LENGTH {
486 entries.push(CodebookEntry {
487 length: len,
488 symbol: i as u16,
489 });
490 num_valid += 1;
491 } else {
492 entries.push(CodebookEntry {
493 length: 0,
494 symbol: i as u16,
495 });
496 }
497 }
498
499 entries.sort_by(|a, b| {
501 if a.length == 0 && b.length == 0 {
502 a.symbol.cmp(&b.symbol)
503 } else if a.length == 0 {
504 core::cmp::Ordering::Greater
505 } else if b.length == 0 {
506 core::cmp::Ordering::Less
507 } else {
508 a.length.cmp(&b.length).then(a.symbol.cmp(&b.symbol))
509 }
510 });
511
512 Ok(VorbisCodebook {
513 entries,
514 num_entries: num_valid,
515 dimensions,
516 lookup_type: 0,
517 })
518 }
519
520 pub fn decode(&self, reader: &mut BitstreamReader<'_>) -> CodecResult<u16> {
522 let mut code: u32 = 0;
523 let mut code_len: u8 = 0;
524 let mut entry_idx = 0;
525 let mut canonical_code: u32 = 0;
527
528 loop {
529 if code_len >= MAX_CODEWORD_LENGTH {
530 return Err(CodecError::HuffmanError);
531 }
532
533 let bit = reader.read_bits(1).ok_or(CodecError::EndOfStream)?;
535 code = (code << 1) | bit;
536 canonical_code <<= 1;
537 code_len += 1;
538
539 let first_entry = entry_idx;
541 while entry_idx < self.entries.len() && self.entries[entry_idx].length == code_len {
542 entry_idx += 1;
543 }
544
545 let count = (entry_idx - first_entry) as u32;
546 if count > 0 && code >= canonical_code && code < canonical_code + count {
547 let symbol_idx = first_entry + (code - canonical_code) as usize;
548 return Ok(self.entries[symbol_idx].symbol);
549 }
550 canonical_code += count;
551 }
552 }
553}
554
555#[derive(Debug, Clone)]
561pub struct BitstreamReader<'a> {
562 data: &'a [u8],
564 byte_pos: usize,
566 bit_pos: u8,
568 total_bits: usize,
570 bits_read: usize,
572}
573
574impl<'a> BitstreamReader<'a> {
575 pub fn new(data: &'a [u8]) -> Self {
577 let total_bits = data.len().saturating_mul(8);
578 Self {
579 data,
580 byte_pos: 0,
581 bit_pos: 0,
582 total_bits,
583 bits_read: 0,
584 }
585 }
586
587 pub fn read_bits(&mut self, count: u8) -> Option<u32> {
589 if count == 0 {
590 return Some(0);
591 }
592 if count > 32 {
593 return None;
594 }
595 if self.bits_read + count as usize > self.total_bits {
596 return None;
597 }
598
599 let mut result: u32 = 0;
600 let mut bits_left = count;
601 let mut output_bit = 0u8;
602
603 while bits_left > 0 {
604 if self.byte_pos >= self.data.len() {
605 return None;
606 }
607
608 let byte = self.data[self.byte_pos];
609 let available = 8 - self.bit_pos;
610 let to_read = bits_left.min(available);
611
612 let mask = (1u32 << to_read) - 1;
614 let bits = ((byte >> self.bit_pos) as u32) & mask;
615 result |= bits << output_bit;
616
617 output_bit += to_read;
618 self.bit_pos += to_read;
619 bits_left -= to_read;
620 self.bits_read += to_read as usize;
621
622 if self.bit_pos >= 8 {
623 self.bit_pos = 0;
624 self.byte_pos += 1;
625 }
626 }
627
628 Some(result)
629 }
630
631 pub fn read_bit(&mut self) -> Option<bool> {
633 self.read_bits(1).map(|v| v != 0)
634 }
635
636 pub fn has_bits(&self, count: usize) -> bool {
638 self.bits_read + count <= self.total_bits
639 }
640
641 pub fn position(&self) -> usize {
643 self.bits_read
644 }
645
646 pub fn skip_bits(&mut self, count: usize) -> bool {
648 if self.bits_read + count > self.total_bits {
649 return false;
650 }
651 let new_total = self.bits_read + count;
652 self.byte_pos = new_total / 8;
653 self.bit_pos = (new_total % 8) as u8;
654 self.bits_read = new_total;
655 true
656 }
657}
658
659#[derive(Debug, Clone, Default)]
665pub struct VorbisFloor1 {
666 pub partitions: u8,
668 pub partition_classes: Vec<u8>,
670 pub class_dimensions: Vec<u8>,
672 pub class_subclasses: Vec<u8>,
674 pub class_masterbooks: Vec<u8>,
676 pub subclass_books: Vec<i16>,
678 pub multiplier: u8,
680 pub range_bits: u8,
682 pub x_list: Vec<u16>,
684}
685
686impl VorbisFloor1 {
687 pub fn new() -> Self {
689 Self::default()
690 }
691
692 pub fn render_line(x0: i32, y0: i32, x1: i32, y1: i32, output: &mut [Fp16], offset: usize) {
695 let dx = x1 - x0;
696 let dy = y1 - y0;
697
698 if dx == 0 {
699 return;
700 }
701
702 let adx = dx.unsigned_abs() as i32;
703 let ady = dy.unsigned_abs() as i32;
704 let base = dy / dx;
705 let sy = if dy < 0 { base - 1 } else { base + 1 };
706
707 let mut err = 0i32;
709 let mut y = y0;
710
711 for x in x0..x1 {
712 let idx = (x as usize).wrapping_add(offset);
713 if idx < output.len() {
714 output[idx] = fp16_from_i32(y);
717 }
718
719 err += ady;
720 if err >= adx {
721 err -= adx;
722 y += sy;
723 } else {
724 y += base;
725 }
726 }
727 }
728}
729
730#[derive(Debug, Clone, Copy, PartialEq, Eq)]
736pub enum ResidueType {
737 Interleaved,
739 Format,
741 InterleavedMultichannel,
743}
744
745impl ResidueType {
746 pub fn from_u16(val: u16) -> CodecResult<Self> {
748 match val {
749 0 => Ok(ResidueType::Interleaved),
750 1 => Ok(ResidueType::Format),
751 2 => Ok(ResidueType::InterleavedMultichannel),
752 _ => Err(CodecError::UnsupportedFeature),
753 }
754 }
755}
756
757#[derive(Debug, Clone)]
759pub struct VorbisResidue {
760 pub residue_type: ResidueType,
762 pub begin: u32,
764 pub end: u32,
766 pub partition_size: u32,
768 pub classifications: u8,
770 pub classbook: u8,
772}
773
774impl VorbisResidue {
775 pub fn new(residue_type: ResidueType) -> Self {
777 Self {
778 residue_type,
779 begin: 0,
780 end: 0,
781 partition_size: 0,
782 classifications: 0,
783 classbook: 0,
784 }
785 }
786
787 pub fn decode_residue(
789 &self,
790 _reader: &mut BitstreamReader<'_>,
791 _codebooks: &[VorbisCodebook],
792 n: usize,
793 channels: usize,
794 ) -> Vec<Vec<Fp16>> {
795 let mut output = Vec::with_capacity(channels);
797 for _ in 0..channels {
798 output.push(vec![0i32; n]);
799 }
800
801 output
802 }
803}
804
805#[derive(Debug, Clone)]
811pub struct MdctContext {
812 pub n: usize,
814 pub twiddle_cos: Vec<Fp30>,
816 pub twiddle_sin: Vec<Fp30>,
818}
819
820impl MdctContext {
821 pub fn new(n: usize) -> Self {
824 let half_n = n / 2;
825 let mut twiddle_cos = Vec::with_capacity(half_n);
826 let mut twiddle_sin = Vec::with_capacity(half_n);
827
828 for k in 0..half_n {
829 let numerator = ((8 * k + 1) * 16) as u64;
831 let table_index = (numerator / n as u64) as usize;
832
833 if table_index < 64 {
834 twiddle_cos.push(MDCT_COS_TABLE_64[table_index]);
835 let sin_idx = 63usize.saturating_sub(table_index);
837 twiddle_sin.push(MDCT_COS_TABLE_64[sin_idx]);
838 } else {
839 let idx = table_index.saturating_sub(64).min(63);
841 twiddle_cos.push(-MDCT_COS_TABLE_64[63 - idx]);
842 twiddle_sin.push(MDCT_COS_TABLE_64[idx]);
843 }
844 }
845
846 Self {
847 n,
848 twiddle_cos,
849 twiddle_sin,
850 }
851 }
852
853 pub fn imdct(&self, input: &[Fp16], output: &mut [Fp16]) {
856 let n = self.n;
857 let half_n = n / 2;
858
859 if input.len() < half_n || output.len() < n {
860 return;
861 }
862
863 let mut temp = vec![0i32; half_n];
865 for k in 0..half_n {
866 if k < self.twiddle_cos.len() {
867 let cos_tw = self.twiddle_cos[k];
869 let _sin_tw = self.twiddle_sin[k];
870
871 let re = fp30_to_fp16(fp30_mul(input[k] << (FP30_SHIFT - FP16_SHIFT), cos_tw));
873 temp[k] = re;
874 }
875 }
876
877 let mut stage_size = 1usize;
880 while stage_size < half_n {
881 let double_stage = stage_size * 2;
882 let mut group = 0;
883 while group < half_n {
884 for k in 0..stage_size {
885 let idx0 = group + k;
886 let idx1 = group + k + stage_size;
887 if idx1 < half_n {
888 let t0 = temp[idx0];
889 let t1 = temp[idx1];
890 temp[idx0] = t0.saturating_add(t1);
892 temp[idx1] = t0.saturating_sub(t1);
893 }
894 }
895 group += double_stage;
896 }
897 stage_size = double_stage;
898 }
899
900 for i in 0..half_n {
902 let val = temp[i];
903 if i < n {
905 output[i] = val;
906 }
907 if half_n + i < n {
908 output[half_n + i] = val;
909 }
910 }
911 }
912}
913
914const VORBIS_WINDOW_256: [Fp30; 256] = {
923 let mut table = [0i32; 256];
924 let mut i = 0usize;
926 while i < 256 {
927 let x = i as i64;
928 let n_minus_x = (256 - i) as i64;
929 let numer = 4 * x * n_minus_x;
930 let val = (numer * (FP30_ONE as i64)) / 65536;
931 table[i] = val as i32;
932 i += 1;
933 }
934
935 table
936};
937
938pub fn apply_vorbis_window(samples: &mut [Fp16], block_size: usize) {
940 if samples.is_empty() || block_size == 0 {
941 return;
942 }
943
944 let half = block_size / 2;
945
946 for i in 0..samples.len().min(block_size) {
947 let table_idx = if i < half {
949 (i * 256) / half
951 } else {
952 ((block_size - 1 - i) * 256) / half
954 };
955
956 let table_idx = table_idx.min(255);
957 let window_val = VORBIS_WINDOW_256[table_idx];
958
959 let window_fp16 = fp30_to_fp16(window_val);
962 samples[i] = fp16_mul(samples[i], window_fp16);
963 }
964}
965
966#[derive(Debug, Clone)]
972pub struct VorbisDecoder {
973 pub ident: VorbisIdentHeader,
975 pub comments: Option<VorbisCommentHeader>,
977 pub codebooks: Vec<VorbisCodebook>,
979 pub floors: Vec<VorbisFloor1>,
981 pub residues: Vec<VorbisResidue>,
983 pub mdct_short: Option<MdctContext>,
985 pub mdct_long: Option<MdctContext>,
986 pub prev_samples: Vec<Vec<Fp16>>,
988 pub headers_parsed: bool,
990 pub output_buffer: Vec<i16>,
992}
993
994impl Default for VorbisDecoder {
995 fn default() -> Self {
996 Self::new()
997 }
998}
999
1000impl VorbisDecoder {
1001 pub fn new() -> Self {
1003 Self {
1004 ident: VorbisIdentHeader {
1005 version: 0,
1006 channels: 0,
1007 sample_rate: 0,
1008 bitrate_max: 0,
1009 bitrate_nominal: 0,
1010 bitrate_min: 0,
1011 blocksize_0: 0,
1012 blocksize_1: 0,
1013 },
1014 comments: None,
1015 codebooks: Vec::new(),
1016 floors: Vec::new(),
1017 residues: Vec::new(),
1018 mdct_short: None,
1019 mdct_long: None,
1020 prev_samples: Vec::new(),
1021 headers_parsed: false,
1022 output_buffer: Vec::new(),
1023 }
1024 }
1025
1026 pub fn parse_headers(&mut self, packets: &[Vec<u8>]) -> CodecResult<()> {
1028 if packets.len() < 3 {
1029 return Err(CodecError::BufferTooShort);
1030 }
1031
1032 self.ident = VorbisIdentHeader::parse(&packets[0])?;
1034
1035 self.comments = Some(VorbisCommentHeader::parse(&packets[1])?);
1037
1038 self.parse_setup_header(&packets[2])?;
1040
1041 self.mdct_short = Some(MdctContext::new(self.ident.short_blocksize()));
1043 self.mdct_long = Some(MdctContext::new(self.ident.long_blocksize()));
1044
1045 self.prev_samples = Vec::with_capacity(self.ident.channels as usize);
1047 for _ in 0..self.ident.channels {
1048 self.prev_samples
1049 .push(vec![0i32; self.ident.long_blocksize()]);
1050 }
1051
1052 self.headers_parsed = true;
1053 Ok(())
1054 }
1055
1056 fn parse_setup_header(&mut self, packet: &[u8]) -> CodecResult<()> {
1058 if packet.len() < 7 {
1059 return Err(CodecError::BufferTooShort);
1060 }
1061
1062 if packet[0] != VORBIS_SETUP_HEADER {
1063 return Err(CodecError::InvalidHeader);
1064 }
1065
1066 if packet[1..7] != VORBIS_MAGIC {
1067 return Err(CodecError::InvalidMagic);
1068 }
1069
1070 let mut reader = BitstreamReader::new(&packet[7..]);
1071
1072 let codebook_count = reader.read_bits(8).ok_or(CodecError::EndOfStream)? + 1;
1074
1075 for _ in 0..codebook_count {
1077 let sync = reader.read_bits(24).ok_or(CodecError::EndOfStream)?;
1079 if sync != 0x564342 {
1080 break;
1082 }
1083
1084 let dimensions = reader.read_bits(16).ok_or(CodecError::EndOfStream)? as u16;
1085 let entries = reader.read_bits(24).ok_or(CodecError::EndOfStream)? as usize;
1086
1087 let ordered = reader.read_bit().ok_or(CodecError::EndOfStream)?;
1089
1090 let mut lengths = vec![0u8; entries.min(MAX_CODEBOOK_ENTRIES)];
1091
1092 if !ordered {
1093 let sparse = reader.read_bit().ok_or(CodecError::EndOfStream)?;
1095
1096 for length in lengths.iter_mut() {
1097 if sparse {
1098 let flag = reader.read_bit().ok_or(CodecError::EndOfStream)?;
1099 if flag {
1100 *length =
1101 (reader.read_bits(5).ok_or(CodecError::EndOfStream)? + 1) as u8;
1102 }
1103 } else {
1104 *length = (reader.read_bits(5).ok_or(CodecError::EndOfStream)? + 1) as u8;
1105 }
1106 }
1107 } else {
1108 let mut current_length =
1110 reader.read_bits(5).ok_or(CodecError::EndOfStream)? as u8 + 1;
1111 let mut _i = 0usize;
1112 while _i < entries.min(MAX_CODEBOOK_ENTRIES) {
1113 let num = reader
1114 .read_bits(ilog(entries as u32 - _i as u32))
1115 .ok_or(CodecError::EndOfStream)? as usize;
1116 for j in 0..num {
1117 if _i + j < lengths.len() {
1118 lengths[_i + j] = current_length;
1119 }
1120 }
1121 _i += num;
1122 current_length += 1;
1123 if current_length > 32 {
1124 break;
1125 }
1126 }
1127 }
1128
1129 let codebook = VorbisCodebook::from_lengths(&lengths, dimensions)?;
1130 self.codebooks.push(codebook);
1131 }
1132
1133 Ok(())
1137 }
1138
1139 pub fn decode_packet(&mut self, _packet: &[u8]) -> CodecResult<usize> {
1141 if !self.headers_parsed {
1142 return Err(CodecError::InvalidHeader);
1143 }
1144
1145 let block_size = self.ident.short_blocksize();
1147 let num_samples = block_size / 2 * self.ident.channels as usize;
1148 self.output_buffer.resize(num_samples, 0i16);
1149
1150 Ok(num_samples)
1151 }
1152
1153 pub fn output(&self) -> &[i16] {
1155 &self.output_buffer
1156 }
1157
1158 pub fn sample_rate(&self) -> u32 {
1160 self.ident.sample_rate
1161 }
1162
1163 pub fn channels(&self) -> u8 {
1165 self.ident.channels
1166 }
1167}
1168
1169#[derive(Debug)]
1176pub struct OggVorbisDecoder {
1177 pub demuxer: OggDemuxer,
1179 pub vorbis: VorbisDecoder,
1181 header_packets: Vec<Vec<u8>>,
1183 headers_received: u8,
1185}
1186
1187impl Default for OggVorbisDecoder {
1188 fn default() -> Self {
1189 Self::new()
1190 }
1191}
1192
1193impl OggVorbisDecoder {
1194 pub fn new() -> Self {
1196 Self {
1197 demuxer: OggDemuxer::new(),
1198 vorbis: VorbisDecoder::new(),
1199 header_packets: Vec::new(),
1200 headers_received: 0,
1201 }
1202 }
1203
1204 pub fn decode_all(&mut self, data: &[u8]) -> CodecResult<(u32, u8, Vec<i16>)> {
1207 self.demuxer.reset();
1208 let mut all_pcm = Vec::new();
1209
1210 while self.demuxer.position < data.len() {
1212 let page = match self.demuxer.next_page(data) {
1213 Ok(p) => p,
1214 Err(CodecError::BufferTooShort) => break,
1215 Err(CodecError::InvalidMagic) => {
1216 if self.demuxer.find_sync(data).is_none() {
1218 break;
1219 }
1220 continue;
1221 }
1222 Err(e) => return Err(e),
1223 };
1224
1225 let packets = page.extract_packets(data, self.demuxer.position - page.total_size);
1226
1227 for packet in &packets {
1228 if self.headers_received < 3 {
1229 self.header_packets.push(packet.clone());
1230 self.headers_received += 1;
1231
1232 if self.headers_received == 3 {
1233 self.vorbis.parse_headers(&self.header_packets)?;
1234 }
1235 } else {
1236 let _n = self.vorbis.decode_packet(packet)?;
1238 all_pcm.extend_from_slice(self.vorbis.output());
1239 }
1240 }
1241 }
1242
1243 Ok((self.vorbis.sample_rate(), self.vorbis.channels(), all_pcm))
1244 }
1245}
1246
1247#[cfg(test)]
1248mod tests {
1249 #[allow(unused_imports)]
1250 use alloc::vec;
1251
1252 use super::*;
1253
1254 #[test]
1257 fn test_ogg_crc32_empty() {
1258 let crc = ogg_crc32(&[]);
1259 assert_eq!(crc, 0);
1260 }
1261
1262 #[test]
1263 fn test_ogg_crc32_known_pattern() {
1264 let crc = ogg_crc32(&OGG_CAPTURE_PATTERN);
1265 assert_ne!(crc, 0);
1266 assert_eq!(crc, ogg_crc32(&OGG_CAPTURE_PATTERN));
1267 }
1268
1269 #[test]
1270 fn test_ogg_page_parse_too_short() {
1271 let data = [0u8; 10];
1272 let result = OggPage::parse(&data, 0);
1273 assert_eq!(result.unwrap_err(), CodecError::BufferTooShort);
1274 }
1275
1276 #[test]
1277 fn test_ogg_page_parse_bad_magic() {
1278 let mut data = [0u8; 30];
1279 data[0] = b'X';
1280 let result = OggPage::parse(&data, 0);
1281 assert_eq!(result.unwrap_err(), CodecError::InvalidMagic);
1282 }
1283
1284 #[test]
1285 fn test_ogg_page_parse_valid() {
1286 let mut page = vec![0u8; 64];
1287 page[0] = b'O';
1288 page[1] = b'g';
1289 page[2] = b'g';
1290 page[3] = b'S';
1291 page[4] = 0;
1292 page[5] = 0x02;
1293 page[6..14].copy_from_slice(&0u64.to_le_bytes());
1294 page[14..18].copy_from_slice(&42u32.to_le_bytes());
1295 page[18..22].copy_from_slice(&0u32.to_le_bytes());
1296 page[22..26].copy_from_slice(&0u32.to_le_bytes());
1297 page[26] = 1;
1298 page[27] = 10;
1299 for i in 0..10 {
1300 page[28 + i] = i as u8;
1301 }
1302
1303 let result = OggPage::parse(&page, 0);
1304 assert!(result.is_ok());
1305 let parsed = result.unwrap();
1306 assert_eq!(parsed.version, 0);
1307 assert!(parsed.header_type.is_bos());
1308 assert_eq!(parsed.serial_number, 42);
1309 assert_eq!(parsed.num_segments, 1);
1310 assert_eq!(parsed.data_size, 10);
1311 }
1312
1313 #[test]
1314 fn test_ogg_header_type_flags() {
1315 let ht = OggHeaderType::new(0x02);
1316 assert!(ht.is_bos());
1317 assert!(!ht.is_eos());
1318 assert!(!ht.is_continuation());
1319
1320 let ht_eos = OggHeaderType::new(0x04);
1321 assert!(ht_eos.is_eos());
1322 assert!(!ht_eos.is_bos());
1323
1324 let ht_cont = OggHeaderType::new(0x01);
1325 assert!(ht_cont.is_continuation());
1326 }
1327
1328 #[test]
1329 fn test_ogg_demuxer_find_sync() {
1330 let mut data = vec![0u8; 20];
1331 data[5] = b'O';
1332 data[6] = b'g';
1333 data[7] = b'g';
1334 data[8] = b'S';
1335
1336 let mut demuxer = OggDemuxer::new();
1337 let pos = demuxer.find_sync(&data);
1338 assert_eq!(pos, Some(5));
1339 }
1340
1341 #[test]
1344 fn test_vorbis_ident_header_parse() {
1345 let mut packet = vec![0u8; 30];
1346 packet[0] = VORBIS_IDENTIFICATION_HEADER;
1347 packet[1..7].copy_from_slice(&VORBIS_MAGIC);
1348 packet[7..11].copy_from_slice(&0u32.to_le_bytes());
1349 packet[11] = 2;
1350 packet[12..16].copy_from_slice(&44100u32.to_le_bytes());
1351 packet[16..20].copy_from_slice(&0u32.to_le_bytes());
1352 packet[20..24].copy_from_slice(&128000u32.to_le_bytes());
1353 packet[24..28].copy_from_slice(&0u32.to_le_bytes());
1354 packet[28] = 0xB8;
1355 packet[29] = 0x01;
1356
1357 let ident = VorbisIdentHeader::parse(&packet).unwrap();
1358 assert_eq!(ident.version, 0);
1359 assert_eq!(ident.channels, 2);
1360 assert_eq!(ident.sample_rate, 44100);
1361 assert_eq!(ident.blocksize_0, 8);
1362 assert_eq!(ident.blocksize_1, 11);
1363 assert_eq!(ident.short_blocksize(), 256);
1364 assert_eq!(ident.long_blocksize(), 2048);
1365 }
1366
1367 #[test]
1368 fn test_vorbis_ident_header_bad_version() {
1369 let mut packet = vec![0u8; 30];
1370 packet[0] = VORBIS_IDENTIFICATION_HEADER;
1371 packet[1..7].copy_from_slice(&VORBIS_MAGIC);
1372 packet[7..11].copy_from_slice(&1u32.to_le_bytes());
1373 let result = VorbisIdentHeader::parse(&packet);
1374 assert_eq!(result.unwrap_err(), CodecError::UnsupportedVersion);
1375 }
1376
1377 #[test]
1378 fn test_vorbis_comment_header_parse() {
1379 let mut packet = Vec::new();
1380 packet.push(VORBIS_COMMENT_HEADER);
1381 packet.extend_from_slice(&VORBIS_MAGIC);
1382 let vendor = b"TestVendor";
1383 packet.extend_from_slice(&(vendor.len() as u32).to_le_bytes());
1384 packet.extend_from_slice(vendor);
1385 packet.extend_from_slice(&2u32.to_le_bytes());
1386 let c1 = b"ARTIST=Test";
1387 packet.extend_from_slice(&(c1.len() as u32).to_le_bytes());
1388 packet.extend_from_slice(c1);
1389 let c2 = b"TITLE=Song";
1390 packet.extend_from_slice(&(c2.len() as u32).to_le_bytes());
1391 packet.extend_from_slice(c2);
1392
1393 let comments = VorbisCommentHeader::parse(&packet).unwrap();
1394 assert_eq!(comments.vendor, "TestVendor");
1395 assert_eq!(comments.comments.len(), 2);
1396 assert_eq!(comments.comments[0], "ARTIST=Test");
1397 assert_eq!(comments.comments[1], "TITLE=Song");
1398 }
1399
1400 #[test]
1403 fn test_codebook_from_lengths() {
1404 let lengths = [2u8, 3, 3, 1, 0];
1405 let cb = VorbisCodebook::from_lengths(&lengths, 1).unwrap();
1406 assert_eq!(cb.num_entries, 4);
1407 assert_eq!(cb.dimensions, 1);
1408 }
1409
1410 #[test]
1411 fn test_codebook_empty() {
1412 let lengths: [u8; 0] = [];
1413 let cb = VorbisCodebook::from_lengths(&lengths, 1).unwrap();
1414 assert_eq!(cb.num_entries, 0);
1415 }
1416
1417 #[test]
1420 fn test_bitstream_reader_read_bits() {
1421 let data = [0xA5u8];
1422 let mut reader = BitstreamReader::new(&data);
1423 let val = reader.read_bits(4).unwrap();
1424 assert_eq!(val, 5);
1425 let val2 = reader.read_bits(4).unwrap();
1426 assert_eq!(val2, 10);
1427 }
1428
1429 #[test]
1430 fn test_bitstream_reader_out_of_bounds() {
1431 let data = [0xFFu8];
1432 let mut reader = BitstreamReader::new(&data);
1433 assert!(reader.read_bits(8).is_some());
1434 assert!(reader.read_bits(1).is_none());
1435 }
1436
1437 #[test]
1440 fn test_mdct_context_creation() {
1441 let ctx = MdctContext::new(256);
1442 assert_eq!(ctx.n, 256);
1443 assert_eq!(ctx.twiddle_cos.len(), 128);
1444 assert_eq!(ctx.twiddle_sin.len(), 128);
1445 }
1446
1447 #[test]
1448 fn test_residue_type_from_u16() {
1449 assert_eq!(ResidueType::from_u16(0).unwrap(), ResidueType::Interleaved);
1450 assert_eq!(ResidueType::from_u16(1).unwrap(), ResidueType::Format);
1451 assert_eq!(
1452 ResidueType::from_u16(2).unwrap(),
1453 ResidueType::InterleavedMultichannel
1454 );
1455 assert_eq!(
1456 ResidueType::from_u16(3).unwrap_err(),
1457 CodecError::UnsupportedFeature
1458 );
1459 }
1460
1461 #[test]
1464 fn test_vorbis_window_endpoints() {
1465 assert_eq!(VORBIS_WINDOW_256[0], 0);
1466 assert!(VORBIS_WINDOW_256[128] > FP30_ONE / 2);
1467 }
1468
1469 #[test]
1470 fn test_apply_vorbis_window_empty() {
1471 let mut samples: Vec<Fp16> = Vec::new();
1472 apply_vorbis_window(&mut samples, 0);
1473 assert!(samples.is_empty());
1474 }
1475
1476 #[test]
1477 fn test_ogg_page_extract_packets() {
1478 let mut page_data = vec![0u8; 64];
1479 page_data[0..4].copy_from_slice(b"OggS");
1480 page_data[4] = 0;
1481 page_data[5] = 0x02;
1482 page_data[6..14].copy_from_slice(&0u64.to_le_bytes());
1483 page_data[14..18].copy_from_slice(&1u32.to_le_bytes());
1484 page_data[18..22].copy_from_slice(&0u32.to_le_bytes());
1485 page_data[22..26].copy_from_slice(&0u32.to_le_bytes());
1486 page_data[26] = 2;
1487 page_data[27] = 5;
1488 page_data[28] = 3;
1489 for i in 0..8 {
1490 page_data[29 + i] = (i + 1) as u8;
1491 }
1492
1493 let parsed = OggPage::parse(&page_data, 0).unwrap();
1494 let packets = parsed.extract_packets(&page_data, 0);
1495
1496 assert_eq!(packets.len(), 2);
1497 assert_eq!(packets[0].len(), 5);
1498 assert_eq!(packets[1].len(), 3);
1499 assert_eq!(packets[0], vec![1, 2, 3, 4, 5]);
1500 assert_eq!(packets[1], vec![6, 7, 8]);
1501 }
1502}