This commit is contained in:
Pedro de Oliveira 2022-11-13 03:12:51 +00:00
parent d55935c54b
commit 8e7c90a770
1 changed files with 324 additions and 326 deletions

View File

@ -1,363 +1,361 @@
use std::fmt; use std::fmt;
use std::fs::File; use std::fs::File;
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum Codec { pub enum Codec {
Pcm8BitUnsigned, Pcm8BitUnsigned,
Adpcm4to8, Adpcm4to8,
Adpcm3to8, Adpcm3to8,
Adpcm2to8, Adpcm2to8,
Pcm16BitSigned, Pcm16BitSigned,
Alaw, Alaw,
Ulaw, Ulaw,
Adpcm4to16, Adpcm4to16,
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum BlockType { pub enum BlockType {
Terminator, Terminator,
SoundData, SoundData,
SoundDataContinuation, SoundDataContinuation,
Silence, Silence,
Marker, Marker,
Text, Text,
Repeat, Repeat,
EndRepeat, EndRepeat,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct VocFile { pub struct VocFile {
pub version: (u8, u8), pub version: (u8, u8),
pub blocks: Vec<BlockT> pub blocks: Vec<BlockT>,
} }
impl VocFile { impl VocFile {
pub(crate) fn from_file(file_name: &str) -> Self { pub(crate) fn from_file(file_name: &str) -> Self {
println!("Parsing {} ...", file_name); println!("Parsing {} ...", file_name);
let mut fp = File::open(file_name).unwrap(); let mut fp = File::open(file_name).unwrap();
// Signature - Creative Voice File // Signature - Creative Voice File
let mut signature1_buffer: [u8; 19] = [0; 19]; let mut signature1_buffer: [u8; 19] = [0; 19];
drop(fp.read(&mut signature1_buffer)); drop(fp.read(&mut signature1_buffer));
let signature1_expected = "Creative Voice File"; let signature1_expected = "Creative Voice File";
let signature1 = std::str::from_utf8(&signature1_buffer).unwrap(); let signature1 = std::str::from_utf8(&signature1_buffer).unwrap();
if signature1 != signature1_expected { if signature1 != signature1_expected {
panic!("Bad file. Expected \"{}\" got \"{}\"", signature1_expected, signature1); panic!("Bad file. Expected \"{}\" got \"{}\"", signature1_expected, signature1);
}
// Signature - 1A 1A 00
let mut signature2_buffer: [u8; 3] = [0; 3];
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);
}
// Version
let mut version_buffer: [u8; 2] = [0; 2];
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];
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);
}
let mut voc = VocFile { version, blocks: Vec::new() };
loop {
let mut block_type_buffer: [u8; 1] = [0];
drop(fp.read(&mut block_type_buffer));
let block_type = match block_type_buffer[0] {
0 => BlockType::Terminator,
1 => BlockType::SoundData,
2 => BlockType::SoundDataContinuation,
3 => BlockType::Silence,
4 => BlockType::Marker,
5 => BlockType::Text,
6 => BlockType::Repeat,
7 => BlockType::EndRepeat,
_ => panic!("Bad block type. Got {}", block_type_buffer[0])
};
if block_type == BlockType::Terminator {
let block = Terminator::new();
voc.blocks.push(Box::new(block));
break;
} }
// Signature - 1A 1A 00 let mut block_size_buffer: [u8; 3] = [0; 3];
let mut signature2_buffer: [u8; 3] = [0; 3]; drop(fp.read(&mut block_size_buffer));
drop(fp.read(&mut signature2_buffer)); let block_size = i32::from_le_bytes(
let signature2_expected: [u8; 3] = [0x1A, 0x1A, 0x0]; [block_size_buffer[0], block_size_buffer[1], block_size_buffer[2], 0]
if signature2_buffer != signature2_expected { );
panic!("Bad file. Expected {:02X?} got {:02X?}", signature2_expected, signature2_buffer);
}
// Version let mut address = fp.seek(SeekFrom::Current(0)).unwrap() as i32;
let mut version_buffer: [u8; 2] = [0; 2]; let next = address + block_size;
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 match block_type {
let mut checksum_buffer: [u8; 2] = [0; 2]; BlockType::SoundData => {
drop(fp.read(&mut checksum_buffer)); let mut frequency_divisor_buffer: [u8; 1] = [0];
let checksum = (!version_int + 0x1234).to_le_bytes(); drop(fp.read(&mut frequency_divisor_buffer));
if checksum_buffer != checksum { println!("Byte: {}", frequency_divisor_buffer[0]);
panic!("Bad file. Expected {:02X?} got {:02X?}", checksum, checksum_buffer); let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32);
} println!("sample_rate: {}", sample_rate);
let mut voc = VocFile{ version, blocks: Vec::new() }; let mut codec_buffer: [u8; 1] = [0];
drop(fp.read(&mut codec_buffer));
let codec = match codec_buffer[0] {
0 => Codec::Pcm8BitUnsigned,
1 => Codec::Adpcm4to8,
2 => Codec::Adpcm3to8,
3 => Codec::Adpcm2to8,
4 => Codec::Pcm16BitSigned,
5 => Codec::Alaw,
6 => Codec::Ulaw,
7 => Codec::Adpcm4to16,
_ => panic!("Bad Sound format. Got {}", codec_buffer[0])
};
loop { address = fp.seek(SeekFrom::Current(0)).unwrap() as i32;
let mut block_type_buffer: [u8; 1] = [0]; let mut data: Vec<u8> = vec![0; (next - address) as usize];
drop(fp.read(&mut block_type_buffer)); drop(fp.read(&mut data));
let block_type = match block_type_buffer[0] {
0 => BlockType::Terminator,
1 => BlockType::SoundData,
2 => BlockType::SoundDataContinuation,
3 => BlockType::Silence,
4 => BlockType::Marker,
5 => BlockType::Text,
6 => BlockType::Repeat,
7 => BlockType::EndRepeat,
_ => panic!("Bad block type. Got {}", block_type_buffer[0])
};
if block_type == BlockType::Terminator { let block = SoundData::new(block_size, sample_rate, codec, data);
let block = Terminator::new();
voc.blocks.push(Box::new(block)); voc.blocks.push(Box::new(block));
break;
} }
BlockType::SoundDataContinuation => {
let mut data: Vec<u8> = vec![0; (next - address) as usize];
drop(fp.read(&mut data));
let mut block_size_buffer: [u8; 3] = [0; 3]; let block = SoundDataContinuation::new(block_size, data);
drop(fp.read(&mut block_size_buffer)); voc.blocks.push(Box::new(block));
let block_size = i32::from_le_bytes(
[block_size_buffer[0], block_size_buffer[1], block_size_buffer[2], 0]
);
let mut address = fp.seek(SeekFrom::Current(0)).unwrap() as i32;
let next = address + block_size;
match block_type {
BlockType::SoundData => {
let mut frequency_divisor_buffer: [u8; 1] = [0];
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];
drop(fp.read(&mut codec_buffer));
let codec = match codec_buffer[0] {
0 => Codec::Pcm8BitUnsigned,
1 => Codec::Adpcm4to8,
2 => Codec::Adpcm3to8,
3 => Codec::Adpcm2to8,
4 => Codec::Pcm16BitSigned,
5 => Codec::Alaw,
6 => Codec::Ulaw,
7 => 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];
drop(fp.read(&mut data));
let block = SoundData::new(block_size, sample_rate, codec, data);
voc.blocks.push(Box::new(block));
},
BlockType::SoundDataContinuation => {
let mut data: Vec<u8> = vec![0; (next - address) as usize];
drop(fp.read(&mut data));
let block = SoundDataContinuation::new(block_size, data);
voc.blocks.push(Box::new(block));
},
BlockType::Silence => {
let mut length_buffer: [u8; 2] = [0; 2];
drop(fp.read(&mut length_buffer));
let length = i16::from_le_bytes(length_buffer);
let mut frequency_divisor_buffer: [u8; 1] = [0];
drop(fp.read(&mut frequency_divisor_buffer));
let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32);
let block = Silence { block_type, size: block_size, sample_rate, length};
voc.blocks.push(Box::new(block));
}
BlockType::Text => {
let mut data: Vec<u8> = vec![0; (next - address) as usize];
drop(fp.read(&mut data));
let block = Text { block_type, size: block_size, data };
voc.blocks.push(Box::new(block));
},
_ => panic!("block Type {:?} not implemented", block_type),
} }
BlockType::Silence => {
let mut length_buffer: [u8; 2] = [0; 2];
drop(fp.read(&mut length_buffer));
let length = i16::from_le_bytes(length_buffer);
} let mut frequency_divisor_buffer: [u8; 1] = [0];
voc drop(fp.read(&mut frequency_divisor_buffer));
} let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32);
}
pub trait Block: std::fmt::Debug { let block = Silence { block_type, size: block_size, sample_rate, length };
fn to_bytes(&self) -> Vec<u8>; voc.blocks.push(Box::new(block));
} }
BlockType::Text => {
let mut data: Vec<u8> = vec![0; (next - address) as usize];
drop(fp.read(&mut data));
impl Block for Terminator { let block = Text { block_type, size: block_size, data };
fn to_bytes(&self) -> Vec<u8> { voc.blocks.push(Box::new(block));
vec![self.block_type as u8] }
} _ => panic!("block Type {:?} not implemented", block_type),
}
impl Block for SoundData {
fn to_bytes(&self) -> Vec<u8> {
let size_bytes : [u8; 4] = self.size.to_le_bytes();
let frequency_divisor: u8 = (256i32 - 1000000i32 / self.sample_rate as i32) as u8;
let mut result: Vec<u8> = vec![
self.block_type as u8,
size_bytes[0],
size_bytes[1],
size_bytes[2],
frequency_divisor,
self.codec as u8
];
result.extend_from_slice(&self.data);
result
}
}
impl Block for SoundDataContinuation {
fn to_bytes(&self) -> Vec<u8> {
let mut result: Vec<u8> = vec![self.block_type as u8];
result.extend_from_slice(&self.data);
result
}
}
impl Block for Silence {
fn to_bytes(&self) -> Vec<u8> {
panic!("Not implemented");
vec![self.block_type as u8]
}
}
impl Block for Marker {
fn to_bytes(&self) -> Vec<u8> {
panic!("Not implemented");
vec![self.block_type as u8]
}
}
impl Block for Text {
fn to_bytes(&self) -> Vec<u8> {
let size_bytes : [u8; 4] = self.size.to_le_bytes();
let mut result: Vec<u8> = 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<u8> {
panic!("Not implemented");
vec![self.block_type as u8]
}
}
impl Block for RepeatEnd {
fn to_bytes(&self) -> Vec<u8> {
panic!("Not implemented");
vec![self.block_type as u8]
}
}
type BlockT = Box<dyn Block>;
pub struct Terminator {
block_type: BlockType,
}
impl fmt::Debug for Terminator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Terminator")
.finish()
}
}
impl Terminator {
pub fn new() -> Self {
Self { block_type: BlockType::Terminator }
}
}
pub struct SoundData {
block_type: BlockType,
pub 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("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<u8>) -> Self {
Self {
block_type: BlockType::SoundData,
size,
sample_rate,
codec,
data
} }
} }
voc
} }
}
pub struct SoundDataContinuation { pub trait Block: std::fmt::Debug {
pub block_type: BlockType, fn to_bytes(&self) -> Vec<u8>;
pub size: i32, }
pub data: Vec<u8>,
impl Block for Terminator {
fn to_bytes(&self) -> Vec<u8> {
vec![self.block_type as u8]
} }
}
impl fmt::Debug for SoundDataContinuation { impl Block for SoundData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn to_bytes(&self) -> Vec<u8> {
f.debug_struct("SoundDataContinuation") let size_bytes: [u8; 4] = self.size.to_le_bytes();
.field("size", &self.size) let frequency_divisor: u8 = (256i32 - 1000000i32 / self.sample_rate as i32) as u8;
.finish()
let mut result: Vec<u8> = vec![
self.block_type as u8,
size_bytes[0],
size_bytes[1],
size_bytes[2],
frequency_divisor,
self.codec as u8,
];
result.extend_from_slice(&self.data);
result
}
}
impl Block for SoundDataContinuation {
fn to_bytes(&self) -> Vec<u8> {
let mut result: Vec<u8> = vec![self.block_type as u8];
result.extend_from_slice(&self.data);
result
}
}
impl Block for Silence {
fn to_bytes(&self) -> Vec<u8> {
panic!("Not implemented");
vec![self.block_type as u8]
}
}
impl Block for Marker {
fn to_bytes(&self) -> Vec<u8> {
panic!("Not implemented");
vec![self.block_type as u8]
}
}
impl Block for Text {
fn to_bytes(&self) -> Vec<u8> {
let size_bytes: [u8; 4] = self.size.to_le_bytes();
let mut result: Vec<u8> = 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<u8> {
panic!("Not implemented");
vec![self.block_type as u8]
}
}
impl Block for RepeatEnd {
fn to_bytes(&self) -> Vec<u8> {
panic!("Not implemented");
vec![self.block_type as u8]
}
}
type BlockT = Box<dyn Block>;
pub struct Terminator {
block_type: BlockType,
}
impl fmt::Debug for Terminator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Terminator")
.finish()
}
}
impl Terminator {
pub fn new() -> Self {
Self { block_type: BlockType::Terminator }
}
}
pub struct SoundData {
block_type: BlockType,
pub 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("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<u8>) -> Self {
Self {
block_type: BlockType::SoundData,
size,
sample_rate,
codec,
data,
} }
} }
}
impl SoundDataContinuation { pub struct SoundDataContinuation {
pub fn new(size: i32, data: Vec<u8>) -> Self { pub block_type: BlockType,
Self { pub size: i32,
block_type: BlockType::SoundDataContinuation, pub data: Vec<u8>,
size, }
data
} impl fmt::Debug for SoundDataContinuation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SoundDataContinuation")
.field("size", &self.size)
.finish()
}
}
impl SoundDataContinuation {
pub fn new(size: i32, data: Vec<u8>) -> Self {
Self {
block_type: BlockType::SoundDataContinuation,
size,
data,
} }
} }
}
#[derive(Debug)] #[derive(Debug)]
pub struct Silence { pub struct Silence {
pub block_type: BlockType, pub block_type: BlockType,
pub size: i32, pub size: i32,
pub sample_rate: i32, pub sample_rate: i32,
pub length: i16, pub length: i16,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Marker { pub struct Marker {
block_type: BlockType, block_type: BlockType,
size: i32, size: i32,
value: i16, value: i16,
} }
pub struct Text { pub struct Text {
pub block_type: BlockType, pub block_type: BlockType,
pub size: i32, pub size: i32,
pub data: Vec<u8>, pub data: Vec<u8>,
} }
impl fmt::Debug for Text { impl fmt::Debug for Text {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Text") f.debug_struct("Text")
.field("size", &self.size) .field("size", &self.size)
.finish() .finish()
}
} }
}
#[derive(Debug)] #[derive(Debug)]
pub struct RepeatStart { pub struct RepeatStart {
block_type: BlockType, block_type: BlockType,
size: i32, size: i32,
repeat: i16, repeat: i16,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct RepeatEnd { pub struct RepeatEnd {
block_type: BlockType, block_type: BlockType,
size: i32, size: i32,
} }