1#![forbid(unsafe_code)]
7#![allow(clippy::cast_possible_truncation)]
8#![allow(clippy::cast_precision_loss)]
9#![allow(clippy::cast_lossless)]
10
11use super::mdct::MdctTwiddles;
12use super::residue::{ResidueConfig, ResidueDecoder, ResidueType};
13use crate::error::{CodecError, CodecResult};
14
15#[derive(Clone, Debug)]
21pub struct VorbisIdHeader {
22 pub channels: u8,
24 pub sample_rate: u32,
26 pub bitrate_max: i32,
28 pub bitrate_nominal: i32,
30 pub bitrate_min: i32,
32 pub blocksize_0: u8,
34 pub blocksize_1: u8,
36}
37
38#[derive(Clone, Debug, Default)]
40pub struct VorbisCommentHeader {
41 pub vendor: String,
43 pub comments: Vec<(String, String)>,
45}
46
47#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49pub enum VorbisHeaderType {
50 Identification,
52 Comment,
54 Setup,
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq)]
60pub enum DecoderState {
61 AwaitingIdHeader,
63 AwaitingCommentHeader,
65 AwaitingSetupHeader,
67 ReadyForAudio,
69}
70
71pub struct VorbisDecoder {
73 pub sample_rate: u32,
75 pub channels: u8,
77 block_size: usize,
79 mdct: MdctTwiddles,
81 residue_dec: ResidueDecoder,
83 floor_x_count: usize,
85 ola_buf: Vec<Vec<f64>>,
87 pub state: DecoderState,
89 pub packets_decoded: u64,
91 stored_id_header: Option<VorbisIdHeader>,
93 stored_comment_header: Option<VorbisCommentHeader>,
95}
96
97impl VorbisDecoder {
98 #[must_use]
102 pub fn new() -> Self {
103 let block_size = 2048;
104 Self {
105 sample_rate: 0,
106 channels: 0,
107 block_size,
108 mdct: MdctTwiddles::new(block_size),
109 residue_dec: ResidueDecoder::new(
110 ResidueConfig {
111 residue_type: ResidueType::Type1,
112 begin: 0,
113 end: 1024,
114 partition_size: 32,
115 classifications: 4,
116 classbook: 0,
117 },
118 0.2, ),
120 floor_x_count: 16,
121 ola_buf: Vec::new(),
122 state: DecoderState::AwaitingIdHeader,
123 packets_decoded: 0,
124 stored_id_header: None,
125 stored_comment_header: None,
126 }
127 }
128
129 pub fn decode_packet(&mut self, data: &[u8]) -> CodecResult<Option<Vec<f32>>> {
140 if data.is_empty() {
141 return Err(CodecError::InvalidBitstream(
142 "Empty Vorbis packet".to_string(),
143 ));
144 }
145
146 let packet_type = data[0];
147
148 match packet_type {
149 1 => self.parse_id_header(data),
150 3 => self.parse_comment_header(data),
151 5 => self.parse_setup_header(data),
152 0 => self.decode_audio(data),
153 _ => Err(CodecError::InvalidBitstream(format!(
154 "Unknown Vorbis packet type: {packet_type}"
155 ))),
156 }
157 }
158
159 pub fn process_header_packet(&mut self, data: &[u8]) -> CodecResult<VorbisHeaderType> {
172 if data.is_empty() {
173 return Err(CodecError::InvalidBitstream(
174 "Empty Vorbis header packet".to_string(),
175 ));
176 }
177 match data[0] {
178 1 => {
179 self.parse_id_header(data)?;
180 Ok(VorbisHeaderType::Identification)
181 }
182 3 => {
183 self.parse_comment_header_full(data)?;
184 Ok(VorbisHeaderType::Comment)
185 }
186 5 => {
187 self.parse_setup_header(data)?;
188 Ok(VorbisHeaderType::Setup)
189 }
190 t => Err(CodecError::InvalidBitstream(format!(
191 "Not a Vorbis header packet (type byte {t})"
192 ))),
193 }
194 }
195
196 pub fn id_header(&self) -> Option<&VorbisIdHeader> {
198 self.stored_id_header.as_ref()
199 }
200
201 pub fn comment_header(&self) -> Option<&VorbisCommentHeader> {
203 self.stored_comment_header.as_ref()
204 }
205
206 pub fn is_ready(&self) -> bool {
209 self.state == DecoderState::ReadyForAudio
210 }
211
212 pub fn decode_audio_packet(&self, data: &[u8]) -> CodecResult<Vec<f32>> {
224 if self.state != DecoderState::ReadyForAudio {
225 return Err(CodecError::InvalidBitstream(
226 "Audio packet received before all headers".to_string(),
227 ));
228 }
229 if data.is_empty() {
230 return Err(CodecError::InvalidBitstream(
231 "Empty audio packet".to_string(),
232 ));
233 }
234 if data[0] != 0x00 {
235 return Err(CodecError::InvalidBitstream(format!(
236 "Expected audio packet type 0x00, got {:#04x}",
237 data[0]
238 )));
239 }
240 Ok(Vec::new())
243 }
244
245 fn parse_id_header(&mut self, data: &[u8]) -> CodecResult<Option<Vec<f32>>> {
250 if self.state != DecoderState::AwaitingIdHeader {
251 return Err(CodecError::InvalidBitstream(
252 "Unexpected ID header".to_string(),
253 ));
254 }
255 if data.len() < 23 || &data[1..7] != b"vorbis" {
256 return Err(CodecError::InvalidBitstream(
257 "Invalid Vorbis ID header".to_string(),
258 ));
259 }
260
261 if data.len() < 29 {
264 return Err(CodecError::InvalidBitstream(
265 "ID header too short".to_string(),
266 ));
267 }
268
269 self.channels = data[11];
270 self.sample_rate = u32::from_le_bytes([data[12], data[13], data[14], data[15]]);
271
272 if self.channels == 0 || self.channels > 8 {
273 return Err(CodecError::InvalidBitstream(format!(
274 "Invalid channel count: {}",
275 self.channels
276 )));
277 }
278
279 let bitrate_max = i32::from_le_bytes([data[16], data[17], data[18], data[19]]);
280 let bitrate_nominal = i32::from_le_bytes([data[20], data[21], data[22], data[23]]);
281 let bitrate_min = i32::from_le_bytes([data[24], data[25], data[26], data[27]]);
282
283 let block_sizes_byte = data[28];
284 let log2_short = block_sizes_byte & 0x0F;
285 let log2_long = (block_sizes_byte >> 4) & 0x0F;
286 let short_sz = 1usize << log2_short;
287 let long_sz = 1usize << log2_long;
288
289 if long_sz < short_sz || long_sz < 4 {
290 return Err(CodecError::InvalidBitstream(
291 "Invalid block sizes in ID header".to_string(),
292 ));
293 }
294
295 if data.len() > 29 && (data[29] & 0x01) == 0 {
297 return Err(CodecError::InvalidBitstream(
298 "Vorbis ID header framing bit not set".to_string(),
299 ));
300 }
301
302 self.stored_id_header = Some(VorbisIdHeader {
303 channels: self.channels,
304 sample_rate: self.sample_rate,
305 bitrate_max,
306 bitrate_nominal,
307 bitrate_min,
308 blocksize_0: log2_short,
309 blocksize_1: log2_long,
310 });
311
312 self.block_size = long_sz;
313 self.mdct = MdctTwiddles::new(long_sz);
314 self.ola_buf = vec![vec![0.0f64; long_sz]; self.channels as usize];
315
316 let _ = short_sz; self.state = DecoderState::AwaitingCommentHeader;
319 Ok(None)
320 }
321
322 fn parse_comment_header(&mut self, data: &[u8]) -> CodecResult<Option<Vec<f32>>> {
323 self.parse_comment_header_full(data)?;
324 Ok(None)
325 }
326
327 fn parse_comment_header_full(&mut self, data: &[u8]) -> CodecResult<()> {
331 if self.state != DecoderState::AwaitingCommentHeader {
332 return Err(CodecError::InvalidBitstream(
333 "Unexpected comment header".to_string(),
334 ));
335 }
336 if data.len() < 11 || &data[0..7] != b"\x03vorbis" {
338 return Err(CodecError::InvalidBitstream(
339 "Invalid Vorbis comment header magic".to_string(),
340 ));
341 }
342
343 let mut offset = 7usize;
344
345 if offset + 4 > data.len() {
347 return Err(CodecError::InvalidBitstream(
348 "Comment header truncated at vendor length".to_string(),
349 ));
350 }
351 let vendor_len = u32::from_le_bytes([
352 data[offset],
353 data[offset + 1],
354 data[offset + 2],
355 data[offset + 3],
356 ]) as usize;
357 offset += 4;
358
359 if offset + vendor_len > data.len() {
360 return Err(CodecError::InvalidBitstream(
361 "Comment header truncated in vendor string".to_string(),
362 ));
363 }
364 let vendor = String::from_utf8_lossy(&data[offset..offset + vendor_len]).into_owned();
365 offset += vendor_len;
366
367 if offset + 4 > data.len() {
369 return Err(CodecError::InvalidBitstream(
370 "Comment header truncated at comment list length".to_string(),
371 ));
372 }
373 let comment_count = u32::from_le_bytes([
374 data[offset],
375 data[offset + 1],
376 data[offset + 2],
377 data[offset + 3],
378 ]) as usize;
379 offset += 4;
380
381 let mut comments = Vec::with_capacity(comment_count);
382 for _ in 0..comment_count {
383 if offset + 4 > data.len() {
384 return Err(CodecError::InvalidBitstream(
385 "Comment header truncated in comment length field".to_string(),
386 ));
387 }
388 let field_len = u32::from_le_bytes([
389 data[offset],
390 data[offset + 1],
391 data[offset + 2],
392 data[offset + 3],
393 ]) as usize;
394 offset += 4;
395
396 if offset + field_len > data.len() {
397 return Err(CodecError::InvalidBitstream(
398 "Comment header truncated in comment value".to_string(),
399 ));
400 }
401 let raw = String::from_utf8_lossy(&data[offset..offset + field_len]).into_owned();
402 offset += field_len;
403
404 let (key, value) = if let Some(eq_pos) = raw.find('=') {
406 let k = raw[..eq_pos].to_ascii_uppercase();
407 let v = raw[eq_pos + 1..].to_string();
408 (k, v)
409 } else {
410 (raw.to_ascii_uppercase(), String::new())
411 };
412 comments.push((key, value));
413 }
414
415 self.stored_comment_header = Some(VorbisCommentHeader { vendor, comments });
416 self.state = DecoderState::AwaitingSetupHeader;
417 Ok(())
418 }
419
420 fn parse_setup_header(&mut self, _data: &[u8]) -> CodecResult<Option<Vec<f32>>> {
421 if self.state != DecoderState::AwaitingSetupHeader {
422 return Err(CodecError::InvalidBitstream(
423 "Unexpected setup header".to_string(),
424 ));
425 }
426 self.state = DecoderState::ReadyForAudio;
427 Ok(None)
428 }
429
430 fn decode_audio(&mut self, data: &[u8]) -> CodecResult<Option<Vec<f32>>> {
435 if self.state != DecoderState::ReadyForAudio {
436 return Err(CodecError::InvalidBitstream(
437 "Audio packet received before headers".to_string(),
438 ));
439 }
440
441 let ch = self.channels as usize;
442 let n = self.block_size;
443 let m = n / 2; let floor_x = self.floor_x_count;
445
446 let per_channel = floor_x * 2 + m * 2;
448 let expected = 1 + ch * per_channel; if data.len() < expected {
451 return Err(CodecError::InvalidBitstream(format!(
452 "Audio packet too short: expected >= {expected}, got {}",
453 data.len()
454 )));
455 }
456
457 let mut interleaved = Vec::with_capacity(m * ch);
458 let mut offset = 1usize; for _c in 0..ch {
461 let mut amps = Vec::with_capacity(floor_x);
463 for _ in 0..floor_x {
464 if offset + 2 > data.len() {
465 return Err(CodecError::InvalidBitstream(
466 "Truncated floor data".to_string(),
467 ));
468 }
469 let a = i16::from_le_bytes([data[offset], data[offset + 1]]);
470 amps.push(a);
471 offset += 2;
472 }
473
474 let mut codes = Vec::with_capacity(m);
476 for _ in 0..m {
477 if offset + 2 > data.len() {
478 return Err(CodecError::InvalidBitstream(
479 "Truncated residue data".to_string(),
480 ));
481 }
482 let c = i16::from_le_bytes([data[offset], data[offset + 1]]);
483 codes.push(c);
484 offset += 2;
485 }
486
487 let residue = self.residue_dec.decode(&codes);
489
490 let coeffs: Vec<f64> = residue
492 .iter()
493 .enumerate()
494 .map(|(i, &r)| {
495 let floor_val = if !amps.is_empty() {
497 let idx = (i * floor_x / m).min(floor_x - 1);
498 f64::from(amps[idx]) * 0.1 } else {
500 0.0
501 };
502 r + floor_val
503 })
504 .collect();
505
506 let mut time_samples = self.mdct.inverse(&coeffs);
508
509 self.mdct.apply_synthesis_window(&mut time_samples);
511
512 let ola = &mut self.ola_buf[_c];
514 let output_start = n / 4; for i in 0..n {
516 let combined = time_samples[i] + ola[i];
517 if i >= output_start && i < output_start + m {
518 interleaved.push(combined as f32);
519 }
520 ola[i] = if i + m < n { time_samples[i + m] } else { 0.0 };
522 }
523 }
524
525 self.packets_decoded += 1;
526
527 if ch > 1 {
529 let samples_per_ch = interleaved.len() / ch;
530 let mut reinterleaved = Vec::with_capacity(interleaved.len());
531 for s in 0..samples_per_ch {
532 for c in 0..ch {
533 reinterleaved.push(interleaved[c * samples_per_ch + s]);
534 }
535 }
536 Ok(Some(reinterleaved))
537 } else {
538 Ok(Some(interleaved))
539 }
540 }
541}
542
543#[cfg(test)]
548mod tests {
549 use super::*;
550 use crate::vorbis::encoder::{VorbisConfig, VorbisEncoder, VorbisQuality};
551
552 fn make_enc_dec() -> (VorbisEncoder, VorbisDecoder) {
553 let cfg = VorbisConfig {
554 sample_rate: 44100,
555 channels: 2,
556 quality: VorbisQuality::Q5,
557 };
558 let enc = VorbisEncoder::new(cfg).expect("encoder");
559 let dec = VorbisDecoder::new();
560 (enc, dec)
561 }
562
563 #[test]
564 fn test_vorbis_decoder_new_state() {
565 let dec = VorbisDecoder::new();
566 assert_eq!(dec.state, DecoderState::AwaitingIdHeader);
567 assert_eq!(dec.packets_decoded, 0);
568 }
569
570 #[test]
571 fn test_vorbis_decoder_parse_headers() {
572 let (mut enc, mut dec) = make_enc_dec();
573 let headers = enc.headers();
574 for h in &headers {
575 let result = dec.decode_packet(&h.data).expect("header decode");
576 assert!(result.is_none(), "Header decode should return None");
577 }
578 assert_eq!(dec.state, DecoderState::ReadyForAudio);
579 }
580
581 #[test]
582 fn test_vorbis_decoder_id_header_channels() {
583 let (mut enc, mut dec) = make_enc_dec();
584 let headers = enc.headers();
585 dec.decode_packet(&headers[0].data).expect("id header");
586 assert_eq!(dec.channels, 2);
587 assert_eq!(dec.sample_rate, 44100);
588 }
589
590 #[test]
591 fn test_vorbis_decoder_wrong_order_errors() {
592 let (mut enc, mut dec) = make_enc_dec();
593 let headers = enc.headers();
594 let result = dec.decode_packet(&headers[1].data);
596 assert!(result.is_err(), "Should error on out-of-order header");
597 }
598
599 #[test]
600 fn test_vorbis_decoder_empty_packet_errors() {
601 let mut dec = VorbisDecoder::new();
602 let result = dec.decode_packet(&[]);
603 assert!(result.is_err());
604 }
605
606 #[test]
607 fn test_vorbis_decoder_audio_before_headers_errors() {
608 let mut dec = VorbisDecoder::new();
609 let result = dec.decode_packet(&[0u8, 1, 2, 3]);
611 assert!(result.is_err());
612 }
613
614 #[test]
615 fn test_vorbis_encoder_decoder_pipeline() {
616 let (mut enc, mut dec) = make_enc_dec();
617
618 let headers = enc.headers();
620 for h in &headers {
621 dec.decode_packet(&h.data).expect("header");
622 }
623
624 let silence = vec![0.0f32; 2048 * 2]; let pkts = enc.encode_interleaved(&silence).expect("encode");
627
628 for pkt in &pkts {
630 let result = dec.decode_packet(&pkt.data);
631 let _ = result;
633 }
634 }
635
636 #[test]
637 fn test_vorbis_packets_decoded_counter() {
638 let (mut enc, mut dec) = make_enc_dec();
639 let headers = enc.headers();
640 for h in &headers {
641 dec.decode_packet(&h.data).expect("header");
642 }
643 assert_eq!(dec.packets_decoded, 0); }
645
646 #[test]
651 fn test_process_header_packet_returns_correct_types() {
652 let (mut enc, mut dec) = make_enc_dec();
653 let headers = enc.headers();
654 assert_eq!(headers.len(), 3);
655
656 let t0 = dec
657 .process_header_packet(&headers[0].data)
658 .expect("id header via process_header_packet");
659 assert_eq!(t0, VorbisHeaderType::Identification);
660
661 let t1 = dec
662 .process_header_packet(&headers[1].data)
663 .expect("comment header via process_header_packet");
664 assert_eq!(t1, VorbisHeaderType::Comment);
665
666 let t2 = dec
667 .process_header_packet(&headers[2].data)
668 .expect("setup header via process_header_packet");
669 assert_eq!(t2, VorbisHeaderType::Setup);
670 }
671
672 #[test]
673 fn test_id_header_populated_after_processing() {
674 let (mut enc, mut dec) = make_enc_dec();
675 let headers = enc.headers();
676
677 assert!(dec.id_header().is_none());
678
679 dec.process_header_packet(&headers[0].data)
680 .expect("process id header");
681
682 let id = dec
683 .id_header()
684 .expect("id_header should be Some after parsing");
685 assert_eq!(id.channels, 2);
686 assert_eq!(id.sample_rate, 44100);
687 assert!(id.blocksize_1 >= id.blocksize_0);
689 }
690
691 #[test]
692 fn test_comment_header_populated_after_processing() {
693 let (mut enc, mut dec) = make_enc_dec();
694 let headers = enc.headers();
695
696 dec.process_header_packet(&headers[0].data).expect("id");
697 assert!(dec.comment_header().is_none());
698 dec.process_header_packet(&headers[1].data)
699 .expect("comment");
700
701 let ch = dec.comment_header().expect("comment_header should be Some");
702 let _ = ch.vendor.len();
704 }
705
706 #[test]
707 fn test_is_ready_only_after_all_three_headers() {
708 let (mut enc, mut dec) = make_enc_dec();
709 let headers = enc.headers();
710
711 assert!(!dec.is_ready());
712 dec.process_header_packet(&headers[0].data).expect("id");
713 assert!(!dec.is_ready());
714 dec.process_header_packet(&headers[1].data)
715 .expect("comment");
716 assert!(!dec.is_ready());
717 dec.process_header_packet(&headers[2].data).expect("setup");
718 assert!(dec.is_ready());
719 }
720
721 #[test]
722 fn test_decode_audio_packet_before_headers_errors() {
723 let dec = VorbisDecoder::new();
724 let result = dec.decode_audio_packet(&[0x00u8, 0x01, 0x02]);
725 assert!(result.is_err(), "should error before headers are processed");
726 }
727
728 #[test]
729 fn test_decode_audio_packet_wrong_type_byte_errors() {
730 let (mut enc, mut dec) = make_enc_dec();
731 let headers = enc.headers();
732 for h in &headers {
733 dec.process_header_packet(&h.data).expect("header");
734 }
735 let result = dec.decode_audio_packet(&[0x01u8, 0x00]);
737 assert!(result.is_err());
738 }
739
740 #[test]
741 fn test_decode_audio_packet_valid_type_returns_empty_vec() {
742 let (mut enc, mut dec) = make_enc_dec();
743 let headers = enc.headers();
744 for h in &headers {
745 dec.process_header_packet(&h.data).expect("header");
746 }
747 let samples = dec
749 .decode_audio_packet(&[0x00u8, 0x00, 0x00])
750 .expect("structural audio decode");
751 assert!(samples.is_empty());
753 }
754
755 #[test]
756 fn test_process_header_packet_empty_errors() {
757 let mut dec = VorbisDecoder::new();
758 assert!(dec.process_header_packet(&[]).is_err());
759 }
760
761 #[test]
762 fn test_process_header_packet_non_header_type_errors() {
763 let mut dec = VorbisDecoder::new();
764 assert!(dec.process_header_packet(&[0x00u8, 0x01]).is_err());
766 }
767
768 fn build_minimal_id_header(channels: u8, sample_rate: u32) -> Vec<u8> {
770 let mut pkt = Vec::new();
771 pkt.push(0x01); pkt.extend_from_slice(b"vorbis");
773 pkt.extend_from_slice(&0u32.to_le_bytes()); pkt.push(channels);
775 pkt.extend_from_slice(&sample_rate.to_le_bytes());
776 pkt.extend_from_slice(&(-1i32).to_le_bytes()); pkt.extend_from_slice(&128_000i32.to_le_bytes()); pkt.extend_from_slice(&(-1i32).to_le_bytes()); pkt.push((11u8 << 4) | 8u8);
781 pkt.push(0x01); pkt
783 }
784
785 #[test]
786 fn test_id_header_bitrates_parsed() {
787 let pkt = build_minimal_id_header(1, 22050);
788 let mut dec = VorbisDecoder::new();
789 dec.process_header_packet(&pkt).expect("id header");
790 let id = dec.id_header().expect("id_header");
791 assert_eq!(id.channels, 1);
792 assert_eq!(id.sample_rate, 22050);
793 assert_eq!(id.bitrate_max, -1);
794 assert_eq!(id.bitrate_nominal, 128_000);
795 assert_eq!(id.bitrate_min, -1);
796 assert_eq!(id.blocksize_0, 8);
797 assert_eq!(id.blocksize_1, 11);
798 }
799
800 #[test]
801 fn test_id_header_framing_bit_required() {
802 let mut pkt = build_minimal_id_header(2, 44100);
803 let last = pkt.last_mut().expect("pkt not empty");
805 *last = 0x00;
806 let mut dec = VorbisDecoder::new();
807 let result = dec.process_header_packet(&pkt);
808 assert!(result.is_err(), "missing framing bit must be an error");
809 }
810}