Improve calculation of arrangement points for Ableton export

This commit is contained in:
2026-07-14 09:38:22 +02:00
parent 496d3ddf21
commit e85124906b

View File

@@ -147,39 +147,49 @@ function getArrangementPoints(
groupMixer: boolean,
target: AbletonAutomationTarget,
) {
const orderedPatterns = patterns.toSorted((a, b) => {
const offsetDifference = a.offset - b.offset;
return offsetDifference || (a.occurrenceIndex ?? 0) - (b.occurrenceIndex ?? 0);
});
const hasAutomation = orderedPatterns.some((pattern) =>
pattern.faderAutomation.some((point) => point.parameter === parameter),
);
if (!hasAutomation) {
return [];
}
const points: AutomationPoint[] = [];
let hasAutomation = false;
let previousValue = patterns[0]
? getConvertedStaticValue(patterns[0], parameter, track, groupMixer, target)
let previousValue = orderedPatterns[0]
? getConvertedStaticValue(orderedPatterns[0], parameter, track, groupMixer, target)
: convertFaderValue(parameter, defaultValue(parameter), track, groupMixer, target);
patterns.forEach((pattern) => {
const beats = pattern.timeSignature.numerator * (4 / pattern.timeSignature.denominator);
const patternTicks = pattern.bars * beats * 96;
const sceneTicks = pattern.sceneBars * beats * 96;
const startTime = pattern.offset * beats;
orderedPatterns.forEach((pattern) => {
const patternTicks = Math.max(1, pattern.loopDuration * 96);
const occurrenceTicks = Math.max(1, pattern.duration * 96);
const startTime = pattern.offset;
const sourcePoints = pattern.faderAutomation
.filter((point) => point.parameter === parameter)
.sort((a, b) => a.position - b.position);
const staticValue = getConvertedStaticValue(pattern, parameter, track, groupMixer, target);
if (sourcePoints.length === 0) {
if (hasAutomation) {
points.push({ time: Math.max(0, startTime - BOUNDARY_EPSILON), value: previousValue });
points.push({ time: startTime, value: staticValue });
}
previousValue = staticValue;
if (sourcePoints.length === 0) {
return;
}
hasAutomation = true;
for (let loopOffset = 0; loopOffset < sceneTicks; loopOffset += patternTicks) {
for (let loopOffset = 0; loopOffset < occurrenceTicks; loopOffset += patternTicks) {
const loopStart = startTime + loopOffset / 96;
if (loopOffset > 0) {
points.push({ time: Math.max(0, loopStart - BOUNDARY_EPSILON), value: previousValue });
points.push({ time: loopStart, value: staticValue });
previousValue = staticValue;
}
sourcePoints.forEach((point) => {
if (loopOffset + point.position >= sceneTicks) {
if (loopOffset + point.position >= occurrenceTicks) {
return;
}
const value = convertFaderValue(parameter, point.value, track, groupMixer, target);
@@ -189,10 +199,6 @@ function getArrangementPoints(
}
});
if (!hasAutomation) {
return [];
}
return [{ time: SENTINEL_TIME, value: points[0]?.value ?? previousValue }, ...points];
}
@@ -206,9 +212,6 @@ function getClipPoints(
const sourcePoints = pattern.faderAutomation
.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 [