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
29 #include "ringbuffer.h"
31 #include <CoreServices/CoreServices.h>
33 #include <AudioUnit/AudioUnit.h>
34 #include <AudioToolbox/AudioToolbox.h>
36 #include "backends/base.h"
39 static const ALCchar ca_device
[] = "CoreAudio Default";
42 typedef struct ALCcoreAudioPlayback
{
43 DERIVE_FROM_TYPE(ALCbackend
);
48 AudioStreamBasicDescription format
; // This is the OpenAL format as a CoreAudio ASBD
49 } ALCcoreAudioPlayback
;
51 static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback
*self
, ALCdevice
*device
);
52 static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback
*self
);
53 static ALCenum
ALCcoreAudioPlayback_open(ALCcoreAudioPlayback
*self
, const ALCchar
*name
);
54 static ALCboolean
ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback
*self
);
55 static ALCboolean
ALCcoreAudioPlayback_start(ALCcoreAudioPlayback
*self
);
56 static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback
*self
);
57 static DECLARE_FORWARD2(ALCcoreAudioPlayback
, ALCbackend
, ALCenum
, captureSamples
, void*, ALCuint
)
58 static DECLARE_FORWARD(ALCcoreAudioPlayback
, ALCbackend
, ALCuint
, availableSamples
)
59 static DECLARE_FORWARD(ALCcoreAudioPlayback
, ALCbackend
, ClockLatency
, getClockLatency
)
60 static DECLARE_FORWARD(ALCcoreAudioPlayback
, ALCbackend
, void, lock
)
61 static DECLARE_FORWARD(ALCcoreAudioPlayback
, ALCbackend
, void, unlock
)
62 DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioPlayback
)
64 DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioPlayback
);
67 static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback
*self
, ALCdevice
*device
)
69 ALCbackend_Construct(STATIC_CAST(ALCbackend
, self
), device
);
70 SET_VTABLE2(ALCcoreAudioPlayback
, ALCbackend
, self
);
73 memset(&self
->format
, 0, sizeof(self
->format
));
76 static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback
*self
)
78 AudioUnitUninitialize(self
->audioUnit
);
79 AudioComponentInstanceDispose(self
->audioUnit
);
81 ALCbackend_Destruct(STATIC_CAST(ALCbackend
, self
));
85 static OSStatus
ALCcoreAudioPlayback_MixerProc(void *inRefCon
,
86 AudioUnitRenderActionFlags
* UNUSED(ioActionFlags
), const AudioTimeStamp
* UNUSED(inTimeStamp
),
87 UInt32
UNUSED(inBusNumber
), UInt32
UNUSED(inNumberFrames
), AudioBufferList
*ioData
)
89 ALCcoreAudioPlayback
*self
= inRefCon
;
90 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
92 ALCcoreAudioPlayback_lock(self
);
93 aluMixData(device
, ioData
->mBuffers
[0].mData
,
94 ioData
->mBuffers
[0].mDataByteSize
/ self
->frameSize
);
95 ALCcoreAudioPlayback_unlock(self
);
101 static ALCenum
ALCcoreAudioPlayback_open(ALCcoreAudioPlayback
*self
, const ALCchar
*name
)
103 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
104 AudioComponentDescription desc
;
110 else if(strcmp(name
, ca_device
) != 0)
111 return ALC_INVALID_VALUE
;
113 /* open the default output unit */
114 desc
.componentType
= kAudioUnitType_Output
;
115 desc
.componentSubType
= kAudioUnitSubType_DefaultOutput
;
116 desc
.componentManufacturer
= kAudioUnitManufacturer_Apple
;
117 desc
.componentFlags
= 0;
118 desc
.componentFlagsMask
= 0;
120 comp
= AudioComponentFindNext(NULL
, &desc
);
123 ERR("AudioComponentFindNext failed\n");
124 return ALC_INVALID_VALUE
;
127 err
= AudioComponentInstanceNew(comp
, &self
->audioUnit
);
130 ERR("AudioComponentInstanceNew failed\n");
131 return ALC_INVALID_VALUE
;
134 /* init and start the default audio unit... */
135 err
= AudioUnitInitialize(self
->audioUnit
);
138 ERR("AudioUnitInitialize failed\n");
139 AudioComponentInstanceDispose(self
->audioUnit
);
140 return ALC_INVALID_VALUE
;
143 alstr_copy_cstr(&device
->DeviceName
, name
);
147 static ALCboolean
ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback
*self
)
149 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
150 AudioStreamBasicDescription streamFormat
;
151 AURenderCallbackStruct input
;
155 err
= AudioUnitUninitialize(self
->audioUnit
);
157 ERR("-- AudioUnitUninitialize failed.\n");
159 /* retrieve default output unit's properties (output side) */
160 size
= sizeof(AudioStreamBasicDescription
);
161 err
= AudioUnitGetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Output
, 0, &streamFormat
, &size
);
162 if(err
!= noErr
|| size
!= sizeof(AudioStreamBasicDescription
))
164 ERR("AudioUnitGetProperty failed\n");
169 TRACE("Output streamFormat of default output unit -\n");
170 TRACE(" streamFormat.mFramesPerPacket = %d\n", streamFormat
.mFramesPerPacket
);
171 TRACE(" streamFormat.mChannelsPerFrame = %d\n", streamFormat
.mChannelsPerFrame
);
172 TRACE(" streamFormat.mBitsPerChannel = %d\n", streamFormat
.mBitsPerChannel
);
173 TRACE(" streamFormat.mBytesPerPacket = %d\n", streamFormat
.mBytesPerPacket
);
174 TRACE(" streamFormat.mBytesPerFrame = %d\n", streamFormat
.mBytesPerFrame
);
175 TRACE(" streamFormat.mSampleRate = %5.0f\n", streamFormat
.mSampleRate
);
178 /* set default output unit's input side to match output side */
179 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Input
, 0, &streamFormat
, size
);
182 ERR("AudioUnitSetProperty failed\n");
186 if(device
->Frequency
!= streamFormat
.mSampleRate
)
188 device
->NumUpdates
= (ALuint
)((ALuint64
)device
->NumUpdates
*
189 streamFormat
.mSampleRate
/
191 device
->Frequency
= streamFormat
.mSampleRate
;
194 /* FIXME: How to tell what channels are what in the output device, and how
195 * to specify what we're giving? eg, 6.0 vs 5.1 */
196 switch(streamFormat
.mChannelsPerFrame
)
199 device
->FmtChans
= DevFmtMono
;
202 device
->FmtChans
= DevFmtStereo
;
205 device
->FmtChans
= DevFmtQuad
;
208 device
->FmtChans
= DevFmtX51
;
211 device
->FmtChans
= DevFmtX61
;
214 device
->FmtChans
= DevFmtX71
;
217 ERR("Unhandled channel count (%d), using Stereo\n", streamFormat
.mChannelsPerFrame
);
218 device
->FmtChans
= DevFmtStereo
;
219 streamFormat
.mChannelsPerFrame
= 2;
222 SetDefaultWFXChannelOrder(device
);
224 /* use channel count and sample rate from the default output unit's current
225 * parameters, but reset everything else */
226 streamFormat
.mFramesPerPacket
= 1;
227 streamFormat
.mFormatFlags
= 0;
228 switch(device
->FmtType
)
231 device
->FmtType
= DevFmtByte
;
234 streamFormat
.mFormatFlags
= kLinearPCMFormatFlagIsSignedInteger
;
235 streamFormat
.mBitsPerChannel
= 8;
238 device
->FmtType
= DevFmtShort
;
241 streamFormat
.mFormatFlags
= kLinearPCMFormatFlagIsSignedInteger
;
242 streamFormat
.mBitsPerChannel
= 16;
245 device
->FmtType
= DevFmtInt
;
248 streamFormat
.mFormatFlags
= kLinearPCMFormatFlagIsSignedInteger
;
249 streamFormat
.mBitsPerChannel
= 32;
252 streamFormat
.mFormatFlags
= kLinearPCMFormatFlagIsFloat
;
253 streamFormat
.mBitsPerChannel
= 32;
256 streamFormat
.mBytesPerFrame
= streamFormat
.mChannelsPerFrame
*
257 streamFormat
.mBitsPerChannel
/ 8;
258 streamFormat
.mBytesPerPacket
= streamFormat
.mBytesPerFrame
;
259 streamFormat
.mFormatID
= kAudioFormatLinearPCM
;
260 streamFormat
.mFormatFlags
|= kAudioFormatFlagsNativeEndian
|
261 kLinearPCMFormatFlagIsPacked
;
263 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Input
, 0, &streamFormat
, sizeof(AudioStreamBasicDescription
));
266 ERR("AudioUnitSetProperty failed\n");
271 self
->frameSize
= FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
, device
->AmbiOrder
);
272 input
.inputProc
= ALCcoreAudioPlayback_MixerProc
;
273 input
.inputProcRefCon
= self
;
275 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_SetRenderCallback
, kAudioUnitScope_Input
, 0, &input
, sizeof(AURenderCallbackStruct
));
278 ERR("AudioUnitSetProperty failed\n");
282 /* init the default audio unit... */
283 err
= AudioUnitInitialize(self
->audioUnit
);
286 ERR("AudioUnitInitialize failed\n");
293 static ALCboolean
ALCcoreAudioPlayback_start(ALCcoreAudioPlayback
*self
)
295 OSStatus err
= AudioOutputUnitStart(self
->audioUnit
);
298 ERR("AudioOutputUnitStart failed\n");
305 static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback
*self
)
307 OSStatus err
= AudioOutputUnitStop(self
->audioUnit
);
309 ERR("AudioOutputUnitStop failed\n");
315 typedef struct ALCcoreAudioCapture
{
316 DERIVE_FROM_TYPE(ALCbackend
);
321 ALdouble sampleRateRatio
; // Ratio of hardware sample rate / requested sample rate
322 AudioStreamBasicDescription format
; // This is the OpenAL format as a CoreAudio ASBD
324 AudioConverterRef audioConverter
; // Sample rate converter if needed
325 AudioBufferList
*bufferList
; // Buffer for data coming from the input device
326 ALCvoid
*resampleBuffer
; // Buffer for returned RingBuffer data when resampling
328 ll_ringbuffer_t
*ring
;
329 } ALCcoreAudioCapture
;
331 static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture
*self
, ALCdevice
*device
);
332 static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture
*self
);
333 static ALCenum
ALCcoreAudioCapture_open(ALCcoreAudioCapture
*self
, const ALCchar
*name
);
334 static DECLARE_FORWARD(ALCcoreAudioCapture
, ALCbackend
, ALCboolean
, reset
)
335 static ALCboolean
ALCcoreAudioCapture_start(ALCcoreAudioCapture
*self
);
336 static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture
*self
);
337 static ALCenum
ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture
*self
, ALCvoid
*buffer
, ALCuint samples
);
338 static ALCuint
ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture
*self
);
339 static DECLARE_FORWARD(ALCcoreAudioCapture
, ALCbackend
, ClockLatency
, getClockLatency
)
340 static DECLARE_FORWARD(ALCcoreAudioCapture
, ALCbackend
, void, lock
)
341 static DECLARE_FORWARD(ALCcoreAudioCapture
, ALCbackend
, void, unlock
)
342 DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioCapture
)
344 DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioCapture
);
347 static AudioBufferList
*allocate_buffer_list(UInt32 channelCount
, UInt32 byteSize
)
349 AudioBufferList
*list
;
351 list
= calloc(1, FAM_SIZE(AudioBufferList
, mBuffers
, 1) + byteSize
);
354 list
->mNumberBuffers
= 1;
356 list
->mBuffers
[0].mNumberChannels
= channelCount
;
357 list
->mBuffers
[0].mDataByteSize
= byteSize
;
358 list
->mBuffers
[0].mData
= &list
->mBuffers
[1];
363 static void destroy_buffer_list(AudioBufferList
*list
)
369 static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture
*self
, ALCdevice
*device
)
371 ALCbackend_Construct(STATIC_CAST(ALCbackend
, self
), device
);
372 SET_VTABLE2(ALCcoreAudioCapture
, ALCbackend
, self
);
375 self
->audioConverter
= NULL
;
376 self
->bufferList
= NULL
;
377 self
->resampleBuffer
= NULL
;
381 static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture
*self
)
383 ll_ringbuffer_free(self
->ring
);
386 free(self
->resampleBuffer
);
387 self
->resampleBuffer
= NULL
;
389 destroy_buffer_list(self
->bufferList
);
390 self
->bufferList
= NULL
;
392 if(self
->audioConverter
)
393 AudioConverterDispose(self
->audioConverter
);
394 self
->audioConverter
= NULL
;
397 AudioComponentInstanceDispose(self
->audioUnit
);
400 ALCbackend_Destruct(STATIC_CAST(ALCbackend
, self
));
404 static OSStatus
ALCcoreAudioCapture_RecordProc(void *inRefCon
,
405 AudioUnitRenderActionFlags
* UNUSED(ioActionFlags
),
406 const AudioTimeStamp
*inTimeStamp
, UInt32
UNUSED(inBusNumber
),
407 UInt32 inNumberFrames
, AudioBufferList
* UNUSED(ioData
))
409 ALCcoreAudioCapture
*self
= inRefCon
;
410 AudioUnitRenderActionFlags flags
= 0;
413 // fill the bufferList with data from the input device
414 err
= AudioUnitRender(self
->audioUnit
, &flags
, inTimeStamp
, 1, inNumberFrames
, self
->bufferList
);
417 ERR("AudioUnitRender error: %d\n", err
);
421 ll_ringbuffer_write(self
->ring
, self
->bufferList
->mBuffers
[0].mData
, inNumberFrames
);
426 static OSStatus
ALCcoreAudioCapture_ConvertCallback(AudioConverterRef
UNUSED(inAudioConverter
),
427 UInt32
*ioNumberDataPackets
, AudioBufferList
*ioData
,
428 AudioStreamPacketDescription
** UNUSED(outDataPacketDescription
),
431 ALCcoreAudioCapture
*self
= inUserData
;
433 // Read from the ring buffer and store temporarily in a large buffer
434 ll_ringbuffer_read(self
->ring
, self
->resampleBuffer
, *ioNumberDataPackets
);
436 // Set the input data
437 ioData
->mNumberBuffers
= 1;
438 ioData
->mBuffers
[0].mNumberChannels
= self
->format
.mChannelsPerFrame
;
439 ioData
->mBuffers
[0].mData
= self
->resampleBuffer
;
440 ioData
->mBuffers
[0].mDataByteSize
= (*ioNumberDataPackets
) * self
->format
.mBytesPerFrame
;
446 static ALCenum
ALCcoreAudioCapture_open(ALCcoreAudioCapture
*self
, const ALCchar
*name
)
448 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
449 AudioStreamBasicDescription requestedFormat
; // The application requested format
450 AudioStreamBasicDescription hardwareFormat
; // The hardware format
451 AudioStreamBasicDescription outputFormat
; // The AudioUnit output format
452 AURenderCallbackStruct input
;
453 AudioComponentDescription desc
;
454 AudioDeviceID inputDevice
;
455 UInt32 outputFrameCount
;
457 AudioObjectPropertyAddress propertyAddress
;
464 else if(strcmp(name
, ca_device
) != 0)
465 return ALC_INVALID_VALUE
;
467 desc
.componentType
= kAudioUnitType_Output
;
468 desc
.componentSubType
= kAudioUnitSubType_HALOutput
;
469 desc
.componentManufacturer
= kAudioUnitManufacturer_Apple
;
470 desc
.componentFlags
= 0;
471 desc
.componentFlagsMask
= 0;
473 // Search for component with given description
474 comp
= AudioComponentFindNext(NULL
, &desc
);
477 ERR("AudioComponentFindNext failed\n");
478 return ALC_INVALID_VALUE
;
481 // Open the component
482 err
= AudioComponentInstanceNew(comp
, &self
->audioUnit
);
485 ERR("AudioComponentInstanceNew failed\n");
489 // Turn off AudioUnit output
491 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioOutputUnitProperty_EnableIO
, kAudioUnitScope_Output
, 0, &enableIO
, sizeof(ALuint
));
494 ERR("AudioUnitSetProperty failed\n");
498 // Turn on AudioUnit input
500 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioOutputUnitProperty_EnableIO
, kAudioUnitScope_Input
, 1, &enableIO
, sizeof(ALuint
));
503 ERR("AudioUnitSetProperty failed\n");
507 // Get the default input device
509 propertySize
= sizeof(AudioDeviceID
);
510 propertyAddress
.mSelector
= kAudioHardwarePropertyDefaultInputDevice
;
511 propertyAddress
.mScope
= kAudioObjectPropertyScopeGlobal
;
512 propertyAddress
.mElement
= kAudioObjectPropertyElementMaster
;
514 err
= AudioObjectGetPropertyData(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &propertySize
, &inputDevice
);
517 ERR("AudioObjectGetPropertyData failed\n");
521 if(inputDevice
== kAudioDeviceUnknown
)
523 ERR("No input device found\n");
527 // Track the input device
528 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioOutputUnitProperty_CurrentDevice
, kAudioUnitScope_Global
, 0, &inputDevice
, sizeof(AudioDeviceID
));
531 ERR("AudioUnitSetProperty failed\n");
535 // set capture callback
536 input
.inputProc
= ALCcoreAudioCapture_RecordProc
;
537 input
.inputProcRefCon
= self
;
539 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioOutputUnitProperty_SetInputCallback
, kAudioUnitScope_Global
, 0, &input
, sizeof(AURenderCallbackStruct
));
542 ERR("AudioUnitSetProperty failed\n");
546 // Initialize the device
547 err
= AudioUnitInitialize(self
->audioUnit
);
550 ERR("AudioUnitInitialize failed\n");
554 // Get the hardware format
555 propertySize
= sizeof(AudioStreamBasicDescription
);
556 err
= AudioUnitGetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Input
, 1, &hardwareFormat
, &propertySize
);
557 if(err
!= noErr
|| propertySize
!= sizeof(AudioStreamBasicDescription
))
559 ERR("AudioUnitGetProperty failed\n");
563 // Set up the requested format description
564 switch(device
->FmtType
)
567 requestedFormat
.mBitsPerChannel
= 8;
568 requestedFormat
.mFormatFlags
= kAudioFormatFlagIsPacked
;
571 requestedFormat
.mBitsPerChannel
= 16;
572 requestedFormat
.mFormatFlags
= kAudioFormatFlagIsSignedInteger
| kAudioFormatFlagsNativeEndian
| kAudioFormatFlagIsPacked
;
575 requestedFormat
.mBitsPerChannel
= 32;
576 requestedFormat
.mFormatFlags
= kAudioFormatFlagIsSignedInteger
| kAudioFormatFlagsNativeEndian
| kAudioFormatFlagIsPacked
;
579 requestedFormat
.mBitsPerChannel
= 32;
580 requestedFormat
.mFormatFlags
= kAudioFormatFlagIsPacked
;
585 ERR("%s samples not supported\n", DevFmtTypeString(device
->FmtType
));
589 switch(device
->FmtChans
)
592 requestedFormat
.mChannelsPerFrame
= 1;
595 requestedFormat
.mChannelsPerFrame
= 2;
604 ERR("%s not supported\n", DevFmtChannelsString(device
->FmtChans
));
608 requestedFormat
.mBytesPerFrame
= requestedFormat
.mChannelsPerFrame
* requestedFormat
.mBitsPerChannel
/ 8;
609 requestedFormat
.mBytesPerPacket
= requestedFormat
.mBytesPerFrame
;
610 requestedFormat
.mSampleRate
= device
->Frequency
;
611 requestedFormat
.mFormatID
= kAudioFormatLinearPCM
;
612 requestedFormat
.mReserved
= 0;
613 requestedFormat
.mFramesPerPacket
= 1;
615 // save requested format description for later use
616 self
->format
= requestedFormat
;
617 self
->frameSize
= FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
, device
->AmbiOrder
);
619 // Use intermediate format for sample rate conversion (outputFormat)
620 // Set sample rate to the same as hardware for resampling later
621 outputFormat
= requestedFormat
;
622 outputFormat
.mSampleRate
= hardwareFormat
.mSampleRate
;
624 // Determine sample rate ratio for resampling
625 self
->sampleRateRatio
= outputFormat
.mSampleRate
/ device
->Frequency
;
627 // The output format should be the requested format, but using the hardware sample rate
628 // This is because the AudioUnit will automatically scale other properties, except for sample rate
629 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Output
, 1, (void *)&outputFormat
, sizeof(outputFormat
));
632 ERR("AudioUnitSetProperty failed\n");
636 // Set the AudioUnit output format frame count
637 outputFrameCount
= device
->UpdateSize
* self
->sampleRateRatio
;
638 err
= AudioUnitSetProperty(self
->audioUnit
, kAudioUnitProperty_MaximumFramesPerSlice
, kAudioUnitScope_Output
, 0, &outputFrameCount
, sizeof(outputFrameCount
));
641 ERR("AudioUnitSetProperty failed: %d\n", err
);
645 // Set up sample converter
646 err
= AudioConverterNew(&outputFormat
, &requestedFormat
, &self
->audioConverter
);
649 ERR("AudioConverterNew failed: %d\n", err
);
653 // Create a buffer for use in the resample callback
654 self
->resampleBuffer
= malloc(device
->UpdateSize
* self
->frameSize
* self
->sampleRateRatio
);
656 // Allocate buffer for the AudioUnit output
657 self
->bufferList
= allocate_buffer_list(outputFormat
.mChannelsPerFrame
, device
->UpdateSize
* self
->frameSize
* self
->sampleRateRatio
);
658 if(self
->bufferList
== NULL
)
661 self
->ring
= ll_ringbuffer_create(
662 (size_t)ceil(device
->UpdateSize
*self
->sampleRateRatio
*device
->NumUpdates
),
663 self
->frameSize
, false
665 if(!self
->ring
) goto error
;
667 alstr_copy_cstr(&device
->DeviceName
, name
);
672 ll_ringbuffer_free(self
->ring
);
674 free(self
->resampleBuffer
);
675 self
->resampleBuffer
= NULL
;
676 destroy_buffer_list(self
->bufferList
);
677 self
->bufferList
= NULL
;
679 if(self
->audioConverter
)
680 AudioConverterDispose(self
->audioConverter
);
681 self
->audioConverter
= NULL
;
683 AudioComponentInstanceDispose(self
->audioUnit
);
686 return ALC_INVALID_VALUE
;
690 static ALCboolean
ALCcoreAudioCapture_start(ALCcoreAudioCapture
*self
)
692 OSStatus err
= AudioOutputUnitStart(self
->audioUnit
);
695 ERR("AudioOutputUnitStart failed\n");
701 static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture
*self
)
703 OSStatus err
= AudioOutputUnitStop(self
->audioUnit
);
705 ERR("AudioOutputUnitStop failed\n");
708 static ALCenum
ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture
*self
, ALCvoid
*buffer
, ALCuint samples
)
711 ALbyte _
[sizeof(AudioBufferList
) + sizeof(AudioBuffer
)];
712 AudioBufferList list
;
713 } audiobuf
= { { 0 } };
717 // If no samples are requested, just return
718 if(samples
== 0) return ALC_NO_ERROR
;
720 // Point the resampling buffer to the capture buffer
721 audiobuf
.list
.mNumberBuffers
= 1;
722 audiobuf
.list
.mBuffers
[0].mNumberChannels
= self
->format
.mChannelsPerFrame
;
723 audiobuf
.list
.mBuffers
[0].mDataByteSize
= samples
* self
->frameSize
;
724 audiobuf
.list
.mBuffers
[0].mData
= buffer
;
726 // Resample into another AudioBufferList
727 frameCount
= samples
;
728 err
= AudioConverterFillComplexBuffer(self
->audioConverter
,
729 ALCcoreAudioCapture_ConvertCallback
, self
, &frameCount
, &audiobuf
.list
, NULL
733 ERR("AudioConverterFillComplexBuffer error: %d\n", err
);
734 return ALC_INVALID_VALUE
;
739 static ALCuint
ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture
*self
)
741 return ll_ringbuffer_read_space(self
->ring
) / self
->sampleRateRatio
;
745 typedef struct ALCcoreAudioBackendFactory
{
746 DERIVE_FROM_TYPE(ALCbackendFactory
);
747 } ALCcoreAudioBackendFactory
;
748 #define ALCCOREAUDIOBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCcoreAudioBackendFactory, ALCbackendFactory) } }
750 ALCbackendFactory
*ALCcoreAudioBackendFactory_getFactory(void);
752 static ALCboolean
ALCcoreAudioBackendFactory_init(ALCcoreAudioBackendFactory
*self
);
753 static DECLARE_FORWARD(ALCcoreAudioBackendFactory
, ALCbackendFactory
, void, deinit
)
754 static ALCboolean
ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFactory
*self
, ALCbackend_Type type
);
755 static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory
*self
, enum DevProbe type
);
756 static ALCbackend
* ALCcoreAudioBackendFactory_createBackend(ALCcoreAudioBackendFactory
*self
, ALCdevice
*device
, ALCbackend_Type type
);
757 DEFINE_ALCBACKENDFACTORY_VTABLE(ALCcoreAudioBackendFactory
);
760 ALCbackendFactory
*ALCcoreAudioBackendFactory_getFactory(void)
762 static ALCcoreAudioBackendFactory factory
= ALCCOREAUDIOBACKENDFACTORY_INITIALIZER
;
763 return STATIC_CAST(ALCbackendFactory
, &factory
);
767 static ALCboolean
ALCcoreAudioBackendFactory_init(ALCcoreAudioBackendFactory
* UNUSED(self
))
772 static ALCboolean
ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFactory
* UNUSED(self
), ALCbackend_Type type
)
774 if(type
== ALCbackend_Playback
|| ALCbackend_Capture
)
779 static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory
* UNUSED(self
), enum DevProbe type
)
783 case ALL_DEVICE_PROBE
:
784 AppendAllDevicesList(ca_device
);
786 case CAPTURE_DEVICE_PROBE
:
787 AppendCaptureDeviceList(ca_device
);
792 static ALCbackend
* ALCcoreAudioBackendFactory_createBackend(ALCcoreAudioBackendFactory
* UNUSED(self
), ALCdevice
*device
, ALCbackend_Type type
)
794 if(type
== ALCbackend_Playback
)
796 ALCcoreAudioPlayback
*backend
;
797 NEW_OBJ(backend
, ALCcoreAudioPlayback
)(device
);
798 if(!backend
) return NULL
;
799 return STATIC_CAST(ALCbackend
, backend
);
801 if(type
== ALCbackend_Capture
)
803 ALCcoreAudioCapture
*backend
;
804 NEW_OBJ(backend
, ALCcoreAudioCapture
)(device
);
805 if(!backend
) return NULL
;
806 return STATIC_CAST(ALCbackend
, backend
);