Mercurial > sdl-ios-xcode
view src/audio/macosx/SDL_coreaudio.c @ 1662:782fd950bd46 SDL-1.3
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.
WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.
The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce
The headers are being converted to automatically generate doxygen documentation.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 28 May 2006 13:04:16 +0000 |
parents | dc6b59e925a2 |
children | 4da1ee79c9af |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" #include <AudioUnit/AudioUnit.h> #include "SDL_audio.h" #include "../SDL_audio_c.h" #include "../SDL_sysaudio.h" #include "SDL_coreaudio.h" /* Audio driver functions */ static int Core_OpenAudio (_THIS, SDL_AudioSpec * spec); static void Core_WaitAudio (_THIS); static void Core_PlayAudio (_THIS); static Uint8 *Core_GetAudioBuf (_THIS); static void Core_CloseAudio (_THIS); /* Audio driver bootstrap functions */ static int Audio_Available (void) { return (1); } static void Audio_DeleteDevice (SDL_AudioDevice * device) { SDL_free (device->hidden); SDL_free (device); } static SDL_AudioDevice * Audio_CreateDevice (int devindex) { SDL_AudioDevice *this; /* Initialize all variables that we clean on shutdown */ this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice)); if (this) { SDL_memset (this, 0, (sizeof *this)); this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc ((sizeof *this->hidden)); } if ((this == NULL) || (this->hidden == NULL)) { SDL_OutOfMemory (); if (this) { SDL_free (this); } return (0); } SDL_memset (this->hidden, 0, (sizeof *this->hidden)); /* Set the function pointers */ this->OpenAudio = Core_OpenAudio; this->WaitAudio = Core_WaitAudio; this->PlayAudio = Core_PlayAudio; this->GetAudioBuf = Core_GetAudioBuf; this->CloseAudio = Core_CloseAudio; this->free = Audio_DeleteDevice; return this; } AudioBootStrap COREAUDIO_bootstrap = { "coreaudio", "Mac OS X CoreAudio", Audio_Available, Audio_CreateDevice }; /* The CoreAudio callback */ static OSStatus audioCallback (void *inRefCon, AudioUnitRenderActionFlags inActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber, AudioBuffer * ioData) { SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon; UInt32 remaining, len; void *ptr; /* Only do anything if audio is enabled and not paused */ if (!this->enabled || this->paused) { SDL_memset (ioData->mData, this->spec.silence, ioData->mDataByteSize); return 0; } /* No SDL conversion should be needed here, ever, since we accept any input format in OpenAudio, and leave the conversion to CoreAudio. */ /* assert(!this->convert.needed); assert(this->spec.channels == ioData->mNumberChannels); */ remaining = ioData->mDataByteSize; ptr = ioData->mData; while (remaining > 0) { if (bufferOffset >= bufferSize) { /* Generate the data */ SDL_memset (buffer, this->spec.silence, bufferSize); SDL_mutexP (this->mixer_lock); (*this->spec.callback) (this->spec.userdata, buffer, bufferSize); SDL_mutexV (this->mixer_lock); bufferOffset = 0; } len = bufferSize - bufferOffset; if (len > remaining) len = remaining; SDL_memcpy (ptr, (char *) buffer + bufferOffset, len); ptr = (char *) ptr + len; remaining -= len; bufferOffset += len; } return 0; } /* Dummy functions -- we don't use thread-based audio */ void Core_WaitAudio (_THIS) { return; } void Core_PlayAudio (_THIS) { return; } Uint8 * Core_GetAudioBuf (_THIS) { return (NULL); } void Core_CloseAudio (_THIS) { OSStatus result; struct AudioUnitInputCallback callback; /* stop processing the audio unit */ result = AudioOutputUnitStop (outputAudioUnit); if (result != noErr) { SDL_SetError ("Core_CloseAudio: AudioOutputUnitStop"); return; } /* Remove the input callback */ callback.inputProc = 0; callback.inputProcRefCon = 0; result = AudioUnitSetProperty (outputAudioUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input, 0, &callback, sizeof (callback)); if (result != noErr) { SDL_SetError ("Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)"); return; } result = CloseComponent (outputAudioUnit); if (result != noErr) { SDL_SetError ("Core_CloseAudio: CloseComponent"); return; } SDL_free (buffer); } #define CHECK_RESULT(msg) \ if (result != noErr) { \ SDL_SetError("Failed to start CoreAudio: " msg); \ return -1; \ } int Core_OpenAudio (_THIS, SDL_AudioSpec * spec) { OSStatus result = noErr; Component comp; ComponentDescription desc; struct AudioUnitInputCallback callback; AudioStreamBasicDescription requestedDesc; /* Setup a AudioStreamBasicDescription with the requested format */ requestedDesc.mFormatID = kAudioFormatLinearPCM; requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked; requestedDesc.mChannelsPerFrame = spec->channels; requestedDesc.mSampleRate = spec->freq; requestedDesc.mBitsPerChannel = spec->format & 0xFF; if (spec->format & 0x8000) requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; if (spec->format & 0x1000) requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; requestedDesc.mFramesPerPacket = 1; requestedDesc.mBytesPerFrame = requestedDesc.mBitsPerChannel * requestedDesc.mChannelsPerFrame / 8; requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * requestedDesc.mFramesPerPacket; /* Locate the default output audio unit */ desc.componentType = kAudioUnitComponentType; desc.componentSubType = kAudioUnitSubType_Output; desc.componentManufacturer = kAudioUnitID_DefaultOutput; desc.componentFlags = 0; desc.componentFlagsMask = 0; comp = FindNextComponent (NULL, &desc); if (comp == NULL) { SDL_SetError ("Failed to start CoreAudio: FindNextComponent returned NULL"); return -1; } /* Open & initialize the default output audio unit */ result = OpenAComponent (comp, &outputAudioUnit); CHECK_RESULT ("OpenAComponent") result = AudioUnitInitialize (outputAudioUnit); CHECK_RESULT ("AudioUnitInitialize") /* Set the input format of the audio unit. */ result = AudioUnitSetProperty (outputAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &requestedDesc, sizeof (requestedDesc)); CHECK_RESULT ("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)") /* Set the audio callback */ callback.inputProc = audioCallback; callback.inputProcRefCon = this; result = AudioUnitSetProperty (outputAudioUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input, 0, &callback, sizeof (callback)); CHECK_RESULT ("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)") /* Calculate the final parameters for this audio specification */ SDL_CalculateAudioSpec (spec); /* Allocate a sample buffer */ bufferOffset = bufferSize = this->spec.size; buffer = SDL_malloc (bufferSize); /* Finally, start processing of the audio unit */ result = AudioOutputUnitStart (outputAudioUnit); CHECK_RESULT ("AudioOutputUnitStart") /* We're running! */ return (1); } /* vi: set ts=4 sw=4 expandtab: */