diff --git a/src/reskit/soundtrack/engines/echo.rs b/src/reskit/soundtrack/engines/echo.rs index 7278556..c224581 100644 --- a/src/reskit/soundtrack/engines/echo.rs +++ b/src/reskit/soundtrack/engines/echo.rs @@ -293,7 +293,7 @@ fn apply_effects_to_channel( channel: &mut Channel, effects: &LinkedHashSet { let left = *left; let right = *right; @@ -332,6 +332,34 @@ fn apply_effects_to_channel( channel: &mut Channel, effects: &LinkedHashSet ) -> Result, Box> { + let mut new_events: Vec = Vec::new(); + + let mut cumulative_delay: u16 = 0; + for delay_event in current_sequence { + let mut iter = delay_event.iter(); + let delay_type = *iter.next().ok_or( "internal error: empty event" )?; + + if delay_type & 0xF0 == ESF_DELAY_SHORT { + cumulative_delay += ( ( delay_type & 0x0F ) as u16 ) + 1; + } else if delay_type == ESF_DELAY_LONG { + cumulative_delay += ( *iter.next().ok_or( "internal error: expected delay byte" )? ) as u16; + } + } + + if cumulative_delay > 0 { + // Push amount of full-256 wait events + for _ in 0..cumulative_delay / 256 { + new_events.push( vec![ ESF_DELAY_LONG, 0x00 ] ); + } + + // Push the remainder under 256 event + new_events.push( get_delay( ( cumulative_delay % 256 ) as u8 )? ); + } + + Ok( new_events ) +} + /** * Replace concurrent sequences of waits with single larger waits. This reduces the ESF stream size. */ @@ -345,32 +373,9 @@ pub fn compact_delays( events: Vec ) -> Result, Box 0 { - // Push amount of full-256 wait events - for _ in 0..cumulative_delay / 256 { - new_events.push( vec![ ESF_DELAY_LONG, 0x00 ] ); - } - - // Push the remainder under 256 event - new_events.push( get_delay( ( cumulative_delay % 256 ) as u8 )? ); - - // Reset the current sequence + let compacted_delay = sequence_to_compacted_delay( ¤t_sequence )?; + if !compacted_delay.is_empty() { + new_events.extend( compacted_delay.into_iter() ); current_sequence.clear(); } @@ -379,6 +384,8 @@ pub fn compact_delays( events: Vec ) -> Result, Box if tick >= after_ticks { if channel.active_note.is_some() { channel.active_note = None; + // Consume the note cut after we are done with it - it does not remain active + channel.active_effects = channel.active_effects + .clone() + .into_iter() + .filter( | effect | !( matches!( effect, Effect::NoteCut { after_ticks: _ } ) ) ) + .collect(); return Ok( vec![ ESF_NOTE_OFF | channel.id ] ); } } diff --git a/src/reskit/soundtrack/formats/dmf.rs b/src/reskit/soundtrack/formats/dmf.rs index 8f7fec1..ff72b6c 100644 --- a/src/reskit/soundtrack/formats/dmf.rs +++ b/src/reskit/soundtrack/formats/dmf.rs @@ -952,6 +952,8 @@ impl EchoFormat for DmfModule { esf.extend( event ); } + esf.push( 0xFF ); // Terminate the stream + Ok( esf ) }