minimqa: start printing mqa bitstream
This commit is contained in:
parent
5998a85dce
commit
9ea3069c09
|
@ -5,6 +5,7 @@ use std::{
|
|||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use bitstream_io::{BitRead, BitReader, LittleEndian};
|
||||
use clap::Parser;
|
||||
use color_eyre::eyre::{self, OptionExt};
|
||||
use symphonia::core::{
|
||||
|
@ -15,8 +16,8 @@ use symphonia::core::{
|
|||
};
|
||||
|
||||
/// Full 40-bit synchronization, including the packet type and 36-bit magic.
|
||||
/// Stored as msb-first for easy searching, though MQA packets are lsb-first
|
||||
const SYNC: u64 = 0xabe0498c88;
|
||||
/// Stored as lsb-first becuase all MQA types are lsb-first
|
||||
const SYNC: u64 = 0x11319207d5;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about)]
|
||||
|
@ -32,6 +33,97 @@ fn main() -> eyre::Result<()> {
|
|||
|
||||
let args = Args::parse();
|
||||
let reader = MQAReader::open(&args.input)?;
|
||||
let mut bit_reader = BitReader::endian(reader, LittleEndian);
|
||||
|
||||
loop {
|
||||
let packet_type: u8 = bit_reader.read(4)?;
|
||||
match packet_type {
|
||||
5 => {
|
||||
print_sync(&mut bit_reader)?;
|
||||
}
|
||||
other => eyre::bail!("Unknown packet type {}", other),
|
||||
}
|
||||
println!("ignoring checksum {}", bit_reader.read::<u8>(4)?);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Sync {
|
||||
pub magic: u64,
|
||||
pub unused: bool,
|
||||
pub orig_rate: u8,
|
||||
pub src_rate: u8,
|
||||
pub render_filter: u8,
|
||||
pub unknown1: u8,
|
||||
pub render_bitdepth: u8,
|
||||
pub unknown: u8,
|
||||
pub auth_info: u8,
|
||||
pub auth_level: u8,
|
||||
pub item_count: u8,
|
||||
pub stream_position: Option<u32>,
|
||||
}
|
||||
|
||||
pub fn print_sync(reader: &mut BitReader<MQAReader, LittleEndian>) -> eyre::Result<()> {
|
||||
println!("magic: {:#x}", reader.read::<u64>(36)?);
|
||||
let stream_pos_flag = reader.read_bit()?;
|
||||
println!("stream_pos_flag: {}", stream_pos_flag);
|
||||
println!("unused: {}", reader.read_bit()?);
|
||||
println!("orig_rate: {}", reader.read::<u8>(5)?);
|
||||
println!("src_rate: {}", reader.read::<u8>(5)?);
|
||||
println!("render_filter: {}", reader.read::<u8>(5)?);
|
||||
println!("unknown: {}", reader.read::<u8>(2)?);
|
||||
println!("renderer_bitdepth: {}", reader.read::<u8>(2)?);
|
||||
println!("unknown: {}", reader.read::<u8>(4)?);
|
||||
println!("auth_info: {}", reader.read::<u8>(4)?);
|
||||
println!("auth_level: {}", reader.read::<u8>(4)?);
|
||||
let item_count = reader.read::<u8>(7)?;
|
||||
println!("item_count: {}", item_count);
|
||||
|
||||
let mut item_sizes = Vec::with_capacity(item_count as usize);
|
||||
for i in 0..item_count {
|
||||
let item_size = reader.read::<u8>(8)?;
|
||||
item_sizes.push(item_size);
|
||||
println!("item_size[{}]: {}", i, item_size);
|
||||
}
|
||||
let mut item_types = Vec::with_capacity(item_count as usize);
|
||||
for i in 0..item_count {
|
||||
let item_type = reader.read::<u8>(8)?;
|
||||
item_types.push(item_type);
|
||||
println!("item_type[{}]: {}", i, item_type);
|
||||
}
|
||||
if stream_pos_flag {
|
||||
println!("stream_position: {}", reader.read::<u32>(32)?);
|
||||
}
|
||||
|
||||
for i in 0..item_count as usize {
|
||||
let item_type = item_types[i];
|
||||
let item_size = item_sizes[i];
|
||||
println!("item {} (type {}, size {}):", i, item_type, item_size);
|
||||
match item_type {
|
||||
0 => {
|
||||
println!(" stage2_dither: {}", reader.read::<u8>(2)?);
|
||||
println!(" gain_index: {}", reader.read::<u8>(4)?);
|
||||
println!(" unknown: {}", reader.read::<u8>(7)?);
|
||||
println!(" unknown: {}", reader.read::<u8>(7)?);
|
||||
if stream_pos_flag {
|
||||
println!(" start_pos: {}", reader.read::<u32>(27)?);
|
||||
reader.skip(1)?;
|
||||
reader.skip(item_size as u32 - 48)?;
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
println!(" unknown: {}", reader.read::<u8>(6)?);
|
||||
println!(" unknown: {}", reader.read::<u8>(2)?);
|
||||
println!(" unknown: {}", reader.read::<u8>(1)?);
|
||||
println!(" unknown: {}", reader.read::<u8>(2)?);
|
||||
if stream_pos_flag {
|
||||
println!(" unknown: {}", reader.read::<u8>(8)?);
|
||||
println!(" unknown: {}", reader.read::<u8>(1)?);
|
||||
println!(" offset: {}", reader.read::<u16>(12)?);
|
||||
}
|
||||
}
|
||||
other => eyre::bail!("Unknown item type {}", other),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -44,8 +136,8 @@ pub struct MQAReader {
|
|||
shift: u32,
|
||||
|
||||
decoded: VecDeque<u8>,
|
||||
remaining_bits: u8,
|
||||
num_remaining_bits: u8,
|
||||
partial_byte: u8,
|
||||
next_bit: u8,
|
||||
}
|
||||
|
||||
impl MQAReader {
|
||||
|
@ -72,8 +164,8 @@ impl MQAReader {
|
|||
track_id,
|
||||
shift: u32::MAX,
|
||||
decoded: VecDeque::new(),
|
||||
remaining_bits: 0,
|
||||
num_remaining_bits: 0,
|
||||
partial_byte: 0,
|
||||
next_bit: 0,
|
||||
};
|
||||
|
||||
let first_packet = result.read_packet_interleaved()?;
|
||||
|
@ -109,21 +201,21 @@ impl MQAReader {
|
|||
fn decode_interleaved(&mut self, sample_buf: &[u32]) {
|
||||
self.decoded.reserve(sample_buf.len() / 16);
|
||||
|
||||
let mut accumulator = self.remaining_bits;
|
||||
let mut num_bits_used = self.num_remaining_bits;
|
||||
let mut accumulator = self.partial_byte;
|
||||
let mut next_bit = self.next_bit;
|
||||
|
||||
for pair in sample_buf.chunks_exact(2) {
|
||||
let bit = (((pair[0] ^ pair[1]) >> self.shift) & 1) as u8;
|
||||
accumulator = accumulator << 1 | bit;
|
||||
num_bits_used += 1;
|
||||
if num_bits_used == 8 {
|
||||
accumulator |= bit << next_bit;
|
||||
next_bit += 1;
|
||||
if next_bit == 8 {
|
||||
self.decoded.push_back(accumulator);
|
||||
num_bits_used = 0;
|
||||
next_bit = 0;
|
||||
accumulator = 0;
|
||||
}
|
||||
}
|
||||
self.remaining_bits = accumulator;
|
||||
self.num_remaining_bits = num_bits_used;
|
||||
self.partial_byte = accumulator;
|
||||
self.next_bit = next_bit;
|
||||
}
|
||||
|
||||
fn find_sync(samples: &[u32]) -> Option<(u32, usize)> {
|
||||
|
@ -131,7 +223,7 @@ impl MQAReader {
|
|||
let mut accumulator: u64 = 0;
|
||||
for (idx, pair) in samples.chunks_exact(2).enumerate() {
|
||||
let bit = (((pair[0] ^ pair[1]) >> shift) & 1) as u64;
|
||||
accumulator = (accumulator << 1 | bit) & 0xff_ffff_ffff;
|
||||
accumulator = accumulator >> 1 | bit << 39;
|
||||
|
||||
if accumulator == SYNC {
|
||||
return Some((shift, idx - 39));
|
||||
|
|
Loading…
Reference in a new issue