Update Simpler device building logic for better compatibility and feature parity

This commit is contained in:
2026-07-13 08:43:43 +02:00
parent 2f36da8f4d
commit b9a0c35ccb

View File

@@ -20,6 +20,14 @@ import {
buildClipEnvelopes, buildClipEnvelopes,
getFaderValueAt, getFaderValueAt,
} from './automation'; } from './automation';
import {
chorusEffectValues,
compressorEffectValues,
delayEffectValues,
distortionEffectValues,
filterEffectValues,
reverbEffectValues,
} from './effects';
import { ALSDrumBranch } from './types/drumBranch'; import { ALSDrumBranch } from './types/drumBranch';
import { ALSDrumRack } from './types/drumRack'; import { ALSDrumRack } from './types/drumRack';
import { ALSChorus } from './types/effectChorus'; import { ALSChorus } from './types/effectChorus';
@@ -59,6 +67,11 @@ function getAbletonVersion(exporterParams: ExporterParams): AbletonVersion {
return exporterParams.abletonVersion === '10' ? '10' : '11'; return exporterParams.abletonVersion === '10' ? '10' : '11';
} }
function simplerEnvelopeMilliseconds(value: number, soundLength: number, oneshot: boolean) {
const milliseconds = koEnvRangeToSeconds(value, soundLength) * 1000;
return oneshot ? Math.min(2000, milliseconds) : milliseconds;
}
function setColorValue(node: any, value: number) { function setColorValue(node: any, value: number) {
const color = node.Color || node.ColorIndex; const color = node.Color || node.ColorIndex;
color['@Value'] = value; color['@Value'] = value;
@@ -323,8 +336,30 @@ async function buildMidiClip(
async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVersion) { async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVersion) {
const simplerTemplate = await loadTemplate<ALSSimpler>('simpler', abletonVersion); const simplerTemplate = await loadTemplate<ALSSimpler>('simpler', abletonVersion);
const device = structuredClone(simplerTemplate.OriginalSimpler); const device = structuredClone(simplerTemplate.OriginalSimpler);
const oneshot = koTrack.playMode === 'oneshot';
const samplePart = device.Player.MultiSampleMap.SampleParts.MultiSamplePart;
const loopModulators = device.Player.LoopModulators;
const simplerFilter = device.Filter.Slot.Value.SimplerFilter;
device.LastPresetRef.Value = {}; device.LastPresetRef.Value = {};
device.ShouldShowPresetName['@Value'] = 'false';
device.UserName['@Value'] = '';
loopModulators.SampleStart.Manual['@Value'] = 0;
loopModulators.SampleLength.Manual['@Value'] = 1;
loopModulators.LoopOn.Manual['@Value'] = 'false';
loopModulators.LoopLength.Manual['@Value'] = 1;
loopModulators.LoopFade.Manual['@Value'] = 0;
device.Filter.IsOn.Manual['@Value'] = 'false';
simplerFilter.Freq.Manual['@Value'] = 22000;
simplerFilter.Res.Manual['@Value'] = 0;
simplerFilter.Envelope.IsOn.Manual['@Value'] = 'false';
simplerFilter.Envelope.Amount.Manual['@Value'] = 0;
simplerFilter.ModByLfo.Manual['@Value'] = 0;
device.Lfo.IsOn.Manual['@Value'] = 'false';
device.Pitch.PitchLfoAmount.Manual['@Value'] = 0;
device.VolumeAndPan.OneShotEnvelope.FadeInTime.Manual['@Value'] = 0;
device.VolumeAndPan.OneShotEnvelope.FadeOutTime.Manual['@Value'] = 0;
device.VolumeAndPan.OneShotEnvelope.SustainMode.Manual['@Value'] = 0;
switch (koTrack.playMode) { switch (koTrack.playMode) {
case 'legato': case 'legato':
device.Globals.PlaybackMode['@Value'] = 0; device.Globals.PlaybackMode['@Value'] = 0;
@@ -355,36 +390,60 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
if (sampleRef.DefaultSampleRate) { if (sampleRef.DefaultSampleRate) {
sampleRef.DefaultSampleRate['@Value'] = koTrack.sampleRate; sampleRef.DefaultSampleRate['@Value'] = koTrack.sampleRate;
} }
device.Player.MultiSampleMap.SampleParts.MultiSamplePart.Name['@Value'] = koTrack.name; samplePart.Name['@Value'] = koTrack.name;
device.Player.MultiSampleMap.SampleParts.MultiSamplePart.RootKey['@Value'] = koTrack.rootNote; samplePart.RootKey['@Value'] = koTrack.rootNote;
device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleStart['@Value'] = koTrack.trimLeft; samplePart.SampleStart['@Value'] = koTrack.trimLeft;
device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleEnd['@Value'] = koTrack.trimRight; samplePart.SampleEnd['@Value'] = koTrack.trimRight;
device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleWarpProperties.TimeSignature.TimeSignatures.RemoteableTimeSignature.Numerator[ samplePart.SustainLoop.Start['@Value'] = koTrack.trimLeft;
samplePart.SustainLoop.End['@Value'] = koTrack.trimRight;
samplePart.SustainLoop.Mode['@Value'] = 0;
samplePart.SustainLoop.Crossfade['@Value'] = 0;
samplePart.ReleaseLoop.Start['@Value'] = 0;
samplePart.ReleaseLoop.End['@Value'] = 0;
samplePart.SampleWarpProperties.TimeSignature.TimeSignatures.RemoteableTimeSignature.Numerator[
'@Value' '@Value'
] = koTrack.timeSignature.numerator; ] = koTrack.timeSignature.numerator;
device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleWarpProperties.TimeSignature.TimeSignatures.RemoteableTimeSignature.Denominator[ samplePart.SampleWarpProperties.TimeSignature.TimeSignatures.RemoteableTimeSignature.Denominator[
'@Value' '@Value'
] = koTrack.timeSignature.denominator; ] = koTrack.timeSignature.denominator;
// setting velocity scaling to 20% to match KO behavior // setting velocity scaling to 20% to match KO behavior
device.VolumeAndPan.VolumeVelScale.Manual['@Value'] = 0.2; device.VolumeAndPan.VolumeVelScale.Manual['@Value'] = 0.2;
device.VolumeAndPan.Envelope.ReleaseTime.Manual['@Value'] = const attackTarget = oneshot
koEnvRangeToSeconds(koTrack.release, koTrack.soundLength) * 1000; ? device.VolumeAndPan.OneShotEnvelope.FadeInTime
device.VolumeAndPan.Envelope.AttackTime.Manual['@Value'] = : device.VolumeAndPan.Envelope.AttackTime;
koEnvRangeToSeconds(koTrack.attack, koTrack.soundLength) * 1000; const releaseTarget = oneshot
? device.VolumeAndPan.OneShotEnvelope.FadeOutTime
: device.VolumeAndPan.Envelope.ReleaseTime;
attackTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
koTrack.attack,
koTrack.soundLength,
oneshot,
);
releaseTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
koTrack.release,
koTrack.soundLength,
oneshot,
);
device.VolumeAndPan.Panorama.Manual['@Value'] = koTrack.pan; device.VolumeAndPan.Panorama.Manual['@Value'] = koTrack.pan;
// overriding attack time if ATK fader param is defined // overriding attack time if ATK fader param is defined
if (koTrack.faderParams[FaderParam.ATK] !== -1) { if (koTrack.faderParams[FaderParam.ATK] !== -1) {
device.VolumeAndPan.Envelope.AttackTime.Manual['@Value'] = attackTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
koEnvRangeToSeconds(koTrack.faderParams[FaderParam.ATK] * 255, koTrack.soundLength) * 1000; koTrack.faderParams[FaderParam.ATK] * 255,
koTrack.soundLength,
oneshot,
);
} }
// overriding release time if REL fader param is defined // overriding release time if REL fader param is defined
if (koTrack.faderParams[FaderParam.REL] !== -1) { if (koTrack.faderParams[FaderParam.REL] !== -1) {
device.VolumeAndPan.Envelope.ReleaseTime.Manual['@Value'] = releaseTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
koEnvRangeToSeconds(koTrack.faderParams[FaderParam.REL] * 255, koTrack.soundLength) * 1000; koTrack.faderParams[FaderParam.REL] * 255,
koTrack.soundLength,
oneshot,
);
} }
let pitch = koTrack.pitch || 0; let pitch = koTrack.pitch || 0;