fix: brush draw per-note duration with noteStartBeats tracking
This commit is contained in:
+17
-5
@@ -5120,7 +5120,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
visitedPitches: snapToScaleRef.current ? [snapPitchToScale(pitch, selectedScaleRef.current)] : [pitch],
|
visitedPitches: snapToScaleRef.current ? [snapPitchToScale(pitch, selectedScaleRef.current)] : [pitch],
|
||||||
initialBeat: start,
|
initialBeat: start,
|
||||||
initialPitch: snapToScaleRef.current ? snapPitchToScale(pitch, selectedScaleRef.current) : pitch,
|
initialPitch: snapToScaleRef.current ? snapPitchToScale(pitch, selectedScaleRef.current) : pitch,
|
||||||
lastDrawBeat: start
|
noteStartBeats: [start]
|
||||||
});
|
});
|
||||||
// Play the note with SoundFont
|
// Play the note with SoundFont
|
||||||
if (window.SonicSF) {
|
if (window.SonicSF) {
|
||||||
@@ -5206,18 +5206,27 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (draggedNote.mode === 'draw') {
|
if (draggedNote.mode === 'draw') {
|
||||||
const rawDur = beat - draggedNote.startOffsetBeat;
|
|
||||||
const newDur = getSnapBeat(Math.max(0.125, rawDur), snapVal);
|
|
||||||
const visited = draggedNote.visitedPitches || [];
|
const visited = draggedNote.visitedPitches || [];
|
||||||
const snappedPitch = snapToScaleRef.current ? snapPitchToScale(pitch, selectedScaleRef.current) : pitch;
|
const snappedPitch = snapToScaleRef.current ? snapPitchToScale(pitch, selectedScaleRef.current) : pitch;
|
||||||
const pitchChanged = !visited.includes(snappedPitch);
|
const pitchChanged = !visited.includes(snappedPitch);
|
||||||
|
const noteBeats = draggedNote.noteStartBeats || [];
|
||||||
|
const defaultDur = getSnapDuration(snapVal);
|
||||||
if (pitchChanged) {
|
if (pitchChanged) {
|
||||||
const brushIds = draggedNote.brushIds || [];
|
const brushIds = draggedNote.brushIds || [];
|
||||||
|
if (brushIds.length > 0 && noteBeats.length > 0) {
|
||||||
|
const prevNoteId = brushIds[brushIds.length - 1];
|
||||||
|
const prevNoteBeat = noteBeats[noteBeats.length - 1];
|
||||||
|
const prevDur = Math.max(0.125, beat - prevNoteBeat);
|
||||||
|
setNotes(prev => prev.map(n => {
|
||||||
|
if (n.id !== prevNoteId) return n;
|
||||||
|
return { ...n, duration_beats: prevDur };
|
||||||
|
}));
|
||||||
|
}
|
||||||
const newNote = {
|
const newNote = {
|
||||||
id: 'note_' + Date.now() + Math.random().toString(36).substr(2, 8) + '_' + (visited.length + 1),
|
id: 'note_' + Date.now() + Math.random().toString(36).substr(2, 8) + '_' + (visited.length + 1),
|
||||||
pitch: snappedPitch,
|
pitch: snappedPitch,
|
||||||
start_beat: beat,
|
start_beat: beat,
|
||||||
duration_beats: getSnapDuration(snapVal),
|
duration_beats: defaultDur,
|
||||||
velocity: brushVelocityRef.current,
|
velocity: brushVelocityRef.current,
|
||||||
pan: 0.0
|
pan: 0.0
|
||||||
};
|
};
|
||||||
@@ -5225,13 +5234,16 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
setSelectedNoteIds(prev => [...prev, newNote.id]);
|
setSelectedNoteIds(prev => [...prev, newNote.id]);
|
||||||
draggedNote.brushIds = [...brushIds, newNote.id];
|
draggedNote.brushIds = [...brushIds, newNote.id];
|
||||||
draggedNote.visitedPitches = [...visited, snappedPitch];
|
draggedNote.visitedPitches = [...visited, snappedPitch];
|
||||||
|
draggedNote.noteStartBeats = [...noteBeats, beat];
|
||||||
} else {
|
} else {
|
||||||
const brushIds = draggedNote.brushIds || [];
|
const brushIds = draggedNote.brushIds || [];
|
||||||
const lastBrushId = brushIds.length > 0 ? brushIds[brushIds.length - 1] : draggedNote.drawNoteId;
|
const lastBrushId = brushIds.length > 0 ? brushIds[brushIds.length - 1] : draggedNote.drawNoteId;
|
||||||
|
const lastNoteBeat = noteBeats.length > 0 ? noteBeats[noteBeats.length - 1] : draggedNote.startOffsetBeat;
|
||||||
if (lastBrushId) {
|
if (lastBrushId) {
|
||||||
|
const extDur = Math.max(0.125, beat - lastNoteBeat);
|
||||||
setNotes(prev => prev.map(n => {
|
setNotes(prev => prev.map(n => {
|
||||||
if (n.id !== lastBrushId) return n;
|
if (n.id !== lastBrushId) return n;
|
||||||
return { ...n, duration_beats: newDur };
|
return { ...n, duration_beats: extDur };
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -200,3 +200,8 @@
|
|||||||
- **Tóm tắt thay đổi:** (1) Brush draw: chỉ tạo note mới khi `pitchChanged` (pitch chưa visited). Nếu cùng pitch, extend `duration_beats` của note cuối cùng trong `brushIds` — không tạo note mới trùng pitch. (2) CC velocity: thêm check `Math.abs(currentVal - val) > 0.001` trước mỗi `setNotes` — skip render khi velocity/pan không thay đổi, loại bỏ flicker cho cả selected + non-selected mode.
|
- **Tóm tắt thay đổi:** (1) Brush draw: chỉ tạo note mới khi `pitchChanged` (pitch chưa visited). Nếu cùng pitch, extend `duration_beats` của note cuối cùng trong `brushIds` — không tạo note mới trùng pitch. (2) CC velocity: thêm check `Math.abs(currentVal - val) > 0.001` trước mỗi `setNotes` — skip render khi velocity/pan không thay đổi, loại bỏ flicker cho cả selected + non-selected mode.
|
||||||
- **Các file ảnh hưởng:** `app/static/js/app.jsx`
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`
|
||||||
- **Ghi chú/Test (nếu có):** `npm run build` pass. currentVal tính: velocity = note.velocity || 0.8; pan = (note.pan || 0) / 2 + 0.5.
|
- **Ghi chú/Test (nếu có):** `npm run build` pass. currentVal tính: velocity = note.velocity || 0.8; pan = (note.pan || 0) / 2 + 0.5.
|
||||||
|
|
||||||
|
### [2026-07-26 10:49] Task: Fix brush draw per-note duration + noteStartBeats tracking
|
||||||
|
- **Tóm tắt thay đổi:** (1) Thêm `noteStartBeats` array trong `draggedNote` — track start beat của từng note. Khi tạo note mới (pitchChanged), fix duration của note trước đó thành `beat - prevNoteBeat`. Khi extend (cùng pitch), chỉ extend note cuối với `beat - lastNoteBeat` (không extend toàn bộ stroke). (2) Khởi tạo `noteStartBeats: [start]` trong setDraggedNote. Fix lỗi note cuối có duration dài bằng toàn bộ brush stroke.
|
||||||
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`
|
||||||
|
- **Ghi chú/Test (nếu có):** `npm run build` pass.
|
||||||
|
|||||||
Reference in New Issue
Block a user