comparison src/audio/nto/SDL_nto_audio.c @ 418:337f3ec4c385

Updated the QNX audio code for QNX 6.2 (thanks Travis!)
author Sam Lantinga <slouken@libsdl.org>
date Sun, 16 Jun 2002 04:17:57 +0000
parents f6ffac90895c
children b82518082828
comparison
equal deleted inserted replaced
417:04ec6995f75d 418:337f3ec4c385
1 Date: Sun, 16 Jun 2002 00:59:13 -0300
2 From: Travis <smallfri@bigfoot.com>
3 To: slouken@libsdl.org
4 Subject: NTO Audio Fixes
5
1 /* 6 /*
2 SDL - Simple DirectMedia Layer 7 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga 8 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
4 9
5 This library is free software; you can redistribute it and/or 10 This library is free software; you can redistribute it and/or
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 23
19 Sam Lantinga 24 Sam Lantinga
20 slouken@libsdl.org 25 slouken@libsdl.org
21 */ 26 */
22
23
24
25 /* Allow access to a raw mixing buffer */
26 27
27 #include <stdlib.h> 28 #include <stdlib.h>
28 #include <stdio.h> 29 #include <stdio.h>
29 #include <string.h> 30 #include <string.h>
30 #include <errno.h> 31 #include <errno.h>
33 #include <signal.h> 34 #include <signal.h>
34 #include <sys/types.h> 35 #include <sys/types.h>
35 #include <sys/time.h> 36 #include <sys/time.h>
36 #include <sched.h> 37 #include <sched.h>
37 #include <sys/asoundlib.h> 38 #include <sys/asoundlib.h>
39 #include <sys/select.h>
38 40
39 #include "SDL_audio.h" 41 #include "SDL_audio.h"
40 #include "SDL_error.h" 42 #include "SDL_error.h"
41 #include "SDL_audiomem.h" 43 #include "SDL_audiomem.h"
42 #include "SDL_audio_c.h" 44 #include "SDL_audio_c.h"
44 #include "SDL_nto_audio.h" 46 #include "SDL_nto_audio.h"
45 47
46 /* The tag name used by NTO audio */ 48 /* The tag name used by NTO audio */
47 #define DRIVER_NAME "nto" 49 #define DRIVER_NAME "nto"
48 50
49 /* default card and device numbers as listed in dev/snd */
50 static int card_no = 0;
51 static int device_no = 0;
52
53 /* default channel communication parameters */ 51 /* default channel communication parameters */
54 #define DEFAULT_CPARAMS_RATE 22050 52 #define DEFAULT_CPARAMS_RATE 22050
55 #define DEFAULT_CPARAMS_VOICES 1 53 #define DEFAULT_CPARAMS_VOICES 1
56 #define DEFAULT_CPARAMS_FRAG_SIZE 4096 //was 512 54 #define DEFAULT_CPARAMS_FRAG_SIZE 4096
57 #define DEFAULT_CPARAMS_FRAGS_MIN 1 55 #define DEFAULT_CPARAMS_FRAGS_MIN 1
58 #define DEFAULT_CPARAMS_FRAGS_MAX 1 56 #define DEFAULT_CPARAMS_FRAGS_MAX 1
59 57
60 /* Open the audio device for playback, and don't block if busy */ 58 /* Open the audio device for playback, and don't block if busy */
61 #define OPEN_FLAGS SND_PCM_OPEN_PLAYBACK 59 #define OPEN_FLAGS SND_PCM_OPEN_PLAYBACK
62 60
63 /* Audio driver functions */ 61 /* Audio driver functions */
64 static int NTO_OpenAudio(_THIS, SDL_AudioSpec *spec); 62 static int NTO_OpenAudio(_THIS, SDL_AudioSpec *spec);
65 static void NTO_WaitAudio(_THIS); 63 static void NTO_WaitAudio(_THIS);
66 static void NTO_PlayAudio(_THIS); 64 static void NTO_PlayAudio(_THIS);
67 static Uint8 *NTO_GetAudioBuf(_THIS); 65 static Uint8 *NTO_GetAudioBuf(_THIS);
68 static void NTO_CloseAudio(_THIS); 66 static void NTO_CloseAudio(_THIS);
69 67
70 static snd_pcm_channel_status_t cstatus; 68 static snd_pcm_channel_status_t cstatus;
71 static snd_pcm_channel_params_t cparams; 69 static snd_pcm_channel_params_t cparams;
72 static snd_pcm_channel_setup_t csetup; 70 static snd_pcm_channel_setup_t csetup;
73 71
74 /* PCM transfer channel parameters initialize function */ 72 /* PCM transfer channel parameters initialize function */
75 static void init_pcm_cparams(snd_pcm_channel_params_t* cparams) 73 static void init_pcm_cparams(snd_pcm_channel_params_t* cparams)
76 { 74 {
77 memset(cparams,0,sizeof(snd_pcm_channel_params_t)); 75 memset(cparams,0,sizeof(snd_pcm_channel_params_t));
78 76
79 cparams->channel = SND_PCM_CHANNEL_PLAYBACK; 77 cparams->channel = SND_PCM_CHANNEL_PLAYBACK;
80 cparams->mode = SND_PCM_MODE_BLOCK; 78 cparams->mode = SND_PCM_MODE_BLOCK;
81 cparams->start_mode = SND_PCM_START_DATA; //_FULL 79 cparams->start_mode = SND_PCM_START_DATA;
82 cparams->stop_mode = SND_PCM_STOP_STOP; 80 cparams->stop_mode = SND_PCM_STOP_STOP;
83 cparams->format.format = SND_PCM_SFMT_S16_LE; 81 cparams->format.format = SND_PCM_SFMT_S16_LE;
84 cparams->format.interleave = 1; 82 cparams->format.interleave = 1;
85 cparams->format.rate = DEFAULT_CPARAMS_RATE; 83 cparams->format.rate = DEFAULT_CPARAMS_RATE;
86 cparams->format.voices = DEFAULT_CPARAMS_VOICES; 84 cparams->format.voices = DEFAULT_CPARAMS_VOICES;
87 cparams->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE; 85 cparams->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE;
88 cparams->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; 86 cparams->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN;
89 cparams->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; 87 cparams->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX;
90 } 88 }
91 89
92 /* Audio driver bootstrap functions */
93
94 static int Audio_Available(void) 90 static int Audio_Available(void)
95 /* 91 {
96 See if we can open a nonblocking channel. 92 /*
97 Return value '1' means we can. 93 See if we can open a nonblocking channel.
98 Return value '0' means we cannot. 94 Return value '1' means we can.
99 */ 95 Return value '0' means we cannot.
100 { 96 */
97
101 int available; 98 int available;
102 int rval; 99 int rval;
103 snd_pcm_t *handle; 100 snd_pcm_t *handle;
104 101
105 available = 0; 102 available = 0;
106 handle = NULL; 103 handle = NULL;
107 104
108 //JB modified to take advantage of software mixer 105 rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS);
109 rval = snd_pcm_open_preferred(&handle, &card_no, &device_no, OPEN_FLAGS); 106
110 107 if (rval >= 0){
111 if (rval >= 0) 108 available = 1;
112 { 109
113 available = 1; 110 if ((rval = snd_pcm_close(handle)) < 0){
114 111 SDL_SetError("snd_pcm_close failed: %s\n",snd_strerror(rval));
115 if ((rval = snd_pcm_close(handle)) < 0)
116 {
117 SDL_SetError("snd_pcm_close failed: %s\n",snd_strerror(rval));
118 available = 0; 112 available = 0;
119 } 113 }
120 } 114 }
121 else 115 else{
122 { 116 SDL_SetError("snd_pcm_open failed: %s\n", snd_strerror(rval));
123 117 }
124 SDL_SetError("snd_pcm_open failed: %s\n", snd_strerror(rval)); 118
125 } 119 #ifdef DEBUG_AUDIO
126
127 #ifdef DEBUG_AUDIO
128 fprintf(stderr,"AudioAvailable rtns %d\n", available); 120 fprintf(stderr,"AudioAvailable rtns %d\n", available);
129 #endif 121 #endif
122
130 return(available); 123 return(available);
131 } 124 }
132 125
133 static void Audio_DeleteDevice(SDL_AudioDevice *device) 126 static void Audio_DeleteDevice(SDL_AudioDevice *device)
134 { 127 {
135 #ifdef DEBUG_AUDIO 128 #ifdef DEBUG_AUDIO
136 fprintf(stderr,"Audio_DeleteDevice\n"); 129 fprintf(stderr,"Audio_DeleteDevice\n");
137 #endif 130 #endif
138 131
139
140 free(device->hidden); 132 free(device->hidden);
141 free(device); 133 free(device);
142 } 134 }
143 135
144 static SDL_AudioDevice *Audio_CreateDevice(int devindex) 136 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
145 { 137 {
146 SDL_AudioDevice *this; 138 SDL_AudioDevice *this;
147 #ifdef DEBUG_AUDIO 139 #ifdef DEBUG_AUDIO
148 fprintf(stderr,"Audio_CreateDevice\n"); 140 fprintf(stderr,"Audio_CreateDevice\n");
149 #endif 141 #endif
150 /* Initialize all variables that we clean on shutdown */ 142 /* Initialize all variables that we clean on shutdown */
151 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); 143 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
152 if ( this ) { 144 if ( this ) {
153 memset(this, 0, (sizeof *this)); 145 memset(this, 0, (sizeof *this));
154 this->hidden = (struct SDL_PrivateAudioData *) 146 this->hidden = (struct SDL_PrivateAudioData *)
155 malloc((sizeof *this->hidden)); 147 malloc((sizeof *this->hidden));
156 } 148 }
157 if ( (this == NULL) || (this->hidden == NULL) ) { 149 if ( (this == NULL) || (this->hidden == NULL) ) {
158 SDL_OutOfMemory(); 150 SDL_OutOfMemory();
159 if ( this ) { 151 if ( this ) {
160 free(this); 152 free(this);
183 }; 175 };
184 176
185 /* This function waits until it is possible to write a full sound buffer */ 177 /* This function waits until it is possible to write a full sound buffer */
186 static void NTO_WaitAudio(_THIS) 178 static void NTO_WaitAudio(_THIS)
187 { 179 {
188 int rval; 180 fd_set wfds;
189 int totalbytes,roomavail; 181
190 /*we consider a full sound buffer to be of size pcm_len bytes */ 182 FD_SET( audio_fd, &wfds );
191 183 switch( select( audio_fd + 1, NULL, &wfds, NULL, NULL ) )
192 #ifdef DEBUG_AUDIO
193 fprintf(stderr,"NTO_WaitAudio\n");
194 #endif
195
196 while(1)
197 { 184 {
198 memset(&cstatus, 0, sizeof(cstatus)); 185 case -1:
199 if( (rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0 ) 186 case 0:
200 { 187 /* Error */
201 SDL_SetError("snd_pcm_plugin_status failed: %s\n", snd_strerror(rval)); 188 SDL_SetError("select() in NTO_WaitAudio failed: %s\n", strerror(errno));
202 return; 189 break;
203 } 190 default:
204 191 if(FD_ISSET(audio_fd, &wfds))
205 totalbytes = csetup.buf.block.frag_size *csetup.buf.block.frags; 192 return;
206 roomavail = totalbytes - cstatus.count; 193 }
207 194 }
208 #ifdef DEBUG_AUDIO 195
209 fprintf(stderr,"NTO_WaitAudio roomavail %d pcm_len %d\n",roomavail,pcm_len); 196 static void NTO_PlayAudio(_THIS)
210 #endif 197 {
211 198 int written, rval;
212 if ((roomavail >= pcm_len) || (roomavail < 0)) 199 int towrite;
200
201 #ifdef DEBUG_AUDIO
202 fprintf(stderr, "NTO_PlayAudio\n");
203 #endif
204
205 if( !this->enabled){
213 return; 206 return;
214 207 }
215 SDL_Delay(10);
216 }
217
218 }
219
220
221
222 static void NTO_PlayAudio(_THIS)
223 {
224 int written, rval;
225 int towrite;
226
227 #ifdef DEBUG_AUDIO
228 fprintf(stderr, "NTO_PlayAudio\n");
229 #endif
230
231 if( !this->enabled)
232 return;
233 208
234 towrite = pcm_len; 209 towrite = pcm_len;
235 210
236 211 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */
237 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ 212 do {
238 do {
239 written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite); 213 written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite);
240 #ifdef DEBUG_AUDIO 214 #ifdef DEBUG_AUDIO
241 fprintf(stderr, "NTO_PlayAudio: written = %d towrite = %d\n",written,towrite); 215 fprintf(stderr, "NTO_PlayAudio: written = %d towrite = %d\n",written,towrite);
242 #endif 216 #endif
243 if (written != towrite) 217 if (written != towrite){
244 { 218 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)){
245 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) 219 SDL_Delay(1); /* Let a little CPU time go by and try to write again */
246 { 220 #ifdef DEBUG_AUDIO
247 SDL_Delay(1); /* Let a little CPU time go by and try to write again */
248 #ifdef DEBUG_AUDIO
249 fprintf(stderr, "errno == EAGAIN written %d\n", written); 221 fprintf(stderr, "errno == EAGAIN written %d\n", written);
222 #endif
250 towrite -= written; //we wrote some data 223 towrite -= written; //we wrote some data
251 #endif
252 continue; 224 continue;
253 } 225 }
254 else if((errno == EINVAL) || (errno == EIO)) 226 else if((errno == EINVAL) || (errno == EIO)){
255 { 227 if(errno == EIO){
256 #ifdef DEBUG_AUDIO 228 #ifdef DEBUG_AUDIO
257 if(errno == EIO) 229 fprintf(stderr,"snd_pcm_plugin_write failed EIO: %s\n", snd_strerror(written));
258 fprintf(stderr,"snd_pcm_plugin_write failed EIO: %s\n", snd_strerror(written)); 230 #endif
259 if(errno == EINVAL) 231 }
260 fprintf(stderr,"snd_pcm_plugin_write failed EINVAL: %s\n", snd_strerror(written)); 232 if(errno == EINVAL){
261 233 #ifdef DEBUG_AUDIO
262 #endif 234 fprintf(stderr,"snd_pcm_plugin_write failed EINVAL: %s\n", snd_strerror(written));
263 235 #endif
264 memset(&cstatus, 0, sizeof(cstatus)); 236 }
265 if( (rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0 ) 237
266 { 238 memset(&cstatus, 0, sizeof(cstatus));
267 #ifdef DEBUG_AUDIO 239 if( (rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0 ){
240 #ifdef DEBUG_AUDIO
268 fprintf(stderr, "snd_pcm_plugin_status failed %s\n",snd_strerror(rval)); 241 fprintf(stderr, "snd_pcm_plugin_status failed %s\n",snd_strerror(rval));
269 #endif 242 #endif
270 SDL_SetError("snd_pcm_plugin_status failed: %s\n", snd_strerror(rval)); 243 SDL_SetError("snd_pcm_plugin_status failed: %s\n", snd_strerror(rval));
271 return; 244 return;
272 } 245 }
273 246
274 if ( (cstatus.status == SND_PCM_STATUS_UNDERRUN) || 247 if ( (cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY) ){
275 (cstatus.status == SND_PCM_STATUS_READY) ) 248 #ifdef DEBUG_AUDIO
276 {
277 #ifdef DEBUG_AUDIO
278 fprintf(stderr, "buffer underrun\n"); 249 fprintf(stderr, "buffer underrun\n");
279 #endif 250 #endif
280 if ( (rval = snd_pcm_plugin_prepare (audio_handle,SND_PCM_CHANNEL_PLAYBACK)) < 0 ) 251 if ( (rval = snd_pcm_plugin_prepare (audio_handle,SND_PCM_CHANNEL_PLAYBACK)) < 0 ){
281 { 252 #ifdef DEBUG_AUDIO
282 #ifdef DEBUG_AUDIO
283 fprintf(stderr, "NTO_PlayAudio: prepare failed %s\n",snd_strerror(rval)); 253 fprintf(stderr, "NTO_PlayAudio: prepare failed %s\n",snd_strerror(rval));
284 #endif 254 #endif
285 SDL_SetError("snd_pcm_plugin_prepare failed: %s\n",snd_strerror(rval) ); 255 SDL_SetError("snd_pcm_plugin_prepare failed: %s\n",snd_strerror(rval) );
286 return; 256 return;
287 } 257 }
288
289 } 258 }
290 continue; 259 continue;
291 } 260 }
292 else 261 else{
293 { 262 #ifdef DEBUG_AUDIO
294 #ifdef DEBUG_AUDIO 263 fprintf(stderr, "NTO_PlayAudio: snd_pcm_plugin_write failed unknown errno %d %s\n",errno, snd_strerror(rval));
295 fprintf(stderr, "NTO_PlayAudio: snd_pcm_plugin_write failed unknown errno %d %s\n",errno, snd_strerror(rval)); 264 #endif
296 #endif
297 return; 265 return;
298
299 } 266 }
300 267
301 } 268 }
302 else 269 else
303 { 270 {
304 towrite -= written; //we wrote all remaining data 271 towrite -= written; //we wrote all remaining data
305 } 272 }
306 } while ( (towrite > 0) && (this->enabled) ); 273 } while ( (towrite > 0) && (this->enabled) );
307 274
308 /* If we couldn't write, assume fatal error for now */ 275 /* If we couldn't write, assume fatal error for now */
309 if ( towrite != 0 ) { 276 if ( towrite != 0 ) {
310 this->enabled = 0; 277 this->enabled = 0;
311 } 278 }
312 return; 279 return;
313 } 280 }
314 281
315 static Uint8 *NTO_GetAudioBuf(_THIS) 282 static Uint8 *NTO_GetAudioBuf(_THIS)
316 { 283 {
317 #ifdef DEBUG_AUDIO 284 #ifdef DEBUG_AUDIO
318 fprintf(stderr, "NTO_GetAudioBuf: pcm_buf %X\n",(Uint8 *)pcm_buf); 285 fprintf(stderr, "NTO_GetAudioBuf: pcm_buf %X\n",(Uint8 *)pcm_buf);
319 #endif 286 #endif
320 return(pcm_buf); 287 return(pcm_buf);
321 } 288 }
322 289
323 static void NTO_CloseAudio(_THIS) 290 static void NTO_CloseAudio(_THIS)
324 { 291 {
325 int rval; 292 int rval;
326 293
327 #ifdef DEBUG_AUDIO 294 #ifdef DEBUG_AUDIO
328 fprintf(stderr, "NTO_CloseAudio\n"); 295 fprintf(stderr, "NTO_CloseAudio\n");
329 #endif 296 #endif
330 297
331 this->enabled = 0; 298 this->enabled = 0;
332 299
333 if ( audio_handle != NULL ) { 300 if ( audio_handle != NULL ) {
334 if ((rval = snd_pcm_plugin_flush(audio_handle,SND_PCM_CHANNEL_PLAYBACK)) < 0) 301 if ((rval = snd_pcm_plugin_flush(audio_handle,SND_PCM_CHANNEL_PLAYBACK)) < 0){
335 { 302 SDL_SetError("snd_pcm_plugin_flush failed: %s\n",snd_strerror(rval));
336 SDL_SetError("snd_pcm_plugin_flush failed: %s\n",snd_strerror(rval));
337 return; 303 return;
338 } 304 }
339 if ((rval = snd_pcm_close(audio_handle)) < 0) 305 if ((rval = snd_pcm_close(audio_handle)) < 0){
340 {
341 SDL_SetError("snd_pcm_close failed: %s\n",snd_strerror(rval)); 306 SDL_SetError("snd_pcm_close failed: %s\n",snd_strerror(rval));
342 return; 307 return;
343 } 308 }
344 audio_handle = NULL; 309 audio_handle = NULL;
345 } 310 }
351 int format; 316 int format;
352 Uint16 test_format; 317 Uint16 test_format;
353 int twidth; 318 int twidth;
354 int found; 319 int found;
355 320
356 #ifdef DEBUG_AUDIO 321 #ifdef DEBUG_AUDIO
357 fprintf(stderr, "NTO_OpenAudio\n"); 322 fprintf(stderr, "NTO_OpenAudio\n");
358 #endif 323 #endif
359 324
360 audio_handle = NULL; 325 audio_handle = NULL;
361 this->enabled = 0; 326 this->enabled = 0;
362 327
363 if ( pcm_buf != NULL ) { 328 if ( pcm_buf != NULL ) {
364 free((Uint8 *)pcm_buf); 329 free((Uint8 *)pcm_buf);
365 pcm_buf = NULL; 330 pcm_buf = NULL;
366 } 331 }
367 332
368 /* initialize channel transfer parameters to default */ 333 /* initialize channel transfer parameters to default */
369 init_pcm_cparams(&cparams); 334 init_pcm_cparams(&cparams);
370 335
371 /* Open the audio device */ 336 /* Open the audio device */
372 337 rval = snd_pcm_open_preferred(&audio_handle, NULL, NULL, OPEN_FLAGS);
373 rval = snd_pcm_open_preferred(&audio_handle, &card_no, &device_no, OPEN_FLAGS);
374 if ( rval < 0 ) { 338 if ( rval < 0 ) {
375 SDL_SetError("snd_pcm_open failed: %s\n", snd_strerror(rval)); 339 SDL_SetError("snd_pcm_open failed: %s\n", snd_strerror(rval));
376 return(-1); 340 return(-1);
377 } 341 }
378 342
379 /* set to nonblocking mode */ 343 /* enable count status parameter */
380 if ((rval = snd_pcm_nonblock_mode(audio_handle, 1))<0) //I assume 1 means on 344 if ((rval = snd_pcm_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP))<0){
381 { 345 SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rval));
382 SDL_SetError("snd_pcm_nonblock_mode failed: %s\n", snd_strerror(rval)); 346 return(-1);
383 return(-1); 347 }
384 }
385
386 /* enable count status parameter */
387 if ((rval = snd_pcm_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP))<0)
388 {
389 SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rval));
390 return(-1);
391 }
392
393 348
394 /* Try for a closest match on audio format */ 349 /* Try for a closest match on audio format */
395 format = 0; 350 format = 0;
396 found = 0; // can't use format as SND_PCM_SFMT_U8 = 0 in nto 351 found = 0; /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */
397 for ( test_format = SDL_FirstAudioFormat(spec->format); !found ; ) 352 for ( test_format = SDL_FirstAudioFormat(spec->format); !found ; )
398
399 { 353 {
400 #ifdef DEBUG_AUDIO 354 #ifdef DEBUG_AUDIO
401 fprintf(stderr, "Trying format 0x%4.4x spec->samples %d\n", test_format,spec->samples); 355 fprintf(stderr, "Trying format 0x%4.4x spec->samples %d\n", test_format,spec->samples);
402 #endif 356 #endif
403 /* if match found set format to equivalent ALSA format */ 357
404 switch ( test_format ) { 358 /* if match found set format to equivalent ALSA format */
359 switch ( test_format ) {
405 case AUDIO_U8: 360 case AUDIO_U8:
406 format = SND_PCM_SFMT_U8; 361 format = SND_PCM_SFMT_U8;
407 cparams.buf.block.frag_size = spec->samples * spec->channels;
408 found = 1; 362 found = 1;
409 break; 363 break;
410 case AUDIO_S8: 364 case AUDIO_S8:
411 format = SND_PCM_SFMT_S8; 365 format = SND_PCM_SFMT_S8;
412 cparams.buf.block.frag_size = spec->samples * spec->channels;
413 found = 1; 366 found = 1;
414 break; 367 break;
415 case AUDIO_S16LSB: 368 case AUDIO_S16LSB:
416 format = SND_PCM_SFMT_S16_LE; 369 format = SND_PCM_SFMT_S16_LE;
417 cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
418 found = 1; 370 found = 1;
419 break; 371 break;
420 case AUDIO_S16MSB: 372 case AUDIO_S16MSB:
421 format = SND_PCM_SFMT_S16_BE; 373 format = SND_PCM_SFMT_S16_BE;
422 cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
423 found = 1; 374 found = 1;
424 break; 375 break;
425 case AUDIO_U16LSB: 376 case AUDIO_U16LSB:
426 format = SND_PCM_SFMT_U16_LE; 377 format = SND_PCM_SFMT_U16_LE;
427 cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
428 found = 1; 378 found = 1;
429 break; 379 break;
430 case AUDIO_U16MSB: 380 case AUDIO_U16MSB:
431 format = SND_PCM_SFMT_U16_BE; 381 format = SND_PCM_SFMT_U16_BE;
432 cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
433 found = 1; 382 found = 1;
434 break; 383 break;
435 default: 384 default:
436 break; 385 break;
437 } 386 }
438 if ( ! found ) { 387 if ( ! found ) {
439 test_format = SDL_NextAudioFormat(); 388 test_format = SDL_NextAudioFormat();
440 } 389 }
441 } 390 }
442 391
443 /* assumes test_format not 0 on success */ 392 /* assumes test_format not 0 on success */
444 if ( test_format == 0 ) { 393 if ( test_format == 0 ) {
445 SDL_SetError("Couldn't find any hardware audio formats"); 394 SDL_SetError("Couldn't find any hardware audio formats");
446 return(-1); 395 return(-1);
447 } 396 }
448 397
449 spec->format = test_format; 398 spec->format = test_format;
450 399
451 /* Set the audio format */ 400 /* Set the audio format */
452 cparams.format.format = format; 401 cparams.format.format = format;
453 402
454 /* Set mono or stereo audio (currently only two channels supported) */ 403 /* Set mono or stereo audio (currently only two channels supported) */
455 cparams.format.voices = spec->channels; 404 cparams.format.voices = spec->channels;
456 405
457 #ifdef DEBUG_AUDIO 406 #ifdef DEBUG_AUDIO
458 fprintf(stderr,"intializing channels %d\n", cparams.format.voices); 407 fprintf(stderr,"intializing channels %d\n", cparams.format.voices);
459 #endif 408 #endif
460 409
461
462 /* Set rate */ 410 /* Set rate */
463 cparams.format.rate = spec->freq ; 411 cparams.format.rate = spec->freq ;
464 412
465 /* Setup the transfer parameters according to cparams */ 413 /* Setup the transfer parameters according to cparams */
466 rval = snd_pcm_plugin_params(audio_handle, &cparams); 414 rval = snd_pcm_plugin_params(audio_handle, &cparams);
467 if (rval < 0) { 415 if (rval < 0) {
468 SDL_SetError("snd_pcm_channel_params failed: %s\n", snd_strerror (rval)); 416 SDL_SetError("snd_pcm_channel_params failed: %s\n", snd_strerror (rval));
469 return(-1); 417 return(-1);
470 } 418 }
471 419
472 /* Make sure channel is setup right one last time */ 420 /* Make sure channel is setup right one last time */
473 memset( &csetup, 0, sizeof( csetup ) ); 421 memset( &csetup, 0, sizeof( csetup ) );
474 csetup.channel = SND_PCM_CHANNEL_PLAYBACK; 422 csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
475 if ( snd_pcm_plugin_setup( audio_handle, &csetup ) < 0 ) 423 if ( snd_pcm_plugin_setup( audio_handle, &csetup ) < 0 )
476 { 424 {
477 SDL_SetError("Unable to setup playback channel\n" ); 425 SDL_SetError("Unable to setup playback channel\n" );
478 return(-1); 426 return(-1);
479 } 427 }
480 else 428 else
481 { 429 {
482 #ifdef DEBUG_AUDIO 430 #ifdef DEBUG_AUDIO
483 fprintf(stderr,"requested format: %d\n",cparams.format.format); 431 fprintf(stderr,"requested format: %d\n",cparams.format.format);
484 fprintf(stderr,"requested frag size: %d\n",cparams.buf.block.frag_size); 432 fprintf(stderr,"requested frag size: %d\n",cparams.buf.block.frag_size);
485 fprintf(stderr,"requested max frags: %d\n\n",cparams.buf.block.frags_max); 433 fprintf(stderr,"requested max frags: %d\n\n",cparams.buf.block.frags_max);
486 434
487 fprintf(stderr,"real format: %d\n", csetup.format.format ); 435 fprintf(stderr,"real format: %d\n", csetup.format.format );
488 fprintf(stderr,"real frag size : %d\n", csetup.buf.block.frag_size ); 436 fprintf(stderr,"real frag size : %d\n", csetup.buf.block.frag_size );
489 fprintf(stderr,"real max frags : %d\n", csetup.buf.block.frags_max ); 437 fprintf(stderr,"real max frags : %d\n", csetup.buf.block.frags_max );
490 #endif // DEBUG_AUDIO 438 #endif
491 } 439 }
492 440
493 441 /*
494 /* Allocate memory to the audio buffer and initialize with silence 442 Allocate memory to the audio buffer and initialize with silence (Note that
495 (Note that buffer size must be a multiple of fragment size, so find closest multiple) 443 buffer size must be a multiple of fragment size, so find closest multiple)
496 */ 444 */
497 445
498 twidth = snd_pcm_format_width(format); 446 twidth = snd_pcm_format_width(format);
499 if (twidth < 0) { 447 if (twidth < 0) {
500 printf("snd_pcm_format_width failed\n"); 448 printf("snd_pcm_format_width failed\n");
501 twidth = 0; 449 twidth = 0;
502 } 450 }
503 451
504 #ifdef DEBUG_AUDIO 452 #ifdef DEBUG_AUDIO
505 fprintf(stderr,"format is %d bits wide\n",twidth); 453 fprintf(stderr,"format is %d bits wide\n",twidth);
506 #endif 454 #endif
507 455
508 pcm_len = spec->size ; 456 pcm_len = spec->size ;
509 457
510 458 #ifdef DEBUG_AUDIO
511 #ifdef DEBUG_AUDIO 459 fprintf(stderr,"pcm_len set to %d\n", pcm_len);
512 fprintf(stderr,"pcm_len set to %d\n", pcm_len); 460 #endif
513 #endif 461
514 462 if (pcm_len == 0){
515 if (pcm_len == 0) 463 pcm_len = csetup.buf.block.frag_size;
516 { 464 }
517 pcm_len = csetup.buf.block.frag_size; 465
518 } 466 pcm_buf = (Uint8*)malloc(pcm_len);
519 467 if (pcm_buf == NULL) {
520 pcm_buf = (Uint8*)malloc(pcm_len); 468 SDL_SetError("pcm_buf malloc failed\n");
521 if (pcm_buf == NULL) { 469 return(-1);
522 SDL_SetError("pcm_buf malloc failed\n"); 470 }
523 return(-1); 471 memset(pcm_buf,spec->silence,pcm_len);
524 } 472
525 memset(pcm_buf,spec->silence,pcm_len); 473 #ifdef DEBUG_AUDIO
526
527 #ifdef DEBUG_AUDIO
528 fprintf(stderr,"pcm_buf malloced and silenced.\n"); 474 fprintf(stderr,"pcm_buf malloced and silenced.\n");
529 #endif 475 #endif
530 476
531 /* get the file descriptor */ 477 /* get the file descriptor */
532 if( (audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) 478 if( (audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0){
533 { 479 fprintf(stderr, "snd_pcm_file_descriptor failed with error code: %d\n", audio_fd);
534 fprintf(stderr, "snd_pcm_file_descriptor failed with error code: %d\n", audio_fd); 480 }
535 }
536 481
537 /* Trigger audio playback */ 482 /* Trigger audio playback */
538 rval = snd_pcm_plugin_prepare( audio_handle, SND_PCM_CHANNEL_PLAYBACK); 483 rval = snd_pcm_plugin_prepare( audio_handle, SND_PCM_CHANNEL_PLAYBACK);
539 if (rval < 0) { 484 if (rval < 0) {
540 SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rval)); 485 SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rval));
541 return(-1); 486 return(-1);
542 } 487 }
543 488
544 this->enabled = 1; 489 this->enabled = 1;
545 490
546 /* Get the parent process id (we're the parent of the audio thread) */ 491 /* Get the parent process id (we're the parent of the audio thread) */
547 parent = getpid(); 492 parent = getpid();
548 493
549 /* We're ready to rock and roll. :-) */ 494 /* We're ready to rock and roll. :-) */
550 return(0); 495 return(0);
551 } 496 }
552 497
553
554