diff --git a/src/main.rs b/src/main.rs index 634c428..c1c5406 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use std::fs::File; use std::io::{Read, Seek, SeekFrom}; + pub mod voc; fn parse_voc(file_name: &str) { @@ -8,7 +9,7 @@ fn parse_voc(file_name: &str) { // Signature - Creative Voice File let mut signature1_buffer: [u8; 19] = [0; 19]; - std::mem::drop(fp.read(&mut signature1_buffer)); + drop(fp.read(&mut signature1_buffer)); let signature1_expected = "Creative Voice File"; let signature1 = std::str::from_utf8(&signature1_buffer).unwrap(); if signature1 != signature1_expected { @@ -17,7 +18,7 @@ fn parse_voc(file_name: &str) { // Signature - 1A 1A 00 let mut signature2_buffer: [u8; 3] = [0; 3]; - std::mem::drop(fp.read(&mut signature2_buffer)); + drop(fp.read(&mut signature2_buffer)); let signature2_expected: [u8; 3] = [0x1A, 0x1A, 0x0]; if signature2_buffer != signature2_expected { panic!("Bad file. Expected {:02X?} got {:02X?}", signature2_expected, signature2_buffer); @@ -25,13 +26,13 @@ fn parse_voc(file_name: &str) { // Version let mut version_buffer: [u8; 2] = [0; 2]; - std::mem::drop(fp.read(&mut version_buffer)); + drop(fp.read(&mut version_buffer)); let version_int = i16::from_le_bytes(version_buffer); let version = (version_buffer[1], version_buffer[0]); // Version checksum let mut checksum_buffer: [u8; 2] = [0; 2]; - std::mem::drop(fp.read(&mut checksum_buffer)); + drop(fp.read(&mut checksum_buffer)); let checksum = (!version_int + 0x1234).to_le_bytes(); if checksum_buffer != checksum { panic!("Bad file. Expected {:02X?} got {:02X?}", checksum, checksum_buffer); @@ -41,29 +42,27 @@ fn parse_voc(file_name: &str) { loop { let mut block_type_buffer: [u8; 1] = [0]; - std::mem::drop(fp.read(&mut block_type_buffer)); + drop(fp.read(&mut block_type_buffer)); let block_type = match block_type_buffer[0] { 0 => voc::BlockType::Terminator, 1 => voc::BlockType::SoundData, - 2 => voc::BlockType::SoundContinue, + 2 => voc::BlockType::SoundDataContinuation, 3 => voc::BlockType::Silence, 4 => voc::BlockType::Marker, - 5 => voc::BlockType::ASCII, + 5 => voc::BlockType::Text, 6 => voc::BlockType::Repeat, 7 => voc::BlockType::EndRepeat, _ => panic!("Bad block type. Got {}", block_type_buffer[0]) }; if block_type == voc::BlockType::Terminator { - let block = voc::Block::Terminator( voc::Terminator{ block_type } ); - //println!("{:?}", block); - //println!("Found block type 0. Exiting"); - voc.blocks.push(block); + let block = voc::Terminator::new(); + voc.blocks.push(Box::new(block)); break; } let mut block_size_buffer: [u8; 3] = [0; 3]; - std::mem::drop(fp.read(&mut block_size_buffer)); + drop(fp.read(&mut block_size_buffer)); let block_size = i32::from_le_bytes( [block_size_buffer[0], block_size_buffer[1], block_size_buffer[2], 0] ); @@ -74,11 +73,13 @@ fn parse_voc(file_name: &str) { match block_type { voc::BlockType::SoundData => { let mut frequency_divisor_buffer: [u8; 1] = [0]; - std::mem::drop(fp.read(&mut frequency_divisor_buffer)); + drop(fp.read(&mut frequency_divisor_buffer)); + println!("Byte: {}", frequency_divisor_buffer[0]); let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32); + println!("sample_rate: {}", sample_rate); let mut codec_buffer: [u8; 1] = [0]; - std::mem::drop(fp.read(&mut codec_buffer)); + drop(fp.read(&mut codec_buffer)); let codec = match codec_buffer[0] { 0 => voc::Codec::Pcm8BitUnsigned, 1 => voc::Codec::Adpcm4to8, @@ -93,44 +94,50 @@ fn parse_voc(file_name: &str) { address = fp.seek(SeekFrom::Current(0)).unwrap() as i32; let mut data: Vec = vec![0; (next - address) as usize]; - std::mem::drop(fp.read(&mut data)); + drop(fp.read(&mut data)); - let block = voc::Block::SoundData(voc::SoundData { block_type, block_size, sample_rate, codec, data }); - voc.blocks.push(block); + let block = voc::SoundData::new(block_size, sample_rate, codec, data); + voc.blocks.push(Box::new(block)); }, - voc::BlockType::SoundContinue => { + voc::BlockType::SoundDataContinuation => { let mut data: Vec = vec![0; (next - address) as usize]; - std::mem::drop(fp.read(&mut data)); + drop(fp.read(&mut data)); - let block = voc::Block::SoundDataContinuation(voc::SoundDataContinuation { block_type, block_size, data }); - voc.blocks.push(block); + let block = voc::SoundDataContinuation::new(block_size, data); + voc.blocks.push(Box::new(block)); }, - /* - BlockType::Silence => { + + voc::BlockType::Silence => { let mut length_buffer: [u8; 2] = [0; 2]; - std::mem::drop(fp.read(&mut length_buffer)); + drop(fp.read(&mut length_buffer)); let length = i16::from_le_bytes(length_buffer); let mut frequency_divisor_buffer: [u8; 1] = [0]; - std::mem::drop(fp.read(&mut frequency_divisor_buffer)); + drop(fp.read(&mut frequency_divisor_buffer)); let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32); - data_block = DataBlock { block_type, block_size, sample_rate: Some(sample_rate), codec: None, data: Vec::new()}; + let block = voc::Silence { block_type, size: block_size, sample_rate, length}; + voc.blocks.push(Box::new(block)); } - */ - voc::BlockType::ASCII => { - let mut data: Vec = vec![0; (next - address) as usize]; - std::mem::drop(fp.read(&mut data)); - let block = voc::Block::Text(voc::Text { block_type, block_size, data }); - voc.blocks.push(block); + voc::BlockType::Text => { + let mut data: Vec = vec![0; (next - address) as usize]; + drop(fp.read(&mut data)); + + let block = voc::Text { block_type, size: block_size, data }; + voc.blocks.push(Box::new(block)); }, _ => panic!("block Type {:?} not implemented", block_type), } } + println!("{:?}", voc); + for b in voc.blocks { + println!("{:02X?}", b.to_bytes()); + } + } fn main() { @@ -140,6 +147,7 @@ fn main() { parse_voc("C24FF78A.voc"); parse_voc("pest2.voc"); */ - parse_voc("EDEN.MUS"); - parse_voc("EDEN_.MUS"); + parse_voc("pest2.voc"); + //parse_voc("EDEN.MUS"); + //parse_voc("EDEN_.MUS"); } diff --git a/src/voc.rs b/src/voc.rs index 839638f..a15f08c 100644 --- a/src/voc.rs +++ b/src/voc.rs @@ -12,14 +12,15 @@ Adpcm4to16, } - #[derive(Debug, PartialEq)] + + #[derive(Clone, Copy, Debug, PartialEq)] pub enum BlockType { Terminator, SoundData, - SoundContinue, + SoundDataContinuation, Silence, Marker, - ASCII, + Text, Repeat, EndRepeat, } @@ -27,36 +28,113 @@ #[derive(Debug)] pub struct VocFile { pub version: (u8, u8), - pub blocks: Vec + pub blocks: Vec } - #[derive(Debug)] - pub enum Block { - Terminator(Terminator), - SoundData(SoundData), - SoundDataContinuation(SoundDataContinuation), - Silence(Silence), - Marker(Marker), - Text(Text), - RepeatStart(RepeatStart), - RepeatEnd(RepeatEnd), + pub trait Block: std::fmt::Debug { + fn to_bytes(&self) -> Vec; } + impl Block for Terminator { + fn to_bytes(&self) -> Vec { + vec![self.block_type as u8] + } + } + + impl Block for SoundData { + fn to_bytes(&self) -> Vec { + let size_bytes : [u8; 4] = self.size.to_le_bytes(); + let frequency_divisor: u8 = (1844416f32 / self.sample_rate as f32).ceil() as u8; + + let mut result: Vec = vec![ + self.block_type as u8, + size_bytes[0], + size_bytes[1], + size_bytes[2], + frequency_divisor, + ]; + + result.extend_from_slice(&self.data); + + result + } + } + + impl Block for SoundDataContinuation { + fn to_bytes(&self) -> Vec { + let mut result: Vec = vec![self.block_type as u8]; + result.extend_from_slice(&self.data); + result + } + } + + impl Block for Silence { + fn to_bytes(&self) -> Vec { + panic!("Not implemented"); + vec![self.block_type as u8] + } + } + + impl Block for Marker { + fn to_bytes(&self) -> Vec { + panic!("Not implemented"); + vec![self.block_type as u8] + } + } + + impl Block for Text { + fn to_bytes(&self) -> Vec { + let size_bytes : [u8; 4] = self.size.to_le_bytes(); + + let mut result: Vec = vec![ + self.block_type as u8, + size_bytes[0], + size_bytes[1], + size_bytes[2], + ]; + + result.extend_from_slice(&self.data); + + result + } + } + + impl Block for RepeatStart { + fn to_bytes(&self) -> Vec { + panic!("Not implemented"); + vec![self.block_type as u8] + } + } + + impl Block for RepeatEnd { + fn to_bytes(&self) -> Vec { + panic!("Not implemented"); + vec![self.block_type as u8] + } + } + + type BlockT = Box; + pub struct Terminator { - pub block_type: BlockType, + block_type: BlockType, } impl fmt::Debug for Terminator { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Terminator") - .field("type", &self.block_type) .finish() } } + impl Terminator { + pub fn new() -> Self { + Self { block_type: BlockType::Terminator } + } + } + pub struct SoundData { - pub block_type: BlockType, - pub block_size: i32, + block_type: BlockType, + pub size: i32, pub sample_rate: i32, pub codec: Codec, pub data: Vec, @@ -65,55 +143,74 @@ impl fmt::Debug for SoundData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SoundData") - .field("type", &self.block_type) - .field("size", &self.block_size) + .field("size", &self.size) .field("sample_rate", &self.sample_rate) .field("codec", &self.codec) .finish() } } + impl SoundData { + pub fn new(size: i32, sample_rate: i32, codec: Codec, data: Vec) -> Self { + Self { + block_type: BlockType::SoundData, + size, + sample_rate, + codec, + data + } + } + } + pub struct SoundDataContinuation { pub block_type: BlockType, - pub block_size: i32, + pub size: i32, pub data: Vec, } impl fmt::Debug for SoundDataContinuation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SoundDataContinuation") - .field("type", &self.block_type) - .field("size", &self.block_size) + .field("size", &self.size) .finish() } } + impl SoundDataContinuation { + pub fn new(size: i32, data: Vec) -> Self { + Self { + block_type: BlockType::SoundDataContinuation, + size, + data + } + } + } + #[derive(Debug)] pub struct Silence { - block_type: BlockType, - block_size: i32, - sample_rate: i32, - length: i16, + pub block_type: BlockType, + pub size: i32, + pub sample_rate: i32, + pub length: i16, } #[derive(Debug)] pub struct Marker { block_type: BlockType, - block_size: i32, + size: i32, value: i16, } pub struct Text { pub block_type: BlockType, - pub block_size: i32, + pub size: i32, pub data: Vec, } impl fmt::Debug for Text { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Text") - .field("type", &self.block_type) - .field("size", &self.block_size) + .field("size", &self.size) .finish() } } @@ -121,12 +218,12 @@ #[derive(Debug)] pub struct RepeatStart { block_type: BlockType, - block_size: i32, + size: i32, repeat: i16, } #[derive(Debug)] pub struct RepeatEnd { block_type: BlockType, - block_size: i32, + size: i32, }