Преглед на файлове

audio: Allow querying of device buffer size.

Ryan C. Gordon преди 1 година
родител
ревизия
2f43f7bc53
променени са 7 файла, в които са добавени 62 реда и са изтрити 38 реда
  1. 13 1
      include/SDL3/SDL_audio.h
  2. 29 24
      src/audio/SDL_audio.c
  3. 1 1
      src/dynapi/SDL_dynapi_procs.h
  4. 8 6
      test/testaudio.c
  5. 2 2
      test/testaudiocapture.c
  6. 8 3
      test/testaudioinfo.c
  7. 1 1
      test/testsurround.c

+ 13 - 1
include/SDL3/SDL_audio.h

@@ -327,8 +327,20 @@ extern DECLSPEC char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID devid);
  * reasonable recommendation before opening the system-recommended default
  * device.
  *
+ * You can also use this to request the current device buffer size. This is
+ * specified in sample frames and represents the amount of data SDL will
+ * feed to the physical hardware in each chunk. This can be converted to
+ * milliseconds of audio with the following equation:
+ *
+ * `ms = (int) ((((Sint64) frames) * 1000) / spec.freq);`
+ *
+ * Buffer size is only important if you need low-level control over the audio
+ * playback timing. Most apps do not need this.
+ *
  * \param devid the instance ID of the device to query.
  * \param spec On return, will be filled with device details.
+ * \param sample_frames Pointer to store device buffer size, in sample frames.
+ *                      Can be NULL.
  * \returns 0 on success or a negative error code on failure; call
  *          SDL_GetError() for more information.
  *
