feat: export selection to WAV (band-limited, time-cropped)

New "Export WAV (W)" button + W key saves the current selection as a mono
WAV — the same band-limited, time-cropped audio you'd hear on playback, so
"what you hear is what you save". Self-documenting filename encodes the
time span and frequency band (rspektrum_sel_<t0>-<t1>s_<f0>-<f1>Hz.wav).

Refactor the shared filtered-region builder out of PlaySelectedRegion
(which also fixes a leak: it never freed regionSamples after
LoadSoundFromWave copies it). Make the export confirmation message persist
~3s instead of flashing for a single frame (affected PNG export too).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 10:42:37 -07:00
parent 9d21dbe82b
commit 542126261e
5 changed files with 82 additions and 17 deletions
+10
View File
@@ -323,6 +323,7 @@ void ExportPNG(const SpectrogramApp* spa, const char* dirPath)
} else {
snprintf((char*)spa->exportMessage, sizeof(spa->exportMessage), "Export failed");
}
((SpectrogramApp*)spa)->exportMessageTimer = 3.0f;
RL_FREE(region.data);
}
@@ -484,6 +485,15 @@ void DrawSidebar(void)
DrawTextScaled("Export PNG (E)", exportButton.x + 10 * scale, exportButton.y + 7 * scale, 14, WHITE);
y += 35 * scale;
// Export selection audio (band-limited, time-cropped) as a WAV
Rectangle wavButton = { x, y, sidebarWidth - 10 * scale, 30 * scale };
if (Clicked(wavButton)) {
ExportSelectionWAV(app.exportDir);
}
DrawPanelBox(wavButton, (Color){ 40, 60, 80, 255 }, CYAN);
DrawTextScaled("Export WAV (W)", wavButton.x + 10 * scale, wavButton.y + 7 * scale, 14, WHITE);
y += 35 * scale;
// Export scale slider
DrawTextScaled(TextFormat("Export Scale: %.1fx", app.exportScale), x, y, 12, LIGHTGRAY); y += 18 * scale;
Rectangle scaleSlider = { x, y, sidebarWidth - 10 * scale, 14 * scale };