Update Simpler device building to use PadSound state and parameters

This commit is contained in:
2026-07-14 11:26:01 +02:00
parent 8b377204c0
commit e8f75c6b39

View File

@@ -343,10 +343,16 @@ async function buildMidiClip(
return midiClip; return midiClip;
} }
async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVersion) { async function buildSimplerDevice(
koTrack: AblTrack,
abletonVersion: AbletonVersion,
automatedParameters: ReadonlySet<FaderParam> = new Set(),
) {
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 playbackState = getSimplerPlaybackState(koTrack.playMode); const padSound = getPadSoundState(koTrack);
const padEnvelope = getPadEnvelopeState(padSound);
const playbackState = getSimplerPlaybackState(padSound.playMode);
const samplePart = device.Player.MultiSampleMap.SampleParts.MultiSamplePart; const samplePart = device.Player.MultiSampleMap.SampleParts.MultiSamplePart;
const loopModulators = device.Player.LoopModulators; const loopModulators = device.Player.LoopModulators;
const simplerFilter = device.Filter.Slot.Value.SimplerFilter; const simplerFilter = device.Filter.Slot.Value.SimplerFilter;
@@ -367,11 +373,13 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
simplerFilter.ModByLfo.Manual['@Value'] = 0; simplerFilter.ModByLfo.Manual['@Value'] = 0;
device.Lfo.IsOn.Manual['@Value'] = 'false'; device.Lfo.IsOn.Manual['@Value'] = 'false';
device.Pitch.PitchLfoAmount.Manual['@Value'] = 0; device.Pitch.PitchLfoAmount.Manual['@Value'] = 0;
device.VolumeAndPan.OneShotEnvelope.FadeInTime.Manual['@Value'] = SIMPLER_FADE_IN_MS; device.VolumeAndPan.OneShotEnvelope.FadeInTime.Manual['@Value'] =
device.VolumeAndPan.OneShotEnvelope.FadeOutTime.Manual['@Value'] = SIMPLER_FADE_OUT_MS; padEnvelope.oneShotFadeInMs;
device.VolumeAndPan.OneShotEnvelope.FadeOutTime.Manual['@Value'] =
padEnvelope.oneShotFadeOutMs;
device.VolumeAndPan.OneShotEnvelope.SustainMode.Manual['@Value'] = 0; device.VolumeAndPan.OneShotEnvelope.SustainMode.Manual['@Value'] = 0;
device.VolumeAndPan.Envelope.AttackTime.Manual['@Value'] = SIMPLER_ATTACK_MS; device.VolumeAndPan.Envelope.AttackTime.Manual['@Value'] = padEnvelope.classicAttackMs;
device.VolumeAndPan.Envelope.ReleaseTime.Manual['@Value'] = SIMPLER_RELEASE_MS; device.VolumeAndPan.Envelope.ReleaseTime.Manual['@Value'] = padEnvelope.classicReleaseMs;
device.Globals.PlaybackMode['@Value'] = playbackState.playbackMode; device.Globals.PlaybackMode['@Value'] = playbackState.playbackMode;
device.Globals.NumVoices['@Value'] = playbackState.voices; device.Globals.NumVoices['@Value'] = playbackState.voices;
device.Globals.RetriggerMode['@Value'] = playbackState.retrigger; device.Globals.RetriggerMode['@Value'] = playbackState.retrigger;
@@ -389,17 +397,17 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
sampleRef.LastModDate['@Value'] = 0; sampleRef.LastModDate['@Value'] = 0;
} }
if (sampleRef.DefaultDuration) { if (sampleRef.DefaultDuration) {
sampleRef.DefaultDuration['@Value'] = Math.round(koTrack.soundLength * koTrack.sampleRate); sampleRef.DefaultDuration['@Value'] = Math.round(padSound.soundLength * koTrack.sampleRate);
} }
if (sampleRef.DefaultSampleRate) { if (sampleRef.DefaultSampleRate) {
sampleRef.DefaultSampleRate['@Value'] = koTrack.sampleRate; sampleRef.DefaultSampleRate['@Value'] = koTrack.sampleRate;
} }
samplePart.Name['@Value'] = koTrack.name; samplePart.Name['@Value'] = koTrack.name;
samplePart.RootKey['@Value'] = koTrack.rootNote; samplePart.RootKey['@Value'] = padSound.rootNote;
samplePart.SampleStart['@Value'] = koTrack.trimLeft; samplePart.SampleStart['@Value'] = padSound.trimStart;
samplePart.SampleEnd['@Value'] = koTrack.trimRight; samplePart.SampleEnd['@Value'] = padSound.trimEnd;
samplePart.SustainLoop.Start['@Value'] = koTrack.trimLeft; samplePart.SustainLoop.Start['@Value'] = padSound.trimStart;
samplePart.SustainLoop.End['@Value'] = koTrack.trimRight; samplePart.SustainLoop.End['@Value'] = padSound.trimEnd;
samplePart.SustainLoop.Mode['@Value'] = 0; samplePart.SustainLoop.Mode['@Value'] = 0;
samplePart.SustainLoop.Crossfade['@Value'] = 0; samplePart.SustainLoop.Crossfade['@Value'] = 0;
samplePart.ReleaseLoop.Start['@Value'] = 0; samplePart.ReleaseLoop.Start['@Value'] = 0;
@@ -414,41 +422,54 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
// 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.Panorama.Manual['@Value'] = koTrack.pan; device.VolumeAndPan.Panorama.Manual['@Value'] = padSound.pan;
let pitch = koTrack.pitch || 0; let pitch = padSound.pitch || 0;
if (koTrack.samplePitch) { if (koTrack.samplePitch) {
pitch += koTrack.samplePitch; pitch += koTrack.samplePitch;
} }
// adding PITCH fader param if defined // adding PITCH fader param if defined
if (koTrack.faderParams[FaderParam.PTC] !== -1) { if (koTrack.faderParams[FaderParam.PTC] !== -1) {
const normalized = (koTrack.faderParams[FaderParam.PTC] - 0.5) * 2; // from 0-1 to -1 to +1 pitch += Math.round(
pitch += Math.round(normalized * 5); convertGroupFaderValue(FaderParam.PTC, koTrack.faderParams[FaderParam.PTC], {
track: koTrack,
}),
);
} }
if (koTrack.faderParams[FaderParam.TUNE] !== -1) { if (koTrack.faderParams[FaderParam.TUNE] !== -1) {
device.Pitch.TransposeFine.Manual['@Value'] = device.Pitch.TransposeFine.Manual['@Value'] = convertGroupFaderValue(
Math.max(-0.5, Math.min(0.5, koTrack.faderParams[FaderParam.TUNE] - 0.5)) * 100; FaderParam.TUNE,
koTrack.faderParams[FaderParam.TUNE],
{ track: koTrack },
);
} }
device.Pitch.TransposeKey.Manual['@Value'] = pitch; device.Pitch.TransposeKey.Manual['@Value'] = pitch;
// adding vibrato from MOD fader param if defined // adding vibrato from MOD fader param if defined
if (koTrack.faderParams[FaderParam.MOD] !== -1) { if (
koTrack.faderParams[FaderParam.MOD] !== -1 ||
automatedParameters.has(FaderParam.MOD)
) {
device.Lfo.IsOn.Manual['@Value'] = 'true'; device.Lfo.IsOn.Manual['@Value'] = 'true';
if (!device.Lfo.Slot.Value.SimplerLfo && abletonVersion === '10') { if (!device.Lfo.Slot.Value.SimplerLfo && abletonVersion === '10') {
const simplerLfoTemplate = await loadTemplate<any>('simplerLfo', abletonVersion); const simplerLfoTemplate = await loadTemplate<any>('simplerLfo', abletonVersion);
device.Lfo.Slot.Value.SimplerLfo = structuredClone(simplerLfoTemplate.SimplerLfo); device.Lfo.Slot.Value.SimplerLfo = structuredClone(simplerLfoTemplate.SimplerLfo);
} }
// KO's MOD wheel on 100% is roughly equal to 5% LFO pitch modulation // KO's MOD wheel on 100% is roughly equal to 5% LFO pitch modulation
device.Pitch.PitchLfoAmount.Manual['@Value'] = koTrack.faderParams[FaderParam.MOD] / 20; device.Pitch.PitchLfoAmount.Manual['@Value'] = convertGroupFaderValue(
FaderParam.MOD,
Math.max(0, koTrack.faderParams[FaderParam.MOD]),
{ track: koTrack },
);
device.Lfo.Slot.Value.SimplerLfo.RateType.Manual['@Value'] = 1; // tempo synced 1/16 device.Lfo.Slot.Value.SimplerLfo.RateType.Manual['@Value'] = 1; // tempo synced 1/16
} }
// TODO: add bandpass filter // TODO: add bandpass filter
if (koTrack.timeStretch === 'bars') { if (padSound.time.mode === 'bars') {
device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleWarpProperties.IsWarped[ device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleWarpProperties.IsWarped[
'@Value' '@Value'
] = 'true'; ] = 'true';
@@ -464,18 +485,18 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
}, },
{ {
'@Id': 1, '@Id': 1,
'@SecTime': koTrack.soundLength, '@SecTime': padSound.soundLength,
'@BeatTime': '@BeatTime':
koTrack.timeStretchBars * padSound.time.bars *
koTrack.timeSignature.numerator * koTrack.timeSignature.numerator *
(4 / koTrack.timeSignature.denominator), // convert bars to beats (4 / koTrack.timeSignature.denominator), // convert bars to beats
}, },
]; ];
} }
if (koTrack.timeStretch === 'bpm') { if (padSound.time.mode === 'bpm') {
// calculating beat length using koTrack.timeStretchBpm // calculating beat length using koTrack.timeStretchBpm
const beatTime = koTrack.soundLength / (60 / koTrack.timeStretchBpm); const beatTime = padSound.soundLength / (60 / padSound.time.bpm);
device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleWarpProperties.IsWarped[ device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleWarpProperties.IsWarped[
'@Value' '@Value'
@@ -492,13 +513,13 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
}, },
{ {
'@Id': 1, '@Id': 1,
'@SecTime': koTrack.soundLength, '@SecTime': padSound.soundLength,
'@BeatTime': beatTime, '@BeatTime': beatTime,
}, },
]; ];
} }
if (koTrack.timeStretch === 'rev') { if (padSound.time.mode === 'rev') {
device.Player.Reverse.Manual['@Value'] = 'true'; device.Player.Reverse.Manual['@Value'] = 'true';
} }
@@ -510,6 +531,7 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
async function buildFaderFilterDevice( async function buildFaderFilterDevice(
parameter: FaderParam.LPF | FaderParam.HPF, parameter: FaderParam.LPF | FaderParam.HPF,
value: number, value: number,
track: AblTrack,
abletonVersion: AbletonVersion, abletonVersion: AbletonVersion,
) { ) {
const filterTemplate = await loadTemplate<ALSFilter>('effectFilter', abletonVersion); const filterTemplate = await loadTemplate<ALSFilter>('effectFilter', abletonVersion);
@@ -519,7 +541,7 @@ async function buildFaderFilterDevice(
filter.FilterType.Manual['@Value'] = highPass ? 1 : 0; filter.FilterType.Manual['@Value'] = highPass ? 1 : 0;
filter.LegacyFilterType.Manual['@Value'] = highPass ? 1 : 0; filter.LegacyFilterType.Manual['@Value'] = highPass ? 1 : 0;
filter.Slope.Manual['@Value'] = highPass ? 'false' : 'true'; filter.Slope.Manual['@Value'] = highPass ? 'false' : 'true';
filter.Cutoff.Manual['@Value'] = highPass ? 20 + value * 0.7 * 115 : 20 + value * 0.9 * 115; filter.Cutoff.Manual['@Value'] = convertGroupFaderValue(parameter, value, { track });
return { AutoFilter: filter }; return { AutoFilter: filter };
} }