Audio improvements from Max Horn, including a new CoreAudio driver for MacOSX
--HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40936
This commit is contained in:
parent
fddd0153c8
commit
35c8da7adb
12 changed files with 436 additions and 135 deletions
32
configure.in
32
configure.in
|
@ -332,6 +332,7 @@ CheckDMEDIA()
|
|||
],[
|
||||
have_dmedia=yes
|
||||
])
|
||||
AC_MSG_RESULT($have_dmedia)
|
||||
# Set up files for the audio library
|
||||
if test x$have_dmedia = xyes; then
|
||||
CFLAGS="$CFLAGS -DDMEDIA_SUPPORT"
|
||||
|
@ -489,6 +490,29 @@ CheckAtariAudio()
|
|||
fi
|
||||
}
|
||||
|
||||
dnl Check whether we want to use CoreAudio
|
||||
CheckCoreAudio()
|
||||
{
|
||||
if test x$enable_audio = xyes; then
|
||||
AC_MSG_CHECKING(for CoreAudio audio support)
|
||||
have_coreaudio=no
|
||||
AC_TRY_COMPILE([
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
],[
|
||||
AudioUnitInputCallback callback;
|
||||
],[
|
||||
have_coreaudio=yes
|
||||
])
|
||||
AC_MSG_RESULT($have_coreaudio)
|
||||
# Set up files for the audio library
|
||||
if test x$have_coreaudio = xyes; then
|
||||
CFLAGS="$CFLAGS -DCOREAUDIO_SUPPORT"
|
||||
AUDIO_SUBDIRS="$AUDIO_SUBDIRS macosx"
|
||||
AUDIO_DRIVERS="$AUDIO_DRIVERS macosx/libaudio_macosx.la"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
dnl See if we can use x86 assembly blitters
|
||||
# NASM is available from: http://nasm.octium.net/
|
||||
CheckNASM()
|
||||
|
@ -2507,10 +2531,15 @@ case "$target" in
|
|||
ARCH=macosx
|
||||
CheckDummyVideo
|
||||
CheckDiskAudio
|
||||
CheckCoreAudio
|
||||
CheckQUARTZ
|
||||
CheckMacGL
|
||||
CheckPTHREAD
|
||||
CheckSIGACTION
|
||||
# If either the audio or CD driver is used, add the AudioUnit framework
|
||||
if test x$enable_audio = xyes -o x$enable_cdrom = xyes; then
|
||||
SYSTEM_LIBS="$SYSTEM_LIBS -framework AudioToolbox -framework AudioUnit"
|
||||
fi
|
||||
# Set up files for the audio library
|
||||
if test x$enable_audio = xyes; then
|
||||
AUDIO_SUBDIRS="$AUDIO_SUBDIRS macrom"
|
||||
|
@ -2526,7 +2555,7 @@ case "$target" in
|
|||
if test x$enable_cdrom = xyes; then
|
||||
CDROM_SUBDIRS="$CDROM_SUBDIRS macosx"
|
||||
CDROM_DRIVERS="$CDROM_DRIVERS macosx/libcdrom_macosx.la"
|
||||
SYSTEM_LIBS="$SYSTEM_LIBS -framework AudioToolbox -framework AudioUnit -lstdc++"
|
||||
SYSTEM_LIBS="$SYSTEM_LIBS -lstdc++"
|
||||
fi
|
||||
# Set up files for the thread library
|
||||
if test x$enable_threads = xyes; then
|
||||
|
@ -2766,6 +2795,7 @@ src/audio/dma/Makefile
|
|||
src/audio/dmedia/Makefile
|
||||
src/audio/dsp/Makefile
|
||||
src/audio/esd/Makefile
|
||||
src/audio/macosx/Makefile
|
||||
src/audio/macrom/Makefile
|
||||
src/audio/mint/Makefile
|
||||
src/audio/mme/Makefile
|
||||
|
|
|
@ -15,6 +15,7 @@ DIST_SUBDIRS = \
|
|||
dmedia \
|
||||
dsp \
|
||||
esd \
|
||||
macosx \
|
||||
macrom \
|
||||
mint \
|
||||
mme \
|
||||
|
|
|
@ -77,6 +77,9 @@ static AudioBootStrap *bootstrap[] = {
|
|||
#ifdef __BEOS__
|
||||
&BAUDIO_bootstrap,
|
||||
#endif
|
||||
#ifdef COREAUDIO_SUPPORT
|
||||
&COREAUDIO_bootstrap,
|
||||
#endif
|
||||
#if defined(macintosh) || TARGET_API_MAC_CARBON
|
||||
&SNDMGR_bootstrap,
|
||||
#endif
|
||||
|
|
|
@ -144,6 +144,9 @@ extern AudioBootStrap Paud_bootstrap;
|
|||
#ifdef __BEOS__
|
||||
extern AudioBootStrap BAUDIO_bootstrap;
|
||||
#endif
|
||||
#ifdef COREAUDIO_SUPPORT
|
||||
extern AudioBootStrap COREAUDIO_bootstrap;
|
||||
#endif
|
||||
#if defined(macintosh) || TARGET_API_MAC_CARBON
|
||||
extern AudioBootStrap SNDMGR_bootstrap;
|
||||
#endif
|
||||
|
|
6
src/audio/macosx/.cvsignore
Normal file
6
src/audio/macosx/.cvsignore
Normal file
|
@ -0,0 +1,6 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
.libs
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
9
src/audio/macosx/Makefile.am
Normal file
9
src/audio/macosx/Makefile.am
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
## Makefile.am for SDL using the Mac OS X CoreAudio driver
|
||||
|
||||
noinst_LTLIBRARIES = libaudio_macosx.la
|
||||
libaudio_macosx_la_SOURCES = $(SRCS)
|
||||
|
||||
# The SDL audio driver sources
|
||||
SRCS = SDL_coreaudio.c \
|
||||
SDL_coreaudio.h
|
287
src/audio/macosx/SDL_coreaudio.c
Normal file
287
src/audio/macosx/SDL_coreaudio.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2004 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_audiomem.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)
|
||||
{
|
||||
free(device->hidden);
|
||||
free(device);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
|
||||
if ( this ) {
|
||||
memset(this, 0, (sizeof *this));
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
malloc((sizeof *this->hidden));
|
||||
}
|
||||
if ( (this == NULL) || (this->hidden == NULL) ) {
|
||||
SDL_OutOfMemory();
|
||||
if ( this ) {
|
||||
free(this);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
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 ) {
|
||||
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 */
|
||||
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;
|
||||
memcpy(ptr, buffer + bufferOffset, len);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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 = malloc(bufferSize);
|
||||
assert(buffer);
|
||||
|
||||
/* Finally, start processing of the audio unit */
|
||||
result = AudioOutputUnitStart (outputAudioUnit);
|
||||
CHECK_RESULT("AudioOutputUnitStart")
|
||||
|
||||
|
||||
/* We're running! */
|
||||
return(1);
|
||||
}
|
49
src/audio/macosx/SDL_coreaudio.h
Normal file
49
src/audio/macosx/SDL_coreaudio.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2004 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
#ifndef _SDL_coreaudio_h
|
||||
#define _SDL_coreaudio_h
|
||||
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the video functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData {
|
||||
AudioUnit outputAudioUnit;
|
||||
void *buffer;
|
||||
UInt32 bufferOffset;
|
||||
UInt32 bufferSize;
|
||||
};
|
||||
|
||||
/* Old variable names */
|
||||
#define outputAudioUnit (this->hidden->outputAudioUnit)
|
||||
#define buffer (this->hidden->buffer)
|
||||
#define bufferOffset (this->hidden->bufferOffset)
|
||||
#define bufferSize (this->hidden->bufferSize)
|
||||
|
||||
#endif /* _SDL_coreaudio_h */
|
|
@ -67,28 +67,27 @@ OSStatus AudioFileManager::FileInputProc (void *inRefCo
|
|||
|
||||
OSStatus AudioFileManager::Render (AudioBuffer &ioData)
|
||||
{
|
||||
OSStatus result = AudioConverterFillBuffer(mParentConverter,
|
||||
AudioFileManager::ACInputProc,
|
||||
this,
|
||||
&ioData.mDataByteSize,
|
||||
ioData.mData);
|
||||
if (result) {
|
||||
SDL_SetError ("AudioConverterFillBuffer:%ld\n", result);
|
||||
mParent.DoNotification (result);
|
||||
} else {
|
||||
mByteCounter += ioData.mDataByteSize / 2;
|
||||
AfterRender();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
OSStatus result = noErr;
|
||||
|
||||
if (mBufferOffset >= mBufferSize) {
|
||||
result = GetFileData(&mTmpBuffer, &mBufferSize);
|
||||
if (result) {
|
||||
SDL_SetError ("AudioConverterFillBuffer:%ld\n", result);
|
||||
mParent.DoNotification (result);
|
||||
return result;
|
||||
}
|
||||
|
||||
OSStatus AudioFileManager::ACInputProc (AudioConverterRef inAudioConverter,
|
||||
UInt32* outDataSize,
|
||||
void** outData,
|
||||
void* inUserData)
|
||||
{
|
||||
AudioFileManager* THIS = (AudioFileManager*)inUserData;
|
||||
return THIS->GetFileData(outData, outDataSize);
|
||||
mBufferOffset = 0;
|
||||
}
|
||||
|
||||
if (ioData.mDataByteSize > mBufferSize - mBufferOffset)
|
||||
ioData.mDataByteSize = mBufferSize - mBufferOffset;
|
||||
ioData.mData = (char *)mTmpBuffer + mBufferOffset;
|
||||
mBufferOffset += ioData.mDataByteSize;
|
||||
|
||||
mByteCounter += ioData.mDataByteSize;
|
||||
AfterRender();
|
||||
return result;
|
||||
}
|
||||
|
||||
AudioFileManager::~AudioFileManager ()
|
||||
|
@ -102,7 +101,6 @@ AudioFileManager::~AudioFileManager ()
|
|||
AudioFilePlayer::AudioFilePlayer (const FSRef *inFileRef)
|
||||
: mConnected (false),
|
||||
mAudioFileManager (0),
|
||||
mConverter (0),
|
||||
mNotifier (0),
|
||||
mStartFrame (0)
|
||||
{
|
||||
|
@ -124,39 +122,14 @@ AudioFilePlayer::AudioFilePlayer (const FSRef *inFileRef)
|
|||
bytesPerSecond);
|
||||
}
|
||||
|
||||
// you can put a rate scalar here to play the file faster or slower
|
||||
// by multiplying the same rate by the desired factor
|
||||
// eg fileSampleRate * 2 -> twice as fast
|
||||
// before you create the AudioConverter
|
||||
void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit,
|
||||
int inBusNumber)
|
||||
void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit)
|
||||
{
|
||||
if (mConnected) throw static_cast<OSStatus>(-1); //can't set dest if already engaged
|
||||
|
||||
mPlayUnit = inDestUnit;
|
||||
mBusNumber = inBusNumber;
|
||||
|
||||
OSStatus result = noErr;
|
||||
|
||||
if (mConverter) {
|
||||
result = AudioConverterDispose (mConverter);
|
||||
THROW_RESULT("AudioConverterDispose")
|
||||
}
|
||||
|
||||
AudioStreamBasicDescription destDesc;
|
||||
UInt32 size = sizeof (destDesc);
|
||||
result = AudioUnitGetProperty (inDestUnit,
|
||||
kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Input,
|
||||
inBusNumber,
|
||||
&destDesc,
|
||||
&size);
|
||||
THROW_RESULT("AudioUnitGetProperty")
|
||||
|
||||
#if DEBUG
|
||||
printf("Destination format:\n");
|
||||
PrintStreamDesc (&destDesc);
|
||||
#endif
|
||||
|
||||
//we can "down" cast a component instance to a component
|
||||
ComponentDescription desc;
|
||||
|
@ -171,19 +144,14 @@ void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit,
|
|||
THROW_RESULT("BAD COMPONENT")
|
||||
}
|
||||
|
||||
|
||||
result = AudioConverterNew (&mFileDescription, &destDesc, &mConverter);
|
||||
THROW_RESULT("AudioConverterNew")
|
||||
|
||||
#if 0
|
||||
// this uses the better quality SRC
|
||||
UInt32 srcID = kAudioUnitSRCAlgorithm_Polyphase;
|
||||
result = AudioConverterSetProperty(mConverter,
|
||||
kAudioConverterSampleRateConverterAlgorithm,
|
||||
sizeof(srcID),
|
||||
&srcID);
|
||||
THROW_RESULT("AudioConverterSetProperty")
|
||||
#endif
|
||||
/* Set the input format of the audio unit. */
|
||||
result = AudioUnitSetProperty (inDestUnit,
|
||||
kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Input,
|
||||
0,
|
||||
&mFileDescription,
|
||||
sizeof (mFileDescription));
|
||||
THROW_RESULT("AudioUnitSetProperty")
|
||||
}
|
||||
|
||||
void AudioFilePlayer::SetStartFrame (int frame)
|
||||
|
@ -220,22 +188,18 @@ AudioFilePlayer::~AudioFilePlayer()
|
|||
FSClose (mForkRefNum);
|
||||
mForkRefNum = 0;
|
||||
}
|
||||
|
||||
if (mConverter) {
|
||||
AudioConverterDispose (mConverter);
|
||||
mConverter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFilePlayer::Connect()
|
||||
{
|
||||
#if DEBUG
|
||||
printf ("Connect:%x,%ld, engaged=%d\n", (int)mPlayUnit, mBusNumber, (mConnected ? 1 : 0));
|
||||
printf ("Connect:%x, engaged=%d\n", (int)mPlayUnit, (mConnected ? 1 : 0));
|
||||
#endif
|
||||
if (!mConnected)
|
||||
{
|
||||
mAudioFileManager->Connect(mConverter);
|
||||
|
||||
mAudioFileManager->DoConnect();
|
||||
|
||||
|
||||
// set the render callback for the file data to be supplied to the sound converter AU
|
||||
mInputCallback.inputProc = AudioFileManager::FileInputProc;
|
||||
mInputCallback.inputProcRefCon = mAudioFileManager;
|
||||
|
@ -243,7 +207,7 @@ void AudioFilePlayer::Connect()
|
|||
OSStatus result = AudioUnitSetProperty (mPlayUnit,
|
||||
kAudioUnitProperty_SetInputCallback,
|
||||
kAudioUnitScope_Input,
|
||||
mBusNumber,
|
||||
0,
|
||||
&mInputCallback,
|
||||
sizeof(mInputCallback));
|
||||
THROW_RESULT("AudioUnitSetProperty")
|
||||
|
@ -272,7 +236,7 @@ void AudioFilePlayer::DoNotification (OSStatus inStatus) const
|
|||
void AudioFilePlayer::Disconnect ()
|
||||
{
|
||||
#if DEBUG
|
||||
printf ("Disconnect:%x,%ld, engaged=%d\n", (int)mPlayUnit, mBusNumber, (mConnected ? 1 : 0));
|
||||
printf ("Disconnect:%x,%ld, engaged=%d\n", (int)mPlayUnit, 0, (mConnected ? 1 : 0));
|
||||
#endif
|
||||
if (mConnected)
|
||||
{
|
||||
|
@ -283,7 +247,7 @@ void AudioFilePlayer::Disconnect ()
|
|||
OSStatus result = AudioUnitSetProperty (mPlayUnit,
|
||||
kAudioUnitProperty_SetInputCallback,
|
||||
kAudioUnitScope_Input,
|
||||
mBusNumber,
|
||||
0,
|
||||
&mInputCallback,
|
||||
sizeof(mInputCallback));
|
||||
if (result)
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
#include <AudioToolbox/AudioConverter.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
|
@ -65,8 +64,7 @@ public:
|
|||
|
||||
~AudioFilePlayer();
|
||||
|
||||
void SetDestination (AudioUnit &inDestUnit,
|
||||
int inBusNumber);
|
||||
void SetDestination (AudioUnit &inDestUnit);
|
||||
|
||||
void SetNotifier (AudioFilePlayNotifier inNotifier, void *inRefCon)
|
||||
{
|
||||
|
@ -88,26 +86,18 @@ public:
|
|||
|
||||
bool IsConnected () const { return mConnected; }
|
||||
|
||||
UInt32 GetBusNumber () const { return mBusNumber; }
|
||||
|
||||
AudioUnit GetDestUnit () const { return mPlayUnit; }
|
||||
|
||||
AudioConverterRef GetAudioConverter() const { return mConverter; }
|
||||
|
||||
#if DEBUG
|
||||
void Print() const
|
||||
{
|
||||
printf ("Destination Bus:%ld\n", GetBusNumber());
|
||||
printf ("Is Connected:%s\n", (IsConnected() ? "true" : "false"));
|
||||
printf ("- - - - - - - - - - - - - - \n");
|
||||
}
|
||||
#endif
|
||||
|
||||
const AudioStreamBasicDescription& GetFileFormat() const { return mFileDescription; }
|
||||
|
||||
private:
|
||||
AudioUnit mPlayUnit;
|
||||
UInt32 mBusNumber;
|
||||
SInt16 mForkRefNum;
|
||||
|
||||
AudioUnitInputCallback mInputCallback;
|
||||
|
@ -117,7 +107,6 @@ private:
|
|||
bool mConnected;
|
||||
|
||||
AudioFileManager* mAudioFileManager;
|
||||
AudioConverterRef mConverter;
|
||||
|
||||
AudioFilePlayNotifier mNotifier;
|
||||
void* mRefCon;
|
||||
|
@ -141,15 +130,11 @@ public:
|
|||
~AudioFileManager();
|
||||
|
||||
|
||||
void Connect (AudioConverterRef inConverter)
|
||||
{
|
||||
mParentConverter = inConverter;
|
||||
DoConnect();
|
||||
}
|
||||
|
||||
// this method should NOT be called by an object of this class
|
||||
// as it is called by the parent's Disconnect() method
|
||||
void Disconnect ();
|
||||
|
||||
void DoConnect ();
|
||||
|
||||
OSStatus Read(char *buffer, UInt32 *len);
|
||||
|
||||
|
@ -165,7 +150,6 @@ public:
|
|||
|
||||
protected:
|
||||
AudioFilePlayer& mParent;
|
||||
AudioConverterRef mParentConverter;
|
||||
SInt16 mForkRefNum;
|
||||
SInt64 mAudioDataOffset;
|
||||
|
||||
|
@ -179,6 +163,10 @@ protected:
|
|||
|
||||
int mNumTimesAskedSinceFinished;
|
||||
|
||||
|
||||
void* mTmpBuffer;
|
||||
UInt32 mBufferSize;
|
||||
UInt32 mBufferOffset;
|
||||
public:
|
||||
const UInt32 mChunkSize;
|
||||
SInt64 mFileLength;
|
||||
|
@ -190,8 +178,6 @@ protected:
|
|||
OSStatus Render (AudioBuffer &ioData);
|
||||
|
||||
OSStatus GetFileData (void** inOutData, UInt32 *inOutDataSize);
|
||||
|
||||
void DoConnect ();
|
||||
|
||||
void AfterRender ();
|
||||
|
||||
|
@ -201,10 +187,6 @@ public:
|
|||
const AudioTimeStamp *inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
AudioBuffer *ioData);
|
||||
static OSStatus ACInputProc (AudioConverterRef inAudioConverter,
|
||||
UInt32* outDataSize,
|
||||
void** outData,
|
||||
void* inUserData);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -287,6 +287,8 @@ AudioFileManager::AudioFileManager (AudioFilePlayer &inParent,
|
|||
mLockUnsuccessful (false),
|
||||
mIsEngaged (false),
|
||||
|
||||
mBufferSize (inChunkSize),
|
||||
mBufferOffset (inChunkSize),
|
||||
mChunkSize (inChunkSize),
|
||||
mFileLength (inFileLength),
|
||||
mReadFilePosition (0),
|
||||
|
@ -364,7 +366,7 @@ OSStatus AudioFileManager::GetFileData (void** inOutData, UInt32 *inOutDataSize)
|
|||
|
||||
if (mReadFromFirstBuffer == mWriteToFirstBuffer) {
|
||||
#if DEBUG
|
||||
printf ("* * * * * * * Can't keep up with reading file:%ld\n", mParent.GetBusNumber());
|
||||
printf ("* * * * * * * Can't keep up with reading file\n");
|
||||
#endif
|
||||
|
||||
mParent.DoNotification (kAudioFilePlayErr_FilePlayUnderrun);
|
||||
|
|
|
@ -68,8 +68,6 @@ static SDL_CD* theCDROM;
|
|||
|
||||
static OSStatus CheckInit ();
|
||||
|
||||
static OSStatus MatchAUFormats (AudioUnit theUnit, UInt32 theInputBus);
|
||||
|
||||
static void FilePlayNotificationHandler (void* inRefCon, OSStatus inStatus);
|
||||
|
||||
static int RunCallBackThread (void* inRefCon);
|
||||
|
@ -423,7 +421,7 @@ int LoadFile (const FSRef *ref, int startFrame, int stopFrame)
|
|||
throw (-3);
|
||||
}
|
||||
|
||||
thePlayer->SetDestination(theUnit, 0);
|
||||
thePlayer->SetDestination(theUnit);
|
||||
|
||||
if (startFrame >= 0)
|
||||
thePlayer->SetStartFrame (startFrame);
|
||||
|
@ -605,16 +603,6 @@ static OSStatus CheckInit ()
|
|||
THROW_RESULT("CheckInit: AudioUnitInitialize")
|
||||
|
||||
|
||||
// In this case we first want to get the output format of the OutputUnit
|
||||
// Then we set that as the input format. Why?
|
||||
// So that only a single conversion process is done
|
||||
// when SetDestination is called it will get the input format of the
|
||||
// unit its supplying data to. This defaults to 44.1K, stereo, so if
|
||||
// the device is not that, then we lose a possibly rendering of data
|
||||
|
||||
result = MatchAUFormats (theUnit, 0);
|
||||
THROW_RESULT("CheckInit: MatchAUFormats")
|
||||
|
||||
playBackWasInit = true;
|
||||
}
|
||||
catch (...)
|
||||
|
@ -625,29 +613,6 @@ static OSStatus CheckInit ()
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static OSStatus MatchAUFormats (AudioUnit theUnit, UInt32 theInputBus)
|
||||
{
|
||||
AudioStreamBasicDescription theDesc;
|
||||
UInt32 size = sizeof (theDesc);
|
||||
OSStatus result = AudioUnitGetProperty (theUnit,
|
||||
kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Output,
|
||||
0,
|
||||
&theDesc,
|
||||
&size);
|
||||
THROW_RESULT("MatchAUFormats: AudioUnitGetProperty")
|
||||
|
||||
result = AudioUnitSetProperty (theUnit,
|
||||
kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Input,
|
||||
theInputBus,
|
||||
&theDesc,
|
||||
size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void FilePlayNotificationHandler(void * inRefCon, OSStatus inStatus)
|
||||
{
|
||||
if (inStatus == kAudioFilePlay_FileIsFinished) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue