Better data structure for tracker effects
parent
8e6e0d9fb8
commit
d86efb29f2
|
@ -2,7 +2,7 @@ use std::{error::Error, fs::File, io::Read, convert::TryInto, collections::HashM
|
|||
use flate2::read::ZlibDecoder;
|
||||
use samplerate::convert;
|
||||
use uuid::Uuid;
|
||||
use crate::reskit::{utility::{get_string, get_u8, skip, get_u32, get_i8, get_i32, get_u16, get_i16, Ring, print_warning}, soundtrack::{types::{SampleFormat, PsgEnvelope, Note, Sample, PsgSettings, PatternRow, Effect}, engines::echo::{EchoFormat, EchoEvent}}};
|
||||
use crate::reskit::{utility::{get_string, get_u8, skip, get_u32, get_i8, get_i32, get_u16, get_i16, Ring, print_warning}, soundtrack::{types::{SampleFormat, PsgEnvelope, Note, Sample, PsgSettings, PatternRow, Effect, DcsgChannelMode, NoiseType}, engines::echo::{EchoFormat, EchoEvent}}};
|
||||
|
||||
const DMF_MAGIC_NUMBER: &'static str = ".DelekDefleMask.";
|
||||
const DMF_SUPPORTED_VERSION: u8 = 27;
|
||||
|
@ -10,6 +10,17 @@ const DMF_MD: u8 = 0x02;
|
|||
const DMF_MD_ENHANCED_CH3: u8 = 0x42;
|
||||
const ECHO_EWF_SAMPLE_RATE: u32 = 10650;
|
||||
|
||||
const DMF_EFFECT_ARPEGGIO: u8 = 0x00;
|
||||
const DMF_EFFECT_PORTAMENTO_UP: u8 = 0x01;
|
||||
const DMF_EFFECT_PORTAMENTO_DOWN: u8 = 0x02;
|
||||
const DMF_EFFECT_PORTA_TO_NOTE: u8 = 0x03;
|
||||
const DMF_EFFECT_SET_PANNING: u8 = 0x08;
|
||||
const DMF_EFFECT_POSITION_JUMP: u8 = 0x0B;
|
||||
const DMF_EFFECT_PATTERN_BREAK: u8 = 0x0D;
|
||||
const DMF_EFFECT_DAC_ENABLE: u8 = 0x17;
|
||||
const DMF_EFFECT_PSG_NOISE_MODE: u8 = 0x20;
|
||||
const DMF_EFFECT_NOTE_CUT: u8 = 0xEC;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FrameMode {
|
||||
Ntsc,
|
||||
|
@ -525,12 +536,68 @@ impl DmfModule {
|
|||
for _ in 0..num_effects {
|
||||
let effect_code = get_i16( bytes.by_ref() )?;
|
||||
let effect_value = get_i16( bytes.by_ref() )?;
|
||||
let effect_value: Option<u8> = if effect_value == -1 { None } else { Some( effect_value as u8 ) };
|
||||
|
||||
if effect_code != -1 {
|
||||
effects.push(
|
||||
Effect{
|
||||
effect_code,
|
||||
effect_value: if effect_value != -1 { Some( effect_value ) } else { None }
|
||||
match effect_code as u8 {
|
||||
DMF_EFFECT_ARPEGGIO => Effect::Arpeggio {
|
||||
first_shift: effect_value.ok_or( "invalid file: expected effect value for arpeggio" )? >> 4,
|
||||
second_shift: effect_value.ok_or( "invalid file: expected effect value for arpeggio" )? & 0x0F
|
||||
},
|
||||
DMF_EFFECT_PORTAMENTO_UP => Effect::PortamentoUp {
|
||||
speed: effect_value.ok_or( "invalid file: expected effect value for portamento up" )?
|
||||
},
|
||||
DMF_EFFECT_PORTAMENTO_DOWN => Effect::PortamentoDown {
|
||||
speed: effect_value.ok_or( "invalid file: expected effect value for portamento down`" )?
|
||||
},
|
||||
DMF_EFFECT_PORTA_TO_NOTE => Effect::PortamentoToNote {
|
||||
speed: effect_value.ok_or( "invalid file: expected effect value for porta to note" )?
|
||||
},
|
||||
DMF_EFFECT_SET_PANNING => {
|
||||
let effect_value = effect_value.ok_or( "invalid file: expected effect value for panning" )?;
|
||||
|
||||
Effect::SetPanning {
|
||||
left: effect_value == 0x10 || effect_value == 0x11,
|
||||
right: effect_value == 0x01 || effect_value == 0x11
|
||||
}
|
||||
},
|
||||
DMF_EFFECT_POSITION_JUMP => {
|
||||
let pattern = effect_value.ok_or( "invalid file: expected effect value for position jump" )?;
|
||||
|
||||
Effect::PositionJump { pattern }
|
||||
},
|
||||
DMF_EFFECT_PATTERN_BREAK => {
|
||||
let start_row = effect_value.ok_or( "invalid file: expected effect value for start row" )?;
|
||||
|
||||
Effect::JumpToNextPattern { start_row }
|
||||
},
|
||||
DMF_EFFECT_DAC_ENABLE => {
|
||||
let enabled = effect_value.ok_or( "invalid file: expected effect value for dac enable" )? != 0;
|
||||
|
||||
Effect::DacEnable { enabled }
|
||||
},
|
||||
DMF_EFFECT_PSG_NOISE_MODE => {
|
||||
let effect_value = effect_value.ok_or( "invalid file: expected effect value for psg noise mode" )?;
|
||||
let mode = match effect_value {
|
||||
0x00 | 0x01 => DcsgChannelMode::FixedFrequency,
|
||||
0x10 | 0x11 => DcsgChannelMode::Ch3Frequency,
|
||||
_ => return Err( "invalid file: invalid effect value setting for psg noise mode" )?
|
||||
};
|
||||
let noise_type = match effect_value {
|
||||
0x00 | 0x10 => NoiseType::PeriodicNoise,
|
||||
0x01 | 0x11 => NoiseType::WhiteNoise,
|
||||
_ => return Err( "invalid file: invalid effect value setting for psg noise mode" )?
|
||||
};
|
||||
|
||||
Effect::DcsgNoiseMode { mode, noise_type }
|
||||
},
|
||||
DMF_EFFECT_NOTE_CUT => {
|
||||
let after_ticks = effect_value.ok_or( "invalid file: expected effect value setting for note cut" )?;
|
||||
|
||||
Effect::NoteCut { after_ticks }
|
||||
}
|
||||
_ => Effect::UnknownEffect{ code: effect_code as u8, parameter: effect_value }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -49,9 +49,30 @@ pub enum Note {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Effect {
|
||||
pub effect_code: i16,
|
||||
pub effect_value: Option<i16>
|
||||
pub enum DcsgChannelMode {
|
||||
Ch3Frequency,
|
||||
FixedFrequency
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum NoiseType {
|
||||
PeriodicNoise,
|
||||
WhiteNoise
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Effect {
|
||||
Arpeggio { first_shift: u8, second_shift: u8 },
|
||||
PortamentoUp { speed: u8 },
|
||||
PortamentoDown { speed: u8 },
|
||||
PortamentoToNote { speed: u8 },
|
||||
SetPanning { left: bool, right: bool },
|
||||
PositionJump { pattern: u8 },
|
||||
JumpToNextPattern { start_row: u8 },
|
||||
DacEnable { enabled: bool },
|
||||
DcsgNoiseMode { mode: DcsgChannelMode, noise_type: NoiseType },
|
||||
NoteCut { after_ticks: u8 },
|
||||
UnknownEffect { code: u8, parameter: Option<u8> }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
Loading…
Reference in New Issue