Instruments import
parent
ff2d2a1a24
commit
48f606f637
|
@ -1,4 +1,4 @@
|
||||||
use std::{error::Error, fs::File, io::Read, str::from_utf8, slice::Iter, convert::TryInto};
|
use std::{error::Error, fs::File, io::Read, str::from_utf8, slice::Iter, convert::TryInto, collections::HashMap};
|
||||||
use flate2::read::ZlibDecoder;
|
use flate2::read::ZlibDecoder;
|
||||||
|
|
||||||
const DMF_MAGIC_NUMBER: &'static str = ".DelekDefleMask.";
|
const DMF_MAGIC_NUMBER: &'static str = ".DelekDefleMask.";
|
||||||
|
@ -6,6 +6,12 @@ const DMF_SUPPORTED_VERSION: u8 = 0x18;
|
||||||
const DMF_MD: u8 = 0x02;
|
const DMF_MD: u8 = 0x02;
|
||||||
const DMF_MD_ENHANCED_CH3: u8 = 0x42;
|
const DMF_MD_ENHANCED_CH3: u8 = 0x42;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Either< Type1, Type2 > {
|
||||||
|
Type1( Type1 ),
|
||||||
|
Type2( Type2 )
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FrameMode {
|
pub enum FrameMode {
|
||||||
Ntsc,
|
Ntsc,
|
||||||
|
@ -13,6 +19,58 @@ pub enum FrameMode {
|
||||||
Custom( u8, u8, u8 )
|
Custom( u8, u8, u8 )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct FmOperator {
|
||||||
|
am: u8,
|
||||||
|
ar: u8,
|
||||||
|
dr: u8,
|
||||||
|
mult: u8,
|
||||||
|
rr: u8,
|
||||||
|
sl: u8,
|
||||||
|
tl: u8,
|
||||||
|
dt2: u8,
|
||||||
|
rs: u8,
|
||||||
|
dt: i8,
|
||||||
|
d2r: u8,
|
||||||
|
ssg_mode: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FmSettings {
|
||||||
|
alg: u8,
|
||||||
|
fb: u8,
|
||||||
|
fms: u8,
|
||||||
|
ams: u8,
|
||||||
|
operators: [FmOperator; 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PsgEnvelope {
|
||||||
|
envelope: Either<Vec<u32>, Vec<i32>>,
|
||||||
|
loop_at: Option<usize>,
|
||||||
|
settings: HashMap<&'static str, bool>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PsgSettings {
|
||||||
|
volume: PsgEnvelope,
|
||||||
|
arpeggio: PsgEnvelope,
|
||||||
|
noise: PsgEnvelope,
|
||||||
|
wavetable: PsgEnvelope
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum InstrumentType {
|
||||||
|
Fm( FmSettings ),
|
||||||
|
Psg( PsgSettings )
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Instrument {
|
||||||
|
name: String,
|
||||||
|
instrument_type: InstrumentType
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DmfModule {
|
pub struct DmfModule {
|
||||||
platform: u8,
|
platform: u8,
|
||||||
version: u8,
|
version: u8,
|
||||||
|
@ -21,7 +79,8 @@ pub struct DmfModule {
|
||||||
speed_b: u8,
|
speed_b: u8,
|
||||||
frame_mode: FrameMode,
|
frame_mode: FrameMode,
|
||||||
rows_per_pattern: u32,
|
rows_per_pattern: u32,
|
||||||
patterns: Vec<Vec<u8>>
|
pattern_matrix: Vec<Vec<u8>>,
|
||||||
|
instruments: Vec<Instrument>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_string( bytes: &mut Iter<'_, u8>, take: usize ) -> Result<String, Box<dyn Error>> {
|
fn get_string( bytes: &mut Iter<'_, u8>, take: usize ) -> Result<String, Box<dyn Error>> {
|
||||||
|
@ -38,6 +97,12 @@ fn get_u8( bytes: &mut Iter<'_, u8> ) -> Result<u8, Box<dyn Error>> {
|
||||||
Ok( took )
|
Ok( took )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_i8( bytes: &mut Iter<'_, u8> ) -> Result<i8, Box<dyn Error>> {
|
||||||
|
let took = bytes.take( 1 ).cloned().next().ok_or( "invalid file: expected 1 byte" )?;
|
||||||
|
|
||||||
|
Ok( took as i8 )
|
||||||
|
}
|
||||||
|
|
||||||
fn get_u32( bytes: &mut Iter<'_, u8> ) -> Result<u32, Box<dyn Error>> {
|
fn get_u32( bytes: &mut Iter<'_, u8> ) -> Result<u32, Box<dyn Error>> {
|
||||||
let took = bytes.take( 4 );
|
let took = bytes.take( 4 );
|
||||||
let took: Vec<u8> = took.cloned().collect();
|
let took: Vec<u8> = took.cloned().collect();
|
||||||
|
@ -46,8 +111,16 @@ fn get_u32( bytes: &mut Iter<'_, u8> ) -> Result<u32, Box<dyn Error>> {
|
||||||
Ok( took )
|
Ok( took )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_i32( bytes: &mut Iter<'_, u8> ) -> Result<i32, Box<dyn Error>> {
|
||||||
|
let took = bytes.take( 4 );
|
||||||
|
let took: Vec<u8> = took.cloned().collect();
|
||||||
|
let took = i32::from_le_bytes( took[0..4].try_into()? );
|
||||||
|
|
||||||
|
Ok( took )
|
||||||
|
}
|
||||||
|
|
||||||
fn skip( bytes: &mut Iter<'_, u8>, by: usize ) {
|
fn skip( bytes: &mut Iter<'_, u8>, by: usize ) {
|
||||||
for i in 0..by {
|
for _i in 0..by {
|
||||||
bytes.next();
|
bytes.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,16 +212,16 @@ impl DmfModule {
|
||||||
13
|
13
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut patterns: Vec<Vec<u8>> = vec![vec![0; system_total_channels]; patterns_count.into()];
|
let mut pattern_matrix: Vec<Vec<u8>> = vec![vec![0; system_total_channels]; patterns_count.into()];
|
||||||
for channel in 0..system_total_channels {
|
for channel in 0..system_total_channels {
|
||||||
for pattern in 0..patterns_count {
|
for pattern in 0..patterns_count {
|
||||||
let channel: usize = channel.into();
|
let channel: usize = channel.into();
|
||||||
let pattern: usize = pattern.into();
|
let pattern: usize = pattern.into();
|
||||||
patterns[ pattern ][ channel ] = get_u8( bytes.by_ref() )?;
|
pattern_matrix[ pattern ][ channel ] = get_u8( bytes.by_ref() )?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for pattern in &patterns {
|
for pattern in &pattern_matrix {
|
||||||
for channel in pattern {
|
for channel in pattern {
|
||||||
print!( "{:#04X?} ", channel );
|
print!( "{:#04X?} ", channel );
|
||||||
}
|
}
|
||||||
|
@ -157,10 +230,296 @@ impl DmfModule {
|
||||||
|
|
||||||
print!( "\n" );
|
print!( "\n" );
|
||||||
|
|
||||||
|
let mut instruments: Vec<Instrument> = Vec::new();
|
||||||
|
let instrument_count = get_u8( bytes.by_ref() )?;
|
||||||
|
|
||||||
|
println!( "Instruments:\t{}", instrument_count );
|
||||||
|
|
||||||
|
for i in 0..instrument_count {
|
||||||
|
let name_len = get_u8( bytes.by_ref() )?;
|
||||||
|
let name = get_string( bytes.by_ref(), name_len.into() )?;
|
||||||
|
|
||||||
|
println!( "Instrument {}:\t{}", i, name );
|
||||||
|
|
||||||
|
let mode = get_u8( bytes.by_ref() )?;
|
||||||
|
let instrument_type = match mode {
|
||||||
|
0 => {
|
||||||
|
println!( "Psg Instrument" );
|
||||||
|
|
||||||
|
// Volume envelope
|
||||||
|
let volume = {
|
||||||
|
let size = get_u8( bytes.by_ref() )?;
|
||||||
|
let mut envelope: Vec<u32> = Vec::new();
|
||||||
|
|
||||||
|
for _i in 0..size {
|
||||||
|
envelope.push( get_u32( bytes.by_ref() )? );
|
||||||
|
}
|
||||||
|
|
||||||
|
let loop_at: Option<usize> = if size > 0 {
|
||||||
|
let loop_position = get_i8( bytes.by_ref() )?;
|
||||||
|
if loop_position != -1 {
|
||||||
|
Some( loop_position.try_into()? )
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
println!( "Volume Envelope Size:\t{}", envelope.len() );
|
||||||
|
|
||||||
|
PsgEnvelope {
|
||||||
|
envelope: Either::Type1( envelope ),
|
||||||
|
loop_at,
|
||||||
|
settings: HashMap::new()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Arpeggio envelope
|
||||||
|
let arpeggio = {
|
||||||
|
let size = get_u8( bytes.by_ref() )?;
|
||||||
|
let mut envelope: Vec<i32> = Vec::new();
|
||||||
|
|
||||||
|
for _i in 0..size {
|
||||||
|
envelope.push( get_i32( bytes.by_ref() )? - 12 );
|
||||||
|
}
|
||||||
|
|
||||||
|
let loop_at: Option<usize> = if size > 0 {
|
||||||
|
let loop_position = get_i8( bytes.by_ref() )?;
|
||||||
|
if loop_position != -1 {
|
||||||
|
Some( loop_position.try_into()? )
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let settings = HashMap::from([
|
||||||
|
( "arpeggio_macro_fixed", get_u8( bytes.by_ref() )? == 1 )
|
||||||
|
]);
|
||||||
|
|
||||||
|
println!( "Arpeggio Envelope Size:\t{}", envelope.len() );
|
||||||
|
println!( "Arpeggio Macro Fixed:\t{}", settings[ "arpeggio_macro_fixed" ] );
|
||||||
|
|
||||||
|
PsgEnvelope {
|
||||||
|
envelope: Either::Type2( envelope ),
|
||||||
|
loop_at,
|
||||||
|
settings
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Noise envelope
|
||||||
|
let noise = {
|
||||||
|
let size = get_u8( bytes.by_ref() )?;
|
||||||
|
let mut envelope: Vec<u32> = Vec::new();
|
||||||
|
|
||||||
|
for _i in 0..size {
|
||||||
|
envelope.push( get_u32( bytes.by_ref() )? );
|
||||||
|
}
|
||||||
|
|
||||||
|
let loop_at: Option<usize> = if size > 0 {
|
||||||
|
let loop_position = get_i8( bytes.by_ref() )?;
|
||||||
|
if loop_position != -1 {
|
||||||
|
Some( loop_position.try_into()? )
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
println!( "Noise Envelope Size:\t{}", envelope.len() );
|
||||||
|
|
||||||
|
PsgEnvelope {
|
||||||
|
envelope: Either::Type1( envelope ),
|
||||||
|
loop_at,
|
||||||
|
settings: HashMap::new()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wavetable envelope
|
||||||
|
let wavetable = {
|
||||||
|
let size = get_u8( bytes.by_ref() )?;
|
||||||
|
let mut envelope: Vec<u32> = Vec::new();
|
||||||
|
|
||||||
|
for _i in 0..size {
|
||||||
|
envelope.push( get_u32( bytes.by_ref() )? );
|
||||||
|
}
|
||||||
|
|
||||||
|
let loop_at: Option<usize> = if size > 0 {
|
||||||
|
let loop_position = get_i8( bytes.by_ref() )?;
|
||||||
|
if loop_position != -1 {
|
||||||
|
Some( loop_position.try_into()? )
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
println!( "WavTbl Envelope Size:\t{}\n", envelope.len() );
|
||||||
|
|
||||||
|
PsgEnvelope {
|
||||||
|
envelope: Either::Type1( envelope ),
|
||||||
|
loop_at,
|
||||||
|
settings: HashMap::new()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
InstrumentType::Psg( PsgSettings { volume, arpeggio, noise, wavetable } )
|
||||||
|
},
|
||||||
|
1 => {
|
||||||
|
println!( "Fm Instrument" );
|
||||||
|
|
||||||
|
let alg = get_u8( bytes.by_ref() )?;
|
||||||
|
let fb = get_u8( bytes.by_ref() )?;
|
||||||
|
let fms = get_u8( bytes.by_ref() )?;
|
||||||
|
let ams = get_u8( bytes.by_ref() )?;
|
||||||
|
|
||||||
|
println!( "Alg:\t{}", alg );
|
||||||
|
println!( "Fb:\t{}", fb );
|
||||||
|
println!( "FMS:\t{}", fms );
|
||||||
|
println!( "AMS:\t{}", ams );
|
||||||
|
|
||||||
|
let mut operators: [FmOperator; 4] = [
|
||||||
|
FmOperator::default(),
|
||||||
|
FmOperator::default(),
|
||||||
|
FmOperator::default(),
|
||||||
|
FmOperator::default()
|
||||||
|
];
|
||||||
|
|
||||||
|
// Operator 1
|
||||||
|
{
|
||||||
|
operators[ 0 ].am = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].ar = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].dr = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].mult = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].rr = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].sl = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].tl = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].dt2 = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].rs = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].dt = get_i8( bytes.by_ref() )? - 3;
|
||||||
|
operators[ 0 ].d2r = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 0 ].ssg_mode = get_u8( bytes.by_ref() )?;
|
||||||
|
|
||||||
|
println!( "Op 1 AM:\t{}", operators[ 0 ].am );
|
||||||
|
println!( "Op 1 AR:\t{}", operators[ 0 ].ar );
|
||||||
|
println!( "Op 1 DR:\t{}", operators[ 0 ].dr );
|
||||||
|
println!( "Op 1 MULT:\t{}", operators[ 0 ].mult );
|
||||||
|
println!( "Op 1 RR:\t{}", operators[ 0 ].rr );
|
||||||
|
println!( "Op 1 SL:\t{}", operators[ 0 ].sl );
|
||||||
|
println!( "Op 1 TL:\t{}", operators[ 0 ].tl );
|
||||||
|
println!( "Op 1 DT2:\t{}", operators[ 0 ].dt2 );
|
||||||
|
println!( "Op 1 RS:\t{}", operators[ 0 ].rs );
|
||||||
|
println!( "Op 1 DT:\t{}", operators[ 0 ].dt );
|
||||||
|
println!( "Op 1 D2R:\t{}", operators[ 0 ].d2r );
|
||||||
|
println!( "Op 1 SSG_MODE:\t{}\n", operators[ 0 ].ssg_mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operator 3
|
||||||
|
{
|
||||||
|
operators[ 2 ].am = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].ar = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].dr = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].mult = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].rr = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].sl = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].tl = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].dt2 = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].rs = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].dt = get_i8( bytes.by_ref() )? - 3;
|
||||||
|
operators[ 2 ].d2r = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 2 ].ssg_mode = get_u8( bytes.by_ref() )?;
|
||||||
|
|
||||||
|
println!( "Op 3 AM:\t{}", operators[ 2 ].am );
|
||||||
|
println!( "Op 3 AR:\t{}", operators[ 2 ].ar );
|
||||||
|
println!( "Op 3 DR:\t{}", operators[ 2 ].dr );
|
||||||
|
println!( "Op 3 MULT:\t{}", operators[ 2 ].mult );
|
||||||
|
println!( "Op 3 RR:\t{}", operators[ 2 ].rr );
|
||||||
|
println!( "Op 3 SL:\t{}", operators[ 2 ].sl );
|
||||||
|
println!( "Op 3 TL:\t{}", operators[ 2 ].tl );
|
||||||
|
println!( "Op 3 DT2:\t{}", operators[ 2 ].dt2 );
|
||||||
|
println!( "Op 3 RS:\t{}", operators[ 2 ].rs );
|
||||||
|
println!( "Op 3 DT:\t{}", operators[ 2 ].dt );
|
||||||
|
println!( "Op 3 D2R:\t{}", operators[ 2 ].d2r );
|
||||||
|
println!( "Op 3 SSG_MODE:\t{}\n", operators[ 2 ].ssg_mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operator 2
|
||||||
|
{
|
||||||
|
operators[ 1 ].am = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].ar = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].dr = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].mult = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].rr = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].sl = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].tl = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].dt2 = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].rs = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].dt = get_i8( bytes.by_ref() )? - 3;
|
||||||
|
operators[ 1 ].d2r = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 1 ].ssg_mode = get_u8( bytes.by_ref() )?;
|
||||||
|
|
||||||
|
println!( "Op 2 AM:\t{}", operators[ 1 ].am );
|
||||||
|
println!( "Op 2 AR:\t{}", operators[ 1 ].ar );
|
||||||
|
println!( "Op 2 DR:\t{}", operators[ 1 ].dr );
|
||||||
|
println!( "Op 2 MULT:\t{}", operators[ 1 ].mult );
|
||||||
|
println!( "Op 2 RR:\t{}", operators[ 1 ].rr );
|
||||||
|
println!( "Op 2 SL:\t{}", operators[ 1 ].sl );
|
||||||
|
println!( "Op 2 TL:\t{}", operators[ 1 ].tl );
|
||||||
|
println!( "Op 2 DT2:\t{}", operators[ 1 ].dt2 );
|
||||||
|
println!( "Op 2 RS:\t{}", operators[ 1 ].rs );
|
||||||
|
println!( "Op 2 DT:\t{}", operators[ 1 ].dt );
|
||||||
|
println!( "Op 2 D2R:\t{}", operators[ 1 ].d2r );
|
||||||
|
println!( "Op 2 SSG_MODE:\t{}\n", operators[ 1 ].ssg_mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operator 4
|
||||||
|
{
|
||||||
|
operators[ 3 ].am = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].ar = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].dr = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].mult = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].rr = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].sl = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].tl = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].dt2 = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].rs = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].dt = get_i8( bytes.by_ref() )? - 3;
|
||||||
|
operators[ 3 ].d2r = get_u8( bytes.by_ref() )?;
|
||||||
|
operators[ 3 ].ssg_mode = get_u8( bytes.by_ref() )?;
|
||||||
|
|
||||||
|
println!( "Op 4 AM:\t{}", operators[ 3 ].am );
|
||||||
|
println!( "Op 4 AR:\t{}", operators[ 3 ].ar );
|
||||||
|
println!( "Op 4 DR:\t{}", operators[ 3 ].dr );
|
||||||
|
println!( "Op 4 MULT:\t{}", operators[ 3 ].mult );
|
||||||
|
println!( "Op 4 RR:\t{}", operators[ 3 ].rr );
|
||||||
|
println!( "Op 4 SL:\t{}", operators[ 3 ].sl );
|
||||||
|
println!( "Op 4 TL:\t{}", operators[ 3 ].tl );
|
||||||
|
println!( "Op 4 DT2:\t{}", operators[ 3 ].dt2 );
|
||||||
|
println!( "Op 4 RS:\t{}", operators[ 3 ].rs );
|
||||||
|
println!( "Op 4 DT:\t{}", operators[ 3 ].dt );
|
||||||
|
println!( "Op 4 D2R:\t{}", operators[ 3 ].d2r );
|
||||||
|
println!( "Op 4 SSG_MODE:\t{}\n", operators[ 3 ].ssg_mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrumentType::Fm( FmSettings { alg, fb, fms, ams, operators } )
|
||||||
|
},
|
||||||
|
_ => return Err( format!( "invalid file: invalid instrument mode {}", mode ) )?
|
||||||
|
};
|
||||||
|
|
||||||
|
instruments.push( Instrument { name, instrument_type } );
|
||||||
|
}
|
||||||
|
|
||||||
// TODO !!
|
// TODO !!
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
DmfModule { platform, version, time_base, speed_a, speed_b, frame_mode, rows_per_pattern, patterns }
|
DmfModule {
|
||||||
|
platform, version, time_base, speed_a, speed_b, frame_mode, rows_per_pattern,
|
||||||
|
pattern_matrix, instruments
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue