1use std::io::{Read, Seek};
2
3use crate::Error;
4use crate::common::*;
5use byteorder::{LittleEndian, ByteOrder};
6use ogg::{Packet, PacketReader};
7use audiopus::{coder::{Decoder as OpusDec, GenericCtl}};
8
9#[cfg(test)]
12use std::cell::RefCell;
13
14#[cfg(test)]
15thread_local! {
16 static LAST_FINAL_RANGE: RefCell<u32> = RefCell::new(0);
17}
18
19#[cfg(test)]
20fn set_final_range(r:u32) {
21 LAST_FINAL_RANGE.with(|f|*f.borrow_mut() = r);
22}
23
24#[cfg(not(test))]
26fn set_final_range(_:u32) {}
27
28#[cfg(test)]
29pub(crate) fn get_final_range() -> u32 {
30 LAST_FINAL_RANGE.with(|f|*f.borrow())
31}
32
33pub struct PlayData {
36 pub channels: u16
37}
38
39pub(crate) const OPUS_MAGIC_HEADER:[u8;8] = [b'O', b'p', b'u', b's', b'H', b'e', b'a', b'd'];
40
41pub fn decode<T: Read + Seek, const TARGET_SPS: u32>(data: T) -> Result<(Vec<i16>, PlayData), Error> {
45 const MAX_FRAME_SAMPLES: usize = 5760; const MAX_FRAME_SIZE: usize = MAX_FRAME_SAMPLES * (MAX_NUM_CHANNELS as usize); let mut reader = PacketReader::new(data);
50 let fp = reader.read_packet_expected().map_err(|_| Error::MalformedAudio)?; struct DecodeData {
53 pre_skip: u16,
54 gain: i32
55 }
56
57 fn check_fp<const TARGET_SPS: u32>(fp: &Packet) -> Result<(PlayData, DecodeData), Error> {
59
60 if fp.data.len() < 19 {
62 return Err(Error::MalformedAudio)
63 }
64
65 if fp.data[0..8] != OPUS_MAGIC_HEADER {
67 return Err(Error::MalformedAudio)
68 }
69
70 if fp.data[8] != 1 {
72 return Err(Error::MalformedAudio)
73 }
74
75
76 Ok((
77 PlayData{
78 channels: fp.data[9] as u16, },
80 DecodeData {
81 pre_skip: calc_sr(LittleEndian::read_u16(&fp.data[10..12]), OGG_OPUS_SPS, TARGET_SPS),
82 gain: LittleEndian::read_i16(&fp.data[16..18]) as i32
83 }
84 ))
85 }
86
87 let (play_data, dec_data) = check_fp::<TARGET_SPS>(&fp)?;
88
89 let chans = match play_data.channels {
90 1 => Ok(audiopus::Channels::Mono),
91 2 => Ok(audiopus::Channels::Stereo),
92 _ => Err(Error::MalformedAudio)
93 }?;
94
95 let opus_sr = s_ps_to_audiopus(TARGET_SPS)?;
96
97 let mut decoder = OpusDec::new(opus_sr, chans)?;
99 decoder.set_gain(dec_data.gain)?;
100
101 let sp = reader.read_packet_expected().map_err(|_| Error::MalformedAudio)?; fn check_sp(sp: &Packet) -> Result<(), Error> {
104 if sp.data.len() < 12 {
105 return Err(Error::MalformedAudio)
106 }
107
108 let head = std::str::from_utf8(&sp.data[0..8]).or_else(|_| Err(Error::MalformedAudio))?;
109 if head != "OpusTags" {
110 return Err(Error::MalformedAudio)
111 }
112
113 Ok(())
114 }
115
116 check_sp(&sp)?;
117
118 let mut buffer: Vec<i16> = Vec::new();
119 let mut rem_skip = dec_data.pre_skip as usize;
120 let mut dec_absgsp = 0;
121 while let Some(packet) = reader.read_packet()? {
122 let mut temp_buffer = [0i16; MAX_FRAME_SIZE];
123 let out_size = decoder.decode(Some(&packet.data), &mut temp_buffer[..], false)?;
124 let absgsp = calc_sr_u64(packet.absgp_page(),OGG_OPUS_SPS, TARGET_SPS) as usize;
125 dec_absgsp += out_size;
126 let trimmed_end = if packet.last_in_stream() && dec_absgsp > absgsp {
127 (out_size as usize * play_data.channels as usize) - (dec_absgsp - absgsp)
128 }
129 else {
130 out_size as usize * play_data.channels as usize
132 } as usize;
133
134 if rem_skip < out_size {
135 buffer.extend_from_slice(&temp_buffer[rem_skip..trimmed_end]);
136 rem_skip = 0;
137 }
138 else {
139 rem_skip -= out_size;
140 }
141
142 }
143
144 if cfg!(test) {set_final_range(decoder.final_range().unwrap())};
145
146 Ok( (buffer, play_data))
147}