From 9bcc64872bfa042349e959f4baf079d21707cf56 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Tue, 25 Mar 2025 14:19:18 +0100 Subject: vorbis setup header reconstruction is hard --- src/fmod.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 25 deletions(-) (limited to 'src/fmod.rs') diff --git a/src/fmod.rs b/src/fmod.rs index f0e7b4c..8713a56 100644 --- a/src/fmod.rs +++ b/src/fmod.rs @@ -1,7 +1,11 @@ use crate::helper::ReadExt; -use anyhow::{Ok, Result, bail}; +use anyhow::{Result, bail}; +use lewton::{ + audio::PreviousWindowRight, + header::{IdentHeader, SetupHeader, read_header_ident}, +}; use log::debug; -use std::io::{Cursor, Read, Seek, SeekFrom}; +use std::io::{Cursor, Read, Seek, SeekFrom, Write}; pub struct FmodSoundBank { inner: T, @@ -12,6 +16,7 @@ pub struct FmodSoundBank { pub struct StreamInfo { header: StreamHeader, + channels: usize, } struct FsbHeader { @@ -95,18 +100,22 @@ impl FmodSoundBank { for _ in 0..header.num_streams { let header = StreamHeader::from_packed(file.read_u64_le()?)?; - eprintln!("{header:?}"); let mut next = header.next_chunk; + let mut info = StreamInfo { + channels: header.channels as usize, + header, + }; while next { let chunk = ChunkHeader::from_packed(file.read_u32_le()?)?; - match chunk.kind { + ChunkKind::Channels => { + info.channels = file.read_u64_le()? as usize; + } k => todo!("chunk kind {k:?}"), } - next = chunk.next_chunk; } - streams.push(StreamInfo { header }); + streams.push(info); } if header.name_table_size != 0 { @@ -132,22 +141,33 @@ impl FmodSoundBank { inner: file, }) } - pub fn read_stream(&mut self, n: usize) -> Result<()> { + fn stream_read_range(&self, n: usize) -> Result<(u64, u64)> { let info = &self.streams[n]; - - let start = info.header.data_offset; + let start = info.header.data_offset as u64; let end = self .streams .get(n + 1) - .map_or(self.header.data_size, |s| s.header.data_offset); + .map_or(self.header.data_size, |s| s.header.data_offset) as u64; - let mut data = vec![0; (end - start) as usize]; - debug!("{} {}", start, end); - self.inner - .seek(SeekFrom::Start(start as u64 + self.data_base_offset))?; + Ok((start + self.data_base_offset, end - start)) + } + pub fn read_stream_raw(&mut self, n: usize) -> Result> { + let (offset, size) = self.stream_read_range(n)?; + let mut data = vec![0; size as usize]; + self.inner.seek(SeekFrom::Start(offset))?; self.inner.read_exact(&mut data)?; - Ok(()) + Ok(data) + } + pub fn read_stream(&mut self, n: usize) -> Result> { + let (offset, size) = self.stream_read_range(n)?; + + match self.header.format { + FsbFormat::Vorbis => {} + _ => todo!(), + } + + Ok(Vec::new()) } } @@ -161,16 +181,17 @@ struct StreamHeader { } impl StreamHeader { const MASKS: &[u64] = &[ - 0b1000000000000000000000000000000000000000000000000000000000000000, - 0b0111100000000000000000000000000000000000000000000000000000000000, - 0b0000011000000000000000000000000000000000000000000000000000000000, - 0b0000000111111111111111111111111111000000000000000000000000000000, - 0b0000000000000000000000000000000000111111111111111111111111111111, + 0b0000000000000000000000000000000000000000000000000000000000000001, + 0b0000000000000000000000000000000000000000000000000000000000011110, + 0b0000000000000000000000000000000000000000000000000000000001100000, + 0b0000000000000000000000000000001111111111111111111111111110000000, + 0b1111111111111111111111111111110000000000000000000000000000000000, ]; pub fn from_packed(x: u64) -> Result { - let next_chunk = x & Self::MASKS[0] != 0; + eprintln!("{x:032b}"); + let next_chunk = (x & Self::MASKS[0]) != 0; let samplerate_raw = (x & Self::MASKS[1]) >> Self::MASKS[1].trailing_zeros(); - let channels_raw = x & Self::MASKS[2] >> Self::MASKS[2].trailing_zeros(); + let channels_raw = (x & Self::MASKS[2]) >> Self::MASKS[2].trailing_zeros(); let data_offset = (x & Self::MASKS[3]) >> Self::MASKS[3].trailing_zeros(); let samples = x & Self::MASKS[4]; Ok(Self { @@ -202,6 +223,7 @@ impl StreamHeader { } } +#[derive(Debug)] struct ChunkHeader { next_chunk: bool, size: u32, @@ -209,9 +231,9 @@ struct ChunkHeader { } impl ChunkHeader { const MASKS: &[u32] = &[ - 0b10000000000000000000000000000000, - 0b01111111111111111111111110000000, - 0b00000000000000000000000001111111, + 0b00000000000000000000000000000001, + 0b00000001111111111111111111111110, + 0b11111110000000000000000000000000, ]; pub fn from_packed(x: u32) -> Result { let next_chunk = x & Self::MASKS[0] != 0; @@ -250,3 +272,45 @@ impl ChunkKind { } } } + +pub struct VorbisStreamReader { + inner: T, + ident: IdentHeader, + setup: SetupHeader, + previous_window: PreviousWindowRight, +} +impl VorbisStreamReader { + fn read_packet(&mut self) -> Result> { + let packet_size = self.inner.read_u16_le()?; + let mut buf = vec![0; packet_size as usize]; + self.inner.read_exact(&mut buf)?; + Ok(buf) + } + fn decode_packet(&mut self) -> Result>> { + let packet = self.read_packet()?; + Ok(lewton::audio::read_audio_packet_generic( + &self.ident, + &self.setup, + &packet, + &mut self.previous_window, + )?) + } +} + +fn make_vorbis_ident(channels: u8, sample_rate: u32) -> Result { + let mut packet = Vec::new(); + packet.write_all(&[1])?; + packet.write_all(b"vorbis")?; + packet.write_all(&0u32.to_le_bytes())?; + packet.write_all(&[channels])?; + packet.write_all(&sample_rate.to_le_bytes())?; + packet.write_all(&0u32.to_le_bytes())?; + packet.write_all(&0u32.to_le_bytes())?; + packet.write_all(&0u32.to_le_bytes())?; + packet.write_all(&[(8 << 4) | 11])?; + packet.write_all(&1u8.to_le_bytes())?; + Ok(read_header_ident(&packet)?) +} +fn make_vorbis_setup() -> Result { + todo!() +} -- cgit v1.2.3-70-g09d2