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
+7 -2
View File
@@ -154,6 +154,7 @@ static void ActionToggleScope(void) { app.showScope = !app.showScope; }
static void ActionToggleAbout(void) { app.showAbout = !app.showAbout; }
static void ActionToggleFullscreen(void){ ToggleFullscreen(); }
static void ActionExport(void) { ExportPNG(&app, app.exportDir); }
static void ActionExportWav(void) { ExportSelectionWAV(app.exportDir); }
static void ActionResetView(void)
{
@@ -177,6 +178,7 @@ static const KeyBinding KEYMAP[] = {
{ KEY_HOME, KEYGATE_MODAL | KEYGATE_LOADED,ActionResetView, "Home", "reset view (fit all)" },
{ KEY_END, KEYGATE_MODAL | KEYGATE_LOADED,ActionZoomToStart, "End", "zoom to start" },
{ KEY_E, KEYGATE_MODAL | KEYGATE_STFT, ActionExport, "E", "export PNG" },
{ KEY_W, KEYGATE_MODAL | KEYGATE_STFT, ActionExportWav, "W", "export selection WAV" },
// Order-sensitive: handled inline (see main loop), listed here for the overlay.
{ KEY_SPACE, KEYGATE_NONE, NULL, "Space", "play / stop selection" },
{ KEY_ESCAPE,KEYGATE_NONE, NULL, "Esc", "clear selection / close dialog" },
@@ -1062,8 +1064,11 @@ int main(int argc, char* argv[])
DrawText(app.exportMessage, boxX + (boxW - msgW) / 2, boxY + 10, 20, WHITE);
}
// Reset export message after one frame display
app.exportMessage[0] = '\0';
// Hold the export message for a few seconds, then clear it.
if (app.exportMessageTimer > 0.0f) {
app.exportMessageTimer -= GetFrameTime();
if (app.exportMessageTimer <= 0.0f) app.exportMessage[0] = '\0';
}
EndDrawing();
}