Refactor Simpler device building to use playback state object
This commit is contained in:
@@ -29,6 +29,7 @@ import {
|
|||||||
filterEffectValues,
|
filterEffectValues,
|
||||||
reverbEffectValues,
|
reverbEffectValues,
|
||||||
} from './effects';
|
} from './effects';
|
||||||
|
import { getSimplerPlaybackState } from './playback';
|
||||||
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';
|
||||||
@@ -388,7 +389,7 @@ 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 projectOneShot = koTrack.playMode === 'oneshot';
|
const playbackState = getSimplerPlaybackState(koTrack.playMode, koTrack.oneShotOverride);
|
||||||
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;
|
||||||
@@ -413,21 +414,10 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
|
|||||||
device.VolumeAndPan.OneShotEnvelope.FadeInTime.Manual['@Value'] = 0;
|
device.VolumeAndPan.OneShotEnvelope.FadeInTime.Manual['@Value'] = 0;
|
||||||
device.VolumeAndPan.OneShotEnvelope.FadeOutTime.Manual['@Value'] = 0;
|
device.VolumeAndPan.OneShotEnvelope.FadeOutTime.Manual['@Value'] = 0;
|
||||||
device.VolumeAndPan.OneShotEnvelope.SustainMode.Manual['@Value'] = 0;
|
device.VolumeAndPan.OneShotEnvelope.SustainMode.Manual['@Value'] = 0;
|
||||||
switch (koTrack.playMode) {
|
device.Globals.PlaybackMode['@Value'] = playbackState.playbackMode;
|
||||||
case 'legato':
|
if (playbackState.monophonic) {
|
||||||
device.Globals.PlaybackMode['@Value'] = 0;
|
|
||||||
device.Globals.NumVoices['@Value'] = 1;
|
device.Globals.NumVoices['@Value'] = 1;
|
||||||
device.Globals.RetriggerMode['@Value'] = 'false';
|
device.Globals.RetriggerMode['@Value'] = 'false';
|
||||||
break;
|
|
||||||
case 'oneshot':
|
|
||||||
device.Globals.PlaybackMode['@Value'] = 1;
|
|
||||||
break;
|
|
||||||
case 'key':
|
|
||||||
device.Globals.PlaybackMode['@Value'] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (koTrack.oneShotOverride) {
|
|
||||||
device.Globals.PlaybackMode['@Value'] = 1;
|
|
||||||
}
|
}
|
||||||
const sampleRef = device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleRef;
|
const sampleRef = device.Player.MultiSampleMap.SampleParts.MultiSamplePart.SampleRef;
|
||||||
if (abletonVersion === '10') {
|
if (abletonVersion === '10') {
|
||||||
@@ -466,22 +456,22 @@ 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;
|
||||||
|
|
||||||
const attackTarget = projectOneShot
|
const attackTarget = playbackState.useOneShotEnvelope
|
||||||
? device.VolumeAndPan.OneShotEnvelope.FadeInTime
|
? device.VolumeAndPan.OneShotEnvelope.FadeInTime
|
||||||
: device.VolumeAndPan.Envelope.AttackTime;
|
: device.VolumeAndPan.Envelope.AttackTime;
|
||||||
const releaseTarget = projectOneShot
|
const releaseTarget = playbackState.useOneShotEnvelope
|
||||||
? device.VolumeAndPan.OneShotEnvelope.FadeOutTime
|
? device.VolumeAndPan.OneShotEnvelope.FadeOutTime
|
||||||
: device.VolumeAndPan.Envelope.ReleaseTime;
|
: device.VolumeAndPan.Envelope.ReleaseTime;
|
||||||
attackTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
|
attackTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
|
||||||
koTrack.attack,
|
koTrack.attack,
|
||||||
playbackDuration,
|
playbackDuration,
|
||||||
projectOneShot,
|
playbackState.useOneShotEnvelope,
|
||||||
);
|
);
|
||||||
releaseTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
|
releaseTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
|
||||||
koTrack.release,
|
koTrack.release,
|
||||||
playbackDuration,
|
playbackDuration,
|
||||||
projectOneShot,
|
playbackState.useOneShotEnvelope,
|
||||||
projectOneShot,
|
playbackState.useOneShotEnvelope,
|
||||||
);
|
);
|
||||||
device.VolumeAndPan.Panorama.Manual['@Value'] = koTrack.pan;
|
device.VolumeAndPan.Panorama.Manual['@Value'] = koTrack.pan;
|
||||||
|
|
||||||
@@ -490,7 +480,7 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
|
|||||||
attackTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
|
attackTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
|
||||||
koTrack.faderParams[FaderParam.ATK] * 255,
|
koTrack.faderParams[FaderParam.ATK] * 255,
|
||||||
playbackDuration,
|
playbackDuration,
|
||||||
projectOneShot,
|
playbackState.useOneShotEnvelope,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,8 +489,8 @@ async function buildSimplerDevice(koTrack: AblTrack, abletonVersion: AbletonVers
|
|||||||
releaseTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
|
releaseTarget.Manual['@Value'] = simplerEnvelopeMilliseconds(
|
||||||
koTrack.faderParams[FaderParam.REL] * 255,
|
koTrack.faderParams[FaderParam.REL] * 255,
|
||||||
playbackDuration,
|
playbackDuration,
|
||||||
projectOneShot,
|
playbackState.useOneShotEnvelope,
|
||||||
projectOneShot,
|
playbackState.useOneShotEnvelope,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,3 +5,14 @@ export type AbletonPlaybackMode = 'oneshot' | 'key' | 'legato';
|
|||||||
export function hasOneShotOverride(padCode: PadCode, oneShotPads: PadCode[] = []) {
|
export function hasOneShotOverride(padCode: PadCode, oneShotPads: PadCode[] = []) {
|
||||||
return oneShotPads.includes(padCode);
|
return oneShotPads.includes(padCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSimplerPlaybackState(
|
||||||
|
projectMode: AbletonPlaybackMode,
|
||||||
|
oneShotOverride: boolean,
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
playbackMode: projectMode === 'oneshot' || oneShotOverride ? 1 : 0,
|
||||||
|
monophonic: projectMode === 'legato',
|
||||||
|
useOneShotEnvelope: projectMode === 'oneshot',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
import { hasOneShotOverride } from '../src/lib/exporters/ableton/playback';
|
import {
|
||||||
|
getSimplerPlaybackState,
|
||||||
|
hasOneShotOverride,
|
||||||
|
} from '../src/lib/exporters/ableton/playback';
|
||||||
import { PadCode } from '../src/types/types';
|
import { PadCode } from '../src/types/types';
|
||||||
|
|
||||||
const project7Overrides = ['b0', 'c1', 'c8', 'c9', 'd3'] as PadCode[];
|
const project7Overrides = ['b0', 'c1', 'c8', 'c9', 'd3'] as PadCode[];
|
||||||
@@ -17,3 +20,29 @@ test('applies the selective Project 7 One-Shot overrides', () => {
|
|||||||
test('preserves project playback modes when no override is selected', () => {
|
test('preserves project playback modes when no override is selected', () => {
|
||||||
assert.equal(hasOneShotOverride('b0'), false);
|
assert.equal(hasOneShotOverride('b0'), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('changes only the active playback mode for forced KEY and LEGATO pads', () => {
|
||||||
|
assert.deepEqual(getSimplerPlaybackState('key', true), {
|
||||||
|
playbackMode: 1,
|
||||||
|
monophonic: false,
|
||||||
|
useOneShotEnvelope: false,
|
||||||
|
});
|
||||||
|
assert.deepEqual(getSimplerPlaybackState('legato', true), {
|
||||||
|
playbackMode: 1,
|
||||||
|
monophonic: true,
|
||||||
|
useOneShotEnvelope: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('uses One-Shot envelopes only for native EP ONE pads', () => {
|
||||||
|
assert.deepEqual(getSimplerPlaybackState('oneshot', false), {
|
||||||
|
playbackMode: 1,
|
||||||
|
monophonic: false,
|
||||||
|
useOneShotEnvelope: true,
|
||||||
|
});
|
||||||
|
assert.deepEqual(getSimplerPlaybackState('legato', false), {
|
||||||
|
playbackMode: 0,
|
||||||
|
monophonic: true,
|
||||||
|
useOneShotEnvelope: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user