Apply default psg instrument

master
Ashley N. 2023-08-27 14:00:14 -04:00
parent 2f84d47d99
commit 375d85adb0
3 changed files with 28 additions and 5 deletions

View File

@ -311,6 +311,7 @@ impl EchoFormat for DmfModule {
for row_number in 0..self.rows_per_pattern {
let events_this_row: Vec<EchoEvent> = get_events_for_row(
&mut channels,
&self.instruments,
{
let mut columns: Vec<&PatternRow> = Vec::new();
for channel in 0..10 {

View File

@ -1,6 +1,6 @@
use std::{collections::HashMap, error::Error};
use linked_hash_set::LinkedHashSet;
use crate::reskit::{soundtrack::types::{PatternRow, Note, Channel, OctaveFrequency, Effect}, utility::print_warning};
use crate::reskit::{soundtrack::types::{PatternRow, Note, Channel, OctaveFrequency, Effect, Instrument}, utility::print_warning};
// https://github.com/sikthehedgehog/Echo/blob/master/doc/esf.txt
const ESF_NOTE_ON: u8 = 0x00;
@ -169,7 +169,7 @@ pub fn get_delay( delay: u8 ) -> Result<EchoEvent, Box<dyn Error>> {
* For a specific row and channel, get the events this row and channel contribute to the stream.
* While doing so, update the state of the channel for future event generation.
*/
pub fn get_events_for_channel( channel: &mut Channel, row: &PatternRow, pcm_offset: u8 ) -> Result<Vec<EchoEvent>, Box<dyn Error>> {
pub fn get_events_for_channel( channel: &mut Channel, row: &PatternRow, pcm_offset: u8, default_psg_instr_index: Option<u16> ) -> Result<Vec<EchoEvent>, Box<dyn Error>> {
let mut events: Vec<EchoEvent> = Vec::new();
// Adjust volume
@ -187,6 +187,18 @@ pub fn get_events_for_channel( channel: &mut Channel, row: &PatternRow, pcm_offs
events.push( vec![ ESF_SET_INSTRUMENT | channel.id, *instrument as u8 ] );
channel.active_instrument = Some( *instrument );
}
} else {
// This is SN1, SN2, or SN3 with no active instrument
// Check if the channel needs "__reskit_default_psg_instrument" set before a note is set
if channel.active_instrument.is_none() && ( 6..=8 ).contains( &channel.id ) {
if row.note.is_some() {
// Set "__reskit_default_psg_instrument"
let instrument = default_psg_instr_index.ok_or( "internal error: no default psg instrument to apply" )?;
events.push( vec![ ESF_SET_INSTRUMENT | channel.id, instrument as u8 ] );
channel.active_instrument = Some( instrument );
}
}
}
// Key on or key off note
@ -555,16 +567,26 @@ pub fn get_delays( events: Vec<EchoEvent>, channels: &mut [Channel], ticks_to_wa
* For an entire row across all channels, generate the events that apply to the row as a whole. This usually means applying
* the waits so that the row can be flushed to Echo and played - ESF ticks are until the nearest wait or stop event.
*/
pub fn get_events_for_row( channels: &mut [Channel], subrows: Vec<&PatternRow>, ticks_to_wait: u8, pcm_offset: u8 ) -> Result<Vec<EchoEvent>, Box<dyn Error>> {
pub fn get_events_for_row( channels: &mut [Channel], instruments: &Vec<Instrument>, subrows: Vec<&PatternRow>, ticks_to_wait: u8, pcm_offset: u8 ) -> Result<Vec<EchoEvent>, Box<dyn Error>> {
let mut events: Vec<EchoEvent> = Vec::new();
let mut index = 0;
let default_psg_instr_index: Option<u16> = instruments.iter().find_map( | item | {
if item.name == "__reskit_default_psg_instrument" {
Some( index )
} else {
index += 1;
None
}
} );
// Get events for each subrow (part of the total row for each channel)
for i in 0..channels.len() {
// Apply effects to channel's current state
events.extend( apply_effects_to_channel( &mut channels[ i ], &subrows[ i ].effects )? );
// Get the ESF events for this channel's part of the row
events.extend( get_events_for_channel( &mut channels[ i ], subrows[ i ], pcm_offset )? );
events.extend( get_events_for_channel( &mut channels[ i ], subrows[ i ], pcm_offset, default_psg_instr_index )? );
}
Ok( get_delays( events, channels, ticks_to_wait )? )

View File

@ -587,7 +587,7 @@ impl DmfModule {
if DmfModule::uses_default_psg( &channel_patterns )? {
print_info( "One or more channels use the default PSG instrument" );
instruments.push( Instrument{
name: format!( "Default PSG Instrument" ),
name: format!( "__reskit_default_psg_instrument" ),
instrument_type: InstrumentType::PsgDcsg( PsgSettings {
volume: PsgEnvelope {
envelope: vec![ 0x0F as u32 ],