fix: di chuyển dspSelectionStats xuống dưới khai báo selLeft/selRight để tránh ReferenceError
This commit is contained in:
+39
-38
@@ -3203,44 +3203,6 @@ const App = () => {
|
|||||||
const [subTabs, setSubTabs] = useState([]); // [{id, label, trackId, startTime, endTime, buffer, effects, currentTime, selectionStart, selectionEnd, isPlaying}, ...]
|
const [subTabs, setSubTabs] = useState([]); // [{id, label, trackId, startTime, endTime, buffer, effects, currentTime, selectionStart, selectionEnd, isPlaying}, ...]
|
||||||
const [selectionCleared, setSelectionCleared] = useState(false); // LOOP_EDITOR_2.md §4.2
|
const [selectionCleared, setSelectionCleared] = useState(false); // LOOP_EDITOR_2.md §4.2
|
||||||
|
|
||||||
const dspSelectionStats = useMemo(() => {
|
|
||||||
const track = tracks.find(t => t.id === selectedTrackId);
|
|
||||||
if (!track) return null;
|
|
||||||
const numChannels = track.buffer ? (track.buffer.numberOfChannels || 1) : 0;
|
|
||||||
if (selLeft === null || selRight === null || selRight <= selLeft || !track.buffer) {
|
|
||||||
return {
|
|
||||||
trackName: track.name,
|
|
||||||
channels: numChannels,
|
|
||||||
timeRange: 'Chưa chọn vùng',
|
|
||||||
peakVolume: 'N/A'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const buffer = track.buffer;
|
|
||||||
const sampleRate = buffer.sampleRate;
|
|
||||||
const startSample = Math.max(0, Math.min(buffer.length - 1, Math.floor(selLeft * sampleRate)));
|
|
||||||
const endSample = Math.max(0, Math.min(buffer.length, Math.floor(selRight * sampleRate)));
|
|
||||||
let maxVal = 0;
|
|
||||||
for (let c = 0; c < numChannels; c++) {
|
|
||||||
const data = buffer.getChannelData(c);
|
|
||||||
for (let i = startSample; i < endSample; i++) {
|
|
||||||
const val = Math.abs(data[i]);
|
|
||||||
if (val > maxVal) maxVal = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let peakDb = 'N/A';
|
|
||||||
if (maxVal > 0) {
|
|
||||||
const db = 20 * Math.log10(maxVal);
|
|
||||||
peakDb = db.toFixed(2) + ' dB';
|
|
||||||
} else {
|
|
||||||
peakDb = '-∞ dB';
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
trackName: track.name,
|
|
||||||
channels: numChannels,
|
|
||||||
timeRange: `${selLeft.toFixed(2)}s - ${selRight.toFixed(2)}s (${(selRight - selLeft).toFixed(2)}s)`,
|
|
||||||
peakVolume: peakDb
|
|
||||||
};
|
|
||||||
}, [tracks, selectedTrackId, selLeft, selRight]);
|
|
||||||
|
|
||||||
// ── Temp Edit Tab (LOOP_EDITOR_2.md §1.2 Sub Tab) ──
|
// ── Temp Edit Tab (LOOP_EDITOR_2.md §1.2 Sub Tab) ──
|
||||||
const [tempTabActive, setTempTabActive] = useState(false);
|
const [tempTabActive, setTempTabActive] = useState(false);
|
||||||
@@ -5087,6 +5049,45 @@ const App = () => {
|
|||||||
return Math.max(selectionStart, selectionEnd);
|
return Math.max(selectionStart, selectionEnd);
|
||||||
}, [selectionStart, selectionEnd, selectionMode, localSelectionStart, localSelectionEnd]);
|
}, [selectionStart, selectionEnd, selectionMode, localSelectionStart, localSelectionEnd]);
|
||||||
|
|
||||||
|
const dspSelectionStats = useMemo(() => {
|
||||||
|
const track = tracks.find(t => t.id === selectedTrackId);
|
||||||
|
if (!track) return null;
|
||||||
|
const numChannels = track.buffer ? (track.buffer.numberOfChannels || 1) : 0;
|
||||||
|
if (selLeft === null || selRight === null || selRight <= selLeft || !track.buffer) {
|
||||||
|
return {
|
||||||
|
trackName: track.name,
|
||||||
|
channels: numChannels,
|
||||||
|
timeRange: 'Chưa chọn vùng',
|
||||||
|
peakVolume: 'N/A'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const buffer = track.buffer;
|
||||||
|
const sampleRate = buffer.sampleRate;
|
||||||
|
const startSample = Math.max(0, Math.min(buffer.length - 1, Math.floor(selLeft * sampleRate)));
|
||||||
|
const endSample = Math.max(0, Math.min(buffer.length, Math.floor(selRight * sampleRate)));
|
||||||
|
let maxVal = 0;
|
||||||
|
for (let c = 0; c < numChannels; c++) {
|
||||||
|
const data = buffer.getChannelData(c);
|
||||||
|
for (let i = startSample; i < endSample; i++) {
|
||||||
|
const val = Math.abs(data[i]);
|
||||||
|
if (val > maxVal) maxVal = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let peakDb = 'N/A';
|
||||||
|
if (maxVal > 0) {
|
||||||
|
const db = 20 * Math.log10(maxVal);
|
||||||
|
peakDb = db.toFixed(2) + ' dB';
|
||||||
|
} else {
|
||||||
|
peakDb = '-∞ dB';
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
trackName: track.name,
|
||||||
|
channels: numChannels,
|
||||||
|
timeRange: `${selLeft.toFixed(2)}s - ${selRight.toFixed(2)}s (${(selRight - selLeft).toFixed(2)}s)`,
|
||||||
|
peakVolume: peakDb
|
||||||
|
};
|
||||||
|
}, [tracks, selectedTrackId, selLeft, selRight]);
|
||||||
|
|
||||||
// ── Toast helper ──
|
// ── Toast helper ──
|
||||||
const showToast = (text, type = 'info') => {
|
const showToast = (text, type = 'info') => {
|
||||||
if (toastTimeoutRef.current) clearTimeout(toastTimeoutRef.current);
|
if (toastTimeoutRef.current) clearTimeout(toastTimeoutRef.current);
|
||||||
|
|||||||
@@ -3246,45 +3246,6 @@ const App = () => {
|
|||||||
const [subTabs, setSubTabs] = useState([]); // [{id, label, trackId, startTime, endTime, buffer, effects, currentTime, selectionStart, selectionEnd, isPlaying}, ...]
|
const [subTabs, setSubTabs] = useState([]); // [{id, label, trackId, startTime, endTime, buffer, effects, currentTime, selectionStart, selectionEnd, isPlaying}, ...]
|
||||||
const [selectionCleared, setSelectionCleared] = useState(false); // LOOP_EDITOR_2.md §4.2
|
const [selectionCleared, setSelectionCleared] = useState(false); // LOOP_EDITOR_2.md §4.2
|
||||||
|
|
||||||
const dspSelectionStats = useMemo(() => {
|
|
||||||
const track = tracks.find(t => t.id === selectedTrackId);
|
|
||||||
if (!track) return null;
|
|
||||||
const numChannels = track.buffer ? track.buffer.numberOfChannels || 1 : 0;
|
|
||||||
if (selLeft === null || selRight === null || selRight <= selLeft || !track.buffer) {
|
|
||||||
return {
|
|
||||||
trackName: track.name,
|
|
||||||
channels: numChannels,
|
|
||||||
timeRange: 'Chưa chọn vùng',
|
|
||||||
peakVolume: 'N/A'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const buffer = track.buffer;
|
|
||||||
const sampleRate = buffer.sampleRate;
|
|
||||||
const startSample = Math.max(0, Math.min(buffer.length - 1, Math.floor(selLeft * sampleRate)));
|
|
||||||
const endSample = Math.max(0, Math.min(buffer.length, Math.floor(selRight * sampleRate)));
|
|
||||||
let maxVal = 0;
|
|
||||||
for (let c = 0; c < numChannels; c++) {
|
|
||||||
const data = buffer.getChannelData(c);
|
|
||||||
for (let i = startSample; i < endSample; i++) {
|
|
||||||
const val = Math.abs(data[i]);
|
|
||||||
if (val > maxVal) maxVal = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let peakDb = 'N/A';
|
|
||||||
if (maxVal > 0) {
|
|
||||||
const db = 20 * Math.log10(maxVal);
|
|
||||||
peakDb = db.toFixed(2) + ' dB';
|
|
||||||
} else {
|
|
||||||
peakDb = '-∞ dB';
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
trackName: track.name,
|
|
||||||
channels: numChannels,
|
|
||||||
timeRange: `${selLeft.toFixed(2)}s - ${selRight.toFixed(2)}s (${(selRight - selLeft).toFixed(2)}s)`,
|
|
||||||
peakVolume: peakDb
|
|
||||||
};
|
|
||||||
}, [tracks, selectedTrackId, selLeft, selRight]);
|
|
||||||
|
|
||||||
// ── Temp Edit Tab (LOOP_EDITOR_2.md §1.2 Sub Tab) ──
|
// ── Temp Edit Tab (LOOP_EDITOR_2.md §1.2 Sub Tab) ──
|
||||||
const [tempTabActive, setTempTabActive] = useState(false);
|
const [tempTabActive, setTempTabActive] = useState(false);
|
||||||
const [tempTabBuffer, setTempTabBuffer] = useState(null);
|
const [tempTabBuffer, setTempTabBuffer] = useState(null);
|
||||||
@@ -5143,6 +5104,44 @@ const App = () => {
|
|||||||
if (selectionStart === null || selectionEnd === null) return null;
|
if (selectionStart === null || selectionEnd === null) return null;
|
||||||
return Math.max(selectionStart, selectionEnd);
|
return Math.max(selectionStart, selectionEnd);
|
||||||
}, [selectionStart, selectionEnd, selectionMode, localSelectionStart, localSelectionEnd]);
|
}, [selectionStart, selectionEnd, selectionMode, localSelectionStart, localSelectionEnd]);
|
||||||
|
const dspSelectionStats = useMemo(() => {
|
||||||
|
const track = tracks.find(t => t.id === selectedTrackId);
|
||||||
|
if (!track) return null;
|
||||||
|
const numChannels = track.buffer ? track.buffer.numberOfChannels || 1 : 0;
|
||||||
|
if (selLeft === null || selRight === null || selRight <= selLeft || !track.buffer) {
|
||||||
|
return {
|
||||||
|
trackName: track.name,
|
||||||
|
channels: numChannels,
|
||||||
|
timeRange: 'Chưa chọn vùng',
|
||||||
|
peakVolume: 'N/A'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const buffer = track.buffer;
|
||||||
|
const sampleRate = buffer.sampleRate;
|
||||||
|
const startSample = Math.max(0, Math.min(buffer.length - 1, Math.floor(selLeft * sampleRate)));
|
||||||
|
const endSample = Math.max(0, Math.min(buffer.length, Math.floor(selRight * sampleRate)));
|
||||||
|
let maxVal = 0;
|
||||||
|
for (let c = 0; c < numChannels; c++) {
|
||||||
|
const data = buffer.getChannelData(c);
|
||||||
|
for (let i = startSample; i < endSample; i++) {
|
||||||
|
const val = Math.abs(data[i]);
|
||||||
|
if (val > maxVal) maxVal = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let peakDb = 'N/A';
|
||||||
|
if (maxVal > 0) {
|
||||||
|
const db = 20 * Math.log10(maxVal);
|
||||||
|
peakDb = db.toFixed(2) + ' dB';
|
||||||
|
} else {
|
||||||
|
peakDb = '-∞ dB';
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
trackName: track.name,
|
||||||
|
channels: numChannels,
|
||||||
|
timeRange: `${selLeft.toFixed(2)}s - ${selRight.toFixed(2)}s (${(selRight - selLeft).toFixed(2)}s)`,
|
||||||
|
peakVolume: peakDb
|
||||||
|
};
|
||||||
|
}, [tracks, selectedTrackId, selLeft, selRight]);
|
||||||
|
|
||||||
// ── Toast helper ──
|
// ── Toast helper ──
|
||||||
const showToast = (text, type = 'info') => {
|
const showToast = (text, type = 'info') => {
|
||||||
|
|||||||
Reference in New Issue
Block a user