SDL  2.0
testmultiaudio.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 1997-2018 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 
21 static Uint8 *sound = NULL; /* Pointer to wave data */
22 static Uint32 soundlen = 0; /* Length of wave data */
23 
24 typedef struct
25 {
27  int soundpos;
30 
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
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);
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__
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 
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 */
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);
194  }
195  }
196 
197  SDL_Quit();
198  return 0;
199 }
#define SDL_GetNumAudioDevices
#define SDL_WINDOWPOS_CENTERED
Definition: SDL_video.h:139
#define SDL_PollEvent
#define SDL_GetError
#define SDL_CloseAudioDevice
#define SDL_OpenAudioDevice
Uint8 silence
Definition: SDL_audio.h:182
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:198
#define SDL_FreeWAV
#define SDL_CreateWindow
void play_through_once(void *arg, Uint8 *stream, int len)
SDL_AudioDeviceID dev
uint32_t Uint32
Definition: SDL_stdinc.h:181
GLenum GLsizei len
#define SDL_LogError
#define SDL_GetAudioDeviceName
static SDL_AudioSpec spec
static Uint8 * sound
#define SDL_Log
#define SDL_memcpy
static void test_multi_audio(int devcount)
GLuint GLuint stream
uint8_t Uint8
Definition: SDL_stdinc.h:157
struct _cl_event * event
#define SDL_Quit
int done
Definition: checkkeys.c:28
#define SDL_LoadWAV(file, spec, audio_buf, audio_len)
Definition: SDL_audio.h:450
SDL_AudioCallback callback
Definition: SDL_audio.h:186
#define SDL_Delay
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define SDL_LogSetPriority
#define SDL_GetCurrentAudioDriver
#define NULL
Definition: begin_code.h:164
int main(int argc, char **argv)
#define SDL_INIT_AUDIO
Definition: SDL.h:77
Uint32 SDL_AudioDeviceID
Definition: SDL_audio.h:329
#define SDL_AtomicSet
#define SDL_AtomicGet
void * userdata
Definition: SDL_audio.h:187
#define SDL_Init
General event structure.
Definition: SDL_events.h:525
static Uint32 soundlen
callback_data cbd[64]
#define SDLCALL
Definition: SDL_internal.h:45
SDL_atomic_t done
#define SDL_memset
#define SDL_PauseAudioDevice
void loop()