This commit is contained in:
Pedro de Oliveira 2022-11-13 00:44:15 +00:00
parent 735cd11a16
commit 4ae4a9ebd8
3 changed files with 197 additions and 88 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/target
*.VOC
*.voc
*.bak
/voctool.iml

View File

@ -1,56 +1,6 @@
use std::fmt;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
#[derive(Debug)]
enum Compression {
Pcm8BitUnsigned,
Adpcm4to8,
Adpcm3to8,
Adpcm2to8,
Pcm16BitSigned,
Alaw1,
Alaw2,
Adpcm4to16
}
#[derive(Debug, PartialEq)]
enum BlockType {
Terminator,
SoundData,
SoundContinue,
Silence,
Marker,
ASCII,
Repeat,
EndRepeat
}
struct DataBlock {
block_type: BlockType,
block_size: i32,
sample_rate: Option<i32>,
audio_format: Option<Compression>,
data: Vec<u8>,
}
impl fmt::Debug for DataBlock {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.block_type == BlockType::SoundData {
f.debug_struct("Voc")
.field("type", &self.block_type)
.field("size", &self.block_size)
.field("sample_rate", &self.sample_rate.unwrap())
.field("audio_format", &self.audio_format.as_ref().unwrap())
.finish()
} else {
f.debug_struct("Voc")
.field("type", &self.block_type)
.field("size", &self.block_size)
.finish()
}
}
}
pub mod voc;
fn parse_voc(file_name: &str) {
println!("Parsing {} ...", file_name);
@ -87,25 +37,28 @@ fn parse_voc(file_name: &str) {
panic!("Bad file. Expected {:02X?} got {:02X?}", checksum, checksum_buffer);
}
let mut voc = voc::VocFile{ version, blocks: Vec::new() };
loop {
let mut block_type_buffer: [u8; 1] = [0];
std::mem::drop(fp.read(&mut block_type_buffer));
let block_type = match block_type_buffer[0] {
0 => BlockType::Terminator,
1 => BlockType::SoundData,
2 => BlockType::SoundContinue,
3 => BlockType::Silence,
4 => BlockType::Marker,
5 => BlockType::ASCII,
6 => BlockType::Repeat,
7 => BlockType::EndRepeat,
0 => voc::BlockType::Terminator,
1 => voc::BlockType::SoundData,
2 => voc::BlockType::SoundContinue,
3 => voc::BlockType::Silence,
4 => voc::BlockType::Marker,
5 => voc::BlockType::ASCII,
6 => voc::BlockType::Repeat,
7 => voc::BlockType::EndRepeat,
_ => panic!("Bad block type. Got {}", block_type_buffer[0])
};
if block_type == BlockType::Terminator {
let data_block = DataBlock { block_type, block_size: 0, sample_rate: None, audio_format: None, data: Vec::new() };
println!("{:?}", data_block);
println!("Found block type 0. Exiting");
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);
break;
}
@ -118,56 +71,75 @@ fn parse_voc(file_name: &str) {
let mut address = fp.seek(SeekFrom::Current(0)).unwrap() as i32;
let next = address + block_size;
let mut data_block: DataBlock;
match block_type {
BlockType::SoundData => {
let mut sample_rate_buffer: [u8; 1] = [0];
std::mem::drop(fp.read(&mut sample_rate_buffer));
let sample_rate: i32 = 1000000i32 / (256i32 - sample_rate_buffer[0] as i32);
voc::BlockType::SoundData => {
let mut frequency_divisor_buffer: [u8; 1] = [0];
std::mem::drop(fp.read(&mut frequency_divisor_buffer));
let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32);
let mut audio_format_buffer: [u8; 1] = [0];
std::mem::drop(fp.read(&mut audio_format_buffer));
let audio_format = match audio_format_buffer[0] {
0 => Compression::Pcm8BitUnsigned,
1 => Compression::Adpcm4to8,
2 => Compression::Adpcm3to8,
3 => Compression::Adpcm2to8,
4 => Compression::Pcm16BitSigned,
5 => Compression::Alaw1,
6 => Compression::Alaw2,
7 => Compression::Adpcm4to16,
_ => panic!("Bad Sound format. Got {}", audio_format_buffer[0])
let mut codec_buffer: [u8; 1] = [0];
std::mem::drop(fp.read(&mut codec_buffer));
let codec = match codec_buffer[0] {
0 => voc::Codec::Pcm8BitUnsigned,
1 => voc::Codec::Adpcm4to8,
2 => voc::Codec::Adpcm3to8,
3 => voc::Codec::Adpcm2to8,
4 => voc::Codec::Pcm16BitSigned,
5 => voc::Codec::Alaw,
6 => voc::Codec::Ulaw,
7 => voc::Codec::Adpcm4to16,
_ => panic!("Bad Sound format. Got {}", codec_buffer[0])
};
address = fp.seek(SeekFrom::Current(0)).unwrap() as i32;
let mut data: Vec<u8> = vec![0; (next - address) as usize];
std::mem::drop(fp.read(&mut data));
data_block = DataBlock { block_type, block_size, sample_rate: Some(sample_rate), audio_format: Some(audio_format), data };
let block = voc::Block::SoundData(voc::SoundData { block_type, block_size, sample_rate, codec, data });
voc.blocks.push(block);
},
BlockType::SoundContinue => {
voc::BlockType::SoundContinue => {
let mut data: Vec<u8> = vec![0; (next - address) as usize];
std::mem::drop(fp.read(&mut data));
data_block = DataBlock { block_type, block_size, sample_rate: None, audio_format: None, data };
let block = voc::Block::SoundDataContinuation(voc::SoundDataContinuation { block_type, block_size, data });
voc.blocks.push(block);
},
BlockType::ASCII => {
/*
BlockType::Silence => {
let mut length_buffer: [u8; 2] = [0; 2];
std::mem::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));
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()};
}
*/
voc::BlockType::ASCII => {
let mut data: Vec<u8> = vec![0; (next - address) as usize];
std::mem::drop(fp.read(&mut data));
data_block = DataBlock { block_type, block_size, sample_rate: None, audio_format: None, data };
let block = voc::Block::Text(voc::Text { block_type, block_size, data });
voc.blocks.push(block);
},
_ => panic!("block Type {:?} not implemented", block_type),
}
println!("{:?}", data_block);
}
println!("{:?}", voc);
}
fn main() {
/*
parse_voc("_C24FF78A.voc");
parse_voc("pest.voc");
parse_voc("C24FF78A.voc");
parse_voc("pest2.voc");
*/
parse_voc("EDEN.MUS");
parse_voc("EDEN_.MUS");
}

132
src/voc.rs Normal file
View File

@ -0,0 +1,132 @@
use std::fmt;
#[derive(Debug)]
pub enum Codec {
Pcm8BitUnsigned,
Adpcm4to8,
Adpcm3to8,
Adpcm2to8,
Pcm16BitSigned,
Alaw,
Ulaw,
Adpcm4to16,
}
#[derive(Debug, PartialEq)]
pub enum BlockType {
Terminator,
SoundData,
SoundContinue,
Silence,
Marker,
ASCII,
Repeat,
EndRepeat,
}
#[derive(Debug)]
pub struct VocFile {
pub version: (u8, u8),
pub blocks: Vec<Block>
}
#[derive(Debug)]
pub enum Block {
Terminator(Terminator),
SoundData(SoundData),
SoundDataContinuation(SoundDataContinuation),
Silence(Silence),
Marker(Marker),
Text(Text),
RepeatStart(RepeatStart),
RepeatEnd(RepeatEnd),
}
pub struct Terminator {
pub 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()
}
}
pub struct SoundData {
pub block_type: BlockType,
pub block_size: i32,
pub sample_rate: i32,
pub codec: Codec,
pub data: Vec<u8>,
}
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("sample_rate", &self.sample_rate)
.field("codec", &self.codec)
.finish()
}
}
pub struct SoundDataContinuation {
pub block_type: BlockType,
pub block_size: i32,
pub data: Vec<u8>,
}
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)
.finish()
}
}
#[derive(Debug)]
pub struct Silence {
block_type: BlockType,
block_size: i32,
sample_rate: i32,
length: i16,
}
#[derive(Debug)]
pub struct Marker {
block_type: BlockType,
block_size: i32,
value: i16,
}
pub struct Text {
pub block_type: BlockType,
pub block_size: i32,
pub data: Vec<u8>,
}
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)
.finish()
}
}
#[derive(Debug)]
pub struct RepeatStart {
block_type: BlockType,
block_size: i32,
repeat: i16,
}
#[derive(Debug)]
pub struct RepeatEnd {
block_type: BlockType,
block_size: i32,
}