fix: should cut a held looped recording note at the loop end when note off arrives after wrap

This commit is contained in:
Xiaohan-Tian
2026-05-04 17:11:29 -07:00
parent 769d70ccb4
commit c733c39814
2 changed files with 73 additions and 4 deletions
+26 -4
View File
@@ -202,6 +202,29 @@ interface ProjectState {
let _recordingActiveNotes: Map<number, number> = new Map(); // pitch → region-relative startBeat
let _recordingRegionStartBeat: number = 0;
function getRecordingLoopEndBeatRelative(): number | null {
const project = KGCore.instance().getCurrentProject();
if (!project.getIsLooping()) {
return null;
}
const [startBar, endBarOriginal] = project.getLoopingRange();
const beatsPerBar = project.getTimeSignature().numerator;
const endBar = (startBar === 0 && endBarOriginal === 0) ? project.getMaxBars() : endBarOriginal;
const loopEndBeatAbsolute = (endBar + 1) * beatsPerBar;
return loopEndBeatAbsolute - _recordingRegionStartBeat;
}
function finalizeRecordedNote(startBeat: number, candidateEndBeat: number): number {
const loopEndBeatRelative = getRecordingLoopEndBeatRelative();
if (loopEndBeatRelative !== null && candidateEndBeat < startBeat) {
return loopEndBeatRelative;
}
return candidateEndBeat;
}
// Create the store
export const useProjectStore = create<ProjectState>((set, get) => {
const currentProject = KGCore.instance().getCurrentProject();
@@ -869,8 +892,9 @@ export const useProjectStore = create<ProjectState>((set, get) => {
const startBeat = _recordingActiveNotes.get(pitch);
if (startBeat !== undefined) {
_recordingActiveNotes.delete(pitch);
const finalizedEndBeat = finalizeRecordedNote(startBeat, endBeat);
set(state => ({
recordingNotes: [...state.recordingNotes, { pitch, startBeat, endBeat }],
recordingNotes: [...state.recordingNotes, { pitch, startBeat, endBeat: finalizedEndBeat }],
}));
}
}
@@ -902,7 +926,7 @@ export const useProjectStore = create<ProjectState>((set, get) => {
const endBeatForHeld = KGAudioInterface.instance().getTransportPosition() - correctionBeats - _recordingRegionStartBeat;
_recordingActiveNotes.forEach((startBeat, pitch) => {
finalNotes.push({ pitch, startBeat, endBeat: endBeatForHeld });
finalNotes.push({ pitch, startBeat, endBeat: finalizeRecordedNote(startBeat, endBeatForHeld) });
});
_recordingActiveNotes.clear();
@@ -1249,5 +1273,3 @@ export const useProjectStore = create<ProjectState>((set, get) => {