]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/sound_samples.c
Merge pull request #1165 from zhiayang/901
[nothing.git] / src / game / sound_samples.c
index edd10e2e5799d5a3df1fb53f3343b9f2df1213d4..77b76ec805a52f0add2503f5c0fb40c747a08626 100644 (file)
@@ -8,9 +8,9 @@
 #include "system/log.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
+#include "config.h"
 
-// TODO(#863): Sound_samples is not implemented
-// TODO: Sound_samples does not implement volume control.
+// TODO(#1022): Sound_samples does not implement volume control.
 
 struct Sound_samples
 {
@@ -18,26 +18,30 @@ struct Sound_samples
     SDL_AudioDeviceID dev;
     uint8_t **audio_buf_array;
     uint32_t *audio_buf_size_array;
+    uint8_t **active_audio_buf_array;
     size_t samples_count;
     int paused;
+    float volume;
+    // TODO(#1127): A better solution for optional sound support
+    int failed;                 // This is hackish
 };
 
-static 
-int init_buffer_and_device(Sound_samples *sound_samples, 
-                           const char *sample_files[]) 
+static
+int init_buffer_and_device(Sound_samples *sound_samples,
+                           const char *sample_files[])
 {
-    // TODO: init_buffer_and_device uses hard-coded audio specification
+    // TODO(#1023): init_buffer_and_device uses hard-coded audio specification
     SDL_AudioSpec destination_spec = { // stereo float32 44100Hz
         .format = AUDIO_F32,
         .channels = 2,
         .freq = 44100
     };
-    // TODO: a return value by SDL_GetNumAudioDevices that is <= 0 may not indicate an error
+    // TODO(#1024): a return value by SDL_GetNumAudioDevices that is <= 0 may not indicate an error
     if (SDL_GetNumAudioDevices(0) <= 0) {
         log_fail("No audio in 2019 LULW\n");
         return -1;
     }
-    
+
     sound_samples->audio_buf_array = PUSH_LT(sound_samples->lt, nth_calloc(sound_samples->samples_count, sizeof(uint8_t*)), free);
     if (sound_samples->audio_buf_array == NULL) {
         log_fail("Failed to allocate memory for audio buffer pointer array\n");
@@ -58,7 +62,7 @@ int init_buffer_and_device(Sound_samples *sound_samples,
         }
         PUSH_LT(sound_samples->lt, wav_buf, SDL_FreeWAV);
         SDL_AudioCVT cvt;
-        int result = SDL_BuildAudioCVT(&cvt, wav_spec.format, (uint8_t)wav_spec.channels, (int)wav_spec.freq, 
+        int result = SDL_BuildAudioCVT(&cvt, wav_spec.format, (uint8_t)wav_spec.channels, (int)wav_spec.freq,
                           destination_spec.format, (uint8_t)destination_spec.channels, (int)destination_spec.freq);
         if (result < 0) {
             log_fail("SDL_BuildAudioCVT failed: %s\n", SDL_GetError());
@@ -83,7 +87,24 @@ int init_buffer_and_device(Sound_samples *sound_samples,
             sound_samples->audio_buf_size_array[i] = (uint32_t)cvt.len_cvt;
         }
     }
-    
+
+    /* Allocating active audio buffer location*/
+    //TODO(#1072): Allocate one huge active audio buffer with length of the maximum of all audio buffer, instead of one active buffer for each audio
+    sound_samples->active_audio_buf_array = PUSH_LT(sound_samples->lt, nth_calloc(sound_samples->samples_count, sizeof(uint8_t*)), free);
+    if (sound_samples->active_audio_buf_array == NULL) {
+      log_fail("Failed to allocate memory for active audio buffer pointer array\n");
+      return -1;
+    }
+    for (size_t i = 0; i < sound_samples->samples_count; ++i) {
+      sound_samples->active_audio_buf_array[i] = PUSH_LT(sound_samples->lt, nth_calloc(sound_samples->audio_buf_size_array[i],
+                                                                                       sizeof(uint8_t)), free);
+      if (sound_samples->active_audio_buf_array == NULL) {
+        log_fail("Failed to allocate memory for active audio buffer array\n");
+        return -1;
+      }
+    }
+
+    /* Opening the device*/
     sound_samples->dev = SDL_OpenAudioDevice(NULL, 0, &destination_spec, NULL, 0);
     if (sound_samples->dev == 0) {
         log_fail("SDL_OpenAudioDevice failed: %s\n", SDL_GetError());
@@ -107,11 +128,12 @@ Sound_samples *create_sound_samples(const char *sample_files[],
         RETURN_LT(lt, NULL);
     }
     sound_samples->lt = lt;
+    sound_samples->volume = SOUND_SAMPLES_DEFAULT_VOLUME;
 
     sound_samples->samples_count = sample_files_count;
     if (init_buffer_and_device(sound_samples, sample_files) < 0) {
         log_fail("init_buffer_and_device failed\n");
-        RETURN_LT(lt, NULL);
+        sound_samples->failed = 1;
     }
 
     sound_samples->paused = 0;
@@ -122,7 +144,8 @@ Sound_samples *create_sound_samples(const char *sample_files[],
 
 void destroy_sound_samples(Sound_samples *sound_samples)
 {
-    // TODO: Use a seperate callback function for audio handling and pass that into SDL_OpenAudioDevice
+    // TODO(#1025): Use a seperate callback function for audio handling and pass that into SDL_OpenAudioDevice
+    if (sound_samples->failed) return;
     trace_assert(sound_samples);
     trace_assert(sound_samples->dev);
     SDL_CloseAudioDevice(sound_samples->dev);
@@ -133,10 +156,23 @@ int sound_samples_play_sound(Sound_samples *sound_samples,
                              size_t sound_index)
 {
     trace_assert(sound_samples);
+    if (sound_samples->failed) return 0;
     trace_assert(sound_index < sound_samples->samples_count);
     trace_assert(sound_samples->dev);
+
+    /* Premix the audio volume */
+    memset(sound_samples->active_audio_buf_array[sound_index], 0, sound_samples->audio_buf_size_array[sound_index]);
+
+    //TODO(#1073): replace this linear scaling volume with logarithmic scale for better audio perception
+    SDL_MixAudioFormat(sound_samples->active_audio_buf_array[sound_index],
+                       sound_samples->audio_buf_array[sound_index],
+                       AUDIO_F32, //Hardcoded format just like in issue #1023
+                       sound_samples->audio_buf_size_array[sound_index],
+                       (int)((float)SDL_MIX_MAXVOLUME * sound_samples->volume / 100.0f));
+
+    /* Play the audio*/
     SDL_ClearQueuedAudio(sound_samples->dev);
-    if (SDL_QueueAudio(sound_samples->dev, sound_samples->audio_buf_array[sound_index], 
+    if (SDL_QueueAudio(sound_samples->dev, sound_samples->active_audio_buf_array[sound_index],
                 sound_samples->audio_buf_size_array[sound_index]) < 0) {
         log_warn("Failed to queue audio data of sound index %zu to device: %s\n", sound_index, SDL_GetError());
         return 0;
@@ -148,8 +184,17 @@ int sound_samples_play_sound(Sound_samples *sound_samples,
 int sound_samples_toggle_pause(Sound_samples *sound_samples)
 {
     trace_assert(sound_samples);
+    if (sound_samples->failed) return 0;
     sound_samples->paused = !sound_samples->paused;
     trace_assert(sound_samples->dev);
     SDL_PauseAudioDevice(sound_samples->dev, sound_samples->paused);
     return 0;
 }
+
+void sound_samples_update_volume(Sound_samples *sound_samples,
+                                 float volume)
+{
+    trace_assert(sound_samples);
+    if (sound_samples->failed) return;
+    sound_samples->volume = volume;
+}