Add comprehensive test coverage for Ableton automation, fader policies, and pad sound export logic
This commit is contained in:
@@ -86,3 +86,38 @@ test('uses absolute automation targets for Session clip envelopes', () => {
|
|||||||
assert.equal(envelopes[0].Automation.Events.FloatEvent[2]['@Time'], 1);
|
assert.equal(envelopes[0].Automation.Events.FloatEvent[2]['@Time'], 1);
|
||||||
assert.deepEqual(envelopes[0].LoopSlot, { Value: {} });
|
assert.deepEqual(envelopes[0].LoopSlot, { Value: {} });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('does not create Session envelopes without recorded parameter events', () => {
|
||||||
|
const withoutPan = {
|
||||||
|
...occurrence,
|
||||||
|
faderAutomation: occurrence.faderAutomation.filter(
|
||||||
|
(point) => point.parameter !== FaderParam.PAN,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
const envelopes = buildClipEnvelopes(
|
||||||
|
withoutPan,
|
||||||
|
{ [FaderParam.PAN]: [{ session: 23000 }] },
|
||||||
|
track,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.deepEqual(envelopes, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('keeps research-only group parameters out of Live target envelopes', () => {
|
||||||
|
const researchOccurrence = {
|
||||||
|
...occurrence,
|
||||||
|
faderAutomation: [
|
||||||
|
{ parameter: FaderParam.TIM, position: 0, value: 0.25, flags: 0 },
|
||||||
|
{ parameter: FaderParam.ATK, position: 0, value: 0.5, flags: 0 },
|
||||||
|
{ parameter: FaderParam.REL, position: 0, value: 0.75, flags: 0 },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const targets = {
|
||||||
|
[FaderParam.TIM]: [{ session: 23000 }],
|
||||||
|
[FaderParam.ATK]: [{ session: 23001 }],
|
||||||
|
[FaderParam.REL]: [{ session: 23002 }],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.deepEqual(buildClipEnvelopes(researchOccurrence, targets, track, false), []);
|
||||||
|
});
|
||||||
|
|||||||
35
tests/ableton-fader-policies.test.ts
Normal file
35
tests/ableton-fader-policies.test.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import test from 'node:test';
|
||||||
|
import {
|
||||||
|
FADER_POLICIES,
|
||||||
|
convertGroupFaderValue,
|
||||||
|
getFaderPolicy,
|
||||||
|
} from '../src/lib/exporters/ableton/faderPolicies';
|
||||||
|
import { AblTrack } from '../src/lib/transformers/ableton';
|
||||||
|
import { FaderParam } from '../src/types/types';
|
||||||
|
|
||||||
|
const track = { volume: 0.4 } as AblTrack;
|
||||||
|
|
||||||
|
test('defines an explicit policy for every EP group fader parameter', () => {
|
||||||
|
assert.equal(Object.keys(FADER_POLICIES).length, 12);
|
||||||
|
for (let parameter = FaderParam.LVL; parameter <= FaderParam.MOD; parameter++) {
|
||||||
|
assert.ok(getFaderPolicy(parameter));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('separates Live targets, note transforms and unsupported group parameters', () => {
|
||||||
|
assert.equal(getFaderPolicy(FaderParam.PAN).renderStrategy, 'target');
|
||||||
|
assert.equal(getFaderPolicy(FaderParam.VEL).renderStrategy, 'note');
|
||||||
|
assert.equal(getFaderPolicy(FaderParam.TIM).renderStrategy, 'unsupported');
|
||||||
|
assert.equal(getFaderPolicy(FaderParam.ATK).renderStrategy, 'unsupported');
|
||||||
|
assert.equal(getFaderPolicy(FaderParam.REL).renderStrategy, 'unsupported');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('uses one group-fader conversion path for mixer and pad targets', () => {
|
||||||
|
assert.equal(convertGroupFaderValue(FaderParam.LVL, 0.5, { track }), 0.2);
|
||||||
|
assert.equal(convertGroupFaderValue(FaderParam.PAN, 0.75, { track }), 0.5);
|
||||||
|
assert.equal(
|
||||||
|
convertGroupFaderValue(FaderParam.PTC, 0.75, { track, valueOffset: 7 }),
|
||||||
|
9.5,
|
||||||
|
);
|
||||||
|
});
|
||||||
47
tests/ableton-pad-sound.test.ts
Normal file
47
tests/ableton-pad-sound.test.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import test from 'node:test';
|
||||||
|
import {
|
||||||
|
getPadEnvelopeState,
|
||||||
|
getPadSoundState,
|
||||||
|
} from '../src/lib/exporters/ableton/padSound';
|
||||||
|
import { AblTrack } from '../src/lib/transformers/ableton';
|
||||||
|
|
||||||
|
const track = {
|
||||||
|
volume: 0.75,
|
||||||
|
pitch: -3,
|
||||||
|
playMode: 'key',
|
||||||
|
pan: 0.25,
|
||||||
|
trimLeft: 100,
|
||||||
|
trimRight: 1000,
|
||||||
|
attack: 64,
|
||||||
|
release: 128,
|
||||||
|
timeStretch: 'bars',
|
||||||
|
timeStretchBpm: 92,
|
||||||
|
timeStretchBars: 2,
|
||||||
|
rootNote: 48,
|
||||||
|
soundLength: 4,
|
||||||
|
} as AblTrack;
|
||||||
|
|
||||||
|
test('keeps static pad sound settings separate from group fader state', () => {
|
||||||
|
assert.deepEqual(getPadSoundState(track), {
|
||||||
|
amp: 0.75,
|
||||||
|
pitch: -3,
|
||||||
|
playMode: 'key',
|
||||||
|
pan: 0.25,
|
||||||
|
trimStart: 100,
|
||||||
|
trimEnd: 1000,
|
||||||
|
envelope: { attack: 64, release: 128 },
|
||||||
|
time: { mode: 'bars', bpm: 92, bars: 2 },
|
||||||
|
rootNote: 48,
|
||||||
|
soundLength: 4,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('maps only pad ENV values into the static Classic envelope', () => {
|
||||||
|
const envelope = getPadEnvelopeState(getPadSoundState(track));
|
||||||
|
|
||||||
|
assert.equal(envelope.classicAttackMs, (64 / 255) * 4000);
|
||||||
|
assert.equal(envelope.classicReleaseMs, (128 / 255) * 4000);
|
||||||
|
assert.equal(envelope.oneShotFadeInMs, 0);
|
||||||
|
assert.equal(envelope.oneShotFadeOutMs, 5);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user