elektron-lfo 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/engine/triggers.ts +16 -4
- package/tests/triggers.test.ts +58 -0
package/package.json
CHANGED
package/src/engine/triggers.ts
CHANGED
|
@@ -112,11 +112,23 @@ export function checkModeStop(
|
|
|
112
112
|
const isForward = config.speed >= 0;
|
|
113
113
|
|
|
114
114
|
if (config.mode === 'ONE') {
|
|
115
|
-
// ONE mode: Stop after completing one full cycle
|
|
116
|
-
//
|
|
117
|
-
//
|
|
115
|
+
// ONE mode: Stop after completing one full cycle back to startPhase
|
|
116
|
+
// For non-zero startPhase, we need to:
|
|
117
|
+
// 1. Wait for phase to wrap (cycleCount >= 1)
|
|
118
|
+
// 2. Then continue until we reach/pass the startPhase again
|
|
118
119
|
if (state.cycleCount >= 1) {
|
|
119
|
-
|
|
120
|
+
if (isForward) {
|
|
121
|
+
// Forward: stop when current phase reaches or passes startPhase after wrapping
|
|
122
|
+
// Handle the case where startPhase is 0 (stop immediately on wrap)
|
|
123
|
+
if (startPhase === 0 || currentPhase >= startPhase) {
|
|
124
|
+
return { shouldStop: true, cycleCompleted: true };
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
// Backward: stop when current phase reaches or goes below startPhase after wrapping
|
|
128
|
+
if (startPhase === 0 || currentPhase <= startPhase) {
|
|
129
|
+
return { shouldStop: true, cycleCompleted: true };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
120
132
|
}
|
|
121
133
|
} else if (config.mode === 'HLF') {
|
|
122
134
|
// HLF mode: Stop after half cycle (0.5 phase distance from start)
|
package/tests/triggers.test.ts
CHANGED
|
@@ -240,6 +240,64 @@ describe('checkModeStop - ONE mode', () => {
|
|
|
240
240
|
const result = checkModeStop(config, state, 0.05, 0.95);
|
|
241
241
|
expect(result.shouldStop).toBe(true);
|
|
242
242
|
});
|
|
243
|
+
|
|
244
|
+
test('with non-zero startPhase, does NOT stop immediately after wrap - must reach startPhase', () => {
|
|
245
|
+
// Bug fix: With startPhase 53 (~0.414), the LFO should:
|
|
246
|
+
// 1. Start at 0.414
|
|
247
|
+
// 2. Run to 1.0, wrap to 0.0 (cycleCount = 1)
|
|
248
|
+
// 3. Continue from 0.0 to 0.414 (startPhase)
|
|
249
|
+
// 4. THEN stop
|
|
250
|
+
const config = createConfig({ mode: 'ONE', speed: 16, startPhase: 53 });
|
|
251
|
+
const startPhaseNormalized = 53 / 128; // ~0.414
|
|
252
|
+
|
|
253
|
+
// After wrap, phase is 0.1, which is BEFORE startPhase (0.414)
|
|
254
|
+
// Should NOT stop yet
|
|
255
|
+
const stateAfterWrap = createState({
|
|
256
|
+
hasTriggered: true,
|
|
257
|
+
startPhaseNormalized,
|
|
258
|
+
cycleCount: 1,
|
|
259
|
+
});
|
|
260
|
+
const resultBeforeStart = checkModeStop(config, stateAfterWrap, 0.05, 0.1);
|
|
261
|
+
expect(resultBeforeStart.shouldStop).toBe(false);
|
|
262
|
+
|
|
263
|
+
// Phase reaches 0.3, still before startPhase - should NOT stop
|
|
264
|
+
const resultStillBefore = checkModeStop(config, stateAfterWrap, 0.2, 0.3);
|
|
265
|
+
expect(resultStillBefore.shouldStop).toBe(false);
|
|
266
|
+
|
|
267
|
+
// Phase crosses startPhase (0.414) - NOW should stop
|
|
268
|
+
const resultAtStart = checkModeStop(config, stateAfterWrap, 0.4, 0.45);
|
|
269
|
+
expect(resultAtStart.shouldStop).toBe(true);
|
|
270
|
+
expect(resultAtStart.cycleCompleted).toBe(true);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test('with non-zero startPhase (backward), continues after wrap until reaching startPhase', () => {
|
|
274
|
+
// Backward direction with startPhase 53 (~0.414):
|
|
275
|
+
// 1. Start at 0.414
|
|
276
|
+
// 2. Run backward to 0.0, wrap to 1.0 (cycleCount = 1)
|
|
277
|
+
// 3. Continue from 1.0 down to 0.414
|
|
278
|
+
// 4. THEN stop
|
|
279
|
+
const config = createConfig({ mode: 'ONE', speed: -16, startPhase: 53 });
|
|
280
|
+
const startPhaseNormalized = 53 / 128; // ~0.414
|
|
281
|
+
|
|
282
|
+
// After wrap going backward, phase is 0.9, which is ABOVE startPhase (0.414)
|
|
283
|
+
// Should NOT stop yet
|
|
284
|
+
const stateAfterWrap = createState({
|
|
285
|
+
hasTriggered: true,
|
|
286
|
+
startPhaseNormalized,
|
|
287
|
+
cycleCount: 1,
|
|
288
|
+
});
|
|
289
|
+
const resultAfterWrap = checkModeStop(config, stateAfterWrap, 0.95, 0.9);
|
|
290
|
+
expect(resultAfterWrap.shouldStop).toBe(false);
|
|
291
|
+
|
|
292
|
+
// Phase reaches 0.5, still above startPhase - should NOT stop
|
|
293
|
+
const resultStillAbove = checkModeStop(config, stateAfterWrap, 0.6, 0.5);
|
|
294
|
+
expect(resultStillAbove.shouldStop).toBe(false);
|
|
295
|
+
|
|
296
|
+
// Phase crosses startPhase (0.414) going down - NOW should stop
|
|
297
|
+
const resultAtStart = checkModeStop(config, stateAfterWrap, 0.45, 0.4);
|
|
298
|
+
expect(resultAtStart.shouldStop).toBe(true);
|
|
299
|
+
expect(resultAtStart.cycleCompleted).toBe(true);
|
|
300
|
+
});
|
|
243
301
|
});
|
|
244
302
|
|
|
245
303
|
describe('checkModeStop - HLF mode', () => {
|