Commit Diff


commit - bf9b5580e07bc389a86112016d9e30dac233d625
commit + 735cbf541a3fcf9d41c38d494facb3163ee5f171
blob - 68402d33e0f048cc3fd11ca09b6ea123ada82493
blob + 320e8191c2df545b0b4caa5332ff45103d63d875
--- sdlamp.c
+++ sdlamp.c
@@ -13,6 +13,7 @@ static SDL_Renderer *renderer = NULL;
 static SDL_AudioDeviceID audio_device = 0;
 static SDL_AudioStream *stream = NULL;
 static float volume_slider_value = 1.0f;
+static float balance_slider_value = 0.5f;
 
 #if defined(__clang__) || defined(__GNUC__)
 static void panic_and_abort(const char *title, const char *text) __attribute__((noreturn));
@@ -30,6 +31,21 @@ static Uint32 wavlen = 0;
 static Uint32 wavpos = 0;
 static SDL_AudioSpec wavspec;
 
+static void stop_audio(void) {
+    if (stream) {
+        SDL_FreeAudioStream(stream);
+        stream = NULL;
+    }
+
+    if (wavbuf) {
+        SDL_FreeWAV(wavbuf);
+        wavbuf = NULL;
+    }
+
+    wavlen = 0;
+    wavpos = 0;
+}
+
 static SDL_bool open_audio_file(const char *fname) {
     SDL_FreeAudioStream(stream);
     stream = NULL;
@@ -46,18 +62,21 @@ static SDL_bool open_audio_file(const char *fname) {
     stream = SDL_NewAudioStream(wavspec.format, wavspec.channels, wavspec.freq, AUDIO_F32, 2, 48000);
     if (!stream) {
         SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create audiostream!", SDL_GetError(), window);
-        SDL_FreeWAV(wavbuf);
-        wavbuf = NULL;
-        wavlen = 0;
-        wavpos = 0;
+        stop_audio();
         return SDL_FALSE;
     }
 
-    if (SDL_AudioStreamPut(stream, wavbuf, wavlen) == -1) { // FIXME: graceful handling
-        panic_and_abort("Audio stream put failed", SDL_GetError());
+    if (SDL_AudioStreamPut(stream, wavbuf, wavlen) == -1) {
+        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "AudioStreamPut failed!", SDL_GetError(), window);
+        stop_audio();
+        return SDL_FALSE;
     }
 
-    SDL_AudioStreamFlush(stream); // FIXME: error handling
+    if (SDL_AudioStreamFlush(stream) == -1) {
+        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "AudioStreamFlush failed!", SDL_GetError(), window);
+        stop_audio();
+        return SDL_FALSE;
+    }
 
     return SDL_TRUE;
 }
@@ -106,6 +125,13 @@ int main(int argc, char **argv) {
         20,
         volume_rect.h
     };
+    const SDL_Rect balance_rect = {(1024 - 500) / 2, 300, 500, 20};
+    SDL_Rect balance_knob = {
+        (balance_rect.x + (balance_rect.w / 2)) - balance_knob.w,
+        balance_rect.y,
+        20,
+        balance_rect.h
+    };
 
     SDL_bool paused = SDL_TRUE;
     SDL_bool quit = SDL_FALSE;
@@ -122,10 +148,14 @@ int main(int argc, char **argv) {
                     if (SDL_PointInRect(&pt, &rewind_rect)) { // Pressed the "rewind" button
                         SDL_ClearQueuedAudio(audio_device);
                         SDL_AudioStreamClear(stream);
-                        if (SDL_AudioStreamPut(stream, wavbuf, wavlen) == -1) { // FIXME: graceful handling
-                            panic_and_abort("Audio stream put failed", SDL_GetError());
+                        if (SDL_AudioStreamPut(stream, wavbuf, wavlen) == -1) {
+                            SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "AudioStreamPut failed!", SDL_GetError(), window);
+                            stop_audio();
                         }
-                        SDL_AudioStreamFlush(stream);
+                        if (SDL_AudioStreamFlush(stream) == -1) {
+                            SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "AudioStreamPut failed!", SDL_GetError(), window);
+                            stop_audio();
+                        }
                     } else if (SDL_PointInRect(&pt, &pause_rect)) { // Pressed the "pause" button
                         paused = paused ? SDL_FALSE : SDL_TRUE;
                         SDL_PauseAudioDevice(audio_device, paused);
@@ -141,6 +171,12 @@ int main(int argc, char **argv) {
                         volume_knob.x = pt.x - (volume_knob.w / 2);
                         volume_knob.x = SDL_max(volume_knob.x, volume_rect.x);
                         volume_knob.x = SDL_min(volume_knob.x, (volume_rect.x + volume_rect.w) - volume_knob.w);
+                    } else if (SDL_PointInRect(&pt, &balance_rect) && (e.motion.state & SDL_BUTTON_LMASK)) { // left mouse pressed inside the "balance" slider
+                        const float fx = (float)(pt.x - balance_rect.x);
+                        balance_slider_value = (fx / (float)balance_rect.w);
+                        balance_knob.x = pt.x - (balance_knob.w / 2);
+                        balance_knob.x = SDL_max(balance_knob.x, balance_rect.x);
+                        balance_knob.x = SDL_min(balance_knob.x, (balance_rect.x + balance_rect.w) - balance_knob.w);
                     }
                     break;
                 }
@@ -158,13 +194,29 @@ int main(int argc, char **argv) {
             if (bytes_remaining > 0) {
                 const int new_bytes = SDL_min(bytes_remaining, KB(32));
                 static Uint8 converted_buffer[KB(32)];
-                SDL_AudioStreamGet(stream, converted_buffer, new_bytes); // FIXME: Error checking
-                const int num_samples = (new_bytes / sizeof(float));
-                float *samples = (float*)converted_buffer;
-                for (size_t i = 0; i < num_samples; ++i) {
-                    samples[i] *= volume_slider_value;
+                const int num_converted_bytes = SDL_AudioStreamGet(stream, converted_buffer, new_bytes);
+                if (num_converted_bytes > 0) {
+                    const int num_samples = (num_converted_bytes / sizeof(float));
+                    float *samples = (float*)converted_buffer;
+
+                    // volume changes
+                    if (volume_slider_value != 1.0f) {
+                        for (size_t i = 0; i < num_samples; ++i) {
+                            samples[i] *= volume_slider_value;
+                        }
+                    }
+
+                    // balance changes
+                    if (balance_slider_value != 0.5f) {
+                        for (size_t i = 0; i < num_samples; i += 2) {
+                            // first sample is left, second is right
+                            samples[i] *= (1.0f - balance_slider_value);
+                            samples[i + 1] *= balance_slider_value;
+                        }
+                    }
+
+                    SDL_QueueAudio(audio_device, converted_buffer, new_bytes);
                 }
-                SDL_QueueAudio(audio_device, converted_buffer, new_bytes);
             }
         }
 
@@ -175,9 +227,11 @@ int main(int argc, char **argv) {
         SDL_RenderFillRect(renderer, &rewind_rect);
         SDL_RenderFillRect(renderer, &pause_rect);
         SDL_RenderFillRect(renderer, &volume_rect);
+        SDL_RenderFillRect(renderer, &balance_rect);
 
         SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
         SDL_RenderFillRect(renderer, &volume_knob);
+        SDL_RenderFillRect(renderer, &balance_knob);
 
         SDL_RenderPresent(renderer);
     }