fix: realtime velocity with updatedNotes + ruler restart without onStop
This commit is contained in:
+46
-31
@@ -5424,12 +5424,13 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
const currentNote = notes[cursorNoteIdx];
|
const currentNote = notes[cursorNoteIdx];
|
||||||
const currentVal = ccMode === 'pan' ? ((currentNote.pan || 0) / 2.0 + 0.5) : (currentNote.velocity !== undefined ? currentNote.velocity : 0.8);
|
const currentVal = ccMode === 'pan' ? ((currentNote.pan || 0) / 2.0 + 0.5) : (currentNote.velocity !== undefined ? currentNote.velocity : 0.8);
|
||||||
if (Math.abs(currentVal - val) > 0.001) {
|
if (Math.abs(currentVal - val) > 0.001) {
|
||||||
setNotes(prev => prev.map((n, i) => {
|
const updatedNotes = notes.map((n, i) => {
|
||||||
if (i !== cursorNoteIdx) return n;
|
if (i !== cursorNoteIdx) return n;
|
||||||
if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 };
|
if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 };
|
||||||
return { ...n, velocity: val };
|
return { ...n, velocity: val };
|
||||||
}));
|
});
|
||||||
if (isPlaying && onRescheduleMidi) onRescheduleMidi();
|
setNotes(updatedNotes);
|
||||||
|
if (isPlaying && onRescheduleMidi) onRescheduleMidi(updatedNotes);
|
||||||
}
|
}
|
||||||
ccDragRef.current = { active: true, lastBeat: beat, selectedMode: true, lastPainted: [cursorNoteIdx] };
|
ccDragRef.current = { active: true, lastBeat: beat, selectedMode: true, lastPainted: [cursorNoteIdx] };
|
||||||
} else {
|
} else {
|
||||||
@@ -5444,11 +5445,13 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
if (noteIdx !== -1) {
|
if (noteIdx !== -1) {
|
||||||
const currentVal = ccMode === 'pan' ? ((notes[noteIdx].pan || 0) / 2.0 + 0.5) : (notes[noteIdx].velocity !== undefined ? notes[noteIdx].velocity : 0.8);
|
const currentVal = ccMode === 'pan' ? ((notes[noteIdx].pan || 0) / 2.0 + 0.5) : (notes[noteIdx].velocity !== undefined ? notes[noteIdx].velocity : 0.8);
|
||||||
if (Math.abs(currentVal - val) > 0.001) {
|
if (Math.abs(currentVal - val) > 0.001) {
|
||||||
setNotes(prev => prev.map((n, i) => {
|
const updatedNotes = notes.map((n, i) => {
|
||||||
if (i !== noteIdx) return n;
|
if (i !== noteIdx) return n;
|
||||||
if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 };
|
if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 };
|
||||||
return { ...n, velocity: val };
|
return { ...n, velocity: val };
|
||||||
}));
|
});
|
||||||
|
setNotes(updatedNotes);
|
||||||
|
if (isPlaying && onRescheduleMidi) onRescheduleMidi(updatedNotes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -5474,12 +5477,13 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
if (cursorNote && selectedNoteIds.includes(cursorNote.id) && !painted.includes(cursorNoteIdx)) {
|
if (cursorNote && selectedNoteIds.includes(cursorNote.id) && !painted.includes(cursorNoteIdx)) {
|
||||||
const currentVal = ccMode === 'pan' ? ((cursorNote.pan || 0) / 2.0 + 0.5) : (cursorNote.velocity !== undefined ? cursorNote.velocity : 0.8);
|
const currentVal = ccMode === 'pan' ? ((cursorNote.pan || 0) / 2.0 + 0.5) : (cursorNote.velocity !== undefined ? cursorNote.velocity : 0.8);
|
||||||
if (Math.abs(currentVal - val) > 0.001) {
|
if (Math.abs(currentVal - val) > 0.001) {
|
||||||
setNotes(prev => prev.map((n, i) => {
|
const updatedNotes = notes.map((n, i) => {
|
||||||
if (i !== cursorNoteIdx) return n;
|
if (i !== cursorNoteIdx) return n;
|
||||||
if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 };
|
if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 };
|
||||||
return { ...n, velocity: val };
|
return { ...n, velocity: val };
|
||||||
}));
|
});
|
||||||
if (isPlaying && onRescheduleMidi) onRescheduleMidi();
|
setNotes(updatedNotes);
|
||||||
|
if (isPlaying && onRescheduleMidi) onRescheduleMidi(updatedNotes);
|
||||||
}
|
}
|
||||||
drag.lastPainted = [...painted, cursorNoteIdx];
|
drag.lastPainted = [...painted, cursorNoteIdx];
|
||||||
}
|
}
|
||||||
@@ -5491,12 +5495,13 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
if (candidateIdx !== -1 && !painted.includes(candidateIdx)) {
|
if (candidateIdx !== -1 && !painted.includes(candidateIdx)) {
|
||||||
const currentVal = ccMode === 'pan' ? ((notes[candidateIdx].pan || 0) / 2.0 + 0.5) : (notes[candidateIdx].velocity !== undefined ? notes[candidateIdx].velocity : 0.8);
|
const currentVal = ccMode === 'pan' ? ((notes[candidateIdx].pan || 0) / 2.0 + 0.5) : (notes[candidateIdx].velocity !== undefined ? notes[candidateIdx].velocity : 0.8);
|
||||||
if (Math.abs(currentVal - val) > 0.001) {
|
if (Math.abs(currentVal - val) > 0.001) {
|
||||||
setNotes(prev => prev.map((n, i) => {
|
const updatedNotes = notes.map((n, i) => {
|
||||||
if (i !== candidateIdx) return n;
|
if (i !== candidateIdx) return n;
|
||||||
if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 };
|
if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 };
|
||||||
return { ...n, velocity: val };
|
return { ...n, velocity: val };
|
||||||
}));
|
});
|
||||||
if (isPlaying && onRescheduleMidi) onRescheduleMidi();
|
setNotes(updatedNotes);
|
||||||
|
if (isPlaying && onRescheduleMidi) onRescheduleMidi(updatedNotes);
|
||||||
}
|
}
|
||||||
drag.lastPainted = [...painted, candidateIdx];
|
drag.lastPainted = [...painted, candidateIdx];
|
||||||
}
|
}
|
||||||
@@ -5855,11 +5860,21 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
|||||||
if (clickTime >= 0) {
|
if (clickTime >= 0) {
|
||||||
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s));
|
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s));
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
onStop();
|
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s));
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s));
|
stopAllPlayback();
|
||||||
onPlayPause();
|
const sub = subTabs.find(s2 => s2.id === st.id);
|
||||||
}, 30);
|
if (sub) {
|
||||||
|
const ctx = getAudioContext();
|
||||||
|
startOffsetTimeRef.current = clickTime;
|
||||||
|
startAudioTimeRef.current = ctx.currentTime;
|
||||||
|
startBufferOffsetRef.current = clickTime * (sub.speed || 1.0);
|
||||||
|
schedulePianoRollMidi(sub, clickTime);
|
||||||
|
startSubTabPlayback(sub, clickTime);
|
||||||
|
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime, isPlaying: true } : s));
|
||||||
|
animationFrameIdRef.current = requestAnimationFrame(updatePlayhead);
|
||||||
|
}
|
||||||
|
}, 20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e.ctrlKey || e.metaKey) {
|
if (e.ctrlKey || e.metaKey) {
|
||||||
@@ -10027,10 +10042,10 @@ const App = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const schedulePianoRollMidi = (st, offsetSeconds) => {
|
const schedulePianoRollMidi = (st, offsetSeconds, notesOverride) => {
|
||||||
if (st.type !== 'PIANO_ROLL') return;
|
if (st.type !== 'PIANO_ROLL') return;
|
||||||
const context = getAudioContext();
|
const context = getAudioContext();
|
||||||
const midiNotes = st.notes || [];
|
const midiNotes = notesOverride || st.notes || [];
|
||||||
const bpmVal = parseInt(bpm) || 120;
|
const bpmVal = parseInt(bpm) || 120;
|
||||||
const secondsPerBeat = 60.0 / bpmVal;
|
const secondsPerBeat = 60.0 / bpmVal;
|
||||||
const startWallTime = context.currentTime;
|
const startWallTime = context.currentTime;
|
||||||
@@ -15814,20 +15829,20 @@ const App = () => {
|
|||||||
onMidiInputSelect: handleMidiInputSelect,
|
onMidiInputSelect: handleMidiInputSelect,
|
||||||
activeMidiPitches: activeMidiPitches,
|
activeMidiPitches: activeMidiPitches,
|
||||||
onInstrumentSelect: (trackId) => { openInstrumentSelector(trackId); },
|
onInstrumentSelect: (trackId) => { openInstrumentSelector(trackId); },
|
||||||
onRescheduleMidi: () => {
|
onRescheduleMidi: (updatedNotes) => {
|
||||||
const playingSub = subTabs.find(s => s.id === activeTab && s.type === 'PIANO_ROLL' && s.isPlaying);
|
const playingSub = subTabs.find(s => s.id === activeTab && s.type === 'PIANO_ROLL' && s.isPlaying);
|
||||||
if (playingSub) {
|
if (playingSub) {
|
||||||
const offset = playingSub.currentTime || 0;
|
const offset = playingSub.currentTime || 0;
|
||||||
window.SonicSF.stopAll();
|
window.SonicSF.stopAll();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const ctx = getAudioContext();
|
const ctx = getAudioContext();
|
||||||
startOffsetTimeRef.current = offset;
|
startOffsetTimeRef.current = offset;
|
||||||
startAudioTimeRef.current = ctx.currentTime;
|
startAudioTimeRef.current = ctx.currentTime;
|
||||||
startBufferOffsetRef.current = offset * (playingSub.speed || 1.0);
|
startBufferOffsetRef.current = offset * (playingSub.speed || 1.0);
|
||||||
schedulePianoRollMidi(playingSub, offset);
|
schedulePianoRollMidi(playingSub, offset, updatedNotes);
|
||||||
}, 20);
|
}, 20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const subTrack = tracks.find(t => t.id === st.trackId);
|
const subTrack = tracks.find(t => t.id === st.trackId);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user