minimqa: start printing mqa bitstream

This commit is contained in:
Artemis Tosini 2024-10-12 00:04:14 +00:00
parent 5998a85dce
commit 9ea3069c09
Signed by: artemist
GPG key ID: EE5227935FE3FF18

View file

@ -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));