Add comprehensive automation target extraction for Ableton export
This commit is contained in:
@@ -7,7 +7,12 @@ import {
|
|||||||
ProjectSettings,
|
ProjectSettings,
|
||||||
} from '../../../types/types';
|
} from '../../../types/types';
|
||||||
import { EFFECTS } from '../../constants';
|
import { EFFECTS } from '../../constants';
|
||||||
import abletonTransformer, { AblClip, AblScene, AblTrack } from '../../transformers/ableton';
|
import abletonTransformer, {
|
||||||
|
AblClip,
|
||||||
|
AblGroupLane,
|
||||||
|
AblScene,
|
||||||
|
AblTrack,
|
||||||
|
} from '../../transformers/ableton';
|
||||||
import { getQuarterNotesPerBar } from '../utils';
|
import { getQuarterNotesPerBar } from '../utils';
|
||||||
import { ALSDrumBranch } from './types/drumBranch';
|
import { ALSDrumBranch } from './types/drumBranch';
|
||||||
import { ALSDrumRack } from './types/drumRack';
|
import { ALSDrumRack } from './types/drumRack';
|
||||||
@@ -25,6 +30,12 @@ import { ALSReturnTrack } from './types/returnTrack';
|
|||||||
import { ALSScene, ALSSceneContent } from './types/scene';
|
import { ALSScene, ALSSceneContent } from './types/scene';
|
||||||
import { ALSSimpler } from './types/simpler';
|
import { ALSSimpler } from './types/simpler';
|
||||||
import { ALSTrackSendHolder } from './types/trackSendHolder';
|
import { ALSTrackSendHolder } from './types/trackSendHolder';
|
||||||
|
import {
|
||||||
|
AbletonAutomationTargets,
|
||||||
|
buildArrangementEnvelopes,
|
||||||
|
buildClipEnvelopes,
|
||||||
|
getFaderValueAt,
|
||||||
|
} from './automation';
|
||||||
import {
|
import {
|
||||||
filterFreqFromNormalized,
|
filterFreqFromNormalized,
|
||||||
fixIds,
|
fixIds,
|
||||||
@@ -82,6 +93,94 @@ function setLive10SampleReference(fileRef: any, sampleName: string) {
|
|||||||
fileRef.LivePackId = { '@Value': '' };
|
fileRef.LivePackId = { '@Value': '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function targetFor(parameter: any): { arrangement?: number; session?: number } {
|
||||||
|
return {
|
||||||
|
arrangement:
|
||||||
|
parameter?.AutomationTarget?.['@Id'] === undefined
|
||||||
|
? undefined
|
||||||
|
: Number(parameter.AutomationTarget['@Id']),
|
||||||
|
session:
|
||||||
|
parameter?.ModulationTarget?.['@Id'] === undefined
|
||||||
|
? undefined
|
||||||
|
: Number(parameter.ModulationTarget['@Id']),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function findSimplers(node: any, result: any[] = []): any[] {
|
||||||
|
if (Array.isArray(node)) {
|
||||||
|
node.forEach((item) => findSimplers(item, result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (!node || typeof node !== 'object') {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (node.OriginalSimpler) {
|
||||||
|
result.push(node.OriginalSimpler);
|
||||||
|
}
|
||||||
|
Object.values(node).forEach((value) => findSimplers(value, result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTarget(
|
||||||
|
targets: AbletonAutomationTargets,
|
||||||
|
parameter: FaderParam,
|
||||||
|
target: { arrangement?: number; session?: number },
|
||||||
|
) {
|
||||||
|
if (target.arrangement === undefined && target.session === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
targets[parameter] = [...(targets[parameter] || []), target];
|
||||||
|
}
|
||||||
|
|
||||||
|
function trackAutomationTargets(midiTrack: any, includeArrangementMixer: boolean) {
|
||||||
|
const targets: AbletonAutomationTargets = {};
|
||||||
|
const mixer = midiTrack.DeviceChain.Mixer;
|
||||||
|
const sequencer = midiTrack.DeviceChain.MainSequencer;
|
||||||
|
addTarget(targets, FaderParam.LVL, {
|
||||||
|
arrangement: includeArrangementMixer
|
||||||
|
? Number(mixer.Volume.AutomationTarget['@Id'])
|
||||||
|
: undefined,
|
||||||
|
session: Number(sequencer.VolumeModulationTarget['@Id']),
|
||||||
|
});
|
||||||
|
addTarget(targets, FaderParam.PAN, {
|
||||||
|
arrangement: includeArrangementMixer ? Number(mixer.Pan.AutomationTarget['@Id']) : undefined,
|
||||||
|
session: Number(mixer.Pan.ModulationTarget['@Id']),
|
||||||
|
});
|
||||||
|
|
||||||
|
const send = mixer.Sends?.TrackSendHolder?.Send;
|
||||||
|
if (send) {
|
||||||
|
const target = targetFor(send);
|
||||||
|
if (!includeArrangementMixer) {
|
||||||
|
target.arrangement = undefined;
|
||||||
|
}
|
||||||
|
addTarget(targets, FaderParam.FX, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
findSimplers(midiTrack.DeviceChain.DeviceChain.Devices).forEach((simpler) => {
|
||||||
|
addTarget(targets, FaderParam.PTC, targetFor(simpler.Pitch.TransposeKey));
|
||||||
|
addTarget(targets, FaderParam.TUNE, targetFor(simpler.Pitch.TransposeFine));
|
||||||
|
addTarget(targets, FaderParam.LPF, targetFor(simpler.Filter.Slot.Value.SimplerFilter.Freq));
|
||||||
|
addTarget(targets, FaderParam.HPF, targetFor(simpler.Filter.Slot.Value.SimplerFilter.Freq));
|
||||||
|
addTarget(targets, FaderParam.ATK, targetFor(simpler.VolumeAndPan.Envelope.AttackTime));
|
||||||
|
addTarget(targets, FaderParam.REL, targetFor(simpler.VolumeAndPan.Envelope.ReleaseTime));
|
||||||
|
addTarget(targets, FaderParam.MOD, targetFor(simpler.Pitch.PitchLfoAmount));
|
||||||
|
});
|
||||||
|
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
function groupAutomationTargets(groupTrack: any) {
|
||||||
|
const targets: AbletonAutomationTargets = {};
|
||||||
|
const mixer = groupTrack.DeviceChain.Mixer;
|
||||||
|
addTarget(targets, FaderParam.LVL, targetFor(mixer.Volume));
|
||||||
|
addTarget(targets, FaderParam.PAN, targetFor(mixer.Pan));
|
||||||
|
const send = mixer.Sends?.TrackSendHolder?.Send;
|
||||||
|
if (send) {
|
||||||
|
addTarget(targets, FaderParam.FX, targetFor(send));
|
||||||
|
}
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
async function buildMidiClip(
|
async function buildMidiClip(
|
||||||
koClip: AblClip,
|
koClip: AblClip,
|
||||||
clipIdx: number,
|
clipIdx: number,
|
||||||
|
|||||||
Reference in New Issue
Block a user