test/testmultiaudio.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 Dec 2017 16:08:47 -0800
changeset 11731 30f337dc8c74
parent 10737 3406a0f8b041
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Added iOS and OSX 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
}