Enhance group track building and add automation envelope support for tracks in groups

This commit is contained in:
2026-07-13 05:01:04 +02:00
parent a370f00150
commit c4d6cbf317

View File

@@ -702,6 +702,7 @@ async function buildTrack(
async function buildGroupTrack(
koTrack: AblTrack,
groupLane: AblGroupLane | undefined,
exporterParams: ExporterParams,
maxScenes: number,
) {
@@ -714,6 +715,21 @@ async function buildGroupTrack(
groupTrack.Name.UserName['@Value'] = koTrack.group.toLocaleUpperCase();
setColorValue(groupTrack, 5 + _localGroupTrackColor++);
groupTrack.Slots.GroupTrackSlot = [];
groupTrack.DeviceChain.Mixer.Sends = {};
if (!exporterParams.clips) {
if (koTrack.faderParams[FaderParam.LVL] !== -1) {
groupTrack.DeviceChain.Mixer.Volume.Manual['@Value'] =
koTrack.faderParams[FaderParam.LVL];
}
if (koTrack.faderParams[FaderParam.PAN] !== -1) {
groupTrack.DeviceChain.Mixer.Pan.Manual['@Value'] =
(koTrack.faderParams[FaderParam.PAN] - 0.5) * 2;
}
} else {
groupTrack.DeviceChain.Mixer.Volume.Manual['@Value'] = 1;
groupTrack.DeviceChain.Mixer.Pan.Manual['@Value'] = 0;
}
// adding empty slots for clips (or Ableton will crash)
// must be at least 8 slots to avoid Ableton crashes
@@ -726,18 +742,36 @@ async function buildGroupTrack(
});
}
if (exporterParams.sendEffects && koTrack.faderParams[FaderParam.FX] !== -1) {
if (
exporterParams.sendEffects &&
!exporterParams.clips &&
koTrack.faderParams[FaderParam.FX] !== -1
) {
const trackSendHolderTemplate = await loadTemplate<ALSTrackSendHolder>(
'trackSendHolder',
abletonVersion,
);
const trackSendHolder = structuredClone(trackSendHolderTemplate.TrackSendHolder);
trackSendHolder['@Id'] = 0;
trackSendHolder.Send.Manual['@Value'] = koTrack.faderParams[FaderParam.FX];
groupTrack.DeviceChain.Mixer.Sends.TrackSendHolder = trackSendHolder;
}
fixIds(groupTrack);
if (!exporterParams.clips && groupLane) {
const envelopes = buildArrangementEnvelopes(
groupLane.patterns,
groupAutomationTargets(groupTrack),
koTrack,
true,
);
groupTrack.AutomationEnvelopes.Envelopes = envelopes.length
? ({ AutomationEnvelope: envelopes } as any)
: {};
}
return { GroupTrack: groupTrack };
}
@@ -769,7 +803,12 @@ async function buildScenes(
return result;
}
async function buildTracks(tracks: AblTrack[], maxScenes: number, exporterParams: ExporterParams) {
async function buildTracks(
tracks: AblTrack[],
groupLanes: AblGroupLane[],
maxScenes: number,
exporterParams: ExporterParams,
) {
const result = [];
let trackGroupId = -1;
let currentGroup = '';
@@ -777,14 +816,21 @@ async function buildTracks(tracks: AblTrack[], maxScenes: number, exporterParams
// if the tracks are grouped, we need to create a group track for each group BEFORE the children midi tracks
// this took me around 3 hours to figure out
for (const koTrack of tracks.sort((a, b) => a.group.localeCompare(b.group))) {
const groupLane = groupLanes.find((lane) => lane.group === koTrack.group);
if (exporterParams.groupTracks && koTrack.group !== currentGroup[0]) {
currentGroup = koTrack.group;
const groupTrack = await buildGroupTrack(koTrack, exporterParams, maxScenes);
const groupTrack = await buildGroupTrack(koTrack, groupLane, exporterParams, maxScenes);
trackGroupId = groupTrack.GroupTrack['@Id'];
result.push(groupTrack);
}
const midiTrack = await buildTrack(koTrack, maxScenes, trackGroupId, exporterParams);
const midiTrack = await buildTrack(
koTrack,
groupLane,
maxScenes,
trackGroupId,
exporterParams,
);
result.push(midiTrack);
}