fix: missing count-in when recording with loop mode on
This commit is contained in:
+14
-6
@@ -10,6 +10,10 @@ import { KGRegion } from './region/KGRegion';
|
||||
import { generateUniqueId } from '../util/miscUtil';
|
||||
import { KGCommand, KGCommandHistory } from './commands';
|
||||
|
||||
interface PlaybackStartOptions {
|
||||
preserveLoopPreroll?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* KGCore - Main application class for the DAW
|
||||
* Implements the singleton pattern for global access
|
||||
@@ -231,7 +235,7 @@ export class KGCore {
|
||||
return this.isPlaying;
|
||||
}
|
||||
|
||||
public async preparePlay(): Promise<void> {
|
||||
public async preparePlay(options?: PlaybackStartOptions): Promise<void> {
|
||||
try {
|
||||
const audioInterface = KGAudioInterface.instance();
|
||||
|
||||
@@ -239,7 +243,9 @@ export class KGCore {
|
||||
await audioInterface.startAudioContext();
|
||||
|
||||
// Prepare playback with current project and playhead position
|
||||
audioInterface.preparePlayback(this.currentProject, this.playheadPosition);
|
||||
audioInterface.preparePlayback(this.currentProject, this.playheadPosition, {
|
||||
allowStartBeforeLoopStart: options?.preserveLoopPreroll ?? false,
|
||||
});
|
||||
|
||||
// Sync BPM and transport settings
|
||||
audioInterface.setBpm(this.currentProject.getBpm());
|
||||
@@ -301,7 +307,7 @@ export class KGCore {
|
||||
}
|
||||
|
||||
// High-level playback control methods
|
||||
public async startPlaying(): Promise<void> {
|
||||
public async startPlaying(options?: PlaybackStartOptions): Promise<void> {
|
||||
// Handle loop mode initialization
|
||||
if (this.currentProject.getIsLooping()) {
|
||||
const [startBar, endBar] = this.currentProject.getLoopingRange();
|
||||
@@ -319,11 +325,13 @@ export class KGCore {
|
||||
const updatedRange = this.currentProject.getLoopingRange();
|
||||
const beatsPerBar = this.currentProject.getTimeSignature().numerator;
|
||||
const loopStartBeats = updatedRange[0] * beatsPerBar;
|
||||
this.setPlayheadPosition(loopStartBeats);
|
||||
if (!options?.preserveLoopPreroll) {
|
||||
this.setPlayheadPosition(loopStartBeats);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare playback first
|
||||
await this.preparePlay();
|
||||
await this.preparePlay(options);
|
||||
|
||||
// Start playing (non-blocking)
|
||||
this.play(); // Don't await this
|
||||
@@ -645,4 +653,4 @@ export class KGCore {
|
||||
public getCommandHistoryStats(): { undoCount: number; redoCount: number; maxSize: number } {
|
||||
return this.commandHistory.getHistoryStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,4 +97,19 @@ describe('KGAudioInterface preroll playback', () => {
|
||||
expect(MockTransport.stop).toHaveBeenCalledTimes(1)
|
||||
expect(audio.getTransportPosition()).toBe(0)
|
||||
})
|
||||
|
||||
it('allows a first-pass start before the loop start when explicitly requested', () => {
|
||||
const project = createMockProject({
|
||||
bpm: 120,
|
||||
timeSignature: { numerator: 4, denominator: 4 },
|
||||
tracks: [],
|
||||
})
|
||||
project.setIsLooping(true)
|
||||
project.setLoopingRange([4, 7])
|
||||
|
||||
const audio = KGAudioInterface.instance()
|
||||
audio.preparePlayback(project, 12, { allowStartBeforeLoopStart: true })
|
||||
|
||||
expect(MockTransport.position).toBe(6)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -12,6 +12,10 @@ import { KGCore } from '../KGCore';
|
||||
import { ConfigManager } from '../config/ConfigManager';
|
||||
import { KGMetronome } from './KGMetronome';
|
||||
|
||||
interface PreparePlaybackOptions {
|
||||
allowStartBeforeLoopStart?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* KGAudioInterface - Audio engine interface for the DAW
|
||||
* Implements the singleton pattern for global audio management
|
||||
@@ -391,7 +395,7 @@ export class KGAudioInterface {
|
||||
/**
|
||||
* Prepare playback by scheduling all MIDI events
|
||||
*/
|
||||
public preparePlayback(project: KGProject, startPosition: number): void {
|
||||
public preparePlayback(project: KGProject, startPosition: number, options?: PreparePlaybackOptions): void {
|
||||
// Clear any existing scheduled events
|
||||
this.clearScheduledEvents();
|
||||
this.clearDelayedTransportStart();
|
||||
@@ -437,7 +441,7 @@ export class KGAudioInterface {
|
||||
console.log(`Loop mode enabled: bars [${startBar}, ${endBar}], beats [${scheduleStartBeat}, ${scheduleEndBeat}]`);
|
||||
|
||||
// Adjust start position to loop start if before loop range
|
||||
if (startPosition < scheduleStartBeat) {
|
||||
if (startPosition < scheduleStartBeat && !options?.allowStartBeforeLoopStart) {
|
||||
startPosition = scheduleStartBeat;
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user