v16: persist cc11_global_curve qua save/load (item + sub_tabs) + commitCC11Curve dong bo subTab st.notes (CC11 realtime khi Play)
This commit is contained in:
+16
-4
@@ -9056,6 +9056,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
target_id: match.id,
|
||||
label: 'Piano Roll: ' + (match.name || 'MIDI'),
|
||||
notes: match.notes || [],
|
||||
cc11_global_curve: match.cc11_global_curve || null,
|
||||
duration: match.duration || 4,
|
||||
instrumentProgram: scope ? scope.instrument_program : (trk ? trk.instrumentProgram : undefined),
|
||||
instrumentName: scope ? scope.instrument_name : (trk ? trk.instrumentName : undefined),
|
||||
@@ -9635,7 +9636,10 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
// CC11 = GLOBAL curve tu note dau den note cuoi (khong per-note). Khi commit
|
||||
// sinh lai per-note expression_curve (engine doc per-note) bang cach sample
|
||||
// global tai vung tung note.
|
||||
const [cc11GlobalCurve, setCc11GlobalCurve] = React.useState([]);
|
||||
const [cc11GlobalCurve, setCc11GlobalCurve] = React.useState(() => Array.isArray(st.cc11_global_curve) && st.cc11_global_curve.length ? st.cc11_global_curve.slice() : []);
|
||||
React.useEffect(() => {
|
||||
setCc11GlobalCurve(Array.isArray(st.cc11_global_curve) && st.cc11_global_curve.length ? st.cc11_global_curve.slice() : []);
|
||||
}, [st.cc11_global_curve]);
|
||||
React.useEffect(() => {
|
||||
if (cc11GlobalCurve && cc11GlobalCurve.length) return;
|
||||
const n = notes.find(x => Array.isArray(x.expression_curve) && x.expression_curve.length);
|
||||
@@ -10598,6 +10602,9 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
return { ...n, expression_curve: pts.sort((a, b) => a.position_ratio - b.position_ratio) };
|
||||
});
|
||||
setNotes(updatedNotes);
|
||||
// Đồng bộ subTab NGAY (không chờ effect): schedulePianoRollMidi đọc
|
||||
// st.notes khi Play (realtime) + cc11_global_curve để persist save/load.
|
||||
if (setSubTabs) setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, notes: updatedNotes, cc11_global_curve: curve, isDirty: true } : s));
|
||||
if (isPlaying && onRescheduleMidi) onRescheduleMidi(updatedNotes);
|
||||
};
|
||||
const handleCC11MouseDown = (e) => {
|
||||
@@ -11894,6 +11901,7 @@ const serializeTracksList = (tracksList, secondsPerBar) => {
|
||||
clip_start_offset_bars: 0.0,
|
||||
source_data: {
|
||||
total_buffer_bars: m.duration ? (m.duration / secondsPerBar) : 8.0,
|
||||
...(Array.isArray(m.cc11_global_curve) && m.cc11_global_curve.length ? { cc11_global_curve: m.cc11_global_curve.map(p => ({ position_ratio: p.position_ratio, value: p.value })) } : {}),
|
||||
notes: (m.notes || []).map(n => ({
|
||||
id: n.id || 'note_' + Math.random().toString(36).substr(2, 9),
|
||||
pitch: n.pitch || 60,
|
||||
@@ -12014,7 +12022,8 @@ const deserializeTracksList = (schemaTracks, secondsPerBar, sectionStore, visite
|
||||
velocity: n.velocity || 0.8,
|
||||
pan: n.pan || 0.0,
|
||||
...(Array.isArray(n.expression_curve) ? { expression_curve: n.expression_curve } : {})
|
||||
}))
|
||||
})),
|
||||
...(Array.isArray(src.cc11_global_curve) && src.cc11_global_curve.length ? { cc11_global_curve: src.cc11_global_curve } : {})
|
||||
});
|
||||
} else if (item.type === "SECTION_ITEM") {
|
||||
const src = item.source_data || {};
|
||||
@@ -12156,6 +12165,7 @@ const serializeProjectToSchema = (projectId, name, bpmVal, tracksList, subTabsLi
|
||||
target_id: st.target_id,
|
||||
parent_tab_id: st.parent_tab_id,
|
||||
notes: st.notes || [],
|
||||
...(Array.isArray(st.cc11_global_curve) && st.cc11_global_curve.length ? { cc11_global_curve: st.cc11_global_curve.map(p => ({ position_ratio: p.position_ratio, value: p.value })) } : {}),
|
||||
duration: st.duration || 4,
|
||||
instrument_program: st.instrumentProgram,
|
||||
instrument_name: st.instrumentName,
|
||||
@@ -12260,6 +12270,7 @@ const deserializeProjectFromSchema = (schemaObj) => {
|
||||
target_id: st.target_id,
|
||||
parent_tab_id: st.parent_tab_id,
|
||||
notes: st.notes || [],
|
||||
cc11_global_curve: st.cc11_global_curve || null,
|
||||
duration: st.duration || 4,
|
||||
instrumentProgram: st.instrument_program,
|
||||
instrumentName: st.instrument_name,
|
||||
@@ -21657,6 +21668,7 @@ const App = () => {
|
||||
target_id: midiItemId,
|
||||
parent_tab_id: activeTab === 'main' ? null : activeTab,
|
||||
notes: midiItem.notes || [],
|
||||
cc11_global_curve: midiItem.cc11_global_curve || null,
|
||||
duration: midiItem.duration || 4,
|
||||
buffer: silentBuffer,
|
||||
instrumentProgram: track.instrumentProgram !== undefined ? track.instrumentProgram : (track.synth_engine ? track.synth_engine.soundfont_program : undefined),
|
||||
@@ -21702,7 +21714,7 @@ const App = () => {
|
||||
...t,
|
||||
midiItems: (t.midiItems || []).map(m => {
|
||||
if (m.id !== midiItemId) return m;
|
||||
return { ...m, notes: updatedNotes };
|
||||
return { ...m, notes: updatedNotes, cc11_global_curve: pianoRollTab ? (pianoRollTab.cc11_global_curve || null) : null };
|
||||
})
|
||||
};
|
||||
})
|
||||
@@ -21715,7 +21727,7 @@ const App = () => {
|
||||
...t,
|
||||
midiItems: (t.midiItems || []).map(m => {
|
||||
if (m.id !== midiItemId) return m;
|
||||
return { ...m, notes: updatedNotes };
|
||||
return { ...m, notes: updatedNotes, cc11_global_curve: pianoRollTab ? (pianoRollTab.cc11_global_curve || null) : null };
|
||||
})
|
||||
};
|
||||
}));
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -51,7 +51,7 @@
|
||||
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
|
||||
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
|
||||
<script src="/static/js/services/chordTheory.js?v=202608211300"></script>
|
||||
<script src="/static/js/app.precompiled.js?v=202608291900" defer></script>
|
||||
<script src="/static/js/app.precompiled.js?v=202608292100" defer></script>
|
||||
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
|
||||
<style>
|
||||
:root {
|
||||
|
||||
Reference in New Issue
Block a user