fix: multitrack play select plays immediately in realtime
This commit is contained in:
+48
-6
@@ -5880,7 +5880,7 @@ const AIPresetModal = ({ isOpen, onClose }) => {
|
||||
}))) : null);
|
||||
};
|
||||
|
||||
const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClose, onUpdateNotes, onSaveNotes, setSubTabs, onPlayPause, onStop, isPlaying, playPreviewNote, showToast, midiDevices, recordingState, recTempMidiNotes, onRecord, selectedMidiInputId, onMidiInputSelect, activeMidiPitches, onInstrumentSelect, onRescheduleMidi, onSeekPlayhead, snapValue, onSnapChange }) => {
|
||||
const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClose, onUpdateNotes, onSaveNotes, setSubTabs, onPlayPause, onStop, isPlaying, playPreviewNote, showToast, midiDevices, recordingState, recTempMidiNotes, onRecord, selectedMidiInputId, onMidiInputSelect, activeMidiPitches, onInstrumentSelect, onRescheduleMidi, onSeekPlayhead, snapValue, onSnapChange, onRealtimePlay }) => {
|
||||
const [activeRollTool, setActiveRollTool] = React.useState('select');
|
||||
const [renderTick, setRenderTick] = React.useState(0);
|
||||
const [ccMode, setCcMode] = React.useState('velocity');
|
||||
@@ -7581,10 +7581,10 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
||||
els.push(React.createElement("button", {
|
||||
key: m._trackId,
|
||||
onClick: function() {
|
||||
setActivePlayTrackIds(function(prev) {
|
||||
var list = prev || [];
|
||||
return list.indexOf(m._trackId) !== -1 ? list.filter(function(id) { return id !== m._trackId; }) : list.concat([m._trackId]);
|
||||
});
|
||||
var prevList = activePlayTrackIds || [];
|
||||
var nextList = prevList.indexOf(m._trackId) !== -1 ? prevList.filter(function(id) { return id !== m._trackId; }) : prevList.concat([m._trackId]);
|
||||
setActivePlayTrackIds(nextList);
|
||||
if (onRealtimePlay) onRealtimePlay(nextList);
|
||||
},
|
||||
className: "flex items-center justify-center h-[20px] border border-zinc-600 rounded-md cursor-pointer outline-none mx-1 my-[2px] " + (isActive ? 'bg-yellow-600 text-black font-bold' : (isPlayOn ? 'bg-red-700 text-white font-semibold' : 'bg-zinc-700 text-zinc-300 hover:bg-zinc-600'))
|
||||
}, React.createElement("span", {
|
||||
@@ -13619,6 +13619,47 @@ const App = () => {
|
||||
}
|
||||
};
|
||||
handlePlayPauseRef.current = handlePlayPause;
|
||||
const handlePianoRollRealtimePlay = (trackIds) => {
|
||||
const prSt = subTabs.find(s => s.id === activeTab && s.type === 'PIANO_ROLL');
|
||||
if (!prSt) return;
|
||||
var prLayers = [];
|
||||
var ghostData = (window.SonicGhost && window.SonicGhost.extractGhostLayers) ? window.SonicGhost.extractGhostLayers(activeTracks, prSt.trackId, prSt.target_id, parseInt(bpm) || 120) : [];
|
||||
(ghostData || []).forEach(function(layer) {
|
||||
if (!trackIds || trackIds.indexOf(layer.track_id) === -1) return;
|
||||
var ltrk = (activeTracks || []).find(function(t) { return t.id === layer.track_id; });
|
||||
prLayers.push({
|
||||
trackId: layer.track_id,
|
||||
notes: layer.notes.map(function(n) { return { pitch: n.pitch, start_beat: n.relative_start_beat, duration_beats: n.duration_beats, velocity: n.velocity || 0.8 }; }),
|
||||
instrumentProgram: ltrk ? ltrk.instrumentProgram : undefined,
|
||||
instrumentName: ltrk ? ltrk.instrumentName : undefined,
|
||||
synthEngine: ltrk ? ltrk.synth_engine : undefined
|
||||
});
|
||||
});
|
||||
stopAllPlayback();
|
||||
const prCtx = getAudioContext();
|
||||
const prTNode = activeTrackNodesRef.current[prSt.trackId];
|
||||
if (prTNode && prTNode.gainNode) {
|
||||
prTNode.gainNode.gain.setValueAtTime(prTNode.gainNode.gain.value || 1, prCtx.currentTime);
|
||||
prTNode.gainNode.gain.linearRampToValueAtTime(0.001, prCtx.currentTime + 0.04);
|
||||
}
|
||||
setTimeout(() => {
|
||||
window.SonicSF.stopAll();
|
||||
if (prTNode && prTNode.gainNode) {
|
||||
const prTrackData = activeTracksRef.current ? activeTracksRef.current.find(t => t.id === prSt.trackId) : null;
|
||||
const prVolDb = prTrackData ? (prTrackData.volumeDb ?? 0) : 0;
|
||||
const prVolLinear = prVolDb <= -50 ? 0 : Math.pow(10, prVolDb / 20);
|
||||
prTNode.gainNode.gain.setValueAtTime(0.001, prCtx.currentTime);
|
||||
prTNode.gainNode.gain.linearRampToValueAtTime(prVolLinear || 0.8, prCtx.currentTime + 0.015);
|
||||
}
|
||||
const prOffset = prSt.currentTime || 0;
|
||||
startOffsetTimeRef.current = prOffset;
|
||||
startAudioTimeRef.current = prCtx.currentTime;
|
||||
startBufferOffsetRef.current = prOffset * (prSt.speed || 1.0);
|
||||
const playTab = Object.assign({}, prSt, { ghostPlayLayers: prLayers });
|
||||
schedulePianoRollMidi(playTab, prOffset);
|
||||
setSubTabs(prev => prev.map(s => s.id === prSt.id ? Object.assign({}, s, { ghostPlayLayers: prLayers, isPlaying: true, currentTime: prOffset }) : s));
|
||||
}, 60);
|
||||
};
|
||||
const handlePause = () => {
|
||||
if (isPlaying || subTabs.some(s => s.isPlaying)) stopAllPlayback();
|
||||
};
|
||||
@@ -20461,7 +20502,8 @@ const App = () => {
|
||||
selectedMidiInputId: selectedMidiInputId,
|
||||
onMidiInputSelect: handleMidiInputSelect,
|
||||
activeMidiPitches: activeMidiPitches,
|
||||
onInstrumentSelect: (trackId) => { openInstrumentSelector(trackId); },
|
||||
onInstrumentSelect: (trackId) => { openInstrumentSelector(trackId); },
|
||||
onRealtimePlay: handlePianoRollRealtimePlay,
|
||||
onRescheduleMidi: (updatedNotes) => {
|
||||
const playingSub = subTabs.find(s => s.id === activeTab && s.type === 'PIANO_ROLL' && s.isPlaying);
|
||||
if (playingSub) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user