feat: added waveform view for audio regions

This commit is contained in:
Xiaohan-Tian
2026-05-26 23:23:01 -07:00
parent 7fc5ac1590
commit c4e4470182
22 changed files with 497 additions and 69 deletions
+19 -13
View File
@@ -37,7 +37,7 @@ interface PianoRollContentProps {
selectedMode: string;
keySignature: KeySignature;
chordGuide: string;
mode?: 'midi-edit' | 'spectrogram' | 'hybrid';
mode?: 'midi-edit' | 'audio-waveform' | 'spectrogram' | 'hybrid';
audioRegion?: KGAudioRegion;
trackId?: string;
projectName?: string;
@@ -94,8 +94,9 @@ const PianoRollContent: React.FC<PianoRollContentProps> = ({
overlayMessage = null,
overlayProgressPercent = null,
}) => {
const isAudioView = mode === 'audio-waveform' || mode === 'spectrogram';
const isSpectrogram = mode === 'spectrogram';
const showAutomationLane = automationEnabled && !isSpectrogram && !sheetMusicViewEnabled;
const showAutomationLane = automationEnabled && !isAudioView && !sheetMusicViewEnabled;
const [spectrogramLoading, setSpectrogramLoading] = useState(false);
const [noteScrollLeft, setNoteScrollLeft] = useState(0);
const handleSpectrogramLoadingChange = useCallback((loading: boolean) => {
@@ -174,7 +175,7 @@ const PianoRollContent: React.FC<PianoRollContentProps> = ({
// Combined click handler for both pointer and pencil modes
const handleCombinedClick = (e: React.MouseEvent) => {
if (isSpectrogram) return;
if (isAudioView) return;
handleBackgroundClick(e);
handleGridClick(e);
};
@@ -212,7 +213,7 @@ const PianoRollContent: React.FC<PianoRollContentProps> = ({
// Memoize the notes rendering to prevent unnecessary recalculations
const memoizedNotes = useMemo(() => {
if (isSpectrogram || sheetMusicViewEnabled || !activeRegion) return null;
if (isAudioView || sheetMusicViewEnabled || !activeRegion) return null;
if (DEBUG_MODE.PIANO_ROLL) {
console.log(`Rendering notes for region: ${activeRegion.getId()}`);
@@ -289,7 +290,7 @@ const PianoRollContent: React.FC<PianoRollContentProps> = ({
/>
);
});
}, [mode, activeRegion, noteUpdateCounter, resizingNoteId, draggingNoteId, tempNoteStyles, selectedNoteIds, selectionBoxRender, tracks, sheetMusicViewEnabled]);
}, [isAudioView, activeRegion, noteUpdateCounter, resizingNoteId, draggingNoteId, tempNoteStyles, selectedNoteIds, selectionBoxRender, tracks, sheetMusicViewEnabled]);
const recordingNoteOverlays = useMemo(() => {
if (!isRecording || !activeRegion || recordingNotes.length === 0) return null;
@@ -341,10 +342,14 @@ const PianoRollContent: React.FC<PianoRollContentProps> = ({
onScroll={(event) => setNoteScrollLeft(event.currentTarget.scrollLeft)}
>
{!sheetMusicViewEnabled && (
<PianoGridHeader maxBars={maxBars} timeSignature={timeSignature} />
<PianoGridHeader
maxBars={maxBars}
timeSignature={timeSignature}
hasPianoKeys={mode !== 'audio-waveform'}
/>
)}
<div className={`piano-roll-body ${sheetMusicViewEnabled ? 'sheet-music-body' : ''}`}>
{!sheetMusicViewEnabled && <PianoKeys activeRegion={activeRegion} />}
<div className={`piano-roll-body ${sheetMusicViewEnabled ? 'sheet-music-body' : ''} ${mode === 'audio-waveform' ? 'audio-waveform-body' : ''}`}>
{!sheetMusicViewEnabled && mode !== 'audio-waveform' && <PianoKeys activeRegion={activeRegion} />}
{sheetMusicViewEnabled && activeRegion && sheetQuantization ? (
<SheetMusicView
activeRegion={activeRegion}
@@ -363,10 +368,10 @@ const PianoRollContent: React.FC<PianoRollContentProps> = ({
<PianoGrid
gridRef={pianoGridRef}
onDoubleClick={isSpectrogram ? () => {} : handleGridDoubleClick}
onClick={isSpectrogram ? () => {} : handleCombinedClick}
onMouseDown={isSpectrogram ? () => {} : handleBackgroundMouseDown}
isBoxSelecting={isSpectrogram ? false : isBoxSelectingRef.current}
selectionBox={isSpectrogram ? { startX: 0, startY: 0, endX: 0, endY: 0 } : selectionBoxRef.current}
onClick={isAudioView ? () => {} : handleCombinedClick}
onMouseDown={isAudioView ? () => {} : handleBackgroundMouseDown}
isBoxSelecting={isAudioView ? false : isBoxSelectingRef.current}
selectionBox={isAudioView ? { startX: 0, startY: 0, endX: 0, endY: 0 } : selectionBoxRef.current}
regionStartBeat={activeRegion?.getStartFromBeat() || 0}
selectedMode={selectedMode}
keySignature={keySignature}
@@ -379,10 +384,11 @@ const PianoRollContent: React.FC<PianoRollContentProps> = ({
spectrogramPower={spectrogramPower}
spectrogramHeightResolution={spectrogramHeightResolution}
pianoRollZoom={pianoRollZoom}
mode={mode}
onSpectrogramLoadingChange={handleSpectrogramLoadingChange}
>
{memoizedNotes}
{!isSpectrogram && recordingNoteOverlays}
{!isAudioView && recordingNoteOverlays}
</PianoGrid>
)}
</div>