Refactor for delays per effect

master
Ashley N. 2023-08-26 11:41:37 -04:00
parent 686d44b137
commit e45972316e
1 changed files with 35 additions and 7 deletions

View File

@ -341,6 +341,19 @@ fn apply_effects_to_channel( channel: &mut Channel, effects: &LinkedHashSet<Effe
channel.active_effects.insert( Effect::PortamentoDown { speed } );
}
},
Effect::NoteCut { after_ticks } => {
let after_ticks = *after_ticks;
// Remove all previous note cuts
channel.active_effects = channel.active_effects
.clone()
.into_iter()
.filter( | effect | !( matches!( effect, Effect::NoteCut { after_ticks: _ } ) ) )
.collect();
// Add new note cut. Being an effect requiring delay generation, it will generate (and expire) in get_delays
channel.active_effects.insert( Effect::NoteCut { after_ticks } );
}
Effect::SetPanning { left, right } => {
let left = *left;
let right = *right;
@ -430,10 +443,13 @@ pub fn compact_delays( events: Vec<EchoEvent> ) -> Result<Vec<EchoEvent>, Box<dy
}
/**
* Get the delays due at the end of a row. These delays are what flushes the tick to Echo so that it can play.
* Calculate delays generated before and after effects applied across all channels. If there are no effects for this row,
* an empty vec will be returned. This means you should just apply ticks_to_wait as the delay for that row. If there
* -are- effects generated by this function, you should not apply ticks_to_wait, since this function will spend out
* the tick budget for that row instead.
*/
fn get_delays( events: Vec<EchoEvent>, channels: &mut [Channel], ticks_to_wait: u8 ) -> Result<Vec<EchoEvent>, Box<dyn Error>> {
let mut events: Vec<EchoEvent> = events;
fn get_delays_for_effects( channels: &mut [Channel], ticks_to_wait: u8 ) -> Result<Vec<EchoEvent>, Box<dyn Error>> {
let mut events: Vec<EchoEvent> = Vec::new();
// All portamento effects deploy per tick, not per row. So we need to aggregate all portamentos across all
// channels for this row, then flush them once per `ticks_to_wait` for this row.
@ -449,9 +465,6 @@ fn get_delays( events: Vec<EchoEvent>, channels: &mut [Channel], ticks_to_wait:
}
}
// Do we have any active portamentos? If so, push them according to the portamento wait pattern.
// So let's say portamentos are defined on FM1 and FM5 and ticks_to_wait is 3. The generated events are:
// [ freq_shift_fm1, freq_shift_fm5, wait 1 tick, freq_shift_fm1, freq_shift_fm5, wait 1 tick, freq_shift_fm1, freq_shift_fm5, wait 1 tick ]
if !active_portamentos.is_empty() {
for _tick in 0..ticks_to_wait {
for ( channel_id, portamento ) in &active_portamentos {
@ -461,9 +474,24 @@ fn get_delays( events: Vec<EchoEvent>, channels: &mut [Channel], ticks_to_wait:
events.push( get_delay( 1 )? );
}
} else {
}
Ok( events )
}
/**
* Get the delays due at the end of a row. These delays are what flushes the tick to Echo so that it can play.
*/
fn get_delays( events: Vec<EchoEvent>, channels: &mut [Channel], ticks_to_wait: u8 ) -> Result<Vec<EchoEvent>, Box<dyn Error>> {
let mut events: Vec<EchoEvent> = events;
let applied_effects = get_delays_for_effects( channels, ticks_to_wait )?;
if applied_effects.is_empty() {
// Push the amount of ticks to wait for this row. ticks_to_wait is speed_a or speed_b, times base_speed.
events.push( get_delay( ticks_to_wait )? );
} else {
// Do not push the default "wait n ticks" event but rather push the delay events generated by effects
events.extend( applied_effects.into_iter() );
}
Ok( events )