Mercurial > sdl-ios-xcode
comparison src/audio/macrom/SDL_romaudio.c @ 3782:8225ef1f4dee SDL-ryan-multiple-audio-device
Removed the pre-Carbon Mac OS 9 audio code, so Mac OS 8 is officially
unsupported now. :)
The "USE_RYANS_SOUNDCODE" portion, which is what remains, has been the
active codepath for years now without complaint, and was used in several
shipping OS X titles before the CoreAudio support obsoleted it, so it's a
good fallback to keep around for testing if nothing else.
This code should still work on both OS 9, and PowerPC/Intel Mac OS X.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sun, 01 Oct 2006 05:19:16 +0000 |
parents | c27292a690b7 |
children | 37c9c4590689 |
comparison
equal
deleted
inserted
replaced
3781:3a64f57eb3cf | 3782:8225ef1f4dee |
---|---|
19 Sam Lantinga | 19 Sam Lantinga |
20 slouken@libsdl.org | 20 slouken@libsdl.org |
21 */ | 21 */ |
22 #include "SDL_config.h" | 22 #include "SDL_config.h" |
23 | 23 |
24 /* This should work on PowerPC and Intel Mac OS X, and Carbonized Mac OS 9. */ | |
25 | |
24 #if defined(__APPLE__) && defined(__MACH__) | 26 #if defined(__APPLE__) && defined(__MACH__) |
27 # define SDL_MACOS_NAME "Mac OS X" | |
25 # include <Carbon/Carbon.h> | 28 # include <Carbon/Carbon.h> |
26 #elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) | 29 #elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) |
30 # define SDL_MACOS_NAME "Mac OS 9" | |
27 # include <Carbon.h> | 31 # include <Carbon.h> |
28 #else | 32 #else |
33 # define SDL_MACOS_NAME "Mac OS 9" | |
29 # include <Sound.h> /* SoundManager interface */ | 34 # include <Sound.h> /* SoundManager interface */ |
30 # include <Gestalt.h> | 35 # include <Gestalt.h> |
31 # include <DriverServices.h> | 36 # include <DriverServices.h> |
32 #endif | 37 #endif |
33 | 38 |
102 #endif | 107 #endif |
103 return this; | 108 return this; |
104 } | 109 } |
105 | 110 |
106 AudioBootStrap SNDMGR_bootstrap = { | 111 AudioBootStrap SNDMGR_bootstrap = { |
107 "sndmgr", "MacOS SoundManager 3.0", | 112 "sndmgr", SDL_MACOS_NAME " SoundManager", |
108 Audio_Available, Audio_CreateDevice | 113 Audio_Available, Audio_CreateDevice |
109 }; | 114 }; |
110 | |
111 #if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE) | |
112 /* This works correctly on Mac OS X */ | |
113 | 115 |
114 #pragma options align=power | 116 #pragma options align=power |
115 | 117 |
116 static volatile SInt32 audio_is_locked = 0; | 118 static volatile SInt32 audio_is_locked = 0; |
117 static volatile SInt32 need_to_mix = 0; | 119 static volatile SInt32 need_to_mix = 0; |
337 buffer[i] = NULL; | 339 buffer[i] = NULL; |
338 } | 340 } |
339 } | 341 } |
340 } | 342 } |
341 | 343 |
342 #else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */ | |
343 | |
344 static void | |
345 Mac_LockAudio(_THIS) | |
346 { | |
347 /* no-op. */ | |
348 } | |
349 | |
350 static void | |
351 Mac_UnlockAudio(_THIS) | |
352 { | |
353 /* no-op. */ | |
354 } | |
355 | |
356 | |
357 /* This function is called by Sound Manager when it has exhausted one of | |
358 the buffers, so we'll zero it to silence and fill it with audio if | |
359 we're not paused. | |
360 */ | |
361 static pascal void | |
362 sndDoubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr newbuf) | |
363 { | |
364 SDL_AudioDevice *audio = (SDL_AudioDevice *) newbuf->dbUserInfo[0]; | |
365 | |
366 /* If audio is quitting, don't do anything */ | |
367 if (!audio->enabled) { | |
368 return; | |
369 } | |
370 memset(newbuf->dbSoundData, 0, audio->spec.size); | |
371 newbuf->dbNumFrames = audio->spec.samples; | |
372 if (!audio->paused) { | |
373 if (audio->convert.needed) { | |
374 audio->spec.callback(audio->spec.userdata, | |
375 (Uint8 *) audio->convert.buf, | |
376 audio->convert.len); | |
377 SDL_ConvertAudio(&audio->convert); | |
378 #if 0 | |
379 if (audio->convert.len_cvt != audio->spec.size) { | |
380 /* Uh oh... probably crashes here */ ; | |
381 } | |
382 #endif | |
383 SDL_memcpy(newbuf->dbSoundData, audio->convert.buf, | |
384 audio->convert.len_cvt); | |
385 } else { | |
386 audio->spec.callback(audio->spec.userdata, | |
387 (Uint8 *) newbuf->dbSoundData, | |
388 audio->spec.size); | |
389 } | |
390 } | |
391 newbuf->dbFlags |= dbBufferReady; | |
392 } | |
393 | |
394 static int | |
395 DoubleBufferAudio_Available(void) | |
396 { | |
397 int available; | |
398 NumVersion sndversion; | |
399 long response; | |
400 | |
401 available = 0; | |
402 sndversion = SndSoundManagerVersion(); | |
403 if (sndversion.majorRev >= 3) { | |
404 if (Gestalt(gestaltSoundAttr, &response) == noErr) { | |
405 if ((response & (1 << gestaltSndPlayDoubleBuffer))) { | |
406 available = 1; | |
407 } | |
408 } | |
409 } else { | |
410 if (Gestalt(gestaltSoundAttr, &response) == noErr) { | |
411 if ((response & (1 << gestaltHasASC))) { | |
412 available = 1; | |
413 } | |
414 } | |
415 } | |
416 return (available); | |
417 } | |
418 | |
419 static void | |
420 Mac_CloseAudio(_THIS) | |
421 { | |
422 int i; | |
423 | |
424 if (channel != NULL) { | |
425 /* Clean up the audio channel */ | |
426 SndDisposeChannel(channel, true); | |
427 channel = NULL; | |
428 } | |
429 for (i = 0; i < 2; ++i) { | |
430 if (audio_buf[i]) { | |
431 SDL_free(audio_buf[i]); | |
432 audio_buf[i] = NULL; | |
433 } | |
434 } | |
435 } | |
436 | |
437 static int | |
438 Mac_OpenAudio(_THIS, SDL_AudioSpec * spec) | |
439 { | |
440 SndDoubleBufferHeader2 audio_dbh; | |
441 int i; | |
442 long initOptions; | |
443 int sample_bits; | |
444 SndDoubleBackUPP doubleBackProc; | |
445 | |
446 /* Check to make sure double-buffered audio is available */ | |
447 if (!DoubleBufferAudio_Available()) { | |
448 SDL_SetError("Sound manager doesn't support double-buffering"); | |
449 return (-1); | |
450 } | |
451 | |
452 /* Very few conversions are required, but... */ | |
453 switch (spec->format) { | |
454 case AUDIO_S8: | |
455 spec->format = AUDIO_U8; | |
456 break; | |
457 case AUDIO_U16LSB: | |
458 spec->format = AUDIO_S16LSB; | |
459 break; | |
460 case AUDIO_U16MSB: | |
461 spec->format = AUDIO_S16MSB; | |
462 break; | |
463 } | |
464 SDL_CalculateAudioSpec(spec); | |
465 | |
466 /* initialize the double-back header */ | |
467 SDL_memset(&audio_dbh, 0, sizeof(audio_dbh)); | |
468 doubleBackProc = NewSndDoubleBackProc(sndDoubleBackProc); | |
469 sample_bits = spec->size / spec->samples / spec->channels * 8; | |
470 | |
471 audio_dbh.dbhNumChannels = spec->channels; | |
472 audio_dbh.dbhSampleSize = sample_bits; | |
473 audio_dbh.dbhCompressionID = 0; | |
474 audio_dbh.dbhPacketSize = 0; | |
475 audio_dbh.dbhSampleRate = spec->freq << 16; | |
476 audio_dbh.dbhDoubleBack = doubleBackProc; | |
477 audio_dbh.dbhFormat = 0; | |
478 | |
479 /* Note that we install the 16bitLittleEndian Converter if needed. */ | |
480 if (spec->format == 0x8010) { | |
481 audio_dbh.dbhCompressionID = fixedCompression; | |
482 audio_dbh.dbhFormat = k16BitLittleEndianFormat; | |
483 } | |
484 | |
485 /* allocate the 2 double-back buffers */ | |
486 for (i = 0; i < 2; ++i) { | |
487 audio_buf[i] = SDL_calloc(1, sizeof(SndDoubleBuffer) + spec->size); | |
488 if (audio_buf[i] == NULL) { | |
489 SDL_OutOfMemory(); | |
490 return (-1); | |
491 } | |
492 audio_buf[i]->dbNumFrames = spec->samples; | |
493 audio_buf[i]->dbFlags = dbBufferReady; | |
494 audio_buf[i]->dbUserInfo[0] = (long) this; | |
495 audio_dbh.dbhBufferPtr[i] = audio_buf[i]; | |
496 } | |
497 | |
498 /* Create the sound manager channel */ | |
499 channel = (SndChannelPtr) SDL_malloc(sizeof(*channel)); | |
500 if (channel == NULL) { | |
501 SDL_OutOfMemory(); | |
502 return (-1); | |
503 } | |
504 if (spec->channels >= 2) { | |
505 initOptions = initStereo; | |
506 } else { | |
507 initOptions = initMono; | |
508 } | |
509 channel->userInfo = 0; | |
510 channel->qLength = 128; | |
511 if (SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr) { | |
512 SDL_SetError("Unable to create audio channel"); | |
513 SDL_free(channel); | |
514 channel = NULL; | |
515 return (-1); | |
516 } | |
517 | |
518 /* Start playback */ | |
519 if (SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr) & audio_dbh) | |
520 != noErr) { | |
521 SDL_SetError("Unable to play double buffered audio"); | |
522 return (-1); | |
523 } | |
524 | |
525 return 1; | |
526 } | |
527 | |
528 #endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */ | |
529 /* vi: set ts=4 sw=4 expandtab: */ | 344 /* vi: set ts=4 sw=4 expandtab: */ |