Fix playback auto-reset, add ffmpeg conversion, fix file browser Open button click

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
2026-03-30 21:38:32 -07:00
parent 5e7841fa76
commit b3eb2ea991
+76 -4
View File
@@ -129,6 +129,7 @@ typedef struct {
// Playback state
bool isPlaying;
bool playbackFinished; // Track if playback completed naturally
} SpectrogramApp;
// ============================================================================
@@ -331,10 +332,53 @@ static void FreeSTFT(StftResult* result)
// Audio Loading
// ============================================================================
// Convert audio file to WAV using ffmpeg (if available)
static bool ConvertToFFmpegWAV(const char* inputPath, char* outputPath, size_t outputSize)
{
// Create temp WAV path
snprintf(outputPath, outputSize, "/tmp/rspektrum_temp_converted.wav");
// Build ffmpeg command
char cmd[1024];
snprintf(cmd, sizeof(cmd), "ffmpeg -y -loglevel quiet -i \"%s\" -ar 48000 -ac 1 -f wav \"%s\" 2>&1", inputPath, outputPath);
int result = system(cmd);
if (result == 0 && FileExists(outputPath)) {
TraceLog(LOG_INFO, "FFmpeg conversion successful: %s", outputPath);
return true;
}
TraceLog(LOG_WARNING, "FFmpeg conversion failed or not available");
return false;
}
static bool LoadWavFile(const char* filepath, AudioSignal* signal)
{
const char* ext = GetFileExtension(filepath);
char convertedPath[512] = { 0 };
bool isConverted = false;
// Check if we need to convert via ffmpeg
bool isWav = ext && (strcmp(ext, ".wav") == 0 || strcmp(ext, ".WAV") == 0);
if (!isWav) {
// Try ffmpeg conversion
if (ConvertToFFmpegWAV(filepath, convertedPath, sizeof(convertedPath))) {
filepath = convertedPath;
isConverted = true;
} else {
TraceLog(LOG_ERROR, "Unsupported format and ffmpeg not available: %s", filepath);
return false;
}
}
Wave wave = LoadWave(filepath);
if (wave.data == NULL) { TraceLog(LOG_ERROR, "Failed to open WAV file: %s", filepath); return false; }
if (wave.data == NULL) {
TraceLog(LOG_ERROR, "Failed to open WAV file: %s", filepath);
if (isConverted) remove(convertedPath);
return false;
}
signal->sampleRate = wave.sampleRate;
signal->channels = wave.channels;
@@ -363,6 +407,13 @@ static bool LoadWavFile(const char* filepath, AudioSignal* signal)
signal->numSamples = monoSamples;
}
UnloadWave(wave);
// Clean up temp file if converted
if (isConverted) {
remove(convertedPath);
TraceLog(LOG_INFO, "Cleaned up temp file: %s", convertedPath);
}
TraceLog(LOG_INFO, "Loaded WAV: %d Hz, %.2f sec, %d samples", signal->sampleRate, signal->duration, signal->numSamples);
return true;
}
@@ -708,14 +759,17 @@ static void DrawFileBrowser(void)
Rectangle openBtn = { bx + bw - 160, btnY, 140, 38 };
Rectangle cancelBtn = { bx + 15, btnY, 110, 38 };
if (CheckCollisionPointRec(GetMousePosition(), openBtn)) DrawRectangleRec(openBtn, (Color){ 80, 80, 90, 255 });
bool openHovered = CheckCollisionPointRec(GetMousePosition(), openBtn);
bool openClicked = openHovered && IsMouseButtonPressed(MOUSE_LEFT_BUTTON);
if (openHovered) DrawRectangleRec(openBtn, (Color){ 100, 100, 120, 255 });
else DrawRectangleRec(openBtn, (Color){ 80, 80, 90, 255 });
DrawRectangleLinesEx(openBtn, 1, WHITE);
DrawText("OPEN (Enter)", openBtn.x + 25, openBtn.y + 12, 16, WHITE);
DrawRectangleRec(cancelBtn, (Color){ 100, 40, 40, 255 });
DrawText("ESC Cancel", cancelBtn.x + 18, cancelBtn.y + 12, 16, WHITE);
if (IsKeyPressed(KEY_ENTER) && app.browserSelected >= 0 && app.browserFileCount > 0) LoadSelectedFile();
if ((IsKeyPressed(KEY_ENTER) || openClicked) && app.browserSelected >= 0 && app.browserFileCount > 0) LoadSelectedFile();
if (IsKeyPressed(KEY_ESCAPE)) app.showFileBrowser = false;
if (IsKeyPressed(KEY_UP) && app.browserSelected > 0 && app.browserFileCount > 0) {
app.browserSelected--;
@@ -1011,6 +1065,7 @@ int main(int argc, char* argv[])
app.visibleTextureValid = false;
app.fftSize = FFT_SIZE_DEFAULT;
app.isPlaying = false;
app.playbackFinished = false;
GenerateColormapTexture();
ScanDirectory(GetWorkingDirectory());
@@ -1063,7 +1118,16 @@ int main(int argc, char* argv[])
if (app.showFileBrowser) {
// Browser handles its own input
}
// Check if playback finished naturally
if (app.isPlaying && AudioPlaybackSound.frameCount > 0) {
// Check if sound stopped playing (IsSoundPlaying returns false when done)
if (!IsSoundPlaying(AudioPlaybackSound)) {
app.isPlaying = false;
app.playbackFinished = true;
}
}
// View controls
if (app.loaded && !app.showFileBrowser) {
// Spectrogram area is to the right of sidebar (320px)
@@ -1137,9 +1201,17 @@ int main(int argc, char* argv[])
// Keyboard shortcuts (SPACE for play/stop toggle, ESC for clear)
if (IsKeyPressed(KEY_SPACE) && !app.showFileBrowser) {
if (app.isPlaying && AudioPlaybackSound.frameCount > 0) {
// Currently playing - stop it
StopSound(AudioPlaybackSound);
app.isPlaying = false;
app.playbackFinished = false;
} else if (app.playbackFinished) {
// Playback finished naturally - restart from beginning
PlaySelectedRegion();
app.isPlaying = true;
app.playbackFinished = false;
} else {
// Not playing and didn't just finish - start playback
PlaySelectedRegion();
app.isPlaying = true;
}