Fix bug with seeking default psg instrument

master
Ashley N. 2023-09-01 23:56:11 -04:00
parent be82baedc8
commit 9d66523671
1 changed files with 25 additions and 30 deletions

View File

@ -1,5 +1,4 @@
use std::{collections::{HashMap, HashSet}, error::Error, cmp::{min, max}};
use linked_hash_map::LinkedHashMap;
use std::{collections::HashSet, error::Error, cmp::{min, max}};
use linked_hash_set::LinkedHashSet;
use crate::reskit::{soundtrack::types::{PatternRow, Note, Channel, OctaveFrequency, Effect, Instrument, NoiseType, DcsgChannelMode, InstrumentType, CombinedAssets, Sample}, utility::print_warning};
@ -63,11 +62,10 @@ const ESF_SEMITONE_B: u8 = 11;
struct InstrumentSet<'a> {
fm_ids: HashSet<u16>,
psg_ids: HashSet<u16>,
module_set: &'a Vec<Instrument>,
total_set: &'a Vec<Instrument>,
module_instruments: &'a Vec<Instrument>,
total_instruments: &'a Vec<Instrument>,
module_samples: &'a Vec<Sample>,
total_samples: &'a Vec<Sample>,
default_psg_id: Option<u16>
total_samples: &'a Vec<Sample>
}
pub type EchoEvent = Vec<u8>;
@ -313,10 +311,10 @@ fn get_events_for_channel( channels: &mut [Channel], active_channel: usize, row:
invalid_channel => return Err( format!( "internal error: get_events_for_channel: invalid channel {:#04X}", invalid_channel ) )?
};
// Hop one layer of indirection from `instrument` by getting it from instrument_set.module_set,
// then finding the index of that instrument in instrument_set.total_set.
let original_instrument = &asset_set.module_set[ *instrument as usize ];
let instrument = asset_set.total_set.iter().position( | instrument | instrument == original_instrument ).ok_or( "internal error: could not locate instrument in combined instrument set" )?;
// Hop one layer of indirection from `instrument` by getting it from instrument_set.module_instruments,
// then finding the index of that instrument in instrument_set.total_instruments.
let original_instrument = &asset_set.module_instruments[ *instrument as usize ];
let instrument = asset_set.total_instruments.iter().position( | instrument | instrument == original_instrument ).ok_or( "internal error: could not locate instrument in combined instrument set" )?;
// Do not set the same instrument if it was already set before
if &channels[ active_channel ].active_instrument != &Some( instrument as u16 ) {
@ -330,7 +328,12 @@ fn get_events_for_channel( channels: &mut [Channel], active_channel: usize, row:
print_warning( "this is a psg channel, seting the default psg instrument so your note can still play..." );
if row.note.is_some() {
// Set "__reskit_default_psg_instrument"
let instrument = asset_set.default_psg_id.ok_or( "internal error: no default psg instrument to apply" )?;
let default_psg_id = if let Some( position ) = asset_set.total_instruments.iter().position( | item | item.name == "__reskit_default_psg_instrument" ) {
Some( position as u16 )
} else {
None
};
let instrument = default_psg_id.ok_or( "internal error: no default psg instrument to apply" )?;
events.push( vec![ ESF_SET_INSTRUMENT | channels[ active_channel ].id, instrument as u8 ] );
channels[ active_channel ].active_instrument = Some( instrument );
@ -344,7 +347,12 @@ fn get_events_for_channel( channels: &mut [Channel], active_channel: usize, row:
if channels[ active_channel ].active_instrument.is_none() && ( ESF_PSG_1..=ESF_PSG_4 ).contains( &channels[ active_channel ].id ) {
if row.note.is_some() {
// Set "__reskit_default_psg_instrument"
let instrument = asset_set.default_psg_id.ok_or( "internal error: no default psg instrument to apply" )?;
let default_psg_id = if let Some( position ) = asset_set.total_instruments.iter().position( | item | item.name == "__reskit_default_psg_instrument" ) {
Some( position as u16 )
} else {
None
};
let instrument = default_psg_id.ok_or( "internal error: no default psg instrument to apply" )?;
events.push( vec![ ESF_SET_INSTRUMENT | channels[ active_channel ].id, instrument as u8 ] );
channels[ active_channel ].active_instrument = Some( instrument );
@ -391,7 +399,7 @@ fn get_events_for_channel( channels: &mut [Channel], active_channel: usize, row:
// Remember, instruments will always be listed first in the output source file, followed by pointers to samples
// So the minimum sample offset is the number of instruments
events.push( vec![ ESF_NOTE_ON | channels[ active_channel ].id, global_sample_index as u8 + asset_set.total_set.len() as u8 ] );
events.push( vec![ ESF_NOTE_ON | channels[ active_channel ].id, global_sample_index as u8 + asset_set.total_instruments.len() as u8 ] );
}
} else if channels[ active_channel ].id == ESF_PSG_4 {
// Find the single (and it should only ever be a single) Effect::DcsgNoiseMode attached to the channel
@ -832,20 +840,8 @@ fn get_delays( events: Vec<EchoEvent>, channels: &mut [Channel], ticks_to_wait:
pub fn get_events_for_row( channels: &mut [Channel], module_instruments: &Vec<Instrument>, module_samples: &Vec<Sample>, asset_set: &CombinedAssets, subrows: Vec<&PatternRow>, ticks_to_wait: u8 ) -> Result<Vec<EchoEvent>, Box<dyn Error>> {
let mut events: Vec<EchoEvent> = Vec::new();
let mut index = 0;
// Find the index of the default psg instrument, if it exists
let default_psg_id: Option<u16> = module_instruments.iter().find_map( | item | {
if item.name == "__reskit_default_psg_instrument" {
Some( index )
} else {
index += 1;
None
}
} );
// Generate InstrumentSet which is used to validate when instruments are set on channels
index = 0;
let mut index = 0;
let fm_ids = module_instruments.iter()
.filter_map( | instrument | if matches!( instrument.instrument_type, InstrumentType::Fm2612( _ ) ) {
let result = index;
@ -872,11 +868,10 @@ pub fn get_events_for_row( channels: &mut [Channel], module_instruments: &Vec<In
let instrument_set = InstrumentSet {
fm_ids,
psg_ids,
module_set: module_instruments,
total_set: &asset_set.instruments,
module_instruments,
total_instruments: &asset_set.instruments,
module_samples,
total_samples: &asset_set.samples,
default_psg_id
total_samples: &asset_set.samples
};
// Get events for each subrow (part of the total row for each channel)