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:
+75
-3
@@ -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());
|
||||
@@ -1064,6 +1119,15 @@ int main(int argc, char* argv[])
|
||||
// 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user