]>
Commit | Line | Data |
---|---|---|
1 | use nihav_core::codecs::*; | |
2 | use nihav_core::io::byteio::*; | |
3 | use super::qdmcommon::*; | |
4 | use super::qdm2fft::*; | |
5 | use super::qdm2qmf::*; | |
6 | ||
7 | pub const MAX_FRAME_SIZE: usize = 8192; | |
8 | ||
9 | const SOFTCLIP_THRESHOLD: usize = 27600; | |
10 | const HARDCLIP_THRESHOLD: usize = 35716; | |
11 | const SOFTCLIP_SIZE: usize = HARDCLIP_THRESHOLD - SOFTCLIP_THRESHOLD + 1; | |
12 | ||
13 | #[derive(Clone,Copy)] | |
14 | struct Packet { | |
15 | id: u8, | |
16 | size: usize, | |
17 | offset: usize, | |
18 | } | |
19 | ||
20 | impl Packet { | |
21 | fn read(br: &mut ByteReader) -> DecoderResult<Self> { | |
22 | let id = br.read_byte()?; | |
23 | let size = if (id & 0x80) == 0 { br.read_byte()? as usize } else { br.read_u16be()? as usize }; | |
24 | validate!(size <= (br.left() as usize)); | |
25 | Ok(Packet { id: id & 0x7F, size, offset: br.tell() as usize }) | |
26 | } | |
27 | } | |
28 | ||
29 | struct Qdmc2Decoder { | |
30 | ainfo: NAAudioInfo, | |
31 | chmap: NAChannelMap, | |
32 | softclip: [i16; SOFTCLIP_SIZE], | |
33 | qmf_part: QDM2QMF, | |
34 | fft_part: QDM2FFT, | |
35 | audio: [[f32; MAX_FRAME_SIZE]; 2], | |
36 | ||
37 | order: u8, | |
38 | frame_bits: u8, | |
39 | samples: usize, | |
40 | frm_bytes: usize, | |
41 | sf_len: usize, | |
42 | channels: usize, | |
43 | ||
44 | subsampling: u8, | |
45 | do_synth: bool, | |
46 | } | |
47 | ||
48 | impl Qdmc2Decoder { | |
49 | fn new() -> Self { | |
50 | let mut softclip = [0; SOFTCLIP_SIZE]; | |
51 | let delta = 1.0 / ((32767 - SOFTCLIP_THRESHOLD) as f32); | |
52 | let diff = f32::from((SOFTCLIP_THRESHOLD as i16) - 32767); | |
53 | for (i, el) in softclip.iter_mut().enumerate() { | |
54 | *el = (SOFTCLIP_THRESHOLD as i16) - ((((i as f32) * delta).sin() * diff) as i16); | |
55 | } | |
56 | ||
57 | Self { | |
58 | ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 1), | |
59 | chmap: NAChannelMap::new(), | |
60 | audio: [[0.0; MAX_FRAME_SIZE]; 2], | |
61 | softclip, | |
62 | qmf_part: QDM2QMF::new(), | |
63 | fft_part: QDM2FFT::new(), | |
64 | ||
65 | order: 0, | |
66 | frame_bits: 0, | |
67 | samples: 0, | |
68 | frm_bytes: 0, | |
69 | sf_len: 0, | |
70 | channels: 0, | |
71 | ||
72 | subsampling: 0, | |
73 | do_synth: false, | |
74 | } | |
75 | } | |
76 | } | |
77 | ||
78 | impl NADecoder for Qdmc2Decoder { | |
79 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { | |
80 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { | |
81 | if let Some(edata) = info.get_extradata() { | |
82 | validate!(edata.len() >= 36); | |
83 | let mut mr = MemoryReader::new_read(edata.as_slice()); | |
84 | let mut br = ByteReader::new(&mut mr); | |
85 | let size = br.read_u32be()? as usize; | |
86 | validate!(size >= 36 && size <= edata.len()); | |
87 | let tag = br.read_tag()?; | |
88 | validate!(&tag == b"QDCA"); | |
89 | let ver = br.read_u32be()?; | |
90 | validate!(ver == 1); | |
91 | let channels = br.read_u32be()? as usize; | |
92 | validate!(channels == 2 || channels == 1); | |
93 | let srate = br.read_u32be()?; | |
94 | let full_bitrate = br.read_u32be()?; | |
95 | let frame_len = br.read_u32be()? as usize; | |
96 | let packet_size = br.read_u32be()? as usize; | |
97 | validate!(packet_size > 0 && (packet_size & (packet_size - 1)) == 0); | |
98 | validate!(frame_len == packet_size * 16); | |
99 | let bytes_per_frame = br.read_u32be()? as usize; | |
100 | validate!(bytes_per_frame > 6); | |
101 | ||
102 | self.order = (31 - (packet_size.leading_zeros() & 31)) as u8; | |
103 | validate!(self.order >= 6 && self.order <= 8); | |
104 | self.frame_bits = self.order + 4; | |
105 | self.samples = frame_len; | |
106 | self.frm_bytes = bytes_per_frame; | |
107 | self.sf_len = packet_size; | |
108 | self.channels = channels; | |
109 | ||
110 | let srate = if ainfo.get_sample_rate() != 0 { | |
111 | ainfo.get_sample_rate() | |
112 | } else { srate }; | |
113 | self.ainfo = NAAudioInfo::new(srate, channels as u8, SND_S16P_FORMAT, 1); | |
114 | self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap(); | |
115 | ||
116 | self.subsampling = self.order - 6; | |
117 | self.fft_part.set_params(channels, self.sf_len, self.subsampling); | |
118 | self.qmf_part.set_ch_and_subsampling(channels, self.subsampling, full_bitrate); | |
119 | } else { | |
120 | return Err(DecoderError::InvalidData); | |
121 | } | |
122 | ||
123 | Ok(()) | |
124 | } else { | |
125 | Err(DecoderError::InvalidData) | |
126 | } | |
127 | } | |
128 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { | |
129 | let info = pkt.get_stream().get_info(); | |
130 | if let NACodecTypeInfo::Audio(_) = info.get_properties() { | |
131 | let pktbuf = pkt.get_buffer(); | |
132 | validate!(pktbuf.len() == self.frm_bytes); | |
133 | ||
134 | let mut mr = MemoryReader::new_read(pktbuf.as_slice()); | |
135 | let mut br = ByteReader::new(&mut mr); | |
136 | let hdr = Packet::read(&mut br)?; | |
137 | ||
138 | let (is_intra, has_checksum) = match hdr.id { | |
139 | 2 => (true, true), | |
140 | 3 => (true, false), | |
141 | 4 | 5 => (false, true), | |
142 | 6 | 7 => (false, false), | |
143 | _ => return Err(DecoderError::InvalidData), | |
144 | }; | |
145 | if has_checksum { | |
146 | let mut csum = u16::from(br.read_byte()?) * 0x101; | |
147 | csum = csum.wrapping_add(u16::from(br.read_byte()?) * 2); | |
148 | for byte in pktbuf.iter() { | |
149 | csum = csum.wrapping_sub(u16::from(*byte)); | |
150 | } | |
151 | validate!(csum == 0); | |
152 | } | |
153 | self.fft_part.is_intra = is_intra; | |
154 | self.qmf_part.is_intra = is_intra; | |
155 | self.qmf_part.new_frame(); | |
156 | ||
157 | let mut tone_pkt_list = Vec::new(); | |
158 | let mut fft_pkt_list = Vec::new(); | |
159 | while br.left() > 1 { | |
160 | let hdr = Packet::read(&mut br)?; | |
161 | if hdr.id == 0 { break; } | |
162 | match hdr.id { | |
163 | 8 => return Err(DecoderError::NotImplemented), | |
164 | 9..=12 => { | |
165 | tone_pkt_list.push(hdr); | |
166 | }, | |
167 | 13 => { | |
168 | let src = &pktbuf[hdr.offset..][..hdr.size]; | |
169 | let mut br = QdmBitReader::new(src); | |
170 | self.fft_part.read_type_13(&mut br)?; | |
171 | }, | |
172 | 14 => { | |
173 | let src = &pktbuf[hdr.offset..][..hdr.size]; | |
174 | let mut br = QdmBitReader::new(src); | |
175 | self.fft_part.read_type_14(&mut br)?; | |
176 | }, | |
177 | 15 => return Err(DecoderError::NotImplemented), | |
178 | 16..=23 | 31..=39 | 46..=47 => { | |
179 | fft_pkt_list.push(hdr); | |
180 | }, | |
181 | _ => {}, | |
182 | }; | |
183 | br.read_skip(hdr.size)?; | |
184 | } | |
185 | ||
186 | if !tone_pkt_list.is_empty() { | |
187 | let mut has_9 = false; | |
188 | let mut has_10 = false; | |
189 | let mut has_11 = false; | |
190 | let mut pkt_12 = Packet { id: 0, size: 0, offset: 0 }; | |
191 | for hdr in tone_pkt_list.iter() { | |
192 | let src = &pktbuf[hdr.offset..][..hdr.size]; | |
193 | let mut br = QdmBitReader::new(src); | |
194 | match hdr.id { | |
195 | 9 => { self.qmf_part.read_type_9(&mut br)?; has_9 = true; }, | |
196 | 10 => { self.qmf_part.read_type_10(&mut br)?; has_10 = true; }, | |
197 | 11 => { self.qmf_part.read_type_11(&mut br)?; has_11 = true; }, | |
198 | 12 => { pkt_12 = *hdr; }, | |
199 | _ => unreachable!(), | |
200 | }; | |
201 | } | |
202 | if !has_10 { | |
203 | self.qmf_part.fill_default(10); | |
204 | } | |
205 | if !has_11 { | |
206 | self.qmf_part.fill_default(11); | |
207 | } | |
208 | if pkt_12.id == 12 && has_9 && has_10 { | |
209 | let src = &pktbuf[pkt_12.offset..][..pkt_12.size]; | |
210 | let mut br = QdmBitReader::new(src); | |
211 | self.qmf_part.read_type_12(&mut br)?; | |
212 | } else { | |
213 | self.qmf_part.fill_default(12); | |
214 | } | |
215 | self.do_synth = true; | |
216 | } | |
217 | ||
218 | if tone_pkt_list.is_empty() && self.do_synth { | |
219 | self.qmf_part.fill_default(10); | |
220 | self.qmf_part.fill_default(11); | |
221 | self.qmf_part.fill_default(12); | |
222 | } | |
223 | ||
224 | let channels = self.chmap.num_channels(); | |
225 | let abuf = alloc_audio_buffer(self.ainfo, self.samples, self.chmap.clone())?; | |
226 | let mut adata = abuf.get_abuf_i16().unwrap(); | |
227 | let off = [adata.get_offset(0), adata.get_offset(1)]; | |
228 | let dst = adata.get_data_mut().unwrap(); | |
229 | ||
230 | self.audio = [[0.0; MAX_FRAME_SIZE]; 2]; | |
231 | for subframe in 0..16 { | |
232 | if subframe == 2 { | |
233 | self.fft_part.new_frame(); | |
234 | for hdr in fft_pkt_list.iter() { | |
235 | let src = &pktbuf[hdr.offset..][..hdr.size]; | |
236 | let mut br = QdmBitReader::new(src); | |
237 | self.fft_part.read_fft_packet(hdr.id, &mut br)?; | |
238 | } | |
239 | } | |
240 | self.fft_part.generate_tones(subframe); | |
241 | for ch in 0..channels { | |
242 | let output = &mut self.audio[ch][subframe * self.sf_len..][..self.sf_len]; | |
243 | self.fft_part.synth(output, ch); | |
244 | if self.do_synth { | |
245 | self.qmf_part.synth(output, subframe, ch); | |
246 | } | |
247 | } | |
248 | } | |
249 | let frame_len = self.sf_len * 16; | |
250 | for ch in 0..channels { | |
251 | for (src, dst) in self.audio[ch].iter().take(frame_len).zip(dst[off[ch]..].iter_mut()) { | |
252 | let samp = *src as i32; | |
253 | if samp > (HARDCLIP_THRESHOLD as i32) { | |
254 | *dst = 0x7FFF; | |
255 | } else if samp > (SOFTCLIP_THRESHOLD as i32) { | |
256 | *dst = self.softclip[(samp as usize) - SOFTCLIP_THRESHOLD]; | |
257 | } else if samp > -(SOFTCLIP_THRESHOLD as i32) { | |
258 | *dst = samp as i16; | |
259 | } else if samp > -(HARDCLIP_THRESHOLD as i32) { | |
260 | *dst = -self.softclip[(-samp as usize) - SOFTCLIP_THRESHOLD]; | |
261 | } else { | |
262 | *dst = -0x8000; | |
263 | } | |
264 | } | |
265 | } | |
266 | ||
267 | let mut frm = NAFrame::new_from_pkt(pkt, info.replace_info(NACodecTypeInfo::Audio(self.ainfo)), abuf); | |
268 | frm.set_duration(Some(self.samples as u64)); | |
269 | frm.set_keyframe(false); | |
270 | Ok(frm.into_ref()) | |
271 | } else { | |
272 | Err(DecoderError::InvalidData) | |
273 | } | |
274 | } | |
275 | fn flush(&mut self) { | |
276 | self.qmf_part.flush(); | |
277 | self.fft_part.flush(); | |
278 | } | |
279 | } | |
280 | ||
281 | impl NAOptionHandler for Qdmc2Decoder { | |
282 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
283 | fn set_options(&mut self, _options: &[NAOption]) { } | |
284 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
285 | } | |
286 | ||
287 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { | |
288 | Box::new(Qdmc2Decoder::new()) | |
289 | } | |
290 | ||
291 | #[cfg(test)] | |
292 | mod test { | |
293 | use nihav_core::codecs::RegisteredDecoders; | |
294 | use nihav_core::demuxers::RegisteredDemuxers; | |
295 | use nihav_codec_support::test::dec_video::*; | |
296 | use crate::qt_register_all_decoders; | |
297 | use nihav_commonfmt::generic_register_all_demuxers; | |
298 | #[test] | |
299 | fn test_qdm2() { | |
300 | let mut dmx_reg = RegisteredDemuxers::new(); | |
301 | generic_register_all_demuxers(&mut dmx_reg); | |
302 | let mut dec_reg = RegisteredDecoders::new(); | |
303 | qt_register_all_decoders(&mut dec_reg); | |
304 | ||
305 | //test_decode_audio("mov", "assets/QT/0-22050HzSweep8kb.mov", None, Some("qdm2"), &dmx_reg, &dec_reg); | |
306 | // sample: https://samples.mplayerhq.hu/A-codecs/QDM2/sweep/0-22050HzSweep10kb.mov | |
307 | test_decoding("mov", "qdesign-music2", "assets/QT/0-22050HzSweep10kb.mov", None, &dmx_reg, &dec_reg, | |
308 | ExpectedTestResult::Decodes); | |
309 | } | |
310 | } | |
311 | ||
312 | pub const TONE_SCALES: [[f32; 64]; 2] = [ | |
313 | [ | |
314 | 0.17677669, 0.42677650, 0.60355347, 0.85355347, | |
315 | 1.20710683, 1.68359375, 2.37500000, 3.36718750, | |
316 | 4.75000000, 6.73437500, 9.50000000, 13.4687500, | |
317 | 19.0000000, 26.9375000, 38.0000000, 53.8750000, | |
318 | 76.0000000, 107.750000, 152.000000, 215.500000, | |
319 | 304.000000, 431.000000, 608.000000, 862.000000, | |
320 | 1216.00000, 1724.00000, 2432.00000, 3448.00000, | |
321 | 4864.00000, 6896.00000, 9728.00000, 13792.0000, | |
322 | 19456.0000, 27584.0000, 38912.0000, 55168.0000, | |
323 | 77824.0000, 110336.000, 155648.000, 220672.000, | |
324 | 311296.000, 441344.000, 622592.000, 882688.000, | |
325 | 1245184.00, 1765376.00, 2490368.00, 0.00000000, | |
326 | 0.00000000, 0.00000000, 0.00000000, 0.00000000, | |
327 | 0.00000000, 0.00000000, 0.00000000, 0.00000000, | |
328 | 0.00000000, 0.00000000, 0.00000000, 0.00000000, | |
329 | 0.00000000, 0.00000000, 0.00000000, 0.00000000 | |
330 | ], [ | |
331 | 0.59375000, 0.84179688, 1.18750000, 1.68359375, | |
332 | 2.37500000, 3.36718750, 4.75000000, 6.73437500, | |
333 | 9.50000000, 13.4687500, 19.0000000, 26.9375000, | |
334 | 38.0000000, 53.8750000, 76.0000000, 107.750000, | |
335 | 152.000000, 215.500000, 304.000000, 431.000000, | |
336 | 608.000000, 862.000000, 1216.00000, 1724.00000, | |
337 | 2432.00000, 3448.00000, 4864.00000, 6896.00000, | |
338 | 9728.00000, 13792.0000, 19456.0000, 27584.0000, | |
339 | 38912.0000, 55168.0000, 77824.0000, 110336.000, | |
340 | 155648.000, 220672.000, 311296.000, 441344.000, | |
341 | 622592.000, 882688.000, 1245184.00, 1765376.00, | |
342 | 2490368.00, 3530752.00, 0.00000000, 0.00000000, | |
343 | 0.00000000, 0.00000000, 0.00000000, 0.00000000, | |
344 | 0.00000000, 0.00000000, 0.00000000, 0.00000000, | |
345 | 0.00000000, 0.00000000, 0.00000000, 0.00000000, | |
346 | 0.00000000, 0.00000000, 0.00000000, 0.00000000 | |
347 | ] | |
348 | ]; |