Enhance group track building and add automation envelope support for tracks in groups
This commit is contained in:
@@ -702,6 +702,7 @@ async function buildTrack(
|
|||||||
|
|
||||||
async function buildGroupTrack(
|
async function buildGroupTrack(
|
||||||
koTrack: AblTrack,
|
koTrack: AblTrack,
|
||||||
|
groupLane: AblGroupLane | undefined,
|
||||||
exporterParams: ExporterParams,
|
exporterParams: ExporterParams,
|
||||||
maxScenes: number,
|
maxScenes: number,
|
||||||
) {
|
) {
|
||||||
@@ -714,6 +715,21 @@ async function buildGroupTrack(
|
|||||||
groupTrack.Name.UserName['@Value'] = koTrack.group.toLocaleUpperCase();
|
groupTrack.Name.UserName['@Value'] = koTrack.group.toLocaleUpperCase();
|
||||||
setColorValue(groupTrack, 5 + _localGroupTrackColor++);
|
setColorValue(groupTrack, 5 + _localGroupTrackColor++);
|
||||||
groupTrack.Slots.GroupTrackSlot = [];
|
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)
|
// adding empty slots for clips (or Ableton will crash)
|
||||||
// must be at least 8 slots to avoid Ableton crashes
|
// 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>(
|
const trackSendHolderTemplate = await loadTemplate<ALSTrackSendHolder>(
|
||||||
'trackSendHolder',
|
'trackSendHolder',
|
||||||
abletonVersion,
|
abletonVersion,
|
||||||
);
|
);
|
||||||
const trackSendHolder = structuredClone(trackSendHolderTemplate.TrackSendHolder);
|
const trackSendHolder = structuredClone(trackSendHolderTemplate.TrackSendHolder);
|
||||||
|
|
||||||
|
trackSendHolder['@Id'] = 0;
|
||||||
trackSendHolder.Send.Manual['@Value'] = koTrack.faderParams[FaderParam.FX];
|
trackSendHolder.Send.Manual['@Value'] = koTrack.faderParams[FaderParam.FX];
|
||||||
|
|
||||||
groupTrack.DeviceChain.Mixer.Sends.TrackSendHolder = trackSendHolder;
|
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 };
|
return { GroupTrack: groupTrack };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,7 +803,12 @@ async function buildScenes(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildTracks(tracks: AblTrack[], maxScenes: number, exporterParams: ExporterParams) {
|
async function buildTracks(
|
||||||
|
tracks: AblTrack[],
|
||||||
|
groupLanes: AblGroupLane[],
|
||||||
|
maxScenes: number,
|
||||||
|
exporterParams: ExporterParams,
|
||||||
|
) {
|
||||||
const result = [];
|
const result = [];
|
||||||
let trackGroupId = -1;
|
let trackGroupId = -1;
|
||||||
let currentGroup = '';
|
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
|
// 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
|
// this took me around 3 hours to figure out
|
||||||
for (const koTrack of tracks.sort((a, b) => a.group.localeCompare(b.group))) {
|
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]) {
|
if (exporterParams.groupTracks && koTrack.group !== currentGroup[0]) {
|
||||||
currentGroup = koTrack.group;
|
currentGroup = koTrack.group;
|
||||||
const groupTrack = await buildGroupTrack(koTrack, exporterParams, maxScenes);
|
const groupTrack = await buildGroupTrack(koTrack, groupLane, exporterParams, maxScenes);
|
||||||
trackGroupId = groupTrack.GroupTrack['@Id'];
|
trackGroupId = groupTrack.GroupTrack['@Id'];
|
||||||
result.push(groupTrack);
|
result.push(groupTrack);
|
||||||
}
|
}
|
||||||
|
|
||||||
const midiTrack = await buildTrack(koTrack, maxScenes, trackGroupId, exporterParams);
|
const midiTrack = await buildTrack(
|
||||||
|
koTrack,
|
||||||
|
groupLane,
|
||||||
|
maxScenes,
|
||||||
|
trackGroupId,
|
||||||
|
exporterParams,
|
||||||
|
);
|
||||||
|
|
||||||
result.push(midiTrack);
|
result.push(midiTrack);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user