test/testmultiaudio.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 Dec 2017 16:08:09 -0800
changeset 11730 ac6c607e065c
parent 10737 3406a0f8b041
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Enable building the Metal renderer by default, and weak link the Metal framework so the SDL library is safe to use on older Macs
Also generate iOS versions of the Metal shaders
     1 /*
     2   Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
     3 
     4   This software is provided 'as-is', without any express or implied
     5   warranty.  In no event will the authors be held liable for any damages
     6   arising from the use of this software.
     7 
     8   Permission is granted to anyone to use this software for any purpose,
     9   including commercial applications, and to alter it and redistribute it
    10   freely.
    11 */
    12 #include "SDL.h"
    13 
    14 #include <stdio.h> /* for fflush() and stdout */
    15 
    16 #ifdef __EMSCRIPTEN__
    17 #include <emscripten/emscripten.h>
    18 #endif
    19 
    20 static SDL_AudioSpec spec;
    21 static Uint8 *sound = NULL;     /* Pointer to wave data */
    22 static Uint32 soundlen = 0;     /* Length of wave data */
    23 
    24 typedef struct
    25 {
    26     SDL_AudioDeviceID dev;
    27     int soundpos;
    28     SDL_atomic_t done;
    29 } callback_data;
    30 
    31 callback_data cbd[64];
    32 
    33 void SDLCALL
    34 play_through_once(void *arg, Uint8 * stream, int len)
    35 {
    36     callback_data *cbd = (callback_data *) arg;
    37     Uint8 *waveptr = sound + cbd->soundpos;
    38     int waveleft = soundlen - cbd->soundpos;
    39     int cpy = len;
    40     if (cpy > waveleft)
    41         cpy = waveleft;
    42 
    43     SDL_memcpy(stream, waveptr, cpy);
    44     len -= cpy;
    45     cbd->soundpos += cpy;
    46     if (len > 0) {
    47         stream += cpy;
    48         SDL_memset(stream, spec.silence, len);
    49         SDL_AtomicSet(&cbd->done, 1);
    50     }
    51 }
    52 
    53 void
    54 loop()
    55 {
    56     if (SDL_AtomicGet(&cbd[0].done)) {
    57 #ifdef __EMSCRIPTEN__
    58         emscripten_cancel_main_loop();
    59 #endif
    60         SDL_PauseAudioDevice(cbd[0].dev, 1);
    61         SDL_CloseAudioDevice(cbd[0].dev);
    62         SDL_FreeWAV(sound);
    63         SDL_Quit();
    64     }
    65 }
    66 
    67 static void
    68 test_multi_audio(int devcount)
    69 {
    70     int keep_going = 1;
    71     int i;
    72     
    73 #ifdef __ANDROID__  
    74     SDL_Event event;
    75   
    76     /* Create a Window to get fully initialized event processing for testing pause on Android. */
    77     SDL_CreateWindow("testmultiaudio", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, 0);
    78 #endif
    79 
    80     if (devcount > 64) {
    81         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Too many devices (%d), clamping to 64...\n",
    82                 devcount);
    83         devcount = 64;
    84     }
    85 
    86     spec.callback = play_through_once;
    87 
    88     for (i = 0; i < devcount; i++) {
    89         const char *devname = SDL_GetAudioDeviceName(i, 0);
    90         SDL_Log("playing on device #%d: ('%s')...", i, devname);
    91         fflush(stdout);
    92 
    93         SDL_memset(&cbd[0], '\0', sizeof(callback_data));
    94         spec.userdata = &cbd[0];
    95         cbd[0].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0);
    96         if (cbd[0].dev == 0) {
    97             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device failed: %s\n", SDL_GetError());
    98         } else {
    99             SDL_PauseAudioDevice(cbd[0].dev, 0);
   100 #ifdef __EMSCRIPTEN__
   101             emscripten_set_main_loop(loop, 0, 1);
   102 #else
   103             while (!SDL_AtomicGet(&cbd[0].done)) {
   104                 #ifdef __ANDROID__                
   105                 /* Empty queue, some application events would prevent pause. */
   106                 while (SDL_PollEvent(&event)){}
   107                 #endif                
   108                 SDL_Delay(100);
   109             }
   110             SDL_PauseAudioDevice(cbd[0].dev, 1);
   111 #endif
   112             SDL_Log("done.\n");
   113             SDL_CloseAudioDevice(cbd[0].dev);
   114         }
   115     }
   116 
   117     SDL_memset(cbd, '\0', sizeof(cbd));
   118 
   119     SDL_Log("playing on all devices...\n");
   120     for (i = 0; i < devcount; i++) {
   121         const char *devname = SDL_GetAudioDeviceName(i, 0);
   122         spec.userdata = &cbd[i];
   123         cbd[i].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0);
   124         if (cbd[i].dev == 0) {
   125             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device %d failed: %s\n", i, SDL_GetError());
   126         }
   127     }
   128 
   129     for (i = 0; i < devcount; i++) {
   130         if (cbd[i].dev) {
   131             SDL_PauseAudioDevice(cbd[i].dev, 0);
   132         }
   133     }
   134 
   135     while (keep_going) {
   136         keep_going = 0;
   137         for (i = 0; i < devcount; i++) {
   138             if ((cbd[i].dev) && (!SDL_AtomicGet(&cbd[i].done))) {
   139                 keep_going = 1;
   140             }
   141         }
   142         #ifdef __ANDROID__        
   143         /* Empty queue, some application events would prevent pause. */
   144         while (SDL_PollEvent(&event)){}
   145         #endif        
   146 
   147         SDL_Delay(100);
   148     }
   149 
   150 #ifndef __EMSCRIPTEN__
   151     for (i = 0; i < devcount; i++) {
   152         if (cbd[i].dev) {
   153             SDL_PauseAudioDevice(cbd[i].dev, 1);
   154             SDL_CloseAudioDevice(cbd[i].dev);
   155         }
   156     }
   157 
   158     SDL_Log("All done!\n");
   159 #endif
   160 }
   161 
   162 
   163 int
   164 main(int argc, char **argv)
   165 {
   166     int devcount = 0;
   167 
   168     /* Enable standard application logging */
   169     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   170 
   171     /* Load the SDL library */
   172     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
   173         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
   174         return (1);
   175     }
   176 
   177     SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
   178     
   179     devcount = SDL_GetNumAudioDevices(0);
   180     if (devcount < 1) {
   181         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio devices!\n");
   182     } else {
   183         if (argv[1] == NULL) {
   184             argv[1] = "sample.wav";
   185         }
   186 
   187         /* Load the wave file into memory */
   188         if (SDL_LoadWAV(argv[1], &spec, &sound, &soundlen) == NULL) {
   189             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", argv[1],
   190                     SDL_GetError());
   191         } else {
   192             test_multi_audio(devcount);
   193             SDL_FreeWAV(sound);
   194         }
   195     }
   196 
   197     SDL_Quit();
   198     return 0;
   199 }