30 #include <CoreServices/CoreServices.h>
32 #include <AudioUnit/AudioUnit.h>
33 #include <AudioToolbox/AudioToolbox.h>
41 AudioStreamBasicDescription
format;
43 AudioConverterRef audioConverter;
44 AudioBufferList *bufferList;
58 for(i = 0;i < list->mNumberBuffers;i++)
59 free(list->mBuffers[i].mData);
66 AudioBufferList *list;
68 list =
calloc(1,
sizeof(AudioBufferList) +
sizeof(AudioBuffer));
71 list->mNumberBuffers = 1;
73 list->mBuffers[0].mNumberChannels = channelCount;
74 list->mBuffers[0].mDataByteSize = byteSize;
75 list->mBuffers[0].mData =
malloc(byteSize);
76 if(list->mBuffers[0].mData ==
NULL)
85 static OSStatus
ca_callback(
void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
86 UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
92 ioData->mBuffers[0].mDataByteSize / data->frameSize);
98 AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription,
void* inUserData)
107 ioData->mNumberBuffers = 1;
108 ioData->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame;
109 ioData->mBuffers[0].mData = data->resampleBuffer;
110 ioData->mBuffers[0].mDataByteSize = (*ioNumberDataPackets) * data->format.mBytesPerFrame;
116 const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
117 UInt32 inNumberFrames, AudioBufferList *ioData)
121 AudioUnitRenderActionFlags
flags = 0;
125 err = AudioUnitRender(data->audioUnit, &
flags, inTimeStamp, 1, inNumberFrames, data->bufferList);
128 ERR(
"AudioUnitRender error: %d\n", err);
132 WriteRingBuffer(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames);
139 ComponentDescription desc;
146 else if(strcmp(deviceName,
ca_device) != 0)
150 desc.componentType = kAudioUnitType_Output;
151 desc.componentSubType = kAudioUnitSubType_DefaultOutput;
152 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
153 desc.componentFlags = 0;
154 desc.componentFlagsMask = 0;
156 comp = FindNextComponent(
NULL, &desc);
159 ERR(
"FindNextComponent failed\n");
163 data =
calloc(1,
sizeof(*data));
165 err = OpenAComponent(comp, &data->audioUnit);
168 ERR(
"OpenAComponent failed\n");
174 err = AudioUnitInitialize(data->audioUnit);
177 ERR(
"AudioUnitInitialize failed\n");
178 CloseComponent(data->audioUnit);
192 AudioUnitUninitialize(data->audioUnit);
193 CloseComponent(data->audioUnit);
202 AudioStreamBasicDescription streamFormat;
203 AURenderCallbackStruct
input;
207 err = AudioUnitUninitialize(data->audioUnit);
209 ERR(
"-- AudioUnitUninitialize failed.\n");
212 size =
sizeof(AudioStreamBasicDescription);
213 err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &
size);
214 if(err != noErr ||
size !=
sizeof(AudioStreamBasicDescription))
216 ERR(
"AudioUnitGetProperty failed\n");
221 TRACE(
"Output streamFormat of default output unit -\n");
222 TRACE(
" streamFormat.mFramesPerPacket = %d\n", streamFormat.mFramesPerPacket);
223 TRACE(
" streamFormat.mChannelsPerFrame = %d\n", streamFormat.mChannelsPerFrame);
224 TRACE(
" streamFormat.mBitsPerChannel = %d\n", streamFormat.mBitsPerChannel);
225 TRACE(
" streamFormat.mBytesPerPacket = %d\n", streamFormat.mBytesPerPacket);
226 TRACE(
" streamFormat.mBytesPerFrame = %d\n", streamFormat.mBytesPerFrame);
227 TRACE(
" streamFormat.mSampleRate = %5.0f\n", streamFormat.mSampleRate);
231 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat,
size);
234 ERR(
"AudioUnitSetProperty failed\n");
238 if(device->
Frequency != streamFormat.mSampleRate)
241 streamFormat.mSampleRate /
243 device->
Frequency = streamFormat.mSampleRate;
248 switch(streamFormat.mChannelsPerFrame)
269 ERR(
"Unhandled channel count (%d), using Stereo\n", streamFormat.mChannelsPerFrame);
271 streamFormat.mChannelsPerFrame = 2;
278 streamFormat.mFramesPerPacket = 1;
279 streamFormat.mFormatFlags = 0;
286 streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
287 streamFormat.mBitsPerChannel = 8;
293 streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
294 streamFormat.mBitsPerChannel = 16;
300 streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
301 streamFormat.mBitsPerChannel = 32;
304 streamFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat;
305 streamFormat.mBitsPerChannel = 32;
308 streamFormat.mBytesPerFrame = streamFormat.mChannelsPerFrame *
309 streamFormat.mBitsPerChannel / 8;
310 streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame;
311 streamFormat.mFormatID = kAudioFormatLinearPCM;
312 streamFormat.mFormatFlags |= kAudioFormatFlagsNativeEndian |
313 kLinearPCMFormatFlagIsPacked;
315 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat,
sizeof(AudioStreamBasicDescription));
318 ERR(
"AudioUnitSetProperty failed\n");
325 input.inputProcRefCon = device;
327 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &
input,
sizeof(AURenderCallbackStruct));
330 ERR(
"AudioUnitSetProperty failed\n");
335 err = AudioUnitInitialize(data->audioUnit);
338 ERR(
"AudioUnitInitialize failed\n");
350 err = AudioOutputUnitStart(data->audioUnit);
353 ERR(
"AudioOutputUnitStart failed\n");
365 err = AudioOutputUnitStop(data->audioUnit);
367 ERR(
"AudioOutputUnitStop failed\n");
372 AudioStreamBasicDescription requestedFormat;
373 AudioStreamBasicDescription hardwareFormat;
374 AudioStreamBasicDescription outputFormat;
375 AURenderCallbackStruct
input;
376 ComponentDescription desc;
377 AudioDeviceID inputDevice;
378 UInt32 outputFrameCount;
385 desc.componentType = kAudioUnitType_Output;
386 desc.componentSubType = kAudioUnitSubType_HALOutput;
387 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
388 desc.componentFlags = 0;
389 desc.componentFlagsMask = 0;
392 comp = FindNextComponent(
NULL, &desc);
395 ERR(
"FindNextComponent failed\n");
399 data =
calloc(1,
sizeof(*data));
403 err = OpenAComponent(comp, &data->audioUnit);
406 ERR(
"OpenAComponent failed\n");
412 err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO,
sizeof(
ALuint));
415 ERR(
"AudioUnitSetProperty failed\n");
421 err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO,
sizeof(
ALuint));
424 ERR(
"AudioUnitSetProperty failed\n");
429 propertySize =
sizeof(AudioDeviceID);
430 err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &inputDevice);
433 ERR(
"AudioHardwareGetProperty failed\n");
437 if(inputDevice == kAudioDeviceUnknown)
439 ERR(
"No input device found\n");
444 err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice,
sizeof(AudioDeviceID));
447 ERR(
"AudioUnitSetProperty failed\n");
453 input.inputProcRefCon = device;
455 err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input,
sizeof(AURenderCallbackStruct));
458 ERR(
"AudioUnitSetProperty failed\n");
463 err = AudioUnitInitialize(data->audioUnit);
466 ERR(
"AudioUnitInitialize failed\n");
471 propertySize =
sizeof(AudioStreamBasicDescription);
472 err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize);
473 if(err != noErr || propertySize !=
sizeof(AudioStreamBasicDescription))
475 ERR(
"AudioUnitGetProperty failed\n");
483 requestedFormat.mBitsPerChannel = 8;
484 requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
487 requestedFormat.mBitsPerChannel = 16;
488 requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
491 requestedFormat.mBitsPerChannel = 32;
492 requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
495 requestedFormat.mBitsPerChannel = 32;
496 requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
508 requestedFormat.mChannelsPerFrame = 1;
511 requestedFormat.mChannelsPerFrame = 2;
523 requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8;
524 requestedFormat.mBytesPerPacket = requestedFormat.mBytesPerFrame;
525 requestedFormat.mSampleRate = device->
Frequency;
526 requestedFormat.mFormatID = kAudioFormatLinearPCM;
527 requestedFormat.mReserved = 0;
528 requestedFormat.mFramesPerPacket = 1;
531 data->format = requestedFormat;
536 outputFormat = requestedFormat;
537 outputFormat.mSampleRate = hardwareFormat.mSampleRate;
540 data->sampleRateRatio = outputFormat.mSampleRate / device->
Frequency;
544 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (
void *)&outputFormat,
sizeof(outputFormat));
547 ERR(
"AudioUnitSetProperty failed\n");
552 outputFrameCount = device->
UpdateSize * data->sampleRateRatio;
553 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount,
sizeof(outputFrameCount));
556 ERR(
"AudioUnitSetProperty failed: %d\n", err);
561 err = AudioConverterNew(&outputFormat, &requestedFormat, &data->audioConverter);
564 ERR(
"AudioConverterNew failed: %d\n", err);
569 data->resampleBuffer =
malloc(device->
UpdateSize * data->frameSize * data->sampleRateRatio);
573 if(data->bufferList ==
NULL)
577 if(data->ring ==
NULL)
584 free(data->resampleBuffer);
587 if(data->audioConverter)
588 AudioConverterDispose(data->audioConverter);
590 CloseComponent(data->audioUnit);
603 free(data->resampleBuffer);
606 AudioConverterDispose(data->audioConverter);
607 CloseComponent(data->audioUnit);
616 OSStatus err = AudioOutputUnitStart(data->audioUnit);
618 ERR(
"AudioOutputUnitStart failed\n");
624 OSStatus err = AudioOutputUnitStop(data->audioUnit);
626 ERR(
"AudioOutputUnitStop failed\n");
632 AudioBufferList *list;
641 list = alloca(
sizeof(AudioBufferList) +
sizeof(AudioBuffer));
644 list->mNumberBuffers = 1;
645 list->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame;
646 list->mBuffers[0].mDataByteSize = samples * data->frameSize;
647 list->mBuffers[0].mData =
buffer;
652 device, &frameCount, list,
NULL);
655 ERR(
"AudioConverterFillComplexBuffer error: %d\n", err);
static OSStatus ca_capture_conversion_callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData)
static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
static void destroy_buffer_list(AudioBufferList *list)
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
char * strdup(const char *inStr)
static ALCuint ca_available_samples(ALCdevice *device)
const ALCchar * DevFmtChannelsString(enum DevFmtChannels chans)
static void ca_close_capture(ALCdevice *device)
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device)
static int comp(const void *a, const void *b)
void alc_ca_probe(enum DevProbe type)
ALsizei RingBufferSize(RingBuffer *ring)
void AppendCaptureDeviceList(const ALCchar *name)
static ALCboolean ca_reset_playback(ALCdevice *device)
struct RingBuffer RingBuffer
static void ca_stop_playback(ALCdevice *device)
EGLContext EGLenum EGLClientBuffer buffer
static OSStatus ca_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
void SetDefaultWFXChannelOrder(ALCdevice *device)
ALCboolean alc_ca_init(BackendFuncs *func_list)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
static void ca_start_capture(ALCdevice *device)
RingBuffer * CreateRingBuffer(ALsizei frame_size, ALsizei length)
static void ca_stop_capture(ALCdevice *device)
static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName)
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
static const BackendFuncs ca_funcs
enum DevFmtChannels FmtChans
static const ALCchar ca_device[]
void ALCdevice_LockDefault(ALCdevice *device)
static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
GLenum GLenum GLenum input
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
static ALCboolean ca_start_playback(ALCdevice *device)
static void ca_close_playback(ALCdevice *device)
#define ALC_INVALID_VALUE
void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len)
static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
static AudioBufferList * allocate_buffer_list(UInt32 channelCount, UInt32 byteSize)
const ALCchar * DevFmtTypeString(enum DevFmtType type)
void DestroyRingBuffer(RingBuffer *ring)
void ALCdevice_UnlockDefault(ALCdevice *device)
void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
void AppendAllDevicesList(const ALCchar *name)
static __inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type)