elektron-lfo 1.0.12 → 1.0.13
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/dist/index.js +1 -9
- package/package.json +1 -1
- package/src/engine/triggers.ts +10 -16
- package/tests/triggers.test.ts +15 -37
package/dist/index.js
CHANGED
|
@@ -283,15 +283,7 @@ function checkModeStop(config, state, previousPhase, currentPhase) {
|
|
|
283
283
|
const isForward = config.speed >= 0;
|
|
284
284
|
if (config.mode === "ONE") {
|
|
285
285
|
if (state.cycleCount >= 1) {
|
|
286
|
-
|
|
287
|
-
if (startPhase === 0 || currentPhase >= startPhase) {
|
|
288
|
-
return { shouldStop: true, cycleCompleted: true };
|
|
289
|
-
}
|
|
290
|
-
} else {
|
|
291
|
-
if (startPhase === 0 || currentPhase <= startPhase) {
|
|
292
|
-
return { shouldStop: true, cycleCompleted: true };
|
|
293
|
-
}
|
|
294
|
-
}
|
|
286
|
+
return { shouldStop: true, cycleCompleted: true };
|
|
295
287
|
}
|
|
296
288
|
} else if (config.mode === "HLF") {
|
|
297
289
|
const halfPhase = (startPhase + 0.5) % 1;
|
package/package.json
CHANGED
package/src/engine/triggers.ts
CHANGED
|
@@ -112,23 +112,17 @@ export function checkModeStop(
|
|
|
112
112
|
const isForward = config.speed >= 0;
|
|
113
113
|
|
|
114
114
|
if (config.mode === 'ONE') {
|
|
115
|
-
// ONE mode: Stop
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
115
|
+
// ONE mode: Stop immediately when phase completes one wrap (cycleCount >= 1)
|
|
116
|
+
// Based on Digitakt II hardware testing (January 2025):
|
|
117
|
+
// - Phase runs from startPhase until it wraps (crosses 1.0→0.0 or 0.0→1.0)
|
|
118
|
+
// - Stops immediately on wrap, does NOT continue back to startPhase
|
|
119
|
+
// - This means non-zero startPhase values result in partial amplitude coverage:
|
|
120
|
+
// - Phase=0: full amplitude range (0→1→0, complete waveform)
|
|
121
|
+
// - Phase=32: full amplitude range (0.25→1→0, starts at peak)
|
|
122
|
+
// - Phase=64: half amplitude range (0.5→1→0, starts at middle)
|
|
123
|
+
// - Phase=96: half amplitude range (0.75→1→0, starts at trough)
|
|
119
124
|
if (state.cycleCount >= 1) {
|
|
120
|
-
|
|
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
|
-
}
|
|
125
|
+
return { shouldStop: true, cycleCompleted: true };
|
|
132
126
|
}
|
|
133
127
|
} else if (config.mode === 'HLF') {
|
|
134
128
|
// HLF mode: Stop after half cycle (0.5 phase distance from start)
|
package/tests/triggers.test.ts
CHANGED
|
@@ -241,62 +241,40 @@ describe('checkModeStop - ONE mode', () => {
|
|
|
241
241
|
expect(result.shouldStop).toBe(true);
|
|
242
242
|
});
|
|
243
243
|
|
|
244
|
-
test('with non-zero startPhase,
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
//
|
|
244
|
+
test('with non-zero startPhase, stops immediately on wrap (Digitakt II verified)', () => {
|
|
245
|
+
// Hardware verified (January 2025): ONE mode stops immediately when phase wraps,
|
|
246
|
+
// regardless of startPhase. It does NOT continue back to startPhase.
|
|
247
|
+
// This means non-zero startPhase results in partial amplitude coverage:
|
|
248
|
+
// - Phase=64 (0.5): only covers half the waveform amplitude
|
|
249
|
+
// - Phase=96 (0.75): only covers quarter of phase distance
|
|
250
250
|
const config = createConfig({ mode: 'ONE', speed: 16, startPhase: 53 });
|
|
251
251
|
const startPhaseNormalized = 53 / 128; // ~0.414
|
|
252
252
|
|
|
253
|
-
// After wrap,
|
|
254
|
-
// Should NOT stop yet
|
|
253
|
+
// After wrap, cycleCount = 1, should stop IMMEDIATELY
|
|
255
254
|
const stateAfterWrap = createState({
|
|
256
255
|
hasTriggered: true,
|
|
257
256
|
startPhaseNormalized,
|
|
258
257
|
cycleCount: 1,
|
|
259
258
|
});
|
|
260
|
-
const
|
|
261
|
-
expect(
|
|
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);
|
|
259
|
+
const resultAfterWrap = checkModeStop(config, stateAfterWrap, 0.05, 0.1);
|
|
260
|
+
expect(resultAfterWrap.shouldStop).toBe(true);
|
|
261
|
+
expect(resultAfterWrap.cycleCompleted).toBe(true);
|
|
271
262
|
});
|
|
272
263
|
|
|
273
|
-
test('with non-zero startPhase (backward),
|
|
274
|
-
//
|
|
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
|
|
264
|
+
test('with non-zero startPhase (backward), stops immediately on wrap (Digitakt II verified)', () => {
|
|
265
|
+
// Hardware verified: backward direction also stops immediately on wrap
|
|
279
266
|
const config = createConfig({ mode: 'ONE', speed: -16, startPhase: 53 });
|
|
280
267
|
const startPhaseNormalized = 53 / 128; // ~0.414
|
|
281
268
|
|
|
282
|
-
// After wrap going backward,
|
|
283
|
-
// Should NOT stop yet
|
|
269
|
+
// After wrap going backward, cycleCount = 1, should stop IMMEDIATELY
|
|
284
270
|
const stateAfterWrap = createState({
|
|
285
271
|
hasTriggered: true,
|
|
286
272
|
startPhaseNormalized,
|
|
287
273
|
cycleCount: 1,
|
|
288
274
|
});
|
|
289
275
|
const resultAfterWrap = checkModeStop(config, stateAfterWrap, 0.95, 0.9);
|
|
290
|
-
expect(resultAfterWrap.shouldStop).toBe(
|
|
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);
|
|
276
|
+
expect(resultAfterWrap.shouldStop).toBe(true);
|
|
277
|
+
expect(resultAfterWrap.cycleCompleted).toBe(true);
|
|
300
278
|
});
|
|
301
279
|
});
|
|
302
280
|
|