Enhance Ableton export logic with scaled note velocity and filter fader canonicalization

This commit is contained in:
2026-07-14 11:49:08 +02:00
parent b74c13621d
commit 82a4c73295
6 changed files with 70 additions and 13 deletions

View File

@@ -52,6 +52,16 @@ export function getFaderValueAt(
return value;
}
export function getScaledNoteVelocity(
originalVelocity: number,
occurrence: AblGroupPatternOccurrence | undefined,
position: number,
) {
const faderValue = getFaderValueAt(occurrence, FaderParam.VEL, position);
const velocity = faderValue === undefined ? originalVelocity : originalVelocity * faderValue;
return Math.max(1, Math.min(127, Math.round(velocity)));
}
function getStaticValue(pattern: AblGroupPatternOccurrence, parameter: FaderParam) {
const value = pattern.faderParams[parameter];
return value === -1 ? getFaderDefaultValue(parameter) : value;

View File

@@ -20,7 +20,7 @@ import {
AbletonAutomationTargets,
buildArrangementEnvelopes,
buildClipEnvelopes,
getFaderValueAt,
getScaledNoteVelocity,
} from './automation';
import {
chorusEffectValues,
@@ -30,7 +30,11 @@ import {
filterEffectValues,
reverbEffectValues,
} from './effects';
import { convertGroupFaderValue, getFaderDefaultValue } from './faderPolicies';
import {
canonicalizeFilterFaderValue,
convertGroupFaderValue,
getFaderDefaultValue,
} from './faderPolicies';
import { AbletonMidiControllerTargets, buildMidiClipEnvelopes } from './midi';
import { getPadEnvelopeState, getPadSoundState } from './padSound';
import { getSimplerPlaybackState } from './playback';
@@ -295,15 +299,10 @@ async function buildMidiClip(
dur = nextNote.position / 96 - noteData.position / 96;
}
const automatedVelocity = koClip.groupPattern
? getFaderValueAt(koClip.groupPattern, FaderParam.VEL, noteData.position)
: undefined;
const velocity = Math.max(
1,
Math.min(
127,
automatedVelocity === undefined ? noteData.velocity : automatedVelocity * 127,
),
const velocity = getScaledNoteVelocity(
noteData.velocity,
koClip.groupPattern,
noteData.position,
);
return {
@@ -644,7 +643,10 @@ async function buildTrack(
if (exporterParams.includeArchivedSamples) {
for (const parameter of [FaderParam.LPF, FaderParam.HPF] as const) {
const staticValue = koTrack.faderParams[parameter];
const staticValue = canonicalizeFilterFaderValue(
parameter,
koTrack.faderParams[parameter],
);
const defaultValue = getFaderDefaultValue(parameter);
const hasAutomation = automatedParameters.has(parameter);
if (hasAutomation || (staticValue !== -1 && staticValue !== defaultValue)) {

View File

@@ -93,7 +93,7 @@ export const FADER_POLICIES = {
toLive: (value) => Math.max(-0.5, Math.min(0.5, value - 0.5)) * 100,
},
[FaderParam.VEL]: {
defaultValue: 0,
defaultValue: 1,
renderStrategy: 'note',
targetScope: 'track',
status: 'research',
@@ -116,6 +116,14 @@ export function getFaderDefaultValue(parameter: FaderParam) {
return getFaderPolicy(parameter).defaultValue;
}
export function canonicalizeFilterFaderValue(
parameter: FaderParam.LPF | FaderParam.HPF,
value: number,
) {
const defaultValue = getFaderDefaultValue(parameter);
return Math.abs(value - defaultValue) <= 0.001 ? defaultValue : value;
}
export function convertGroupFaderValue(
parameter: FaderParam,
value: number,