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