Update Ableton effect parameter mapping and refactor value calculation logic across multiple effects (Reverb, Delay, Distortion, Chorus, Filter, Compressor).

This commit is contained in:
2026-07-13 08:49:30 +02:00
parent 943876e9d1
commit af18829b95
2 changed files with 44 additions and 18 deletions

View File

@@ -978,14 +978,22 @@ async function buildReturnTrack(
if (projectData.effects.effectType === EffectType.Reverb) {
const effectReverbTemplate = await loadTemplate<ALSReverb>('effectReverb', abletonVersion);
const effectReverb = structuredClone(effectReverbTemplate.Reverb);
const values = reverbEffectValues(projectData.effects.param1, projectData.effects.param2);
// these params are very rough approximation of the KO's reverb
// it's not exact, but close enough
effectReverb.PreDelay.Manual['@Value'] = 0.5;
effectReverb.RoomSize.Manual['@Value'] = 300;
effectReverb.ShelfHiFreq.Manual['@Value'] = 1000;
effectReverb.DecayTime.Manual['@Value'] = projectData.effects.param1 * 8000; // max 8 seconds which is kinda close to how it sounds in KO
effectReverb.ShelfHiGain.Manual['@Value'] = projectData.effects.param2; // param2 is "color" which roughly matches the high shelf gain cut amount
effectReverb.ShelfLoFreq.Manual['@Value'] = 1000;
effectReverb.DecayTime.Manual['@Value'] = values.decayTime;
effectReverb.ShelfHighOn.Manual['@Value'] = values.highShelfOn ? 'true' : 'false';
effectReverb.ShelfHiGain.Manual['@Value'] = values.highShelfGain;
effectReverb.ShelfLowOn.Manual['@Value'] = values.lowShelfOn ? 'true' : 'false';
effectReverb.ShelfLoGain.Manual['@Value'] = values.lowShelfGain;
effectReverb.MixReflect.Manual['@Value'] = 1;
effectReverb.MixDiffuse.Manual['@Value'] = 1;
effectReverb.MixDirect.Manual['@Value'] = 0;
returnTrack.DeviceChain.DeviceChain.Devices = { Reverb: effectReverb };
}
@@ -993,15 +1001,16 @@ async function buildReturnTrack(
if (projectData.effects.effectType === EffectType.Delay) {
const effectDelayTemplate = await loadTemplate<ALSDelay>('effectDelay', abletonVersion);
const effectDelay = structuredClone(effectDelayTemplate.Delay);
const values = delayEffectValues(projectData.effects.param1, projectData.effects.param2);
effectDelay.DelayLine_SyncL.Manual['@Value'] = 'false';
effectDelay.DelayLine_SyncR.Manual['@Value'] = 'false';
// don't even ask how I came up with this formula
effectDelay.DelayLine_TimeL.Manual['@Value'] =
0.017397 * (287.725 ** projectData.effects.param1 - 1);
effectDelay.DelayLine_TimeR.Manual['@Value'] =
0.017397 * (287.725 ** projectData.effects.param1 - 1);
effectDelay.Feedback.Manual['@Value'] = projectData.effects.param2;
effectDelay.DelayLine_TimeL.Manual['@Value'] = values.time;
effectDelay.DelayLine_TimeR.Manual['@Value'] = values.time;
effectDelay.Feedback.Manual['@Value'] = values.feedback;
effectDelay.Filter_On.Manual['@Value'] = 'false';
effectDelay.DryWet.Manual['@Value'] = 1;
returnTrack.DeviceChain.DeviceChain.Devices = { Delay: effectDelay };
}
@@ -1012,9 +1021,11 @@ async function buildReturnTrack(
abletonVersion,
);
const effectDistortion = structuredClone(effectDistortionTemplate.Overdrive);
const values = distortionEffectValues(projectData.effects.param1, projectData.effects.param2);
effectDistortion.Drive.Manual['@Value'] = projectData.effects.param1 * 50;
effectDistortion.Tone.Manual['@Value'] = projectData.effects.param2 * 100;
effectDistortion.Drive.Manual['@Value'] = values.drive;
effectDistortion.Tone.Manual['@Value'] = values.tone;
effectDistortion.DryWet.Manual['@Value'] = 100;
returnTrack.DeviceChain.DeviceChain.Devices = { Overdrive: effectDistortion };
}
@@ -1024,13 +1035,16 @@ async function buildReturnTrack(
const effectChorus = structuredClone(
abletonVersion === '10' ? (effectChorusTemplate as any).Chorus : effectChorusTemplate.Chorus2,
);
const values = chorusEffectValues(projectData.effects.param1, projectData.effects.param2);
if (abletonVersion === '10') {
effectChorus.ModAmount.Manual['@Value'] = projectData.effects.param1 * 6.5;
effectChorus.ModFreq.Manual['@Value'] = values.rate;
effectChorus.LfoMultiplier.Manual['@Value'] = 'false';
} else {
effectChorus.Amount.Manual['@Value'] = projectData.effects.param1;
effectChorus.Rate.Manual['@Value'] = values.rate;
}
effectChorus.Feedback.Manual['@Value'] = projectData.effects.param2 * 0.8;
effectChorus.Feedback.Manual['@Value'] = values.feedback;
effectChorus.DryWet.Manual['@Value'] = 1;
returnTrack.DeviceChain.DeviceChain.Devices = (
abletonVersion === '10' ? { Chorus: effectChorus } : { Chorus2: effectChorus }
@@ -1041,9 +1055,12 @@ async function buildReturnTrack(
if (projectData.effects.effectType === EffectType.Filter) {
const effectFilterTemplate = await loadTemplate<ALSFilter>('effectFilter', abletonVersion);
const effectFilter = structuredClone(effectFilterTemplate.AutoFilter);
const values = filterEffectValues(projectData.effects.param1, projectData.effects.param2);
effectFilter.Cutoff.Manual['@Value'] = 20 + projectData.effects.param1 * (135 - 20);
effectFilter.Resonance.Manual['@Value'] = projectData.effects.param2 * 1.25;
effectFilter.FilterType.Manual['@Value'] = values.filterType;
effectFilter.LegacyFilterType.Manual['@Value'] = values.filterType;
effectFilter.Cutoff.Manual['@Value'] = values.cutoff;
effectFilter.Resonance.Manual['@Value'] = values.resonance;
returnTrack.DeviceChain.DeviceChain.Devices = { AutoFilter: effectFilter };
}
@@ -1054,8 +1071,19 @@ async function buildReturnTrack(
abletonVersion,
);
const effectCompressor = structuredClone(effectCompressorTemplate.Compressor2);
const values = compressorEffectValues(projectData.effects.param1, projectData.effects.param2);
// params are ignored for now, just putting a basic compressor
effectCompressor.Threshold.Manual['@Value'] = values.threshold;
effectCompressor.Ratio.Manual['@Value'] = values.ratio;
effectCompressor.Attack.Manual['@Value'] = values.attack;
effectCompressor.Release.Manual['@Value'] = values.release;
effectCompressor.AutoReleaseControlOnOff.Manual['@Value'] = 'false';
effectCompressor.Gain.Manual['@Value'] = 0;
effectCompressor.GainCompensation.Manual['@Value'] = 'true';
effectCompressor.DryWet.Manual['@Value'] = 1;
effectCompressor.Model.Manual['@Value'] = 0;
effectCompressor.Knee.Manual['@Value'] = 6;
effectCompressor.LookAhead.Manual['@Value'] = 0;
returnTrack.DeviceChain.DeviceChain.Devices = { Compressor2: effectCompressor };
}