aboutsummaryrefslogtreecommitdiffstats
path: root/src/audioOutputs/audioOutput_osx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/audioOutputs/audioOutput_osx.c')
-rw-r--r--src/audioOutputs/audioOutput_osx.c329
1 files changed, 143 insertions, 186 deletions
diff --git a/src/audioOutputs/audioOutput_osx.c b/src/audioOutputs/audioOutput_osx.c
index ab31cc6f6..c14bdc17d 100644
--- a/src/audioOutputs/audioOutput_osx.c
+++ b/src/audioOutputs/audioOutput_osx.c
@@ -20,73 +20,28 @@
#ifdef HAVE_OSX
-#include "../conf.h"
-#include "../log.h"
-
-#include <CoreAudio/AudioHardware.h>
+#include <AudioUnit/AudioUnit.h>
#include <stdlib.h>
#include <pthread.h>
-#define BUFFER_SIZE 1024
+#include "../log.h"
+
+#define BUFFER_SIZE 8192
typedef struct _OsxData {
- AudioDeviceID deviceID;
- AudioStreamBasicDescription streamDesc;
+ AudioUnit au;
pthread_mutex_t mutex;
pthread_cond_t condition;
- Float32 buffer[BUFFER_SIZE];
+ char buffer[BUFFER_SIZE];
int pos;
int len;
int go;
int started;
} OsxData;
-static void printError(OSStatus val) {
- switch(val) {
- case kAudioHardwareNoError:
- ERROR("kAudioHardwareNoErr");
- break;
- case kAudioHardwareNotRunningError:
- ERROR("kAudioHardwareNotRunningError");
- break;
- case kAudioHardwareUnspecifiedError:
- ERROR("kAudioHardwareUnspecifiedError");
- break;
- case kAudioHardwareUnknownPropertyError:
- ERROR("kAudioHardwareUnknownPropertyError");
- break;
- case kAudioHardwareBadPropertySizeError:
- ERROR("kAudioHardwareBadPropertySizeError");
- break;
- case kAudioHardwareIllegalOperationError:
- ERROR("kAudioHardwareIllegalOperationError");
- break;
- case kAudioHardwareBadDeviceError:
- ERROR("kAudioHardwareBadDeviceError");
- break;
- case kAudioHardwareBadStreamError:
- ERROR("kAudioHardwareBadStreamError");
- break;
- case kAudioHardwareUnsupportedOperationError:
- ERROR("kAudioHardwareUnsupportedOperationError");
- break;
- case kAudioDeviceUnsupportedFormatError:
- ERROR("kAudioDeviceUnsupportedFormatError");
- break;
- case kAudioDevicePermissionsError:
- ERROR("kAudioDevicePermissionsError");
- break;
- default:
- ERROR("unknown");
- break;
- }
-}
-
static OsxData * newOsxData() {
OsxData * ret = malloc(sizeof(OsxData));
- ret->deviceID = kAudioDeviceUnknown;
-
pthread_mutex_init(&ret->mutex, NULL);
pthread_cond_init(&ret->condition, NULL);
@@ -99,17 +54,28 @@ static OsxData * newOsxData() {
}
static int osx_testDefault() {
- int err;
- AudioDeviceID deviceID;
- UInt32 propertySize = sizeof(deviceID);
-
- err = AudioHardwareGetProperty(
- kAudioHardwarePropertyDefaultOutputDevice,
- &propertySize, &deviceID);
- if(err || deviceID == kAudioDeviceUnknown) {
- WARNING("Not able to get the default OS X device\n");
+ /*AudioUnit au;
+ ComponentDescription desc;
+ Component comp;
+
+ desc.componentType = kAudioUnitType_Output;
+ desc.componentSubType = kAudioUnitSubType_Output;
+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+ desc.componentFlags = 0;
+ desc.componentFlagsMask = 0;
+
+ comp = FindNextComponent(NULL, &desc);
+ if(!comp) {
+ ERROR("Unable to open default OS X defice\n");
+ return -1;
+ }
+
+ if(OpenAComponent(comp, &au) != noErr) {
+ ERROR("Unable to open default OS X defice\n");
return -1;
}
+
+ CloseComponent(au);*/
return 0;
}
@@ -141,109 +107,132 @@ static void osx_closeDevice(AudioOutput * audioOutput) {
audioOutput->open = 0;
}
-static OSStatus osx_IOProc(AudioDeviceID deviceID,
- const AudioTimeStamp * inNow, const AudioBufferList *inData,
- const AudioTimeStamp * inInputTime, AudioBufferList *outData,
- const AudioTimeStamp * inOutputTime, void * vdata)
+static OSStatus osx_render(void * vdata,
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber, UInt32 inNumberFrames,
+ AudioBufferList *bufferList)
{
OsxData * od = (OsxData *)vdata;
- AudioBuffer * buffer = &outData->mBuffers[0];
- int bufferSize = buffer->mDataByteSize/sizeof(Float32);
- int floatsToCopy;
+ AudioBuffer * buffer = &bufferList->mBuffers[0];
+ int bufferSize = buffer->mDataByteSize;
+ int bytesToCopy;
int curpos = 0;
- DEBUG("entering IOProc\n");
-
pthread_mutex_lock(&od->mutex);
while((od->go || od->len) && bufferSize) {
while(od->go && od->len < bufferSize &&
od->len < BUFFER_SIZE)
{
+ pthread_cond_signal(&od->condition);
pthread_cond_wait(&od->condition, &od->mutex);
}
- floatsToCopy = od->len < bufferSize ? od->len : bufferSize;
- bufferSize -= floatsToCopy;
+ bytesToCopy = od->len < bufferSize ? od->len : bufferSize;
+ bufferSize -= bytesToCopy;
+ od->len -= bytesToCopy;
- if(od->pos+floatsToCopy > BUFFER_SIZE) {
- int floats = BUFFER_SIZE-od->pos;
- memcpy(buffer->mData+curpos, od->buffer+od->pos,
- floats*sizeof(Float32));
- od->len -= floats;
+ if(od->pos+bytesToCopy > BUFFER_SIZE) {
+ int bytes = BUFFER_SIZE-od->pos;
+ memcpy(buffer->mData+curpos, od->buffer+od->pos, bytes);
od->pos = 0;
- curpos += floats;
- floatsToCopy -= floats;
+ curpos += bytes;
+ bytesToCopy -= bytes;
}
- memcpy(buffer->mData+curpos, od->buffer+od->pos,
- floatsToCopy*sizeof(Float32));
- od->len -= floatsToCopy;
- od->pos += floatsToCopy;
- curpos += floatsToCopy;
+ assert(bytesToCopy);
+ memcpy(buffer->mData+curpos, od->buffer+od->pos, bytesToCopy);
+ od->pos += bytesToCopy;
+ curpos += bytesToCopy;
+
+ if(od->pos >= BUFFER_SIZE) od->pos = 0;
}
if(bufferSize) {
- memset(buffer->mData+curpos, 0, bufferSize*sizeof(Float32));
+ memset(buffer->mData+curpos, 0, bufferSize);
}
- pthread_mutex_unlock(&od->mutex);
pthread_cond_signal(&od->condition);
-
- DEBUG("exiting IOProc\n");
+ pthread_mutex_unlock(&od->mutex);
return 0;
}
static int osx_openDevice(AudioOutput * audioOutput) {
- int err;
OsxData * od = (OsxData *)audioOutput->data;
- UInt32 propertySize;
+ ComponentDescription desc;
+ Component comp;
+ AURenderCallbackStruct callback;
AudioFormat * audioFormat = &audioOutput->outAudioFormat;
- UInt32 bufferByteCount = 8192;
-
- propertySize = sizeof(od->deviceID);
- err = AudioHardwareGetProperty(
- kAudioHardwarePropertyDefaultOutputDevice,
- &propertySize, &od->deviceID);
- if(err || od->deviceID == kAudioDeviceUnknown) {
- ERROR("Not able to get the default OS X device\n");
+ AudioStreamBasicDescription streamDesc;
+
+ desc.componentType = kAudioUnitType_Output;
+ desc.componentSubType = kAudioUnitSubType_DefaultOutput;
+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+ desc.componentFlags = 0;
+ desc.componentFlagsMask = 0;
+
+ DEBUG("finding component\n");
+
+ comp = FindNextComponent(NULL, &desc);
+ if(comp == 0) {
+ ERROR("Error finding OS X component\n");
return -1;
}
- od->streamDesc.mFormatID = kAudioFormatLinearPCM;
- od->streamDesc.mSampleRate = audioFormat->sampleRate;
- od->streamDesc.mFormatFlags = kLinearPCMFormatFlagIsFloat |
- kLinearPCMFormatFlagIsBigEndian |
- kLinearPCMFormatFlagIsPacked;
- od->streamDesc.mBytesPerPacket = audioFormat->channels*sizeof(Float32);
- od->streamDesc.mFramesPerPacket = 1;
- od->streamDesc.mBytesPerFrame = audioFormat->channels*sizeof(Float32);
- od->streamDesc.mChannelsPerFrame = audioFormat->channels;
- od->streamDesc.mBitsPerChannel = 8 * sizeof(Float32);
-
- audioFormat->bits = 16;
-
- propertySize = sizeof(od->streamDesc);
- err = AudioDeviceSetProperty(od->deviceID, 0, 0, false,
- kAudioDevicePropertyStreamFormat,
- propertySize, &od->streamDesc);
- if(err) {
- ERROR("unable to set format %i:%i:% on osx device\n",
- (int)audioFormat->sampleRate,
- (int)audioFormat->bits,
- (int)audioFormat->channels);
+ DEBUG("opening component\n");
+ if(OpenAComponent(comp, &od->au) != noErr) {
+ ERROR("Unable to open OS X component\n");
return -1;
}
- propertySize = sizeof(UInt32);
- err = AudioDeviceSetProperty(od->deviceID, 0, 0, false,
- kAudioDevicePropertyBufferSize,
- propertySize, &bufferByteCount);
+ DEBUG("initializing au\n");
+ if(AudioUnitInitialize(od->au) != 0) {
+ CloseComponent(od->au);
+ ERROR("Unable to initialuze OS X audio unit\n");
+ return -1;
+ }
+
+ callback.inputProc = osx_render;
+ callback.inputProcRefCon = od;
+
+ DEBUG("set callback\n");
+ if(AudioUnitSetProperty(od->au, kAudioUnitProperty_SetRenderCallback,
+ kAudioUnitScope_Input, 0,
+ &callback, sizeof(callback)) != 0)
+ {
+ AudioUnitUninitialize(od->au);
+ CloseComponent(od->au);
+ ERROR("unable to set callbak for OS X audio unit\n");
+ return -1;
+ }
- err = AudioDeviceAddIOProc(od->deviceID, osx_IOProc, od);
+ streamDesc.mSampleRate = audioFormat->sampleRate;
+ streamDesc.mFormatID = kAudioFormatLinearPCM;
+ streamDesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
+ kLinearPCMFormatFlagIsBigEndian;
+ streamDesc.mBytesPerPacket = audioFormat->channels*audioFormat->bits/8;
+ streamDesc.mFramesPerPacket = 1;
+ streamDesc.mBytesPerFrame = streamDesc.mBytesPerPacket;
+ streamDesc.mChannelsPerFrame = audioFormat->channels;
+ streamDesc.mBitsPerChannel = audioFormat->bits;
+
+ DEBUG("set format\n");
+ if(AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input, 0,
+ &streamDesc, sizeof(streamDesc)) != 0)
+ {
+ AudioUnitUninitialize(od->au);
+ CloseComponent(od->au);
+ ERROR("Unable to set format on OS X device\n");
+ return -1;
+ }
+
+ DEBUG("start\n");
+ int err = AudioOutputUnitStart(od->au);
if(err) {
- ERROR("error adding IOProc\n");
+ ERROR("unable to start audio output: %i\n", err);
return -1;
}
@@ -253,86 +242,54 @@ static int osx_openDevice(AudioOutput * audioOutput) {
audioOutput->open = 1;
+ DEBUG("opened OS X device\n");
return 0;
}
-static void copyIntBufferToFloat(char * playChunk, int size, float * buffer,
- int floats)
-{
- /* this is for 16-bit audio only */
- SInt16 * sample;
-
- while(floats) {
- sample = (SInt16 *)playChunk;
- *buffer = *sample/32767.0;
- playChunk += 2;
- buffer++;
- floats--;
- }
-}
-
static int osx_play(AudioOutput * audioOutput, char * playChunk, int size) {
OsxData * od = (OsxData *)audioOutput->data;
- int floatsToCopy;
-
- size /= 2;
-
- DEBUG("entering osx_play\n");
+ int bytesToCopy;
+ int curpos;
pthread_mutex_lock(&od->mutex);
- DEBUG("entering while loop\n");
+ curpos = od->pos+od->len;
+ if(curpos >= BUFFER_SIZE) curpos -= BUFFER_SIZE;
+
while(size) {
- DEBUG("iterating loop with size = %i\n", size);
- while(od->len == BUFFER_SIZE) {
- if(!od->started) {
- OSStatus err = AudioDeviceStart(od->deviceID,
- osx_IOProc);
- DEBUG("start audio device\n");
- if(err) {
- printError(err);
- ERROR(" error doing AudioDeviceStart "
- "for osx device: %i\n",
- (int)err);
- pthread_mutex_unlock(&od->mutex);
- return -1;
- }
- od->started = 1;
- DEBUG("audio device started\n");
+ while(od->len >= BUFFER_SIZE) {
+ if(curpos!=od->pos) {
+ DEBUG("%i != %i\n", curpos, od->pos);
+ abort();
}
-
- DEBUG("cond_wait\n");
+ pthread_cond_signal(&od->condition);
pthread_cond_wait(&od->condition, &od->mutex);
}
- floatsToCopy = BUFFER_SIZE - od->len;
- floatsToCopy = floatsToCopy < size ? floatsToCopy : size;
- size -= floatsToCopy;
-
- if(od->pos+floatsToCopy > BUFFER_SIZE) {
- int floats = BUFFER_SIZE-od->pos;
- copyIntBufferToFloat(playChunk,
- audioOutput->outAudioFormat.bits/8,
- od->buffer,
- floats);
- od->pos = 0;
- od->len += floats;
- playChunk += floats*sizeof(Float32);
+ bytesToCopy = BUFFER_SIZE - od->len;
+ bytesToCopy = bytesToCopy < size ? bytesToCopy : size;
+ size -= bytesToCopy;
+ od->len += bytesToCopy;
+
+ if(curpos+bytesToCopy > BUFFER_SIZE) {
+ int bytes = BUFFER_SIZE-curpos;
+ memcpy(od->buffer+curpos, playChunk, bytes);
+ curpos = 0;
+ playChunk += bytes;
+ bytesToCopy -= bytes;
}
- copyIntBufferToFloat(playChunk,
- audioOutput->outAudioFormat.bits/8,
- od->buffer,
- floatsToCopy);
- od->pos += floatsToCopy;
- od->len += floatsToCopy;
- playChunk += floatsToCopy*sizeof(Float32);
+ assert(bytesToCopy);
+ memcpy(od->buffer+curpos, playChunk, bytesToCopy);
+ curpos += bytesToCopy;
+ playChunk += bytesToCopy;
+
+ if(curpos >= BUFFER_SIZE) curpos = 0;
}
- pthread_mutex_unlock(&od->mutex);
pthread_cond_signal(&od->condition);
+ pthread_mutex_unlock(&od->mutex);
- DEBUG("exiting osx_play\n");
return 0;
}