@@ -336,7 +348,7 @@ extern DECLSPEC char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID devid);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec);
+extern DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int *sample_frames);
 
 
 /**

+ 29 - 24
src/audio/SDL_audio.c

@@ -116,6 +116,30 @@ const char *SDL_GetCurrentAudioDriver(void)
     return current_audio.name;
 }
 
+static int GetDefaultSampleFramesFromFreq(const int freq)
+{
+    const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES);
+    if (hint) {
+        const int val = SDL_atoi(hint);
+        if (val > 0) {
+            return val;
+        }
+    }
+
+    if (freq <= 11025) {
+        return 512;
+    } else if (freq <= 22050) {
+        return 1024;
+    } else if (freq <= 48000) {
+        return 2048;
+    } else if (freq <= 96000) {
+        return 4096;
+    }
+
+    return 8192;  // shrug
+}
+
+
 // device management and hotplug...
 
 
@@ -238,6 +262,7 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc
     device->iscapture = iscapture;
     SDL_memcpy(&device->spec, spec, sizeof (SDL_AudioSpec));
     SDL_memcpy(&device->default_spec, spec, sizeof (SDL_AudioSpec));
+    device->sample_frames = GetDefaultSampleFramesFromFreq(device->spec.freq);
     device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format);
     device->handle = handle;
     device->prev = NULL;
@@ -1112,7 +1137,7 @@ char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
     return retval;
 }
 
-int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec)
+int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int *sample_frames)
 {
     if (!spec) {
         return SDL_InvalidParamError("spec");
@@ -1137,6 +1162,9 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec)
     }
 
     SDL_memcpy(spec, &device->spec, sizeof (SDL_AudioSpec));
+    if (sample_frames) {
+        *sample_frames = device->sample_frames;
+    }
     SDL_UnlockMutex(device->lock);
 
     return 0;
@@ -1246,29 +1274,6 @@ static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec)
     }
 }
 
-static int GetDefaultSampleFramesFromFreq(const int freq)
-{
-    const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES);
-    if (hint) {
-        const int val = SDL_atoi(hint);
-        if (val > 0) {
-            return val;
-        }
-    }
-
-    if (freq <= 11025) {
-        return 512;
-    } else if (freq <= 22050) {
-        return 1024;
-    } else if (freq <= 48000) {
-        return 2048;
-    } else if (freq <= 96000) {
-        return 4096;
-    }
-
-    return 8192;  // shrug
-}
-
 void SDL_UpdatedAudioDeviceFormat(SDL_AudioDevice *device)
 {
     device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format);

+ 1 - 1
src/dynapi/SDL_dynapi_procs.h

@@ -926,7 +926,7 @@ SDL_DYNAPI_PROC(const char*,SDL_GetCurrentAudioDriver,(void),(),return)
 SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioOutputDevices,(int *a),(a),return)
 SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioCaptureDevices,(int *a),(a),return)
 SDL_DYNAPI_PROC(char*,SDL_GetAudioDeviceName,(SDL_AudioDeviceID a),(a),return)
-SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b, int *c),(a,b,c),return)
 SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_OpenAudioDevice,(SDL_AudioDeviceID a, const SDL_AudioSpec *b),(a,b),return)
 SDL_DYNAPI_PROC(void,SDL_CloseAudioDevice,(SDL_AudioDeviceID a),(a),)
 SDL_DYNAPI_PROC(int,SDL_BindAudioStreams,(SDL_AudioDeviceID a, SDL_AudioStream **b, int c),(a,b,c),return)

+ 8 - 6
test/testaudio.c

@@ -765,9 +765,10 @@ static void DeviceThing_ondrag(Thing *thing, int button, float x, float y)
 static void SetLogicalDeviceTitlebar(Thing *thing)
 {
     SDL_AudioSpec *spec = &thing->data.logdev.spec;
-    SDL_GetAudioDeviceFormat(thing->data.logdev.devid, spec);
+    int frames = 0;
+    SDL_GetAudioDeviceFormat(thing->data.logdev.devid, spec, &frames);
     SDL_free(thing->titlebar);
-    SDL_asprintf(&thing->titlebar, "Logical device #%u (%s, %s, %s, %uHz)", (unsigned int) thing->data.logdev.devid, thing->data.logdev.iscapture ? "CAPTURE" : "OUTPUT", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
+    SDL_asprintf(&thing->titlebar, "Logical device #%u (%s, %s, %s, %uHz, %d frames)", (unsigned int) thing->data.logdev.devid, thing->data.logdev.iscapture ? "CAPTURE" : "OUTPUT", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
 }
 
 static void LogicalDeviceThing_ondrop(Thing *thing, int button, float x, float y)
@@ -938,15 +939,16 @@ static Thing *CreateLogicalDeviceThing(Thing *parent, const SDL_AudioDeviceID wh
 
 static void SetPhysicalDeviceTitlebar(Thing *thing)
 {
+    int frames = 0;
     SDL_AudioSpec *spec = &thing->data.physdev.spec;
-    SDL_GetAudioDeviceFormat(thing->data.physdev.devid, spec);
+    SDL_GetAudioDeviceFormat(thing->data.physdev.devid, spec, &frames);
     SDL_free(thing->titlebar);
     if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) {
-        SDL_asprintf(&thing->titlebar, "Default system device (CAPTURE, %s, %s, %uHz)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
+        SDL_asprintf(&thing->titlebar, "Default system device (CAPTURE, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
     } else if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) {
-        SDL_asprintf(&thing->titlebar, "Default system device (OUTPUT, %s, %s, %uHz)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
+        SDL_asprintf(&thing->titlebar, "Default system device (OUTPUT, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
     } else {
-        SDL_asprintf(&thing->titlebar, "Physical device #%u (%s, \"%s\", %s, %s, %uHz)", (unsigned int) thing->data.physdev.devid, thing->data.physdev.iscapture ? "CAPTURE" : "OUTPUT", thing->data.physdev.name, AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
+        SDL_asprintf(&thing->titlebar, "Physical device #%u (%s, \"%s\", %s, %s, %uHz, %d frames)", (unsigned int) thing->data.physdev.devid, thing->data.physdev.iscapture ? "CAPTURE" : "OUTPUT", thing->data.physdev.name, AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
     }
 }
 

+ 2 - 2
test/testaudiocapture.c

@@ -179,7 +179,7 @@ int main(int argc, char **argv)
         exit(1);
     }
     SDL_PauseAudioDevice(device);
-    SDL_GetAudioDeviceFormat(device, &outspec);
+    SDL_GetAudioDeviceFormat(device, &outspec, NULL);
     stream_out = SDL_CreateAudioStream(&outspec, &outspec);
     if (!stream_out) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for playback: %s!\n", SDL_GetError());
@@ -203,7 +203,7 @@ int main(int argc, char **argv)
         exit(1);
     }
     SDL_PauseAudioDevice(device);
-    SDL_GetAudioDeviceFormat(device, &inspec);
+    SDL_GetAudioDeviceFormat(device, &inspec, NULL);
     stream_in = SDL_CreateAudioStream(&inspec, &inspec);
     if (!stream_in) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for capture: %s!\n", SDL_GetError());

+ 8 - 3
test/testaudioinfo.c

@@ -19,6 +19,7 @@ print_devices(SDL_bool iscapture)
     SDL_AudioSpec spec;
     const char *typestr = ((iscapture) ? "capture" : "output");
     int n = 0;
+    int frames;
     SDL_AudioDeviceID *devices = iscapture ? SDL_GetAudioCaptureDevices(&n) : SDL_GetAudioOutputDevices(&n);
 
     if (devices == NULL) {
@@ -37,10 +38,11 @@ print_devices(SDL_bool iscapture)
                 SDL_Log("  %d Error: %s\n", i, SDL_GetError());
             }
 
-            if (SDL_GetAudioDeviceFormat(devices[i], &spec) == 0) {
+            if (SDL_GetAudioDeviceFormat(devices[i], &spec, &frames) == 0) {
                 SDL_Log("     Sample Rate: %d\n", spec.freq);
                 SDL_Log("     Channels: %d\n", spec.channels);
                 SDL_Log("     SDL_AudioFormat: %X\n", spec.format);
+                SDL_Log("     Buffer Size: %d frames\n", frames);
             }
         }
         SDL_Log("\n");
@@ -53,6 +55,7 @@ int main(int argc, char **argv)
     SDL_AudioSpec spec;
     int i;
     int n;
+    int frames;
     SDLTest_CommonState *state;
 
     /* Initialize test framework */
