use std::collections::HashMap;
use crate::FileLoader;
use crate::SoundPool;
#[derive(Debug)]
pub struct SoundBank {
sound_pools: HashMap< String, SoundPool >,
debug: bool,
}
impl SoundBank {
pub fn new() -> Self {
Self {
sound_pools: HashMap::new(),
debug: false,
}
}
pub fn load_sound( &mut self, fileloader: &mut impl FileLoader, filename: &str, name: &str, number: u16 ) {
let mut sound_pool = SoundPool::new();
if self.debug {
sound_pool.enable_debug();
} else {
sound_pool.disable_debug();
}
sound_pool.load( fileloader, filename, number );
if let Some( old_sound ) = self.sound_pools.insert( name.to_string(), sound_pool ) {
}
}
pub fn load( &mut self, fileloader: &mut impl FileLoader, filename: &str ) {
let mut file = SoundBankFile::new();
file.load( fileloader, filename );
for e in file.entries() {
self.load_sound( fileloader, &e.filename, &e.id, e.max_instances );
}
}
pub fn play( &mut self, name: &str ) {
if let Some( sound ) = self.sound_pools.get_mut( name ) {
sound.play();
}
}
pub fn update( &mut self, timestep: f64 ) {
for sound in self.sound_pools.values_mut() {
sound.update( timestep );
}
}
pub fn next_sample( &mut self ) -> f32 {
let mut v = 0.0;
for p in self.sound_pools.values_mut() {
v += p.next_sample();
}
v
}
pub fn enable_debug( &mut self ) {
self.debug = true;
for sp in self.sound_pools.values_mut() {
sp.enable_debug();
}
}
pub fn disable_debug( &mut self ) {
self.debug = false;
for sp in self.sound_pools.values_mut() {
sp.disable_debug();
}
}
}
#[derive(Debug,Clone)]
pub enum DropMode {
Drop,
Oldest,
}
#[derive(Debug,Clone)]
pub struct Entry {
id: String,
id_crc: u32,
filename: String,
max_instances: u16,
drop_mode: DropMode,
do_loop: bool,
}
#[derive(Debug)]
pub struct SoundBankFile {
entries: Vec<Entry>,
}
impl SoundBankFile {
pub fn new() -> Self {
Self {
entries: vec![],
}
}
pub fn load( &mut self, fileloader: &mut impl FileLoader, filename: &str ) -> bool {
let mut f = fileloader.open( &filename );
if ! f.is_valid() {
println!("Couldn't open file: {}", filename);
return false;
}
let s0 = f.read_u16();
if 0x4f53 != s0 {
println!("Wrong signature {:#02x}", s0 );
return false;
}
let v0 = f.read_u16();
if 0x0001 != v0 {
println!("Wrong version {:#02x}", v0 );
return false;
}
for b in &[ 0x4f, 0x4d, 0x53, 0x4e, 0x44, 0x42, 0x4e ] {
let b1 = f.read_u8();
if *b != b1 {
println!("Wrong signature {:#02x} != {:#02x}", b, b1 );
return false;
}
}
let c = f.read_u8();
if c != b'K' { println!("Unsupported compression mode {}", c );
return false;
}
for b in &[ 0x03, 0x00, 0x00, 0x00 ] {
let b1 = f.read_u8();
if *b != b1 {
println!("Wrong signature {:#02x} != {:#02x}", b, b1 );
return false;
}
}
let ne = f.read_u16();
for e in 0..ne {
let id_crc = f.read_u32();
let mut filename_bytes = vec![0;32];
let mut filename_len = 0;
for n in 0..32 {
let b = f.read_u8();
filename_bytes[ n ] = b;
if b != 0 {
filename_len = n+1;
}
}
filename_bytes.resize( filename_len, 0 );
let filename = String::from_utf8_lossy( &filename_bytes );
let mut name_bytes = vec![0;32];
let mut name_len = 0;
for n in 0..32 {
let b = f.read_u8();
name_bytes[ n ] = b;
if b != 0 {
name_len = n+1;
}
}
name_bytes.resize( name_len, 0 );
let name = String::from_utf8_lossy( &name_bytes );
let max_instances = f.read_u16();
let drop_mode = f.read_u16();
let flags = f.read_u32();
let entry = Entry {
id: name.to_string(),
id_crc,
filename: filename.to_string(),
max_instances,
drop_mode: DropMode::Oldest, do_loop: false, };
self.entries.push( entry );
}
true
}
pub fn entries( self ) -> Vec<Entry> {
self.entries
}
}