Mercurial > sdl-ios-xcode
comparison src/audio/mint/SDL_mintaudio_xbios.c @ 2049:5f6550e5184f
Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Tue, 17 Oct 2006 09:15:21 +0000 |
parents | adf732f1f016 |
children | 866052b01ee5 |
comparison
equal
deleted
inserted
replaced
2048:6067c7f9a672 | 2049:5f6550e5184f |
---|---|
58 } | 58 } |
59 #else | 59 #else |
60 #define DEBUG_PRINT(what) | 60 #define DEBUG_PRINT(what) |
61 #endif | 61 #endif |
62 | 62 |
63 /*--- Static variables ---*/ | 63 static unsigned long cookie_snd = 0; |
64 | 64 |
65 static unsigned long cookie_snd; | 65 static void |
66 | 66 MINTXBIOS_LockDevice(_THIS) |
67 /*--- Audio driver functions ---*/ | |
68 | |
69 static void Mint_CloseAudio(_THIS); | |
70 static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec); | |
71 static void Mint_LockAudio(_THIS); | |
72 static void Mint_UnlockAudio(_THIS); | |
73 | |
74 /* To check/init hardware audio */ | |
75 static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec); | |
76 static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec); | |
77 | |
78 /*--- Audio driver bootstrap functions ---*/ | |
79 | |
80 static int | |
81 Audio_Available(void) | |
82 { | |
83 unsigned long dummy; | |
84 const char *envr = SDL_getenv("SDL_AUDIODRIVER"); | |
85 | |
86 /*SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); */ | |
87 SDL_MintAudio_mint_present = SDL_FALSE; | |
88 | |
89 /* We can't use XBIOS in interrupt with Magic, don't know about thread */ | |
90 if (Getcookie(C_MagX, &dummy) == C_FOUND) { | |
91 return (0); | |
92 } | |
93 | |
94 /* Check if user asked a different audio driver */ | |
95 if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) { | |
96 DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); | |
97 return (0); | |
98 } | |
99 | |
100 /* Cookie _SND present ? if not, assume ST machine */ | |
101 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { | |
102 cookie_snd = SND_PSG; | |
103 } | |
104 | |
105 /* Check if we have 16 bits audio */ | |
106 if ((cookie_snd & SND_16BIT) == 0) { | |
107 DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n")); | |
108 return (0); | |
109 } | |
110 | |
111 /* Check if audio is lockable */ | |
112 if (Locksnd() != 1) { | |
113 DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n")); | |
114 return (0); | |
115 } | |
116 | |
117 Unlocksnd(); | |
118 | |
119 DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n")); | |
120 return (1); | |
121 } | |
122 | |
123 static void | |
124 Audio_DeleteDevice(SDL_AudioDevice * device) | |
125 { | |
126 SDL_free(device->hidden); | |
127 SDL_free(device); | |
128 } | |
129 | |
130 static SDL_AudioDevice * | |
131 Audio_CreateDevice(int devindex) | |
132 { | |
133 SDL_AudioDevice *this; | |
134 | |
135 /* Initialize all variables that we clean on shutdown */ | |
136 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); | |
137 if (this) { | |
138 SDL_memset(this, 0, (sizeof *this)); | |
139 this->hidden = (struct SDL_PrivateAudioData *) | |
140 SDL_malloc((sizeof *this->hidden)); | |
141 } | |
142 if ((this == NULL) || (this->hidden == NULL)) { | |
143 SDL_OutOfMemory(); | |
144 if (this) { | |
145 SDL_free(this); | |
146 } | |
147 return (0); | |
148 } | |
149 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
150 | |
151 /* Set the function pointers */ | |
152 this->OpenAudio = Mint_OpenAudio; | |
153 this->CloseAudio = Mint_CloseAudio; | |
154 this->LockAudio = Mint_LockAudio; | |
155 this->UnlockAudio = Mint_UnlockAudio; | |
156 this->free = Audio_DeleteDevice; | |
157 | |
158 return this; | |
159 } | |
160 | |
161 AudioBootStrap MINTAUDIO_XBIOS_bootstrap = { | |
162 MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver", | |
163 Audio_Available, Audio_CreateDevice | |
164 }; | |
165 | |
166 static void | |
167 Mint_LockAudio(_THIS) | |
168 { | 67 { |
169 /* Stop replay */ | 68 /* Stop replay */ |
170 Buffoper(0); | 69 Buffoper(0); |
171 } | 70 } |
172 | 71 |
173 static void | 72 static void |
174 Mint_UnlockAudio(_THIS) | 73 MINTXBIOS_UnlockDevice(_THIS) |
175 { | 74 { |
176 /* Restart replay */ | 75 /* Restart replay */ |
177 Buffoper(SB_PLA_ENA | SB_PLA_RPT); | 76 Buffoper(SB_PLA_ENA | SB_PLA_RPT); |
178 } | 77 } |
179 | 78 |
180 static void | 79 static void |
181 Mint_CloseAudio(_THIS) | 80 MINTXBIOS_CloseDevice(_THIS) |
182 { | 81 { |
183 /* Stop replay */ | 82 if (this->hidden != NULL) { |
184 SDL_MintAudio_WaitThread(); | 83 /* Stop replay */ |
185 Buffoper(0); | 84 SDL_MintAudio_WaitThread(); |
186 | 85 Buffoper(0); |
187 if (!SDL_MintAudio_mint_present) { | 86 |
188 /* Uninstall interrupt */ | 87 if (!SDL_MintAudio_mint_present) { |
189 Jdisint(MFP_DMASOUND); | 88 /* Uninstall interrupt */ |
190 } | 89 Jdisint(MFP_DMASOUND); |
191 | 90 } |
192 /* Wait if currently playing sound */ | 91 |
193 while (SDL_MintAudio_mutex != 0) { | 92 /* Wait if currently playing sound */ |
194 } | 93 while (SDL_MintAudio_mutex != 0) {} |
195 | 94 |
196 /* Clear buffers */ | 95 /* Clear buffers */ |
197 if (SDL_MintAudio_audiobuf[0]) { | 96 if (SDL_MintAudio_audiobuf[0]) { |
198 Mfree(SDL_MintAudio_audiobuf[0]); | 97 Mfree(SDL_MintAudio_audiobuf[0]); |
199 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; | 98 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; |
200 } | 99 } |
201 | 100 |
202 /* Unlock sound system */ | 101 /* Unlock sound system */ |
203 Unlocksnd(); | 102 Unlocksnd(); |
103 | |
104 SDL_free(this->hidden); | |
105 this->hidden = NULL; | |
106 } | |
204 } | 107 } |
205 | 108 |
206 /* Falcon XBIOS implementation of Devconnect() is buggy with external clock */ | 109 /* Falcon XBIOS implementation of Devconnect() is buggy with external clock */ |
207 static void | 110 static void |
208 Devconnect2(int src, int dst, int sclk, int pre) | 111 Devconnect2(int src, int dst, int sclk, int pre) |
267 | 170 |
268 Super(oldstack); | 171 Super(oldstack); |
269 } | 172 } |
270 | 173 |
271 static void | 174 static void |
272 Mint_CheckExternalClock(_THIS) | 175 MINTXBIOS_CheckExternalClock(_THIS) |
273 { | 176 { |
274 #define SIZE_BUF_CLOCK_MEASURE (44100/10) | 177 #define SIZE_BUF_CLOCK_MEASURE (44100/10) |
275 | 178 |
276 unsigned long cookie_snd; | 179 unsigned long cookie_snd; |
277 char *buffer; | 180 char *buffer; |
353 | 256 |
354 Mfree(buffer); | 257 Mfree(buffer); |
355 } | 258 } |
356 | 259 |
357 static int | 260 static int |
358 Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) | 261 MINTXBIOS_CheckAudio(_THIS) |
359 { | 262 { |
360 int i; | 263 int i; |
361 Uint32 extclock; | 264 Uint32 extclock; |
362 | 265 |
363 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", | 266 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", |
364 SDL_AUDIO_BITSIZE(spec->format))); | 267 SDL_AUDIO_BITSIZE(this->spec.format))); |
365 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); | 268 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); |
366 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); | 269 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); |
367 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); | 270 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); |
368 DEBUG_PRINT(("channels=%d, ", spec->channels)); | 271 DEBUG_PRINT(("channels=%d, ", this->spec.channels)); |
369 DEBUG_PRINT(("freq=%d\n", spec->freq)); | 272 DEBUG_PRINT(("freq=%d\n", this->spec.freq)); |
370 | 273 |
371 spec->format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */ | 274 this->spec.format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */ |
372 | 275 |
373 /* clamp out int32/float32 */ | 276 /* clamp out int32/float32 */ |
374 if (SDL_AUDIO_BITSIZE(spec->format) >= 16) { | 277 if (SDL_AUDIO_BITSIZE(this->spec.format) >= 16) { |
375 spec->format = AUDIO_S16MSB; /* Audio is always big endian */ | 278 this->spec.format = AUDIO_S16MSB; /* Audio is always big endian */ |
376 spec->channels = 2; /* 16 bits always stereo */ | 279 this->spec.channels = 2; /* 16 bits always stereo */ |
377 } else if (spec->channels > 2) { | 280 } else if (this->spec.channels > 2) { |
378 spec->channels = 2; /* no more than stereo! */ | 281 this->spec.channels = 2; /* no more than stereo! */ |
379 } | 282 } |
380 | 283 |
381 MINTAUDIO_freqcount = 0; | 284 MINTAUDIO_freqcount = 0; |
382 | 285 |
383 /* Add external clocks if present */ | 286 /* Add external clocks if present */ |
384 Mint_CheckExternalClock(this); | 287 MINTXBIOS_CheckExternalClock(this); |
385 | 288 |
386 /* Standard clocks */ | 289 /* Standard clocks */ |
387 for (i = 1; i < 12; i++) { | 290 for (i = 1; i < 12; i++) { |
388 /* Remove unusable Falcon codec predivisors */ | 291 /* Remove unusable Falcon codec predivisors */ |
389 if ((i == 6) || (i == 8) || (i == 10)) { | 292 if ((i == 6) || (i == 8) || (i == 10)) { |
402 MINTAUDIO_frequencies[i].masterclock, | 305 MINTAUDIO_frequencies[i].masterclock, |
403 MINTAUDIO_frequencies[i].predivisor)); | 306 MINTAUDIO_frequencies[i].predivisor)); |
404 } | 307 } |
405 #endif | 308 #endif |
406 | 309 |
407 MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq); | 310 MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq); |
408 spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; | 311 this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; |
409 | 312 |
410 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ", | 313 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ", |
411 SDL_AUDIO_BITSIZE(spec->format))); | 314 SDL_AUDIO_BITSIZE(this->spec.format))); |
412 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); | 315 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); |
413 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); | 316 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); |
414 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); | 317 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); |
415 DEBUG_PRINT(("channels=%d, ", spec->channels)); | 318 DEBUG_PRINT(("channels=%d, ", this->spec.channels)); |
416 DEBUG_PRINT(("freq=%d\n", spec->freq)); | 319 DEBUG_PRINT(("freq=%d\n", this->spec.freq)); |
417 | 320 |
418 return 0; | 321 return 0; |
419 } | 322 } |
420 | 323 |
421 static void | 324 static void |
422 Mint_InitAudio(_THIS, SDL_AudioSpec * spec) | 325 MINTXBIOS_InitAudio(_THIS) |
423 { | 326 { |
424 int channels_mode, dmaclock, prediv; | 327 int channels_mode, dmaclock, prediv; |
425 void *buffer; | 328 void *buffer; |
426 | 329 |
427 /* Stop currently playing sound */ | 330 /* Stop currently playing sound */ |
434 Settracks(0, 0); | 337 Settracks(0, 0); |
435 Setmontracks(0); | 338 Setmontracks(0); |
436 | 339 |
437 /* Select replay format */ | 340 /* Select replay format */ |
438 channels_mode = STEREO16; | 341 channels_mode = STEREO16; |
439 switch (SDL_AUDIO_BITSIZE(spec->format)) { | 342 switch (SDL_AUDIO_BITSIZE(this->spec.format)) { |
440 case 8: | 343 case 8: |
441 if (spec->channels == 2) { | 344 if (this->spec.channels == 2) { |
442 channels_mode = STEREO8; | 345 channels_mode = STEREO8; |
443 } else { | 346 } else { |
444 channels_mode = MONO8; | 347 channels_mode = MONO8; |
445 } | 348 } |
446 break; | 349 break; |
459 Devconnect2(DMAPLAY, DAC, CLK25M, prediv); | 362 Devconnect2(DMAPLAY, DAC, CLK25M, prediv); |
460 } | 363 } |
461 | 364 |
462 /* Set buffer */ | 365 /* Set buffer */ |
463 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; | 366 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; |
464 if (Setbuffer(0, buffer, buffer + spec->size) < 0) { | 367 if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) { |
465 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); | 368 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); |
466 } | 369 } |
467 | 370 |
468 if (SDL_MintAudio_mint_present) { | 371 if (SDL_MintAudio_mint_present) { |
469 SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0); | 372 SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0); |
483 Buffoper(SB_PLA_ENA | SB_PLA_RPT); | 386 Buffoper(SB_PLA_ENA | SB_PLA_RPT); |
484 DEBUG_PRINT((DEBUG_NAME "hardware initialized\n")); | 387 DEBUG_PRINT((DEBUG_NAME "hardware initialized\n")); |
485 } | 388 } |
486 | 389 |
487 static int | 390 static int |
488 Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) | 391 MINTXBIOS_OpenDevice(_THIS, const char *devname, int iscapture) |
489 { | 392 { |
490 /* Lock sound system */ | 393 /* Lock sound system */ |
491 if (Locksnd() != 1) { | 394 if (Locksnd() != 1) { |
492 SDL_SetError("Mint_OpenAudio: Audio system already in use"); | 395 SDL_SetError("MINTXBIOS_OpenAudio: Audio system already in use"); |
493 return (-1); | 396 return 0; |
494 } | 397 } |
495 | 398 |
496 SDL_MintAudio_device = this; | 399 SDL_MintAudio_device = this; |
497 | 400 |
498 /* Check audio capabilities */ | 401 /* Check audio capabilities */ |
499 if (Mint_CheckAudio(this, spec) == -1) { | 402 if (MINTXBIOS_CheckAudio(this) == -1) { |
500 return -1; | 403 return 0; |
501 } | 404 } |
502 | 405 |
503 SDL_CalculateAudioSpec(spec); | 406 /* Initialize all variables that we clean on shutdown */ |
407 this->hidden = (struct SDL_PrivateAudioData *) | |
408 SDL_malloc((sizeof *this->hidden)); | |
409 if (this->hidden == NULL) { | |
410 SDL_OutOfMemory(); | |
411 return 0; | |
412 } | |
413 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
414 | |
415 SDL_CalculateAudioSpec(&this->spec); | |
504 | 416 |
505 /* Allocate memory for audio buffers in DMA-able RAM */ | 417 /* Allocate memory for audio buffers in DMA-able RAM */ |
506 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); | 418 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size)); |
507 | 419 |
508 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM); | 420 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM); |
509 if (SDL_MintAudio_audiobuf[0] == NULL) { | 421 if (SDL_MintAudio_audiobuf[0] == NULL) { |
510 SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); | 422 SDL_free(this->hidden); |
511 return (-1); | 423 this->hidden = NULL; |
512 } | 424 SDL_OutOfMemory(); |
513 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size; | 425 return 0; |
426 } | |
427 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size; | |
514 SDL_MintAudio_numbuf = 0; | 428 SDL_MintAudio_numbuf = 0; |
515 SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2); | 429 SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2); |
516 SDL_MintAudio_audiosize = spec->size; | 430 SDL_MintAudio_audiosize = this->spec.size; |
517 SDL_MintAudio_mutex = 0; | 431 SDL_MintAudio_mutex = 0; |
518 | 432 |
519 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", | 433 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", |
520 SDL_MintAudio_audiobuf[0])); | 434 SDL_MintAudio_audiobuf[0])); |
521 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", | 435 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", |
522 SDL_MintAudio_audiobuf[1])); | 436 SDL_MintAudio_audiobuf[1])); |
523 | 437 |
524 SDL_MintAudio_CheckFpu(); | 438 SDL_MintAudio_CheckFpu(); |
525 | 439 |
526 /* Setup audio hardware */ | 440 /* Setup audio hardware */ |
527 Mint_InitAudio(this, spec); | 441 MINTXBIOS_InitAudio(this); |
528 | 442 |
529 return (1); /* We don't use SDL threaded audio */ | 443 return 1; /* good to go. */ |
530 } | 444 } |
445 | |
446 static int | |
447 MINTXBIOS_Init(SDL_AudioDriverImpl *impl) | |
448 { | |
449 unsigned long dummy = 0; | |
450 /*SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); */ | |
451 SDL_MintAudio_mint_present = SDL_FALSE; | |
452 | |
453 /* We can't use XBIOS in interrupt with Magic, don't know about thread */ | |
454 if (Getcookie(C_MagX, &dummy) == C_FOUND) { | |
455 return (0); | |
456 } | |
457 | |
458 /* Cookie _SND present ? if not, assume ST machine */ | |
459 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { | |
460 cookie_snd = SND_PSG; | |
461 } | |
462 | |
463 /* Check if we have 16 bits audio */ | |
464 if ((cookie_snd & SND_16BIT) == 0) { | |
465 SDL_SetError(DEBUG_NAME "no 16-bit sound"); | |
466 return (0); | |
467 } | |
468 | |
469 /* Check if audio is lockable */ | |
470 if (Locksnd() != 1) { | |
471 SDL_SetError(DEBUG_NAME "audio locked by other application"); | |
472 return (0); | |
473 } | |
474 | |
475 Unlocksnd(); | |
476 | |
477 DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n")); | |
478 | |
479 /* Set the function pointers */ | |
480 impl->OpenDevice = MINTXBIOS_OpenDevice; | |
481 impl->CloseDevice = MINTXBIOS_CloseDevice; | |
482 impl->LockAudio = MINTXBIOS_LockAudio; | |
483 impl->UnlockAudio = MINTXBIOS_UnlockAudio; | |
484 impl->OnlyHasDefaultOutputDevice = 1; | |
485 impl->ProvidesOwnCallbackThread = 1; | |
486 impl->SkipMixerLock = 1; | |
487 | |
488 return 1; | |
489 } | |
490 | |
491 AudioBootStrap MINTAUDIO_XBIOS_bootstrap = { | |
492 MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver", MINTXBIOS_Init, 0 | |
493 }; | |
531 | 494 |
532 /* vi: set ts=4 sw=4 expandtab: */ | 495 /* vi: set ts=4 sw=4 expandtab: */ |