mirror of
https://github.com/aphrody-labs/soundcraft.git
synced 2026-10-13 19:26:53 +00:00
Instrument params: never read insert slot A's automation; regression tests for #152
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
99992fe78c
commit
ec920cd975
1 file changed
+53
-7
+53
-7
@@ -1287,20 +1287,31 @@ fn schedule_notes(s: &Session, t: &Track, pos: Samples, frames: usize, inst: &mu
|
||||
}
|
||||
|
||||
fn apply_params(slot: &mut PluginSlot, ins: &soundcraft_model::Insert, t: &Track, i: usize, pos: Samples) {
|
||||
let slot_u8 = u8::try_from(i).unwrap_or(0);
|
||||
// Automation lanes address insert slots; the instrument (`INSTRUMENT_SLOT`) has none, so it
|
||||
// must not pick up slot A's lanes.
|
||||
let Ok(slot_u8) = u8::try_from(i) else {
|
||||
return apply_values(slot, ins, |_, v| v);
|
||||
};
|
||||
let automated = t.mixer.automation_mode.reads()
|
||||
&& t.automation.iter().any(|l| matches!(&l.param, AutoParam::Plugin { slot, .. } if *slot == slot_u8) && !l.points.is_empty());
|
||||
if slot.applied.len() != ins.params.len() {
|
||||
slot.applied = vec![f32::NAN; ins.params.len()];
|
||||
}
|
||||
for ((k, v), last) in ins.params.iter().zip(slot.applied.iter_mut()) {
|
||||
let mut val = *v;
|
||||
apply_values(slot, ins, |k, val| {
|
||||
if automated
|
||||
&& let Some(l) = t.automation.iter().find(|l| matches!(&l.param, AutoParam::Plugin { slot, param } if *slot == slot_u8 && param == k))
|
||||
&& !l.points.is_empty()
|
||||
{
|
||||
val = l.value_at(pos, val);
|
||||
return l.value_at(pos, val);
|
||||
}
|
||||
val
|
||||
});
|
||||
}
|
||||
|
||||
/// Sends each stored param (as mapped by `value`) to the plugin when it changed since last time.
|
||||
fn apply_values(slot: &mut PluginSlot, ins: &soundcraft_model::Insert, value: impl Fn(&str, f32) -> f32) {
|
||||
if slot.applied.len() != ins.params.len() {
|
||||
slot.applied = vec![f32::NAN; ins.params.len()];
|
||||
}
|
||||
for ((k, v), last) in ins.params.iter().zip(slot.applied.iter_mut()) {
|
||||
let val = value(k, *v);
|
||||
if val.to_bits() != last.to_bits() {
|
||||
slot.plugin.set_param(k, val);
|
||||
*last = val;
|
||||
@@ -1808,6 +1819,41 @@ mod tests {
|
||||
use soundcraft_model::{Insert, SourceAudio, SourceId};
|
||||
use std::sync::Arc;
|
||||
|
||||
fn synth_session(level_db: f32) -> Session {
|
||||
use soundcraft_midi::{Note, Sequence};
|
||||
let mut s = Session::default();
|
||||
let t = s.add_track(TrackKind::Instrument, ChannelFormat::Stereo, None);
|
||||
let mut seq = Sequence::default();
|
||||
seq.notes.push(Note { pitch: 60, velocity: 100, release_velocity: 64, channel: 0, start: 0, length: 960 });
|
||||
let cid = s.new_clip_id();
|
||||
let tr = s.track_mut(t).unwrap();
|
||||
tr.playlist_mut().unwrap().clips.push(Clip::midi(cid, "n", 0, 24_000, seq));
|
||||
let mut ins = Insert::new("subtractive_synth");
|
||||
ins.params.insert("level".into(), level_db);
|
||||
tr.instrument = Some(ins);
|
||||
s
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stored_instrument_params_reach_the_plugin() {
|
||||
// #152: a saved instrument level of -12 dB must render quieter than -6 dB.
|
||||
let peak = |db: f32| render_range(&synth_session(db), Range::new(0, 12_000), 512)[0].iter().fold(0.0f32, |m, x| m.max(x.abs()));
|
||||
let (loud, quiet) = (peak(-6.0), peak(-12.0));
|
||||
assert!(loud > 0.0, "the synth should sound");
|
||||
assert!((quiet / loud - 0.5).abs() < 0.05, "-12 dB vs -6 dB should halve the peak: {quiet} / {loud}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_slot_a_automation_does_not_drive_the_instrument() {
|
||||
let mut s = synth_session(-6.0);
|
||||
let reference = render_range(&s, Range::new(0, 12_000), 512);
|
||||
let tr = &mut s.tracks[0];
|
||||
let mut lane = soundcraft_model::AutomationLane::new(AutoParam::Plugin { slot: 0, param: "level".into() });
|
||||
lane.set_point(0, -48.0);
|
||||
tr.automation.push(lane);
|
||||
assert_eq!(render_range(&s, Range::new(0, 12_000), 512), reference);
|
||||
}
|
||||
|
||||
fn session_with_dc(level: f32, frames: usize) -> (Session, TrackId) {
|
||||
let mut s = Session::default();
|
||||
let t = s.add_track(TrackKind::Audio, ChannelFormat::Mono, None);
|
||||
|
||||
Reference in new issue
Block a user