123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely.
- */
- #include <SDL3/SDL.h>
- #include <SDL3/SDL_main.h>
- #include <SDL3/SDL_test.h>
- #include "testutils.h"
- #ifdef SDL_PLATFORM_EMSCRIPTEN
- #include <emscripten/emscripten.h>
- #endif
- #include <stdio.h> /* for fflush() and stdout */
- static SDL_AudioSpec spec;
- static Uint8 *sound = NULL; /* Pointer to wave data */
- static Uint32 soundlen = 0; /* Length of wave data */
- /* these have to be in globals so the Emscripten port can see them in the mainloop. :/ */
- static SDL_AudioStream *stream = NULL;
- #ifdef SDL_PLATFORM_EMSCRIPTEN
- static void loop(void)
- {
- if (SDL_GetAudioStreamAvailable(stream) == 0) {
- SDL_Log("done.");
- SDL_DestroyAudioStream(stream);
- SDL_free(sound);
- SDL_Quit();
- emscripten_cancel_main_loop();
- }
- }
- #endif
- static void
- test_multi_audio(const SDL_AudioDeviceID *devices, int devcount)
- {
- int keep_going = 1;
- SDL_AudioStream **streams = NULL;
- int i;
- #ifdef SDL_PLATFORM_ANDROID /* !!! FIXME: maybe always create a window, in the SDLTest layer, so these #ifdefs don't have to be here? */
- SDL_Event event;
- /* Create a Window to get fully initialized event processing for testing pause on Android. */
- SDL_CreateWindow("testmultiaudio", 320, 240, 0);
- #endif
- for (i = 0; i < devcount; i++) {
- const char *devname = SDL_GetAudioDeviceName(devices[i]);
- SDL_Log("Playing on device #%d of %d: id=%u, name='%s'...", i, devcount, (unsigned int) devices[i], devname);
- if ((stream = SDL_OpenAudioDeviceStream(devices[i], &spec, NULL, NULL)) == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Audio stream creation failed: %s", SDL_GetError());
- } else {
- SDL_ResumeAudioStreamDevice(stream);
- SDL_PutAudioStreamData(stream, sound, soundlen);
- SDL_FlushAudioStream(stream);
- #ifdef SDL_PLATFORM_EMSCRIPTEN
- emscripten_set_main_loop(loop, 0, 1);
- #else
- while (SDL_GetAudioStreamAvailable(stream) > 0) {
- #ifdef SDL_PLATFORM_ANDROID
- /* Empty queue, some application events would prevent pause. */
- while (SDL_PollEvent(&event)) {
- }
- #endif
- SDL_Delay(100);
- }
- #endif
- SDL_Log("done.");
- SDL_DestroyAudioStream(stream);
- }
- stream = NULL;
- }
- /* note that Emscripten currently doesn't run this part (but maybe only has a single audio device anyhow?) */
- SDL_Log("Playing on all devices...\n");
- streams = (SDL_AudioStream **) SDL_calloc(devcount, sizeof (SDL_AudioStream *));
- if (!streams) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
- } else {
- for (i = 0; i < devcount; i++) {
- streams[i] = SDL_OpenAudioDeviceStream(devices[i], &spec, NULL, NULL);
- if (streams[i] == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Audio stream creation failed for device %d of %d: %s", i, devcount, SDL_GetError());
- } else {
- SDL_PutAudioStreamData(streams[i], sound, soundlen);
- SDL_FlushAudioStream(streams[i]);
- }
- }
- /* try to start all the devices about the same time. SDL does not guarantee sync across physical devices. */
- for (i = 0; i < devcount; i++) {
- if (streams[i]) {
- SDL_ResumeAudioStreamDevice(streams[i]);
- }
- }
- while (keep_going) {
- keep_going = 0;
- for (i = 0; i < devcount; i++) {
- if (streams[i] && (SDL_GetAudioStreamAvailable(streams[i]) > 0)) {
- keep_going = 1;
- }
- }
- #ifdef SDL_PLATFORM_ANDROID
- /* Empty queue, some application events would prevent pause. */
- while (SDL_PollEvent(&event)) {}
- #endif
- SDL_Delay(100);
- }
- for (i = 0; i < devcount; i++) {
- SDL_DestroyAudioStream(streams[i]);
- }
- SDL_free(streams);
- }
- SDL_Log("All done!\n");
- }
- int main(int argc, char **argv)
- {
- SDL_AudioDeviceID *devices;
- int devcount = 0;
- int i;
- char *filename = NULL;
- SDLTest_CommonState *state;
- /* Initialize test framework */
- state = SDLTest_CommonCreateState(argv, SDL_INIT_AUDIO);
- if (!state) {
- return 1;
- }
- /* Parse commandline */
- for (i = 1; i < argc;) {
- int consumed;
- consumed = SDLTest_CommonArg(state, i);
- if (!consumed) {
- if (!filename) {
- filename = argv[i];
- consumed = 1;
- }
- }
- if (consumed <= 0) {
- static const char *options[] = { "[sample.wav]", NULL };
- SDLTest_CommonLogUsage(state, argv[0], options);
- return 1;
- }
- i += consumed;
- }
- /* Load the SDL library */
- if (!SDLTest_CommonInit(state)) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
- return 1;
- }
- SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
- filename = GetResourceFilename(filename, "sample.wav");
- devices = SDL_GetAudioPlaybackDevices(&devcount);
- if (!devices) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio playback devices!");
- } else {
- /* Load the wave file into memory */
- if (SDL_LoadWAV(filename, &spec, &sound, &soundlen)) {
- test_multi_audio(devices, devcount);
- SDL_free(sound);
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename,
- SDL_GetError());
- }
- SDL_free(devices);
- }
- SDL_free(filename);
- SDLTest_CommonQuit(state);
- return 0;
- }
|