Mercurial > sdl-ios-xcode
comparison src/audio/windib/SDL_dibaudio.c @ 1895:c121d94672cb
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 10 Jul 2006 21:04:37 +0000 |
parents | 84de7511f79f |
children | 4ad1e863d100 |
comparison
equal
deleted
inserted
replaced
1894:c69cee13dd76 | 1895:c121d94672cb |
---|---|
35 #include "win_ce_semaphore.h" | 35 #include "win_ce_semaphore.h" |
36 #endif | 36 #endif |
37 | 37 |
38 | 38 |
39 /* Audio driver functions */ | 39 /* Audio driver functions */ |
40 static int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec); | 40 static int DIB_OpenAudio(_THIS, SDL_AudioSpec * spec); |
41 static void DIB_ThreadInit(_THIS); | 41 static void DIB_ThreadInit(_THIS); |
42 static void DIB_WaitAudio(_THIS); | 42 static void DIB_WaitAudio(_THIS); |
43 static Uint8 *DIB_GetAudioBuf(_THIS); | 43 static Uint8 *DIB_GetAudioBuf(_THIS); |
44 static void DIB_PlayAudio(_THIS); | 44 static void DIB_PlayAudio(_THIS); |
45 static void DIB_WaitDone(_THIS); | 45 static void DIB_WaitDone(_THIS); |
46 static void DIB_CloseAudio(_THIS); | 46 static void DIB_CloseAudio(_THIS); |
47 | 47 |
48 /* Audio driver bootstrap functions */ | 48 /* Audio driver bootstrap functions */ |
49 | 49 |
50 static int Audio_Available(void) | 50 static int |
51 { | 51 Audio_Available(void) |
52 return(1); | 52 { |
53 } | 53 return (1); |
54 | 54 } |
55 static void Audio_DeleteDevice(SDL_AudioDevice *device) | 55 |
56 { | 56 static void |
57 SDL_free(device->hidden); | 57 Audio_DeleteDevice(SDL_AudioDevice * device) |
58 SDL_free(device); | 58 { |
59 } | 59 SDL_free(device->hidden); |
60 | 60 SDL_free(device); |
61 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | 61 } |
62 { | 62 |
63 SDL_AudioDevice *this; | 63 static SDL_AudioDevice * |
64 | 64 Audio_CreateDevice(int devindex) |
65 /* Initialize all variables that we clean on shutdown */ | 65 { |
66 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); | 66 SDL_AudioDevice *this; |
67 if ( this ) { | 67 |
68 SDL_memset(this, 0, (sizeof *this)); | 68 /* Initialize all variables that we clean on shutdown */ |
69 this->hidden = (struct SDL_PrivateAudioData *) | 69 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); |
70 SDL_malloc((sizeof *this->hidden)); | 70 if (this) { |
71 } | 71 SDL_memset(this, 0, (sizeof *this)); |
72 if ( (this == NULL) || (this->hidden == NULL) ) { | 72 this->hidden = (struct SDL_PrivateAudioData *) |
73 SDL_OutOfMemory(); | 73 SDL_malloc((sizeof *this->hidden)); |
74 if ( this ) { | 74 } |
75 SDL_free(this); | 75 if ((this == NULL) || (this->hidden == NULL)) { |
76 } | 76 SDL_OutOfMemory(); |
77 return(0); | 77 if (this) { |
78 } | 78 SDL_free(this); |
79 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | 79 } |
80 | 80 return (0); |
81 /* Set the function pointers */ | 81 } |
82 this->OpenAudio = DIB_OpenAudio; | 82 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
83 this->ThreadInit = DIB_ThreadInit; | 83 |
84 this->WaitAudio = DIB_WaitAudio; | 84 /* Set the function pointers */ |
85 this->PlayAudio = DIB_PlayAudio; | 85 this->OpenAudio = DIB_OpenAudio; |
86 this->GetAudioBuf = DIB_GetAudioBuf; | 86 this->ThreadInit = DIB_ThreadInit; |
87 this->WaitDone = DIB_WaitDone; | 87 this->WaitAudio = DIB_WaitAudio; |
88 this->CloseAudio = DIB_CloseAudio; | 88 this->PlayAudio = DIB_PlayAudio; |
89 | 89 this->GetAudioBuf = DIB_GetAudioBuf; |
90 this->free = Audio_DeleteDevice; | 90 this->WaitDone = DIB_WaitDone; |
91 | 91 this->CloseAudio = DIB_CloseAudio; |
92 return this; | 92 |
93 this->free = Audio_DeleteDevice; | |
94 | |
95 return this; | |
93 } | 96 } |
94 | 97 |
95 AudioBootStrap WAVEOUT_bootstrap = { | 98 AudioBootStrap WAVEOUT_bootstrap = { |
96 "waveout", "Win95/98/NT/2000 WaveOut", | 99 "waveout", "Win95/98/NT/2000 WaveOut", |
97 Audio_Available, Audio_CreateDevice | 100 Audio_Available, Audio_CreateDevice |
98 }; | 101 }; |
99 | 102 |
100 | 103 |
101 /* The Win32 callback for filling the WAVE device */ | 104 /* The Win32 callback for filling the WAVE device */ |
102 static void CALLBACK FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, | 105 static void CALLBACK |
103 DWORD dwParam1, DWORD dwParam2) | 106 FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, |
104 { | 107 DWORD dwParam1, DWORD dwParam2) |
105 SDL_AudioDevice *this = (SDL_AudioDevice *)dwInstance; | 108 { |
106 | 109 SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance; |
107 /* Only service "buffer done playing" messages */ | 110 |
108 if ( uMsg != WOM_DONE ) | 111 /* Only service "buffer done playing" messages */ |
109 return; | 112 if (uMsg != WOM_DONE) |
110 | 113 return; |
111 /* Signal that we are done playing a buffer */ | 114 |
112 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) | 115 /* Signal that we are done playing a buffer */ |
113 ReleaseSemaphoreCE(audio_sem, 1, NULL); | 116 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
114 #else | 117 ReleaseSemaphoreCE(audio_sem, 1, NULL); |
115 ReleaseSemaphore(audio_sem, 1, NULL); | 118 #else |
116 #endif | 119 ReleaseSemaphore(audio_sem, 1, NULL); |
117 } | 120 #endif |
118 | 121 } |
119 static void SetMMerror(char *function, MMRESULT code) | 122 |
120 { | 123 static void |
121 size_t len; | 124 SetMMerror(char *function, MMRESULT code) |
122 char errbuf[MAXERRORLENGTH]; | 125 { |
126 size_t len; | |
127 char errbuf[MAXERRORLENGTH]; | |
123 #ifdef _WIN32_WCE | 128 #ifdef _WIN32_WCE |
124 wchar_t werrbuf[MAXERRORLENGTH]; | 129 wchar_t werrbuf[MAXERRORLENGTH]; |
125 #endif | 130 #endif |
126 | 131 |
127 SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function); | 132 SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function); |
128 len = SDL_strlen(errbuf); | 133 len = SDL_strlen(errbuf); |
129 | 134 |
130 #ifdef _WIN32_WCE | 135 #ifdef _WIN32_WCE |
131 /* UNICODE version */ | 136 /* UNICODE version */ |
132 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH-len); | 137 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len); |
133 WideCharToMultiByte(CP_ACP,0,werrbuf,-1,errbuf+len,MAXERRORLENGTH-len,NULL,NULL); | 138 WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len, |
134 #else | 139 MAXERRORLENGTH - len, NULL, NULL); |
135 waveOutGetErrorText(code, errbuf+len, (UINT)(MAXERRORLENGTH-len)); | 140 #else |
136 #endif | 141 waveOutGetErrorText(code, errbuf + len, (UINT) (MAXERRORLENGTH - len)); |
137 | 142 #endif |
138 SDL_SetError("%s",errbuf); | 143 |
144 SDL_SetError("%s", errbuf); | |
139 } | 145 } |
140 | 146 |
141 /* Set high priority for the audio thread */ | 147 /* Set high priority for the audio thread */ |
142 static void DIB_ThreadInit(_THIS) | 148 static void |
143 { | 149 DIB_ThreadInit(_THIS) |
144 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); | 150 { |
145 } | 151 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); |
146 | 152 } |
147 void DIB_WaitAudio(_THIS) | 153 |
148 { | 154 void |
149 /* Wait for an audio chunk to finish */ | 155 DIB_WaitAudio(_THIS) |
150 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) | 156 { |
151 WaitForSemaphoreCE(audio_sem, INFINITE); | 157 /* Wait for an audio chunk to finish */ |
152 #else | 158 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
153 WaitForSingleObject(audio_sem, INFINITE); | 159 WaitForSemaphoreCE(audio_sem, INFINITE); |
154 #endif | 160 #else |
155 } | 161 WaitForSingleObject(audio_sem, INFINITE); |
156 | 162 #endif |
157 Uint8 *DIB_GetAudioBuf(_THIS) | 163 } |
158 { | 164 |
159 Uint8 *retval; | 165 Uint8 * |
160 | 166 DIB_GetAudioBuf(_THIS) |
161 retval = (Uint8 *)(wavebuf[next_buffer].lpData); | 167 { |
162 return retval; | 168 Uint8 *retval; |
163 } | 169 |
164 | 170 retval = (Uint8 *) (wavebuf[next_buffer].lpData); |
165 void DIB_PlayAudio(_THIS) | 171 return retval; |
166 { | 172 } |
167 /* Queue it up */ | 173 |
168 waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0])); | 174 void |
169 next_buffer = (next_buffer+1)%NUM_BUFFERS; | 175 DIB_PlayAudio(_THIS) |
170 } | 176 { |
171 | 177 /* Queue it up */ |
172 void DIB_WaitDone(_THIS) | 178 waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0])); |
173 { | 179 next_buffer = (next_buffer + 1) % NUM_BUFFERS; |
174 int i, left; | 180 } |
175 | 181 |
176 do { | 182 void |
177 left = NUM_BUFFERS; | 183 DIB_WaitDone(_THIS) |
178 for ( i=0; i<NUM_BUFFERS; ++i ) { | 184 { |
179 if ( wavebuf[i].dwFlags & WHDR_DONE ) { | 185 int i, left; |
180 --left; | 186 |
181 } | 187 do { |
182 } | 188 left = NUM_BUFFERS; |
183 if ( left > 0 ) { | 189 for (i = 0; i < NUM_BUFFERS; ++i) { |
184 SDL_Delay(100); | 190 if (wavebuf[i].dwFlags & WHDR_DONE) { |
185 } | 191 --left; |
186 } while ( left > 0 ); | 192 } |
187 } | 193 } |
188 | 194 if (left > 0) { |
189 void DIB_CloseAudio(_THIS) | 195 SDL_Delay(100); |
190 { | 196 } |
191 int i; | 197 } |
192 | 198 while (left > 0); |
193 /* Close up audio */ | 199 } |
194 if ( audio_sem ) { | 200 |
195 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) | 201 void |
196 CloseSynchHandle(audio_sem); | 202 DIB_CloseAudio(_THIS) |
197 #else | 203 { |
198 CloseHandle(audio_sem); | 204 int i; |
199 #endif | 205 |
200 } | 206 /* Close up audio */ |
201 if ( sound ) { | 207 if (audio_sem) { |
202 waveOutClose(sound); | 208 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
203 } | 209 CloseSynchHandle(audio_sem); |
204 | 210 #else |
205 /* Clean up mixing buffers */ | 211 CloseHandle(audio_sem); |
206 for ( i=0; i<NUM_BUFFERS; ++i ) { | 212 #endif |
207 if ( wavebuf[i].dwUser != 0xFFFF ) { | 213 } |
208 waveOutUnprepareHeader(sound, &wavebuf[i], | 214 if (sound) { |
209 sizeof(wavebuf[i])); | 215 waveOutClose(sound); |
210 wavebuf[i].dwUser = 0xFFFF; | 216 } |
211 } | 217 |
212 } | 218 /* Clean up mixing buffers */ |
213 /* Free raw mixing buffer */ | 219 for (i = 0; i < NUM_BUFFERS; ++i) { |
214 if ( mixbuf != NULL ) { | 220 if (wavebuf[i].dwUser != 0xFFFF) { |
215 SDL_free(mixbuf); | 221 waveOutUnprepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i])); |
216 mixbuf = NULL; | 222 wavebuf[i].dwUser = 0xFFFF; |
217 } | 223 } |
218 } | 224 } |
219 | 225 /* Free raw mixing buffer */ |
220 int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec) | 226 if (mixbuf != NULL) { |
221 { | 227 SDL_free(mixbuf); |
222 MMRESULT result; | 228 mixbuf = NULL; |
223 int i; | 229 } |
224 WAVEFORMATEX waveformat; | 230 } |
225 | 231 |
226 /* Initialize the wavebuf structures for closing */ | 232 int |
227 sound = NULL; | 233 DIB_OpenAudio(_THIS, SDL_AudioSpec * spec) |
228 audio_sem = NULL; | 234 { |
229 for ( i = 0; i < NUM_BUFFERS; ++i ) | 235 MMRESULT result; |
230 wavebuf[i].dwUser = 0xFFFF; | 236 int i; |
231 mixbuf = NULL; | 237 WAVEFORMATEX waveformat; |
232 | 238 |
233 /* Set basic WAVE format parameters */ | 239 /* Initialize the wavebuf structures for closing */ |
234 SDL_memset(&waveformat, 0, sizeof(waveformat)); | 240 sound = NULL; |
235 waveformat.wFormatTag = WAVE_FORMAT_PCM; | 241 audio_sem = NULL; |
236 | 242 for (i = 0; i < NUM_BUFFERS; ++i) |
237 /* Determine the audio parameters from the AudioSpec */ | 243 wavebuf[i].dwUser = 0xFFFF; |
238 switch ( spec->format & 0xFF ) { | 244 mixbuf = NULL; |
239 case 8: | 245 |
240 /* Unsigned 8 bit audio data */ | 246 /* Set basic WAVE format parameters */ |
241 spec->format = AUDIO_U8; | 247 SDL_memset(&waveformat, 0, sizeof(waveformat)); |
242 waveformat.wBitsPerSample = 8; | 248 waveformat.wFormatTag = WAVE_FORMAT_PCM; |
243 break; | 249 |
244 case 16: | 250 /* Determine the audio parameters from the AudioSpec */ |
245 /* Signed 16 bit audio data */ | 251 switch (spec->format & 0xFF) { |
246 spec->format = AUDIO_S16; | 252 case 8: |
247 waveformat.wBitsPerSample = 16; | 253 /* Unsigned 8 bit audio data */ |
248 break; | 254 spec->format = AUDIO_U8; |
249 default: | 255 waveformat.wBitsPerSample = 8; |
250 SDL_SetError("Unsupported audio format"); | 256 break; |
251 return(-1); | 257 case 16: |
252 } | 258 /* Signed 16 bit audio data */ |
253 waveformat.nChannels = spec->channels; | 259 spec->format = AUDIO_S16; |
254 waveformat.nSamplesPerSec = spec->freq; | 260 waveformat.wBitsPerSample = 16; |
255 waveformat.nBlockAlign = | 261 break; |
256 waveformat.nChannels * (waveformat.wBitsPerSample/8); | 262 default: |
257 waveformat.nAvgBytesPerSec = | 263 SDL_SetError("Unsupported audio format"); |
258 waveformat.nSamplesPerSec * waveformat.nBlockAlign; | 264 return (-1); |
259 | 265 } |
260 /* Check the buffer size -- minimum of 1/4 second (word aligned) */ | 266 waveformat.nChannels = spec->channels; |
261 if ( spec->samples < (spec->freq/4) ) | 267 waveformat.nSamplesPerSec = spec->freq; |
262 spec->samples = ((spec->freq/4)+3)&~3; | 268 waveformat.nBlockAlign = |
263 | 269 waveformat.nChannels * (waveformat.wBitsPerSample / 8); |
264 /* Update the fragment size as size in bytes */ | 270 waveformat.nAvgBytesPerSec = |
265 SDL_CalculateAudioSpec(spec); | 271 waveformat.nSamplesPerSec * waveformat.nBlockAlign; |
266 | 272 |
267 /* Open the audio device */ | 273 /* Check the buffer size -- minimum of 1/4 second (word aligned) */ |
268 result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat, | 274 if (spec->samples < (spec->freq / 4)) |
269 (DWORD_PTR)FillSound, (DWORD_PTR)this, CALLBACK_FUNCTION); | 275 spec->samples = ((spec->freq / 4) + 3) & ~3; |
270 if ( result != MMSYSERR_NOERROR ) { | 276 |
271 SetMMerror("waveOutOpen()", result); | 277 /* Update the fragment size as size in bytes */ |
272 return(-1); | 278 SDL_CalculateAudioSpec(spec); |
273 } | 279 |
274 | 280 /* Open the audio device */ |
281 result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat, | |
282 (DWORD_PTR) FillSound, (DWORD_PTR) this, | |
283 CALLBACK_FUNCTION); | |
284 if (result != MMSYSERR_NOERROR) { | |
285 SetMMerror("waveOutOpen()", result); | |
286 return (-1); | |
287 } | |
275 #ifdef SOUND_DEBUG | 288 #ifdef SOUND_DEBUG |
276 /* Check the sound device we retrieved */ | 289 /* Check the sound device we retrieved */ |
277 { | 290 { |
278 WAVEOUTCAPS caps; | 291 WAVEOUTCAPS caps; |
279 | 292 |
280 result = waveOutGetDevCaps((UINT)sound, &caps, sizeof(caps)); | 293 result = waveOutGetDevCaps((UINT) sound, &caps, sizeof(caps)); |
281 if ( result != MMSYSERR_NOERROR ) { | 294 if (result != MMSYSERR_NOERROR) { |
282 SetMMerror("waveOutGetDevCaps()", result); | 295 SetMMerror("waveOutGetDevCaps()", result); |
283 return(-1); | 296 return (-1); |
284 } | 297 } |
285 printf("Audio device: %s\n", caps.szPname); | 298 printf("Audio device: %s\n", caps.szPname); |
286 } | 299 } |
287 #endif | 300 #endif |
288 | 301 |
289 /* Create the audio buffer semaphore */ | 302 /* Create the audio buffer semaphore */ |
290 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) | 303 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
291 audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS-1, NUM_BUFFERS, NULL); | 304 audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); |
292 #else | 305 #else |
293 audio_sem = CreateSemaphore(NULL, NUM_BUFFERS-1, NUM_BUFFERS, NULL); | 306 audio_sem = CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); |
294 #endif | 307 #endif |
295 if ( audio_sem == NULL ) { | 308 if (audio_sem == NULL) { |
296 SDL_SetError("Couldn't create semaphore"); | 309 SDL_SetError("Couldn't create semaphore"); |
297 return(-1); | 310 return (-1); |
298 } | 311 } |
299 | 312 |
300 /* Create the sound buffers */ | 313 /* Create the sound buffers */ |
301 mixbuf = (Uint8 *)SDL_malloc(NUM_BUFFERS*spec->size); | 314 mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * spec->size); |
302 if ( mixbuf == NULL ) { | 315 if (mixbuf == NULL) { |
303 SDL_SetError("Out of memory"); | 316 SDL_SetError("Out of memory"); |
304 return(-1); | 317 return (-1); |
305 } | 318 } |
306 for ( i = 0; i < NUM_BUFFERS; ++i ) { | 319 for (i = 0; i < NUM_BUFFERS; ++i) { |
307 SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i])); | 320 SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i])); |
308 wavebuf[i].lpData = (LPSTR) &mixbuf[i*spec->size]; | 321 wavebuf[i].lpData = (LPSTR) & mixbuf[i * spec->size]; |
309 wavebuf[i].dwBufferLength = spec->size; | 322 wavebuf[i].dwBufferLength = spec->size; |
310 wavebuf[i].dwFlags = WHDR_DONE; | 323 wavebuf[i].dwFlags = WHDR_DONE; |
311 result = waveOutPrepareHeader(sound, &wavebuf[i], | 324 result = waveOutPrepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i])); |
312 sizeof(wavebuf[i])); | 325 if (result != MMSYSERR_NOERROR) { |
313 if ( result != MMSYSERR_NOERROR ) { | 326 SetMMerror("waveOutPrepareHeader()", result); |
314 SetMMerror("waveOutPrepareHeader()", result); | 327 return (-1); |
315 return(-1); | 328 } |
316 } | 329 } |
317 } | 330 |
318 | 331 /* Ready to go! */ |
319 /* Ready to go! */ | 332 next_buffer = 0; |
320 next_buffer = 0; | 333 return (0); |
321 return(0); | 334 } |
322 } | 335 |
336 /* vi: set ts=4 sw=4 expandtab: */ |