fix: per-track instrument + ghost note visibility

soundfontPlayer.js:
- selectInstrument: respect passed channel (don't allocate new one)
- _playNoteFluid: only use _engineChMap when channel is undefined

ghostNoteExtractor.js:
- Include ALL notes from overlapping items (not clipped)
- relative_start_beat can be negative (notes before window)
- Keep original duration instead of clamping
This commit is contained in:
2026-07-27 20:04:56 +07:00
parent e14554a75a
commit 4a9cbcdef1
2 changed files with 18 additions and 16 deletions
+3 -7
View File
@@ -40,17 +40,13 @@
var noteAbsStart = itemStartBeat + (note.start_beat || 0); var noteAbsStart = itemStartBeat + (note.start_beat || 0);
var noteAbsEnd = noteAbsStart + (note.duration_beats || 1); var noteAbsEnd = noteAbsStart + (note.duration_beats || 1);
if (noteAbsStart >= windowEndBeat || noteAbsEnd < windowStartBeat) continue; if (noteAbsStart >= windowEndBeat) continue;
var clampedStart = Math.max(noteAbsStart, windowStartBeat);
var clampedEnd = Math.min(noteAbsEnd, windowEndBeat);
var clampedDur = clampedEnd - clampedStart;
trackGhostNotes.push({ trackGhostNotes.push({
id: 'ghost_' + (note.id || Math.random().toString(36).substr(2, 9)), id: 'ghost_' + (note.id || Math.random().toString(36).substr(2, 9)),
pitch: note.pitch, pitch: note.pitch,
relative_start_beat: clampedStart - windowStartBeat, relative_start_beat: noteAbsStart - windowStartBeat,
duration_beats: clampedDur, duration_beats: (note.duration_beats || 1),
velocity: note.velocity, velocity: note.velocity,
original_track_name: track.name, original_track_name: track.name,
original_track_color: track.color || '#888888' original_track_color: track.color || '#888888'
+15 -9
View File
@@ -233,9 +233,13 @@
} }
var engKey = (sfId || '') + ':' + bank + ':' + program; var engKey = (sfId || '') + ':' + bank + ':' + program;
if (!_engineChMap[engKey]) { if (!_engineChMap[engKey]) {
var allocCh = this.allocateChannel(bank); if (channel === undefined || channel === null) {
_engineChMap[engKey] = allocCh; var allocCh = this.allocateChannel(bank);
channel = allocCh; _engineChMap[engKey] = allocCh;
channel = allocCh;
} else {
_engineChMap[engKey] = channel;
}
} else { } else {
channel = _engineChMap[engKey]; channel = _engineChMap[engKey];
} }
@@ -363,12 +367,14 @@
if (synthEngine) { if (synthEngine) {
usedBank = synthEngine.soundfont_bank || 0; usedBank = synthEngine.soundfont_bank || 0;
usedProg = synthEngine.soundfont_program || 0; usedProg = synthEngine.soundfont_program || 0;
var engKey = (synthEngine.soundfont_id || '') + ':' + usedBank + ':' + usedProg; if (ch === undefined) {
var mappedCh = _engineChMap[engKey]; var engKey = (synthEngine.soundfont_id || '') + ':' + usedBank + ':' + usedProg;
if (mappedCh !== undefined) { var mappedCh = _engineChMap[engKey];
ch = mappedCh; if (mappedCh !== undefined) {
} else if (ch === undefined) { ch = mappedCh;
ch = usedBank === 128 ? 9 : 0; } else {
ch = usedBank === 128 ? 9 : 0;
}
} }
if (ch === undefined) ch = (usedBank === 128 ? 9 : 0); if (ch === undefined) ch = (usedBank === 128 ? 9 : 0);
var sfHandle = synthEngine.soundfont_id ? _sfHandleMap.get(synthEngine.soundfont_id) : undefined; var sfHandle = synthEngine.soundfont_id ? _sfHandleMap.get(synthEngine.soundfont_id) : undefined;