2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
31 #include <CoreServices/CoreServices.h>
33 #include <AudioUnit/AudioUnit.h>
34 #include <AudioToolbox/AudioToolbox.h>
36 #include "backends/base.h"
43 ALdouble sampleRateRatio
; // Ratio of hardware sample rate / requested sample rate
44 AudioStreamBasicDescription format
; // This is the OpenAL format as a CoreAudio ASBD
46 AudioConverterRef audioConverter
; // Sample rate converter if needed
47 AudioBufferList
*bufferList
; // Buffer for data coming from the input device
48 ALCvoid
*resampleBuffer
; // Buffer for returned RingBuffer data when resampling
50 ll_ringbuffer_t
*ring
;
53 static const ALCchar ca_device
[] = "CoreAudio Default";
56 static AudioBufferList
* allocate_buffer_list(UInt32 channelCount
, UInt32 byteSize
)
58 AudioBufferList
*list
;
60 list
= calloc(1, sizeof(AudioBufferList
) + sizeof(AudioBuffer
));
63 list
->mNumberBuffers
= 1;
65 list
->mBuffers
[0].mNumberChannels
= channelCount
;
66 list
->mBuffers
[0].mDataByteSize
= byteSize
;
67 list
->mBuffers
[0].mData
= malloc(byteSize
);
68 if(list
->mBuffers
[0].mData
== NULL
)
77 static void destroy_buffer_list(AudioBufferList
* list
)
82 for(i
= 0;i
< list
->mNumberBuffers
;i
++)
83 free(list
->mBuffers
[i
].mData
);
89 typedef struct ALCcoreAudioPlayback
{
90 DERIVE_FROM_TYPE(ALCbackend
);
95 AudioStreamBasicDescription format
; // This is the OpenAL format as a CoreAudio ASBD
96 } ALCcoreAudioPlayback
;
98 static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback
*self
, ALCdevice
*device
);
99 static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback
*self
);
100 static ALCenum
ALCcoreAudioPlayback_open(ALCcoreAudioPlayback
*self
, const ALCchar
*name
);
101 static void ALCcoreAudioPlayback_close(ALCcoreAudioPlayback
*self
);
102 static ALCboolean
ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback
*self
);
103 static ALCboolean
ALCcoreAudioPlayback_start(ALCcoreAudioPlayback
*self
);
104 static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback
*self
);
105 static DECLARE_FORWARD2(ALCcoreAudioPlayback
, ALCbackend
, ALCenum
, captureSamples
, void*, ALCuint
)
106 static DECLARE_FORWARD(ALCcoreAudioPlayback
, ALCbackend
, ALCuint
, availableSamples
)
107 static DECLARE_FORWARD(ALCcoreAudioPlayback
, ALCbackend
, ClockLatency
, getClockLatency
)
108 static DECLARE_FORWARD(ALCcoreAudioPlayback
, ALCbackend
, void, lock
)
109 static DECLARE_FORWARD(ALCcoreAudioPlayback
, ALCbackend
, void, unlock
)
110 DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioPlayback
)
112 DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioPlayback
);
115 static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback
*self
, ALCdevice
*device
)
117 ALCbackend_Construct(STATIC_CAST(ALCbackend
, self
), device
);
118 SET_VTABLE2(ALCcoreAudioPlayback
, ALCbackend
, self
);
121 memset(&self
->format
, 0, sizeof(self
->format
));
124 static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback
*self
)
126 ALCbackend_Destruct(STATIC_CAST(ALCbackend
, self
));
130 static OSStatus
ALCcoreAudioPlayback_MixerProc(void *inRefCon
,
131 AudioUnitRenderActionFlags
* UNUSED(ioActionFlags
), const AudioTimeStamp
* UNUSED(inTimeStamp
),
132 UInt32
UNUSED(inBusNumber
), UInt32
UNUSED(inNumberFrames
), AudioBufferList
*ioData
)
134 ALCcoreAudioPlayback
*self
= inRefCon
;
135 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
137 ALCdevice_Lock(device
);
138 aluMixData(device
, ioData
->mBuffers
[0].mData
,
139 ioData
->mBuffers
[0].mDataByteSize
/ self
->frameSize
);
140 ALCdevice_Unlock(device
);
146 static ALCenum
ALCcoreAudioPlayback_open(ALCcoreAudioPlayback
*self
, const ALCchar
*name
)
148 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
149 AudioComponentDescription desc
;
155 else if(strcmp(name
, ca_device
) != 0)
156 return ALC_INVALID_VALUE
;
158 /* open the default output unit */
159 desc
.componentType
= kAudioUnitType_Output
;
160 desc
.componentSubType
= kAudioUnitSubType_DefaultOutput
;
161 desc
.componentManufacturer
= kAudioUnitManufacturer_Apple
;
162 desc
.componentFlags
= 0;
163 desc
.componentFlagsMask
= 0;
165 comp
= AudioComponentFindNext(NULL
, &desc
);
168 ERR("AudioComponentFindNext failed\n");
169 return ALC_INVALID_VALUE
;
172 err
= AudioComponentInstanceNew(comp
, &self
->audioUnit
);
175 ERR("AudioComponentInstanceNew failed\n");
176 return ALC_INVALID_VALUE
;
179 /* init and start the default audio unit... */
180 err
= AudioUnitInitialize(self
->audioUnit
);
183 ERR("AudioUnitInitialize failed\n");
184 AudioComponentInstanceDispose(self
->audioUnit
);
185 return ALC_INVALID_VALUE
;
188 alstr_copy_cstr(&device
->DeviceName
, name
);
192 static void ALCcoreAudioPlayback_close(ALCcoreAudioPlayback
*self
)
194 AudioUnitUninitialize(self
->audioUnit
);
195 AudioComponentInstanceDispose(self
->audioUnit
);
198 static ALCboolean
ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback
*self
)
200 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
201 AudioStreamBasicDescription streamFormat
;
202 AURenderCallbackStruct input
;
206 err
= AudioUnitUninitialize(self
->audioUnit
);
208 ERR("-- AudioUnitUninitialize failed.\n");
210 /* retrieve default output unit's properties (output side) */
211 size
= sizeof(AudioStreamBasicDescription
);
212 err
= AudioUnitGetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Output
, 0, &streamFormat
, &size
);
213 if(err
!= noErr
|| size
!= sizeof(AudioStreamBasicDescription
))
215 ERR("AudioUnitGetProperty failed\n");
220 TRACE("Output streamFormat of default output unit -\n");
221 TRACE(" streamFormat.mFramesPerPacket = %d\n", streamFormat
.mFramesPerPacket
);
222 TRACE(" streamFormat.mChannelsPerFrame = %d\n", streamFormat
.mChannelsPerFrame
);
223 TRACE(" streamFormat.mBitsPerChannel = %d\n", streamFormat
.mBitsPerChannel
);
224 TRACE(" streamFormat.mBytesPerPacket = %d\n", streamFormat
.mBytesPerPacket
);
225 TRACE(" streamFormat.mBytesPerFrame = %d\n", streamFormat
.mBytesPerFrame
);
226 TRACE(" streamFormat.mSampleRate = %5.0f\n", streamFormat
.mSampleRate
);
229 /* set default output unit's input side to match output side */
230 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Input
, 0, &streamFormat
, size
);
233 ERR("AudioUnitSetProperty failed\n");
237 if(device
->Frequency
!= streamFormat
.mSampleRate
)
239 device
->NumUpdates
= (ALuint
)((ALuint64
)device
->NumUpdates
*
240 streamFormat
.mSampleRate
/
242 device
->Frequency
= streamFormat
.mSampleRate
;
245 /* FIXME: How to tell what channels are what in the output device, and how
246 * to specify what we're giving? eg, 6.0 vs 5.1 */
247 switch(streamFormat
.mChannelsPerFrame
)
250 device
->FmtChans
= DevFmtMono
;
253 device
->FmtChans
= DevFmtStereo
;
256 device
->FmtChans
= DevFmtQuad
;
259 device
->FmtChans
= DevFmtX51
;
262 device
->FmtChans
= DevFmtX61
;
265 device
->FmtChans
= DevFmtX71
;
268 ERR("Unhandled channel count (%d), using Stereo\n", streamFormat
.mChannelsPerFrame
);
269 device
->FmtChans
= DevFmtStereo
;
270 streamFormat
.mChannelsPerFrame
= 2;
273 SetDefaultWFXChannelOrder(device
);
275 /* use channel count and sample rate from the default output unit's current
276 * parameters, but reset everything else */
277 streamFormat
.mFramesPerPacket
= 1;
278 streamFormat
.mFormatFlags
= 0;
279 switch(device
->FmtType
)
282 device
->FmtType
= DevFmtByte
;
285 streamFormat
.mFormatFlags
= kLinearPCMFormatFlagIsSignedInteger
;
286 streamFormat
.mBitsPerChannel
= 8;
289 device
->FmtType
= DevFmtShort
;
292 streamFormat
.mFormatFlags
= kLinearPCMFormatFlagIsSignedInteger
;
293 streamFormat
.mBitsPerChannel
= 16;
296 device
->FmtType
= DevFmtInt
;
299 streamFormat
.mFormatFlags
= kLinearPCMFormatFlagIsSignedInteger
;
300 streamFormat
.mBitsPerChannel
= 32;
303 streamFormat
.mFormatFlags
= kLinearPCMFormatFlagIsFloat
;
304 streamFormat
.mBitsPerChannel
= 32;
307 streamFormat
.mBytesPerFrame
= streamFormat
.mChannelsPerFrame
*
308 streamFormat
.mBitsPerChannel
/ 8;
309 streamFormat
.mBytesPerPacket
= streamFormat
.mBytesPerFrame
;
310 streamFormat
.mFormatID
= kAudioFormatLinearPCM
;
311 streamFormat
.mFormatFlags
|= kAudioFormatFlagsNativeEndian
|
312 kLinearPCMFormatFlagIsPacked
;
314 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Input
, 0, &streamFormat
, sizeof(AudioStreamBasicDescription
));
317 ERR("AudioUnitSetProperty failed\n");
322 self
->frameSize
= FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
, device
->AmbiOrder
);
323 input
.inputProc
= ALCcoreAudioPlayback_MixerProc
;
324 input
.inputProcRefCon
= self
;
326 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_SetRenderCallback
, kAudioUnitScope_Input
, 0, &input
, sizeof(AURenderCallbackStruct
));
329 ERR("AudioUnitSetProperty failed\n");
333 /* init the default audio unit... */
334 err
= AudioUnitInitialize(self
->audioUnit
);
337 ERR("AudioUnitInitialize failed\n");
344 static ALCboolean
ALCcoreAudioPlayback_start(ALCcoreAudioPlayback
*self
)
346 OSStatus err
= AudioOutputUnitStart(self
->audioUnit
);
349 ERR("AudioOutputUnitStart failed\n");
356 static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback
*self
)
358 OSStatus err
= AudioOutputUnitStop(self
->audioUnit
);
360 ERR("AudioOutputUnitStop failed\n");
366 typedef struct ALCcoreAudioCapture
{
367 DERIVE_FROM_TYPE(ALCbackend
);
372 ALdouble sampleRateRatio
; // Ratio of hardware sample rate / requested sample rate
373 AudioStreamBasicDescription format
; // This is the OpenAL format as a CoreAudio ASBD
375 AudioConverterRef audioConverter
; // Sample rate converter if needed
376 AudioBufferList
*bufferList
; // Buffer for data coming from the input device
377 ALCvoid
*resampleBuffer
; // Buffer for returned RingBuffer data when resampling
379 ll_ringbuffer_t
*ring
;
380 } ALCcoreAudioCapture
;
382 static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture
*self
, ALCdevice
*device
);
383 static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture
*self
);
384 static ALCenum
ALCcoreAudioCapture_open(ALCcoreAudioCapture
*self
, const ALCchar
*name
);
385 static void ALCcoreAudioCapture_close(ALCcoreAudioCapture
*self
);
386 static DECLARE_FORWARD(ALCcoreAudioCapture
, ALCbackend
, ALCboolean
, reset
)
387 static ALCboolean
ALCcoreAudioCapture_start(ALCcoreAudioCapture
*self
);
388 static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture
*self
);
389 static ALCenum
ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture
*self
, ALCvoid
*buffer
, ALCuint samples
);
390 static ALCuint
ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture
*self
);
391 static DECLARE_FORWARD(ALCcoreAudioCapture
, ALCbackend
, ClockLatency
, getClockLatency
)
392 static DECLARE_FORWARD(ALCcoreAudioCapture
, ALCbackend
, void, lock
)
393 static DECLARE_FORWARD(ALCcoreAudioCapture
, ALCbackend
, void, unlock
)
394 DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioCapture
)
396 DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioCapture
);
399 static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture
*self
, ALCdevice
*device
)
401 ALCbackend_Construct(STATIC_CAST(ALCbackend
, self
), device
);
402 SET_VTABLE2(ALCcoreAudioCapture
, ALCbackend
, self
);
406 static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture
*self
)
408 ALCbackend_Destruct(STATIC_CAST(ALCbackend
, self
));
412 static OSStatus
ALCcoreAudioCapture_RecordProc(void *inRefCon
,
413 AudioUnitRenderActionFlags
* UNUSED(ioActionFlags
),
414 const AudioTimeStamp
*inTimeStamp
, UInt32
UNUSED(inBusNumber
),
415 UInt32 inNumberFrames
, AudioBufferList
* UNUSED(ioData
))
417 ALCcoreAudioCapture
*self
= inRefCon
;
418 AudioUnitRenderActionFlags flags
= 0;
421 // fill the bufferList with data from the input device
422 err
= AudioUnitRender(self
->audioUnit
, &flags
, inTimeStamp
, 1, inNumberFrames
, self
->bufferList
);
425 ERR("AudioUnitRender error: %d\n", err
);
429 ll_ringbuffer_write(self
->ring
, self
->bufferList
->mBuffers
[0].mData
, inNumberFrames
);
434 static OSStatus
ALCcoreAudioCapture_ConvertCallback(AudioConverterRef
UNUSED(inAudioConverter
),
435 UInt32
*ioNumberDataPackets
, AudioBufferList
*ioData
,
436 AudioStreamPacketDescription
** UNUSED(outDataPacketDescription
),
439 ALCcoreAudioCapture
*self
= inUserData
;
441 // Read from the ring buffer and store temporarily in a large buffer
442 ll_ringbuffer_read(self
->ring
, self
->resampleBuffer
, *ioNumberDataPackets
);
444 // Set the input data
445 ioData
->mNumberBuffers
= 1;
446 ioData
->mBuffers
[0].mNumberChannels
= self
->format
.mChannelsPerFrame
;
447 ioData
->mBuffers
[0].mData
= self
->resampleBuffer
;
448 ioData
->mBuffers
[0].mDataByteSize
= (*ioNumberDataPackets
) * self
->format
.mBytesPerFrame
;
454 static ALCenum
ALCcoreAudioCapture_open(ALCcoreAudioCapture
*self
, const ALCchar
*name
)
456 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
457 AudioStreamBasicDescription requestedFormat
; // The application requested format
458 AudioStreamBasicDescription hardwareFormat
; // The hardware format
459 AudioStreamBasicDescription outputFormat
; // The AudioUnit output format
460 AURenderCallbackStruct input
;
461 AudioComponentDescription desc
;
462 AudioDeviceID inputDevice
;
463 UInt32 outputFrameCount
;
465 AudioObjectPropertyAddress propertyAddress
;
472 else if(strcmp(name
, ca_device
) != 0)
473 return ALC_INVALID_VALUE
;
475 desc
.componentType
= kAudioUnitType_Output
;
476 desc
.componentSubType
= kAudioUnitSubType_HALOutput
;
477 desc
.componentManufacturer
= kAudioUnitManufacturer_Apple
;
478 desc
.componentFlags
= 0;
479 desc
.componentFlagsMask
= 0;
481 // Search for component with given description
482 comp
= AudioComponentFindNext(NULL
, &desc
);
485 ERR("AudioComponentFindNext failed\n");
486 return ALC_INVALID_VALUE
;
489 // Open the component
490 err
= AudioComponentInstanceNew(comp
, &self
->audioUnit
);
493 ERR("AudioComponentInstanceNew failed\n");
497 // Turn off AudioUnit output
499 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioOutputUnitProperty_EnableIO
, kAudioUnitScope_Output
, 0, &enableIO
, sizeof(ALuint
));
502 ERR("AudioUnitSetProperty failed\n");
506 // Turn on AudioUnit input
508 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioOutputUnitProperty_EnableIO
, kAudioUnitScope_Input
, 1, &enableIO
, sizeof(ALuint
));
511 ERR("AudioUnitSetProperty failed\n");
515 // Get the default input device
517 propertySize
= sizeof(AudioDeviceID
);
518 propertyAddress
.mSelector
= kAudioHardwarePropertyDefaultInputDevice
;
519 propertyAddress
.mScope
= kAudioObjectPropertyScopeGlobal
;
520 propertyAddress
.mElement
= kAudioObjectPropertyElementMaster
;
522 err
= AudioObjectGetPropertyData(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &propertySize
, &inputDevice
);
525 ERR("AudioObjectGetPropertyData failed\n");
529 if(inputDevice
== kAudioDeviceUnknown
)
531 ERR("No input device found\n");
535 // Track the input device
536 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioOutputUnitProperty_CurrentDevice
, kAudioUnitScope_Global
, 0, &inputDevice
, sizeof(AudioDeviceID
));
539 ERR("AudioUnitSetProperty failed\n");
543 // set capture callback
544 input
.inputProc
= ALCcoreAudioCapture_RecordProc
;
545 input
.inputProcRefCon
= self
;
547 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioOutputUnitProperty_SetInputCallback
, kAudioUnitScope_Global
, 0, &input
, sizeof(AURenderCallbackStruct
));
550 ERR("AudioUnitSetProperty failed\n");
554 // Initialize the device
555 err
= AudioUnitInitialize(self
->audioUnit
);
558 ERR("AudioUnitInitialize failed\n");
562 // Get the hardware format
563 propertySize
= sizeof(AudioStreamBasicDescription
);
564 err
= AudioUnitGetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Input
, 1, &hardwareFormat
, &propertySize
);
565 if(err
!= noErr
|| propertySize
!= sizeof(AudioStreamBasicDescription
))
567 ERR("AudioUnitGetProperty failed\n");
571 // Set up the requested format description
572 switch(device
->FmtType
)
575 requestedFormat
.mBitsPerChannel
= 8;
576 requestedFormat
.mFormatFlags
= kAudioFormatFlagIsPacked
;
579 requestedFormat
.mBitsPerChannel
= 16;
580 requestedFormat
.mFormatFlags
= kAudioFormatFlagIsSignedInteger
| kAudioFormatFlagsNativeEndian
| kAudioFormatFlagIsPacked
;
583 requestedFormat
.mBitsPerChannel
= 32;
584 requestedFormat
.mFormatFlags
= kAudioFormatFlagIsSignedInteger
| kAudioFormatFlagsNativeEndian
| kAudioFormatFlagIsPacked
;
587 requestedFormat
.mBitsPerChannel
= 32;
588 requestedFormat
.mFormatFlags
= kAudioFormatFlagIsPacked
;
593 ERR("%s samples not supported\n", DevFmtTypeString(device
->FmtType
));
597 switch(device
->FmtChans
)
600 requestedFormat
.mChannelsPerFrame
= 1;
603 requestedFormat
.mChannelsPerFrame
= 2;
612 ERR("%s not supported\n", DevFmtChannelsString(device
->FmtChans
));
616 requestedFormat
.mBytesPerFrame
= requestedFormat
.mChannelsPerFrame
* requestedFormat
.mBitsPerChannel
/ 8;
617 requestedFormat
.mBytesPerPacket
= requestedFormat
.mBytesPerFrame
;
618 requestedFormat
.mSampleRate
= device
->Frequency
;
619 requestedFormat
.mFormatID
= kAudioFormatLinearPCM
;
620 requestedFormat
.mReserved
= 0;
621 requestedFormat
.mFramesPerPacket
= 1;
623 // save requested format description for later use
624 self
->format
= requestedFormat
;
625 self
->frameSize
= FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
, device
->AmbiOrder
);
627 // Use intermediate format for sample rate conversion (outputFormat)
628 // Set sample rate to the same as hardware for resampling later
629 outputFormat
= requestedFormat
;
630 outputFormat
.mSampleRate
= hardwareFormat
.mSampleRate
;
632 // Determine sample rate ratio for resampling
633 self
->sampleRateRatio
= outputFormat
.mSampleRate
/ device
->Frequency
;
635 // The output format should be the requested format, but using the hardware sample rate
636 // This is because the AudioUnit will automatically scale other properties, except for sample rate
637 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Output
, 1, (void *)&outputFormat
, sizeof(outputFormat
));
640 ERR("AudioUnitSetProperty failed\n");
644 // Set the AudioUnit output format frame count
645 outputFrameCount
= device
->UpdateSize
* self
->sampleRateRatio
;
646 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_MaximumFramesPerSlice
, kAudioUnitScope_Output
, 0, &outputFrameCount
, sizeof(outputFrameCount
));
649 ERR("AudioUnitSetProperty failed: %d\n", err
);
653 // Set up sample converter
654 err
= AudioConverterNew(&outputFormat
, &requestedFormat
, &self
->audioConverter
);
657 ERR("AudioConverterNew failed: %d\n", err
);
661 // Create a buffer for use in the resample callback
662 self
->resampleBuffer
= malloc(device
->UpdateSize
* self
->frameSize
* self
->sampleRateRatio
);
664 // Allocate buffer for the AudioUnit output
665 self
->bufferList
= allocate_buffer_list(outputFormat
.mChannelsPerFrame
, device
->UpdateSize
* self
->frameSize
* self
->sampleRateRatio
);
666 if(self
->bufferList
== NULL
)
669 self
->ring
= ll_ringbuffer_create(
670 device
->UpdateSize
*self
->sampleRateRatio
*device
->NumUpdates
+ 1,
673 if(!self
->ring
) goto error
;
675 alstr_copy_cstr(&device
->DeviceName
, name
);
680 ll_ringbuffer_free(self
->ring
);
682 free(self
->resampleBuffer
);
683 destroy_buffer_list(self
->bufferList
);
685 if(self
->audioConverter
)
686 AudioConverterDispose(self
->audioConverter
);
688 AudioComponentInstanceDispose(self
->audioUnit
);
690 return ALC_INVALID_VALUE
;
694 static void ALCcoreAudioCapture_close(ALCcoreAudioCapture
*self
)
696 ll_ringbuffer_free(self
->ring
);
699 free(self
->resampleBuffer
);
701 destroy_buffer_list(self
->bufferList
);
703 AudioConverterDispose(self
->audioConverter
);
704 AudioComponentInstanceDispose(self
->audioUnit
);
707 static ALCboolean
ALCcoreAudioCapture_start(ALCcoreAudioCapture
*self
)
709 OSStatus err
= AudioOutputUnitStart(self
->audioUnit
);
712 ERR("AudioOutputUnitStart failed\n");
718 static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture
*self
)
720 OSStatus err
= AudioOutputUnitStop(self
->audioUnit
);
722 ERR("AudioOutputUnitStop failed\n");
725 static ALCenum
ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture
*self
, ALCvoid
*buffer
, ALCuint samples
)
727 AudioBufferList
*list
;
731 // If no samples are requested, just return
735 // Allocate a temporary AudioBufferList to use as the return resamples data
736 list
= alloca(sizeof(AudioBufferList
) + sizeof(AudioBuffer
));
738 // Point the resampling buffer to the capture buffer
739 list
->mNumberBuffers
= 1;
740 list
->mBuffers
[0].mNumberChannels
= self
->format
.mChannelsPerFrame
;
741 list
->mBuffers
[0].mDataByteSize
= samples
* self
->frameSize
;
742 list
->mBuffers
[0].mData
= buffer
;
744 // Resample into another AudioBufferList
745 frameCount
= samples
;
746 err
= AudioConverterFillComplexBuffer(self
->audioConverter
,
747 ALCcoreAudioCapture_ConvertCallback
, self
, &frameCount
, list
, NULL
751 ERR("AudioConverterFillComplexBuffer error: %d\n", err
);
752 return ALC_INVALID_VALUE
;
757 static ALCuint
ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture
*self
)
759 return ll_ringbuffer_read_space(self
->ring
) / self
->sampleRateRatio
;
763 typedef struct ALCcoreAudioBackendFactory
{
764 DERIVE_FROM_TYPE(ALCbackendFactory
);
765 } ALCcoreAudioBackendFactory
;
766 #define ALCCOREAUDIOBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCcoreAudioBackendFactory, ALCbackendFactory) } }
768 ALCbackendFactory
*ALCcoreAudioBackendFactory_getFactory(void);
770 static ALCboolean
ALCcoreAudioBackendFactory_init(ALCcoreAudioBackendFactory
*self
);
771 static DECLARE_FORWARD(ALCcoreAudioBackendFactory
, ALCbackendFactory
, void, deinit
)
772 static ALCboolean
ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFactory
*self
, ALCbackend_Type type
);
773 static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory
*self
, enum DevProbe type
);
774 static ALCbackend
* ALCcoreAudioBackendFactory_createBackend(ALCcoreAudioBackendFactory
*self
, ALCdevice
*device
, ALCbackend_Type type
);
775 DEFINE_ALCBACKENDFACTORY_VTABLE(ALCcoreAudioBackendFactory
);
778 ALCbackendFactory
*ALCcoreAudioBackendFactory_getFactory(void)
780 static ALCcoreAudioBackendFactory factory
= ALCCOREAUDIOBACKENDFACTORY_INITIALIZER
;
781 return STATIC_CAST(ALCbackendFactory
, &factory
);
785 static ALCboolean
ALCcoreAudioBackendFactory_init(ALCcoreAudioBackendFactory
* UNUSED(self
))
790 static ALCboolean
ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFactory
* UNUSED(self
), ALCbackend_Type type
)
792 if(type
== ALCbackend_Playback
|| ALCbackend_Capture
)
797 static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory
* UNUSED(self
), enum DevProbe type
)
801 case ALL_DEVICE_PROBE
:
802 AppendAllDevicesList(ca_device
);
804 case CAPTURE_DEVICE_PROBE
:
805 AppendCaptureDeviceList(ca_device
);
810 static ALCbackend
* ALCcoreAudioBackendFactory_createBackend(ALCcoreAudioBackendFactory
* UNUSED(self
), ALCdevice
*device
, ALCbackend_Type type
)
812 if(type
== ALCbackend_Playback
)
814 ALCcoreAudioPlayback
*backend
;
815 NEW_OBJ(backend
, ALCcoreAudioPlayback
)(device
);
816 if(!backend
) return NULL
;
817 return STATIC_CAST(ALCbackend
, backend
);
819 if(type
== ALCbackend_Capture
)
821 ALCcoreAudioCapture
*backend
;
822 NEW_OBJ(backend
, ALCcoreAudioCapture
)(device
);
823 if(!backend
) return NULL
;
824 return STATIC_CAST(ALCbackend
, backend
);