diff --git a/Cargo.toml b/Cargo.toml index 7badb56..d2e7889 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,5 @@ flate2 = "1.0.26" samplerate = "0.2.4" hound = "3.5.0" pitch_shift = "1.0.0" -uuid = { version = "1.4.1", features = [ "v4" ] } linked_hash_set = "0.1.4" convert_case = "0.6.0" \ No newline at end of file diff --git a/src/reskit/cli/evaluator.rs b/src/reskit/cli/evaluator.rs index 0c04f81..25ca473 100644 --- a/src/reskit/cli/evaluator.rs +++ b/src/reskit/cli/evaluator.rs @@ -21,9 +21,11 @@ pub fn run_command() -> Result<(), Box> { } ), Tools::Soundtrack { input_file, output_file, input_format: _, output_format: _, source_file_format: _, artifact_output_directory, soundtrack_label, instrument_list_label } => { - let result = DmfModule::from_file( &input_file )?; + let result: Vec = input_file.iter().map( | filename | Ok( DmfModule::from_file( &filename )? ) ).collect::, Box>>()?; + // very temporary! + let result: &DmfModule = result.first().ok_or( "must provide input_file" )?; - for ( filename, data ) in result.get_artifacts( &soundtrack_label, &output_file, &artifact_output_directory, &instrument_list_label )? { + for ( filename, data ) in result.get_artifacts( 0, &soundtrack_label, &output_file, &artifact_output_directory, &instrument_list_label )? { println!( "Creating artifact file {}{}", artifact_output_directory, filename ); let mut file = File::create( format!( "{}{}", artifact_output_directory, filename ) )?; file.write_all( &data )? diff --git a/src/reskit/cli/settings.rs b/src/reskit/cli/settings.rs index b7cb176..88a9be9 100644 --- a/src/reskit/cli/settings.rs +++ b/src/reskit/cli/settings.rs @@ -66,9 +66,9 @@ pub enum Tools { Soundtrack { /// Input filename #[arg(short, long)] - input_file: String, + input_file: Vec, - /// Output filename + /// Output filename (if multiple input_files are provided, used as output parent directory) #[arg(short, long)] output_file: String, diff --git a/src/reskit/soundtrack/engines/echo/dmf.rs b/src/reskit/soundtrack/engines/echo/dmf.rs index 866c247..2c9dda3 100644 --- a/src/reskit/soundtrack/engines/echo/dmf.rs +++ b/src/reskit/soundtrack/engines/echo/dmf.rs @@ -1,24 +1,20 @@ use std::{collections::HashMap, cmp::{max, min}, error::Error}; use convert_case::{Case, Casing}; use samplerate::convert; -use uuid::Uuid; -use crate::reskit::{soundtrack::{formats::dmf::{DmfModule, ECHO_EWF_SAMPLE_RATE}, types::{InstrumentType, SampleFormat, Channel, PatternRow, Effect}}, utility::{print_warning, Ring, print_info}}; +use crate::reskit::{soundtrack::{formats::dmf::{DmfModule, ECHO_EWF_SAMPLE_RATE}, types::{InstrumentType, SampleFormat, Channel, PatternRow, Effect}}, utility::{print_warning, Ring}}; use super::engine::{EchoFormat, ESF_FM_1, ESF_FM_2, ESF_FM_3, ESF_FM_4, ESF_FM_5, ESF_FM_6, ESF_PSG_1, ESF_PSG_2, ESF_PSG_3, ESF_PSG_4, EchoEvent, get_events_for_row, compact_delays, ESF_SET_LOOP, ESF_GO_TO_LOOP, ESF_STOP}; - impl EchoFormat for DmfModule { - fn get_artifacts( &self, soundtrack_label: &str, soundtrack_path: &str, artifact_path: &str, instr_list_label: &str ) -> Result>, Box> { + fn get_artifacts( &self, file_index: u32, soundtrack_label: &str, soundtrack_path: &str, artifact_path: &str, instr_list_label: &str ) -> Result>, Box> { let mut files: HashMap> = HashMap::new(); // This next list preserves order of filenames to generate the echo .asm file let mut instrument_filenames: Vec = Vec::new(); + let mut index = 0; for instrument in &self.instruments { match &instrument.instrument_type { InstrumentType::Fm2612( settings ) => { - let uuid = Uuid::new_v4().to_string(); - instrument_filenames.push( format!( "{}.eif", if instrument.name.is_empty() { format!( "fm_{}", uuid ) } else { instrument.name.to_owned() } ) ); - // Create feedback + algorithm byte let alg_fb: u8 = ( settings.fb << 3 ) | settings.alg; @@ -71,12 +67,11 @@ impl EchoFormat for DmfModule { eif.extend( rr_sl ); eif.extend( ssg_eg ); - files.insert( format!( "{}.eif", if instrument.name.is_empty() { format!( "fm_{}", uuid ) } else { instrument.name.to_owned() } ), eif ); + let filename = format!( "file{}_ins{}_{}.eif", file_index, index, instrument.name ); + instrument_filenames.push( filename.clone() ); + files.insert( filename, eif ); }, InstrumentType::PsgDcsg( settings ) => { - let uuid = Uuid::new_v4().to_string(); - instrument_filenames.push( format!( "{}.eef", if instrument.name.is_empty() { format!( "psg_{}", uuid ) } else { instrument.name.to_owned() } ) ); - // Echo uses volume and arpeggio envelopes // Noise envelopes are usable but cannot be articulated in an instrument. // For use of the noise envelope, use ESF $0Bnn/$3Bnn and $3Ann in the stream. @@ -204,15 +199,17 @@ impl EchoFormat for DmfModule { // Echo end loop command envelope.push( 0xFF ); - files.insert( format!( "{}.eef", if instrument.name.is_empty() { format!( "psg_{}", uuid ) } else { instrument.name.to_owned() } ), envelope ); + let filename = format!( "file{}_ins{}_{}.eef", file_index, index, instrument.name ); + instrument_filenames.push( filename.clone() ); + files.insert( filename, envelope ); } } + + index += 1; } + index = 0; for sample in &self.samples { - let uuid = Uuid::new_v4().to_string(); - instrument_filenames.push( format!( "{}.ewf", if sample.name.is_empty() { format!( "sample_{}", uuid ) } else { sample.name.to_owned() } ) ); - // Amplify data in original sample let data: Vec = sample.data .iter() @@ -262,7 +259,11 @@ impl EchoFormat for DmfModule { // Terminate stream data.push( 0xFF ); - files.insert( format!( "{}.ewf", if sample.name.is_empty() { format!( "sample_{}", uuid ) } else { sample.name.to_owned() } ), data ); + let filename = format!( "file{}_sample{}_{}.ewf", file_index, index, sample.name ); + instrument_filenames.push( filename.clone() ); + files.insert( filename, data ); + + index += 1; } // Write Echo ASM file that includes all the instruments diff --git a/src/reskit/soundtrack/engines/echo/engine.rs b/src/reskit/soundtrack/engines/echo/engine.rs index e18282e..d467c7b 100644 --- a/src/reskit/soundtrack/engines/echo/engine.rs +++ b/src/reskit/soundtrack/engines/echo/engine.rs @@ -69,7 +69,7 @@ pub type EchoEvent = Vec; pub trait EchoFormat { - fn get_artifacts( &self, soundtrack_label: &str, soundtrack_path: &str, artifact_path: &str, instrument_list_label: &str ) -> Result>, Box>; + fn get_artifacts( &self, file_index: u32, soundtrack_label: &str, soundtrack_path: &str, artifact_path: &str, instrument_list_label: &str ) -> Result>, Box>; fn get_esf( &self ) -> Result, Box>; diff --git a/src/reskit/soundtrack/types.rs b/src/reskit/soundtrack/types.rs index e2c8a22..1194cbb 100644 --- a/src/reskit/soundtrack/types.rs +++ b/src/reskit/soundtrack/types.rs @@ -2,14 +2,14 @@ use std::{collections::HashMap, error::Error}; use linked_hash_set::LinkedHashSet; -#[derive(Debug)] -pub struct PsgEnvelope< DataFormat > { +#[derive(Debug, PartialEq)] +pub struct PsgEnvelope< DataFormat: PartialEq > { pub envelope: Vec, pub loop_at: Option, pub settings: HashMap<&'static str, bool> } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct PsgSettings { pub volume: PsgEnvelope< u32 >, pub arpeggio: PsgEnvelope< i32 >, @@ -17,7 +17,7 @@ pub struct PsgSettings { pub wavetable: PsgEnvelope< u32 > } -#[derive(Debug, Default)] +#[derive(Debug, Default, PartialEq)] pub struct Fm2612Operator { pub am: u8, pub ar: u8, @@ -33,7 +33,7 @@ pub struct Fm2612Operator { pub ssg_mode: u8 } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct Fm2612Settings { pub alg: u8, pub fb: u8, @@ -42,7 +42,7 @@ pub struct Fm2612Settings { pub operators: [Fm2612Operator; 4] } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum InstrumentType { Fm2612( Fm2612Settings ), PsgDcsg( PsgSettings )