feat: add bounce-to-WAV export with offline rendering via Tone.Offline

This commit is contained in:
Xiaohan-Tian
2026-04-11 12:18:30 -07:00
parent d94b53dcf5
commit d4864426e3
6 changed files with 643 additions and 2 deletions
+20 -1
View File
@@ -22,6 +22,7 @@ import { regionDeleteManager } from '../util/regionDeleteUtil';
import { handleCopyOperation, handlePasteOperation } from '../util/copyPasteUtil';
import { convertProjectToMidi, convertMidiToProject } from '../util/midiUtil';
import { KEY_SIGNATURE_MAP } from '../constants/coreConstants';
import { KGOfflineRenderer } from '../core/audio-interface/KGOfflineRenderer';
import KGDropdown from './common/KGDropdown';
import FileImportModal from './common/FileImportModal';
import OpenProjectModal from './common/OpenProjectModal';
@@ -82,7 +83,7 @@ const Toolbar: React.FC = () => {
const keySignatureOptions = Object.keys(KEY_SIGNATURE_MAP) as KeySignature[];
// Export options
const exportOptions = ["Export to KGStudio file", "Export to MIDI file"];
const exportOptions = ["Export to KGStudio file", "Export to MIDI file", "Export to WAV"];
const handleProjectNameClick = () => {
const newName = prompt("Enter project name:", projectName);
@@ -202,6 +203,8 @@ const Toolbar: React.FC = () => {
handleExportKGStudio();
} else if (exportType === "Export to MIDI file") {
handleExportMIDI();
} else if (exportType === "Export to WAV") {
handleBounceToWav();
}
setShowExportDropdown(false);
@@ -285,6 +288,22 @@ const Toolbar: React.FC = () => {
}
};
const handleBounceToWav = async () => {
if (DEBUG_MODE.TOOLBAR) {
console.log("bouncing to WAV");
}
try {
const currentProject = KGCore.instance().getCurrentProject();
await KGOfflineRenderer.instance().bounceToWav(currentProject, projectName);
setStatus(`Project "${projectName}" exported as WAV file`);
} catch (error) {
console.error("Error bouncing to WAV:", error);
setStatus(`Error exporting WAV: ${error}`);
window.alert(`Failed to export project as WAV: ${error}`);
}
};
const handleImportProject = () => {
if (DEBUG_MODE.TOOLBAR) {
console.log("user clicked import button");
+1
View File
@@ -3,6 +3,7 @@
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(4px);
z-index: 20000;
display: flex;
align-items: center;