@@ -92,22 +95,24 @@ int main(int argc, char **argv)
     print_devices(SDL_FALSE);
     print_devices(SDL_TRUE);
 
-    if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec) < 0) {
+    if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, &frames) < 0) {
         SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default output): %s\n", SDL_GetError());
     } else {
         SDL_Log("Default Output Device:\n");
         SDL_Log("Sample Rate: %d\n", spec.freq);
         SDL_Log("Channels: %d\n", spec.channels);
         SDL_Log("SDL_AudioFormat: %X\n", spec.format);
+        SDL_Log("Buffer Size: %d frames\n", frames);
     }
 
-    if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_CAPTURE, &spec) < 0) {
+    if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_CAPTURE, &spec, &frames) < 0) {
         SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default capture): %s\n", SDL_GetError());
     } else {
         SDL_Log("Default Capture Device:\n");
         SDL_Log("Sample Rate: %d\n", spec.freq);
         SDL_Log("Channels: %d\n", spec.channels);
         SDL_Log("SDL_AudioFormat: %X\n", spec.format);
+        SDL_Log("Buffer Size: %d frames\n", frames);
     }
 
     SDL_Quit();

+ 1 - 1
test/testsurround.c

@@ -197,7 +197,7 @@ int main(int argc, char *argv[])
         SDL_Log("Testing audio device: %s\n", devname);
         SDL_free(devname);
 
-        if (SDL_GetAudioDeviceFormat(devices[i], &spec) != 0) {
+        if (SDL_GetAudioDeviceFormat(devices[i], &spec, NULL) != 0) {
             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GetAudioDeviceFormat() failed: %s\n", SDL_GetError());
             continue;
         }