diff --git a/src/lib/exporters/ableton/builders.ts b/src/lib/exporters/ableton/builders.ts index e7b169b..63eef79 100644 --- a/src/lib/exporters/ableton/builders.ts +++ b/src/lib/exporters/ableton/builders.ts @@ -187,6 +187,8 @@ async function buildMidiClip( color: number, clipForLauncher: boolean = false, abletonVersion: AbletonVersion = '11', + automationTargets: AbletonAutomationTargets = {}, + koTrack?: AblTrack, ): Promise { const midiClipTemplate = await loadTemplate('midiClip', abletonVersion); const midiClip = structuredClone(midiClipTemplate.MidiClip); @@ -206,6 +208,9 @@ async function buildMidiClip( midiClip.Loop.LoopOn['@Value'] = 'true'; midiClip.Loop.LoopStart['@Value'] = 0; midiClip.Loop.LoopEnd['@Value'] = koClip.bars * beats; + if (midiClip.Loop.OutMarker) { + midiClip.Loop.OutMarker['@Value'] = koClip.bars * beats; + } midiClip.Loop.HiddenLoopStart['@Value'] = 0; midiClip.Loop.HiddenLoopEnd['@Value'] = koClip.bars * beats; setColorValue(midiClip, color); @@ -251,11 +256,15 @@ async function buildMidiClip( dur = nextNote.position / 96 - noteData.position / 96; } - let velocity = noteData.velocity; - - if (koClip.faderParams[FaderParam.VEL] !== -1) { - velocity = koClip.faderParams[FaderParam.VEL] * 127; - } + const velocity = Math.max( + 1, + Math.min( + 127, + koClip.groupPattern + ? getFaderValueAt(koClip.groupPattern, FaderParam.VEL, noteData.position) * 127 + : noteData.velocity, + ), + ); return { '@Time': noteData.position / 96, @@ -263,6 +272,7 @@ async function buildMidiClip( '@Velocity': velocity, '@OffVelocity': 64, '@NoteId': _noteId++, + '@IsEnabled': 'true', }; }), }, @@ -272,6 +282,20 @@ async function buildMidiClip( }); }); + midiClip.Notes.NoteIdGenerator.NextId['@Value'] = _noteId; + + if (clipForLauncher && koTrack) { + const clipEnvelopes = buildClipEnvelopes( + koClip.groupPattern, + automationTargets, + koTrack, + false, + ); + midiClip.Envelopes.Envelopes = clipEnvelopes.length + ? ({ ClipEnvelope: clipEnvelopes } as any) + : {}; + } + return midiClip; }