add RealMedia and RealAudio muxers
[nihav.git] / nihav-realmedia / src / muxers / rmvb / audiostream.rs
CommitLineData
9dc1fb4b
KS
1use nihav_core::frame::*;
2use nihav_core::muxers::*;
3use super::RMStreamWriter;
4
5// fourcc, codec name, interleaver, version
6static AUDIO_CODEC_REGISTRY: &[(&[u8;4], &str, &[u8;4], u8)] = &[
7 (b"lpcJ", "ra14.4", b"Int0", 3),
8 (b"28_8", "ra28.8", b"Int4", 4),
9 (b"cook", "cook", b"genr", 5),
10 (b"dnet", "ac3", b"Int0", 4),
11 (b"sipr", "sipro", b"sipr", 4),
12 (b"atrc", "atrac3", b"genr", 5),
13 (b"LSD:", "ralf", b"Int0", 6),
14 (b"raac", "aac", b"vbrs", 5),
15 (b"racp", "aac", b"vbrf", 5),
16];
17
18struct InterleaveParams {
19 block_size: usize,
20 factor: usize,
21 frames_per_blk: usize,
22}
23
24trait Interleaver {
25 fn get_flavor(&self) -> usize;
26 fn get_block_size(&self) -> usize;
27 fn get_factor(&self) -> usize;
28 fn get_frames_per_block(&self) -> usize;
29 fn add_packet(&mut self, src: &[u8]) -> bool;
30 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)>;
31 fn flush(&mut self);
32
33 fn get_frame_size(&self) -> usize { self.get_block_size() / self.get_frames_per_block() }
34}
35
36struct NoInterleaver {
37 frame_size: usize,
38 pkt: Option<Vec<u8>>,
39}
40impl Interleaver for NoInterleaver {
41 fn get_flavor(&self) -> usize { 0 }
42 fn get_block_size(&self) -> usize { self.frame_size }
43 fn get_factor(&self) -> usize { 1 }
44 fn get_frames_per_block(&self) -> usize { 1 }
45 fn add_packet(&mut self, src: &[u8]) -> bool {
46 if self.pkt.is_none() {
47 self.pkt = Some(src.to_vec());
48 true
49 } else {
50 false
51 }
52 }
53 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
54 let mut ret = None;
55 std::mem::swap(&mut self.pkt, &mut ret);
56 if let Some(pkt) = ret {
57 Some((pkt, true))
58 } else {
59 None
60 }
61 }
62 fn flush(&mut self) {}
63}
64
65struct Int4Interleaver {
66 flavor: usize,
67 factor: usize,
68 frame_size: usize,
69 block_size: usize,
70 fpb: usize,
71 cur_frame: usize,
72 rd_block: usize,
73 buf: Vec<u8>,
74 map: Vec<usize>,
75}
76impl Int4Interleaver {
77 fn new(frame_size: usize) -> MuxerResult<Self> {
78 let params = RA_28_8_INTERLEAVE_PARAMS;
79 for (flavor, entry) in params.iter().enumerate() {
80 if entry.block_size / entry.frames_per_blk == frame_size {
81 let full_size = entry.frames_per_blk * entry.factor;
82 let mut map = vec![0; full_size];
83 for i in 0..full_size {
84 let fval = i * entry.factor;
85 let mapped = (fval % full_size) + fval / full_size;
86 map[mapped] = i;
87 }
88
89 return Ok(Self {
90 flavor,
91 frame_size,
92 map,
93 factor: entry.factor,
94 block_size: entry.block_size,
95 fpb: entry.frames_per_blk,
96 cur_frame: 0,
97 rd_block: 0,
98 buf: vec![0; entry.block_size * entry.factor],
99 });
100 }
101 }
102 Err(MuxerError::UnsupportedFormat)
103 }
104}
105impl Interleaver for Int4Interleaver {
106 fn get_flavor(&self) -> usize { self.flavor }
107 fn get_block_size(&self) -> usize { self.block_size }
108 fn get_factor(&self) -> usize { self.factor }
109 fn get_frames_per_block(&self) -> usize { self.fpb }
110 fn add_packet(&mut self, src: &[u8]) -> bool {
111 if self.cur_frame == self.factor * self.fpb {
112 return false;
113 }
114 let pos = self.map[self.cur_frame];
115 self.buf[pos * self.frame_size..][..self.frame_size].copy_from_slice(&src);
116 self.cur_frame += 1;
117 true
118 }
119 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
120 if self.cur_frame == self.factor * self.fpb {
121 let first = self.rd_block == 0;
122 let src = &self.buf[self.rd_block * self.block_size..][..self.block_size];
123 self.rd_block += 1;
124 if self.rd_block == self.factor {
125 self.rd_block = 0;
126 self.cur_frame = 0;
127 }
128 Some((src.to_vec(), first))
129 } else {
130 None
131 }
132 }
133 fn flush(&mut self) {
134 if self.cur_frame != 0 {
135 self.cur_frame = self.factor * self.fpb;
136 }
137 }
138}
139
140struct GenericInterleaver {
141 flavor: usize,
142 factor: usize,
143 frame_size: usize,
144 block_size: usize,
145 fpb: usize,
146 cur_frame: usize,
147 rd_block: usize,
148 buf: Vec<u8>,
149 map: Vec<usize>,
150}
151impl GenericInterleaver {
152 fn new(frame_size: usize, fcc: [u8; 4]) -> MuxerResult<Self> {
153 let params = match &fcc {
154 b"atrc" => ATRAC_INTERLEAVE_PARAMS,
155 b"cook" => COOK_INTERLEAVE_PARAMS,
156 b"sipr" => SIPRO_INTERLEAVE_PARAMS,
157 _ => return Err(MuxerError::UnsupportedFormat),
158 };
159 for (flavor, entry) in params.iter().enumerate() {
160 if entry.block_size / entry.frames_per_blk == frame_size {
161 let full_size = entry.frames_per_blk * entry.factor;
162 let mut map = vec![0; full_size];
163
164 let mut frm = 0;
165 let mut blk = 0;
166 let mut even = true;
167 for dst in map.iter_mut() {
168 let mapped = blk * entry.frames_per_blk + frm;
169 blk += 2;
170 if blk >= entry.factor {
171 if even {
172 blk = 1;
173 } else {
174 blk = 0;
175 frm += 1;
176 }
177 even = !even;
178 }
179 *dst = mapped;
180 }
181
182 return Ok(Self {
183 flavor,
184 frame_size,
185 map,
186 factor: entry.factor,
187 block_size: entry.block_size,
188 fpb: entry.frames_per_blk,
189 cur_frame: 0,
190 rd_block: 0,
191 buf: vec![0; entry.block_size * entry.factor],
192 });
193 }
194 }
195 Err(MuxerError::UnsupportedFormat)
196 }
197}
198impl Interleaver for GenericInterleaver {
199 fn get_flavor(&self) -> usize { self.flavor }
200 fn get_block_size(&self) -> usize { self.block_size }
201 fn get_factor(&self) -> usize { self.factor }
202 fn get_frames_per_block(&self) -> usize { self.fpb }
203 fn add_packet(&mut self, src: &[u8]) -> bool {
204 if self.cur_frame == self.factor * self.fpb {
205 return false;
206 }
207 let pos = self.map[self.cur_frame];
208 self.buf[pos * self.frame_size..][..self.frame_size].copy_from_slice(&src);
209 self.cur_frame += 1;
210 true
211 }
212 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
213 if self.cur_frame == self.factor * self.fpb {
214 let first = self.rd_block == 0;
215 let src = &self.buf[self.rd_block * self.block_size..][..self.block_size];
216 self.rd_block += 1;
217 if self.rd_block == self.factor {
218 self.rd_block = 0;
219 self.cur_frame = 0;
220 }
221 Some((src.to_vec(), first))
222 } else {
223 None
224 }
225 }
226 fn flush(&mut self) {
227 if self.cur_frame != 0 {
228 self.cur_frame = self.factor * self.fpb;
229 }
230 }
231}
232
233struct SiproInterleaver {
234 block_size: usize,
235 factor: usize,
236 flavor: usize,
237 buf: Vec<u8>,
238 wr_pos: usize,
239 rd_pos: usize,
240}
241impl SiproInterleaver {
242 fn new(mut frame_size: usize) -> MuxerResult<Self> {
243 if frame_size == 0 {
244 return Err(MuxerError::UnsupportedFormat);
245 }
246 while frame_size < 200 {
247 frame_size <<= 1;
248 }
249 for (flavor, entry) in SIPRO_INTERLEAVE_PARAMS.iter().enumerate() {
250 if entry.block_size == frame_size {
251 return Ok(Self {
252 block_size: entry.block_size,
253 factor: entry.factor,
254 flavor,
255 buf: vec![0; entry.block_size * entry.factor],
256 wr_pos: 0,
257 rd_pos: 0,
258 });
259 }
260 }
261 Err(MuxerError::UnsupportedFormat)
262 }
263}
264impl Interleaver for SiproInterleaver {
265 fn get_flavor(&self) -> usize { self.flavor }
266 fn get_block_size(&self) -> usize { self.block_size }
267 fn get_factor(&self) -> usize { self.factor }
268 fn get_frames_per_block(&self) -> usize { 1 }
269 fn add_packet(&mut self, src: &[u8]) -> bool {
270 if self.wr_pos < self.factor {
271 self.buf[self.wr_pos * self.block_size..][..self.block_size].copy_from_slice(src);
272 self.wr_pos += 1;
273 true
274 } else {
275 false
276 }
277 }
278 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
279 if self.wr_pos == self.factor {
280 let first = self.rd_pos == 0;
281 if self.rd_pos == 0 {
282 sipro_scramble(&mut self.buf, self.factor, self.block_size);
283 }
284 let ret = self.buf[self.rd_pos * self.block_size..][..self.block_size].to_vec();
285 self.rd_pos += 1;
286 if self.rd_pos == self.factor {
287 self.rd_pos = 0;
288 self.wr_pos = 0;
289 }
290 Some((ret, first))
291 } else {
292 None
293 }
294 }
295 fn flush(&mut self) {
296 if self.wr_pos != self.factor {
297 self.wr_pos = self.factor;
298 }
299 }
300}
301
302fn sipro_scramble(buf: &mut [u8], factor: usize, fsize: usize) {
303 let stride = factor * fsize * 2 / 96;
304 for &swap_pair in SIPRO_SWAPS.iter() {
305 let mut sidx = usize::from(swap_pair[0]) * stride;
306 let mut didx = usize::from(swap_pair[1]) * stride;
307 for _ in 0..stride {
308 let in0 = buf[sidx >> 1];
309 let in1 = buf[didx >> 1];
310 let nib0 = (in0 >> ((sidx & 1) * 4)) & 0xF;
311 let nib1 = (in1 >> ((didx & 1) * 4)) & 0xF;
312
313 buf[didx >> 1] = (nib0 << (4 * (didx & 1))) | (in1 & (0xF << (4 * (!didx & 1))));
314 buf[sidx >> 1] = (nib1 << (4 * (sidx & 1))) | (in0 & (0xF << (4 * (!sidx & 1))));
315
316 sidx += 1;
317 didx += 1;
318 }
319 }
320}
321
322struct AACInterleaver {
323 frame_size: usize,
324 data: Vec<u8>,
325 sizes: Vec<usize>,
326 full: bool,
327}
328impl AACInterleaver {
329 fn new(frame_size: usize) -> Self {
330 Self {
331 frame_size,
332 data: Vec::with_capacity(frame_size * 3 / 2),
333 sizes: Vec::with_capacity((frame_size / 128).max(8)),
334 full: false,
335 }
336 }
337}
338impl Interleaver for AACInterleaver {
339 fn get_flavor(&self) -> usize { 0 }
340 fn get_block_size(&self) -> usize { self.frame_size }
341 fn get_factor(&self) -> usize { 1 }
342 fn get_frames_per_block(&self) -> usize { 1 }
343 fn add_packet(&mut self, src: &[u8]) -> bool {
344 if !self.full {
345 self.data.extend_from_slice(src);
346 self.sizes.push(src.len());
347 if self.data.len() >= self.frame_size {
348 self.full = true;
349 }
350 true
351 } else {
352 false
353 }
354 }
355 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
356 if self.full {
357 let mut dst = Vec::with_capacity(self.frame_size);
358 let mut gw = GrowableMemoryWriter::new_write(&mut dst);
359 let mut bw = ByteWriter::new(&mut gw);
360 bw.write_u16be((self.sizes.len() * 16) as u16).unwrap();
361 for &pkt_size in self.sizes.iter() {
362 bw.write_u16be(pkt_size as u16).unwrap();
363 }
364 bw.write_buf(&self.data).unwrap();
365
366 self.data.clear();
367 self.sizes.clear();
368 self.full = false;
369
370 Some((dst, true))
371 } else {
372 None
373 }
374 }
375 fn flush(&mut self) {
376 if !self.sizes.is_empty() {
377 self.full = true;
378 }
379 }
380}
381
382struct InterleaveInfo {
383 fcc: [u8; 4],
384 il_fcc: [u8; 4],
385 block_size: usize,
386 frame_size: usize,
387 factor: usize,
388 flavor: usize,
389}
390
391struct AudioStreamWriter {
392 fcc: [u8; 4],
393 il_fcc: [u8; 4],
394 is_raw: bool,
395 version: u8,
396 header_pos: u64,
397 interleave: Box<dyn Interleaver>,
398 data_size: usize,
399}
400
401impl RMStreamWriter for AudioStreamWriter {
402 fn write_header(&mut self, bw: &mut ByteWriter, astream: &NAStream) -> MuxerResult<()> {
403 self.header_pos = bw.tell();
404 if self.version < 6 {
405 bw.write_buf(b".ra\xFD")?;
406 bw.write_u16be(self.version.into())?;
407 }
408
409 let il_info = InterleaveInfo {
410 fcc: self.fcc,
411 il_fcc: self.il_fcc,
412 block_size: self.interleave.get_block_size(),
413 frame_size: self.interleave.get_frame_size(),
414 factor: self.interleave.get_factor(),
415 flavor: self.interleave.get_flavor(),
416 };
417
418 match self.version {
419 3 => write_aformat3(bw, astream, &il_info)?,
420 4 => write_aformat4(bw, astream, &il_info)?,
421 5 => write_aformat5(bw, astream, &il_info)?,
422 6 => write_lsd(bw, astream)?,
423 _ => unreachable!(),
424 }
425 Ok(())
426 }
427 fn queue_packet(&mut self, pkt: NAPacket) -> bool {
428 let src = pkt.get_buffer();
429 self.data_size += src.len();
430 let frame_size = self.interleave.get_frame_size();
431 if !self.is_raw {
432 let mut ret = false;
433 for frame in src.chunks(frame_size) {
434 ret = self.interleave.add_packet(frame);
435 }
436 ret
437 } else {
438 self.interleave.add_packet(&src)
439 }
440 }
441 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> { self.interleave.get_packet() }
442 fn flush(&mut self) { self.interleave.flush() }
443 fn finish(&mut self, bw: &mut ByteWriter) -> MuxerResult<()> {
444 let cur_pos = bw.tell();
445 match self.version {
446 3 => {
447 bw.seek(SeekFrom::Start(self.header_pos + 18))?;
448 bw.write_u32be(self.data_size as u32)?;
449 },
450 4 | 5 => {
451 bw.seek(SeekFrom::Start(self.header_pos + 12))?;
452 bw.write_u32be(self.data_size/*+header_size*/ as u32)?;
453 bw.seek(SeekFrom::Current(12))?;
454 bw.write_u32be(self.data_size as u32)?;
455 },
456 6 => unimplemented!(),
457 _ => unreachable!(),
458 };
459 bw.seek(SeekFrom::Start(cur_pos))?;
460 Ok(())
461 }
462}
463
464fn write_audio_metadata(bw: &mut ByteWriter) -> MuxerResult<()> {
465 bw.write_byte(0)?; // title_string_length
466 bw.write_byte(0)?; // author_string_length
467 bw.write_byte(0)?; // copyright_string_length
468 bw.write_byte(0)?; // user_string_length
469 Ok(())
470}
471
472fn write_aformat3(bw: &mut ByteWriter, _stream: &NAStream, il_info: &InterleaveInfo) -> MuxerResult<()> {
473 let start = bw.tell();
474 bw.write_u16be(0)?; // header_bytes
475 bw.write_u16be(il_info.flavor as u16)?;
476 bw.write_u32be(il_info.frame_size as u32)?; // granularity
477 bw.write_u32be(0)?; // bytes per minute
478 bw.write_u32be(0)?; // total bytes
479 write_audio_metadata(bw)?;
480 bw.write_byte(0)?; //can_copy
481 bw.write_byte(4)?; // FCC length
482 bw.write_buf(&il_info.fcc)?;
483 let end = bw.tell();
484 bw.seek(SeekFrom::Start(start))?;
485 bw.write_u16be((end - start - 2) as u16)?;
486 bw.seek(SeekFrom::Start(end))?;
487
488 Ok(())
489}
490
491fn write_aformat4(bw: &mut ByteWriter, stream: &NAStream, il_info: &InterleaveInfo) -> MuxerResult<()> {
492 let info = stream.get_info().get_properties().get_audio_info().unwrap();
493
494 bw.write_u16be(0)?;
495 let start = bw.tell();
496 bw.write_buf(b".ra4")?;
497 bw.write_u32be(0)?; // data size
498 bw.write_u16be(4)?; // version
499 bw.write_u16be(0)?; // revision
500 bw.write_u16be(0)?; // header_bytes
501 bw.write_u16be(il_info.flavor as u16)?;
502 bw.write_u32be(il_info.frame_size as u32)?; // granularity
503 bw.write_u32be(0)?; // total bytes
504 bw.write_u32be(0)?; // bytes_per_minute
505 bw.write_u32be(0)?; // bytes_per_minute2
506 bw.write_u16be(il_info.factor as u16)?;
507 bw.write_u16be(il_info.block_size as u16)?;
508 bw.write_u16be(0)?; // user data
509 bw.write_u32be(info.sample_rate)?; // sample rate
510 bw.write_u32be(info.format.bits.into())?; // sample size
511 bw.write_u16be(info.channels.into())?; // num channels
512 bw.write_byte(4)?; // ileave ID len
513 bw.write_buf(&il_info.il_fcc)?;
514 bw.write_byte(4)?; // codec ID len
515 bw.write_buf(&il_info.fcc)?;
516 bw.write_byte(if &il_info.il_fcc == b"Int0" { 0 } else { 1 })?;
517 bw.write_byte(7)?; // can_copy
518 bw.write_byte(0)?; // stream_type
519 write_audio_metadata(bw)?;
520 let end = bw.tell();
521 bw.seek(SeekFrom::Start(start + 12))?;
522 bw.write_u16be((end - start - 4) as u16)?;
523 bw.seek(SeekFrom::Start(end))?;
524
525 Ok(())
526}
527
528fn write_aformat5(bw: &mut ByteWriter, stream: &NAStream, il_info: &InterleaveInfo) -> MuxerResult<()> {
529 let info = stream.get_info().get_properties().get_audio_info().unwrap();
530
531 bw.write_u16be(0)?;
532 let start = bw.tell();
533 bw.write_buf(b".ra5")?;
534 bw.write_u32be(0)?; // data size
535 bw.write_u16be(5)?; // version
536 bw.write_u16be(0)?; // revision
537 bw.write_u16be(0)?; // header_bytes
538 bw.write_u16be(il_info.flavor as u16)?;
539 bw.write_u32be(il_info.block_size as u32)?; // granularity
540 bw.write_u32be(0)?; // total bytes
541 bw.write_u32be(0)?; // bytes_per_minute
542 bw.write_u32be(0)?; // bytes_per_minute2
543 bw.write_u16be(il_info.factor as u16)?;
544 bw.write_u16be(il_info.block_size as u16)?;
545 bw.write_u16be(il_info.frame_size as u16)?;
546 bw.write_u16be(0)?; // user data
547 bw.write_u32be(info.sample_rate)?; // sample rate
548 bw.write_u32be(info.sample_rate)?; // actual sample rate
549 bw.write_u32be(info.format.bits.into())?; // sample size
550 bw.write_u16be(info.channels.into())?; // num channels
551 bw.write_buf(&il_info.il_fcc)?;
552 bw.write_buf(&il_info.fcc)?;
553 bw.write_byte(if &il_info.il_fcc == b"Int0" { 0 } else { 1 })?;
554 bw.write_byte(7)?; // can_copy
555 bw.write_byte(0)?; // stream_type
556 bw.write_byte(0)?; // has_interleave_pattern
557 if let Some(edata) = stream.get_info().get_extradata() {
558 if !matches!(&il_info.fcc, b"raac" | b"racp") {
559 bw.write_u32be(edata.len() as u32)?;
560 bw.write_buf(&edata)?;
561 } else {
562 bw.write_u32be((edata.len() + 1) as u32)?;
563 bw.write_byte(2)?;
564 bw.write_buf(&edata)?;
565 }
566 } else {
567 bw.write_u32be(0)?;
568 }
569 let end = bw.tell();
570 bw.seek(SeekFrom::Start(start + 12))?;
571 bw.write_u16be((end - start - 4) as u16)?;
572 bw.seek(SeekFrom::Start(end))?;
573
574 Ok(())
575}
576
577fn write_lsd(bw: &mut ByteWriter, stream: &NAStream) -> MuxerResult<()> {
578 if let Some(edata) = stream.get_info().get_extradata() {
579 bw.write_buf(&edata)?;
580 }
581 Ok(())
582}
583
584fn create_interleaver(id: [u8; 4], fcc: [u8; 4], ainfo: NAAudioInfo) -> MuxerResult<Box<dyn Interleaver>> {
585 let frame_size = ainfo.block_len;
586 match &id {
587 b"Int0" => Ok(Box::new(NoInterleaver{ frame_size, pkt: None })),
588 b"Int4" => Ok(Box::new(Int4Interleaver::new(frame_size)?)),
589 b"sipr" => Ok(Box::new(SiproInterleaver::new(frame_size)?)),
590 b"genr" => Ok(Box::new(GenericInterleaver::new(frame_size, fcc)?)),
591 b"vbrs" | b"vbrf" => Ok(Box::new(AACInterleaver::new(1024))),
592 _ => unimplemented!(),
593 }
594}
595
596pub fn create_audio_stream(stream: &NAStream) -> MuxerResult<Box<dyn RMStreamWriter>> {
597 let info = stream.get_info();
598 let cname = info.get_name();
599 let mut fourcc = [0u8; 4];
600 let mut ileave = [0u8; 4];
601 let mut version = 0;
602 for &(fcc, name, ileaver, cversion) in AUDIO_CODEC_REGISTRY.iter() {
603 if name == cname {
604 fourcc = *fcc;
605 ileave = *ileaver;
606 version = cversion;
607 break;
608 }
609 }
610 if version > 0 {
611 let ainfo = info.get_properties().get_audio_info().unwrap();
612 Ok(Box::new(AudioStreamWriter {
613 fcc: fourcc,
614 il_fcc: ileave,
615 is_raw: &ileave == b"Int0",
616 version,
617 interleave: create_interleaver(ileave, fourcc, ainfo)?,
618 header_pos: 0,
619 data_size: 0,
620 }))
621 } else {
622 Err(MuxerError::UnsupportedFormat)
623 }
624}
625
626const SIPRO_SWAPS: [[u8; 2]; 38] = [
627 [ 0, 63 ], [ 1, 22 ], [ 2, 44 ], [ 3, 90 ],
628 [ 5, 81 ], [ 7, 31 ], [ 8, 86 ], [ 9, 58 ],
629 [ 10, 36 ], [ 12, 68 ], [ 13, 39 ], [ 14, 73 ],
630 [ 15, 53 ], [ 16, 69 ], [ 17, 57 ], [ 19, 88 ],
631 [ 20, 34 ], [ 21, 71 ], [ 24, 46 ], [ 25, 94 ],
632 [ 26, 54 ], [ 28, 75 ], [ 29, 50 ], [ 32, 70 ],
633 [ 33, 92 ], [ 35, 74 ], [ 38, 85 ], [ 40, 56 ],
634 [ 42, 87 ], [ 43, 65 ], [ 45, 59 ], [ 48, 79 ],
635 [ 49, 93 ], [ 51, 89 ], [ 55, 95 ], [ 61, 76 ],
636 [ 67, 83 ], [ 77, 80 ]
637];
638
639const RA_28_8_INTERLEAVE_PARAMS: &[InterleaveParams] = &[
640 InterleaveParams { block_size: 228, factor: 12, frames_per_blk: 6 },
641];
642const SIPRO_INTERLEAVE_PARAMS: &[InterleaveParams] = &[
643 InterleaveParams { block_size: 232, factor: 6, frames_per_blk: 16 },
644 InterleaveParams { block_size: 304, factor: 6, frames_per_blk: 16 },
645 InterleaveParams { block_size: 296, factor: 6, frames_per_blk: 16 },
646 InterleaveParams { block_size: 320, factor: 6, frames_per_blk: 16 }
647];
648const ATRAC_INTERLEAVE_PARAMS: &[InterleaveParams] = &[
649 InterleaveParams { block_size: 768, factor: 20, frames_per_blk: 4 },
650 InterleaveParams { block_size: 1088, factor: 20, frames_per_blk: 4 },
651 InterleaveParams { block_size: 912, factor: 30, frames_per_blk: 3 },
652 InterleaveParams { block_size: 1152, factor: 30, frames_per_blk: 3 },
653 InterleaveParams { block_size: 1272, factor: 30, frames_per_blk: 3 },
654 InterleaveParams { block_size: 1024, factor: 30, frames_per_blk: 2 },
655 InterleaveParams { block_size: 768, factor: 10, frames_per_blk: 1 },
656 InterleaveParams { block_size: 1024, factor: 10, frames_per_blk: 1 }
657];
658const COOK_INTERLEAVE_PARAMS: &[InterleaveParams] = &[
659 InterleaveParams { block_size: 288, factor: 8, frames_per_blk: 9 },
660 InterleaveParams { block_size: 352, factor: 8, frames_per_blk: 11 },
661 InterleaveParams { block_size: 564, factor: 8, frames_per_blk: 12 },
662 InterleaveParams { block_size: 600, factor: 9, frames_per_blk: 10 },
663 InterleaveParams { block_size: 651, factor: 14, frames_per_blk: 7 },
664 InterleaveParams { block_size: 640, factor: 15, frames_per_blk: 5 },
665 InterleaveParams { block_size: 744, factor: 20, frames_per_blk: 4 },
666 InterleaveParams { block_size: 558, factor: 16, frames_per_blk: 6 },
667 InterleaveParams { block_size: 288, factor: 6, frames_per_blk: 12 },
668 InterleaveParams { block_size: 580, factor: 10, frames_per_blk: 10 },
669 InterleaveParams { block_size: 564, factor: 14, frames_per_blk: 6 },
670 InterleaveParams { block_size: 640, factor: 16, frames_per_blk: 5 },
671 InterleaveParams { block_size: 744, factor: 20, frames_per_blk: 4 },
672 InterleaveParams { block_size: 834, factor: 30, frames_per_blk: 3 },
673 InterleaveParams { block_size: 644, factor: 20, frames_per_blk: 4 },
674 InterleaveParams { block_size: 600, factor: 9, frames_per_blk: 10 },
675 InterleaveParams { block_size: 651, factor: 14, frames_per_blk: 7 },
676 InterleaveParams { block_size: 528, factor: 8, frames_per_blk: 11 },
677 InterleaveParams { block_size: 600, factor: 10, frames_per_blk: 10 },
678 InterleaveParams { block_size: 600, factor: 10, frames_per_blk: 10 },
679 InterleaveParams { block_size: 465, factor: 16, frames_per_blk: 5 },
680 InterleaveParams { block_size: 465, factor: 16, frames_per_blk: 5 },
681 InterleaveParams { block_size: 640, factor: 16, frames_per_blk: 5 },
682 InterleaveParams { block_size: 640, factor: 16, frames_per_blk: 5 },
683 InterleaveParams { block_size: 930, factor: 16, frames_per_blk: 5 },
684 InterleaveParams { block_size: 1400, factor: 16, frames_per_blk: 5 },
685 InterleaveParams { block_size: 376, factor: 8, frames_per_blk: 11 },
686 InterleaveParams { block_size: 930, factor: 16, frames_per_blk: 5 },
687 InterleaveParams { block_size: 1400, factor: 16, frames_per_blk: 5 },
688 InterleaveParams { block_size: 640, factor: 16, frames_per_blk: 5 },
689 InterleaveParams { block_size: 1395, factor: 16, frames_per_blk: 5 },
690 InterleaveParams { block_size: 1143, factor: 10, frames_per_blk: 3 },
691 InterleaveParams { block_size: 1064, factor: 10, frames_per_blk: 2 },
692 InterleaveParams { block_size: 778, factor: 1, frames_per_blk: 1 }
693];