Refactor fader value conversion and default handling for Ableton export

This commit is contained in:
2026-07-14 11:24:57 +02:00
parent 0d7c574677
commit f046f355fb

View File

@@ -1,11 +1,17 @@
import { FaderParam } from '../../../types/types';
import { AblGroupPatternOccurrence, AblTrack } from '../../transformers/ableton';
import {
convertGroupFaderValue,
getFaderDefaultValue,
getFaderPolicy,
} from './faderPolicies';
export type AbletonAutomationTarget = {
arrangement?: number;
session?: number;
staticValue?: number;
valueOffset?: number;
padTrack?: AblTrack;
};
export type AbletonAutomationTargets = Partial<Record<FaderParam, AbletonAutomationTarget[]>>;
@@ -18,21 +24,6 @@ type AutomationPoint = {
const SENTINEL_TIME = -63072000;
const BOUNDARY_EPSILON = 0.000001;
function defaultValue(parameter: FaderParam) {
switch (parameter) {
case FaderParam.LVL:
case FaderParam.LPF:
return 1;
case FaderParam.PTC:
case FaderParam.TIM:
case FaderParam.PAN:
case FaderParam.TUNE:
return 0.5;
default:
return 0;
}
}
export function convertFaderValue(
parameter: FaderParam,
value: number,
@@ -40,42 +31,11 @@ export function convertFaderValue(
groupMixer: boolean,
target?: AbletonAutomationTarget,
) {
let convertedValue: number;
switch (parameter) {
case FaderParam.LVL:
if (groupMixer) {
convertedValue = value;
} else {
convertedValue = track.volume * value;
}
break;
case FaderParam.PTC:
convertedValue = (target?.valueOffset ?? 0) + (value - 0.5) * 10;
break;
case FaderParam.LPF:
convertedValue = 20 + value * 0.9 * 115;
break;
case FaderParam.HPF:
convertedValue = 20 + value * 0.7 * 115;
break;
case FaderParam.FX:
convertedValue = value;
break;
case FaderParam.PAN:
convertedValue = (value - 0.5) * 2;
break;
case FaderParam.TUNE:
convertedValue = Math.max(-0.5, Math.min(0.5, value - 0.5)) * 100;
break;
case FaderParam.MOD:
convertedValue = value / 20;
break;
default:
convertedValue = value;
break;
}
return convertedValue;
return convertGroupFaderValue(parameter, value, {
track: target?.padTrack ?? track,
groupMixer,
valueOffset: target?.valueOffset,
});
}
export function getFaderValueAt(
@@ -98,7 +58,7 @@ export function getFaderValueAt(
function getStaticValue(pattern: AblGroupPatternOccurrence, parameter: FaderParam) {
const value = pattern.faderParams[parameter];
return value === -1 ? defaultValue(parameter) : value;
return value === -1 ? getFaderDefaultValue(parameter) : value;
}
function getConvertedStaticValue(
@@ -141,7 +101,13 @@ function getArrangementPoints(
const points: AutomationPoint[] = [];
let previousValue = orderedPatterns[0]
? getConvertedStaticValue(orderedPatterns[0], parameter, track, groupMixer, target)
: convertFaderValue(parameter, defaultValue(parameter), track, groupMixer, target);
: convertFaderValue(
parameter,
getFaderDefaultValue(parameter),
track,
groupMixer,
target,
);
orderedPatterns.forEach((pattern) => {
const patternTicks = Math.max(1, pattern.loopDuration * 96);
@@ -193,6 +159,10 @@ function getClipPoints(
.filter((point) => point.parameter === parameter)
.sort((a, b) => a.position - b.position);
if (sourcePoints.length === 0) {
return [];
}
const staticValue = getConvertedStaticValue(pattern, parameter, track, groupMixer, target);
return [
{ time: SENTINEL_TIME, value: staticValue },
@@ -231,7 +201,7 @@ export function buildArrangementEnvelopes(
const envelopes: any[] = [];
Object.entries(targets).forEach(([parameterString, targetList]) => {
const parameter = Number(parameterString) as FaderParam;
if (parameter === FaderParam.TIM || parameter === FaderParam.VEL) {
if (getFaderPolicy(parameter).renderStrategy !== 'target') {
return;
}
targetList?.forEach((target) => {
@@ -265,7 +235,7 @@ export function buildClipEnvelopes(
const envelopes: any[] = [];
Object.entries(targets).forEach(([parameterString, targetList]) => {
const parameter = Number(parameterString) as FaderParam;
if (parameter === FaderParam.TIM || parameter === FaderParam.VEL) {
if (getFaderPolicy(parameter).renderStrategy !== 'target') {
return;
}
targetList?.forEach((target) => {