Use logging macros in the coreaudio backend
[openal-soft/android.git] / Alc / coreaudio.c
blob0fa8a0ff1f7508445a7f30e9ba2a7dbd222b1e6f
1 /**
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
27 #include "alMain.h"
28 #include "AL/al.h"
29 #include "AL/alc.h"
31 #include <CoreServices/CoreServices.h>
32 #include <unistd.h>
33 #include <AudioUnit/AudioUnit.h>
34 #include <AudioToolbox/AudioToolbox.h>
37 typedef struct {
38 AudioUnit audioUnit;
40 ALuint frameSize;
41 ALdouble sampleRateRatio; // Ratio of hardware sample rate / requested sample rate
42 AudioStreamBasicDescription format; // This is the OpenAL format as a CoreAudio ASBD
44 AudioConverterRef audioConverter; // Sample rate converter if needed
45 AudioBufferList *bufferList; // Buffer for data coming from the input device
46 ALCvoid *resampleBuffer; // Buffer for returned RingBuffer data when resampling
48 RingBuffer *ring;
49 } ca_data;
51 static const ALCchar ca_device[] = "CoreAudio Default";
54 static void destroy_buffer_list(AudioBufferList* list)
56 if(list)
58 for(UInt32 i = 0;i < list->mNumberBuffers;i++)
59 free(list->mBuffers[i].mData);
60 free(list);
64 static AudioBufferList* allocate_buffer_list(UInt32 channelCount, UInt32 byteSize)
66 AudioBufferList *list;
68 list = calloc(1, sizeof(AudioBufferList) + sizeof(AudioBuffer));
69 if(list)
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)
78 free(list);
79 list = NULL;
82 return list;
85 static OSStatus ca_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp,
86 UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
88 ALCdevice *device = (ALCdevice*)inRefCon;
89 ca_data *data = (ca_data*)device->ExtraData;
91 aluMixData(device, ioData->mBuffers[0].mData,
92 ioData->mBuffers[0].mDataByteSize / data->frameSize);
94 return noErr;
97 static OSStatus ca_capture_conversion_callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets,
98 AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void* inUserData)
100 ALCdevice *device = (ALCdevice*)inUserData;
101 ca_data *data = (ca_data*)device->ExtraData;
103 // Read from the ring buffer and store temporarily in a large buffer
104 ReadRingBuffer(data->ring, data->resampleBuffer, (ALsizei)(*ioNumberDataPackets));
106 // Set the input data
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;
112 return noErr;
115 static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
116 const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
117 UInt32 inNumberFrames, AudioBufferList *ioData)
119 ALCdevice *device = (ALCdevice*)inRefCon;
120 ca_data *data = (ca_data*)device->ExtraData;
121 AudioUnitRenderActionFlags flags = 0;
122 OSStatus err;
124 // fill the bufferList with data from the input device
125 err = AudioUnitRender(data->audioUnit, &flags, inTimeStamp, 1, inNumberFrames, data->bufferList);
126 if(err != noErr)
128 ERROR("AudioUnitRender error: %d\n", err);
129 return err;
132 WriteRingBuffer(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames);
134 return noErr;
137 static ALCboolean ca_open_playback(ALCdevice *device, const ALCchar *deviceName)
139 ComponentDescription desc;
140 Component comp;
141 ca_data *data;
142 OSStatus err;
144 if(!deviceName)
145 deviceName = ca_device;
146 else if(strcmp(deviceName, ca_device) != 0)
147 return ALC_FALSE;
149 /* open the default output unit */
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);
157 if(comp == NULL)
159 ERROR("FindNextComponent failed\n");
160 return ALC_FALSE;
163 data = calloc(1, sizeof(*data));
164 device->ExtraData = data;
166 err = OpenAComponent(comp, &data->audioUnit);
167 if(err != noErr)
169 ERROR("OpenAComponent failed\n");
170 free(data);
171 device->ExtraData = NULL;
172 return ALC_FALSE;
175 return ALC_TRUE;
178 static void ca_close_playback(ALCdevice *device)
180 ca_data *data = (ca_data*)device->ExtraData;
182 CloseComponent(data->audioUnit);
184 free(data);
185 device->ExtraData = NULL;
188 static ALCboolean ca_reset_playback(ALCdevice *device)
190 ca_data *data = (ca_data*)device->ExtraData;
191 AudioStreamBasicDescription streamFormat;
192 AURenderCallbackStruct input;
193 OSStatus err;
194 UInt32 size;
196 /* init and start the default audio unit... */
197 err = AudioUnitInitialize(data->audioUnit);
198 if(err != noErr)
200 ERROR("AudioUnitInitialize failed\n");
201 return ALC_FALSE;
204 err = AudioOutputUnitStart(data->audioUnit);
205 if(err != noErr)
207 ERROR("AudioOutputUnitStart failed\n");
208 return ALC_FALSE;
211 /* retrieve default output unit's properties (output side) */
212 size = sizeof(AudioStreamBasicDescription);
213 err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &size);
214 if(err != noErr || size != sizeof(AudioStreamBasicDescription))
216 ERROR("AudioUnitGetProperty failed\n");
217 return ALC_FALSE;
220 #if 0
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);
228 #endif
230 /* set default output unit's input side to match output side */
231 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size);
232 if(err != noErr)
234 ERROR("AudioUnitSetProperty failed\n");
235 return ALC_FALSE;
238 if(device->Frequency != streamFormat.mSampleRate)
240 if((device->Flags&DEVICE_FREQUENCY_REQUEST))
241 ERROR("CoreAudio does not support changing sample rates (wanted %dhz, got %dhz)\n", device->Frequency, streamFormat.mSampleRate);
242 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
244 device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
245 streamFormat.mSampleRate /
246 device->Frequency);
247 device->Frequency = streamFormat.mSampleRate;
250 /* FIXME: How to tell what channels are what in the output device, and how
251 * to specify what we're giving? eg, 6.0 vs 5.1 */
252 switch(streamFormat.mChannelsPerFrame)
254 case 1:
255 if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
256 device->FmtChans != DevFmtMono)
258 ERROR("Failed to set %s, got Mono instead\n", DevFmtChannelsString(device->FmtChans));
259 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
261 device->FmtChans = DevFmtMono;
262 break;
263 case 2:
264 if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
265 device->FmtChans != DevFmtStereo)
267 ERROR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(device->FmtChans));
268 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
270 device->FmtChans = DevFmtStereo;
271 break;
272 case 4:
273 if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
274 device->FmtChans != DevFmtQuad)
276 ERROR("Failed to set %s, got Quad instead\n", DevFmtChannelsString(device->FmtChans));
277 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
279 device->FmtChans = DevFmtQuad;
280 break;
281 case 6:
282 if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
283 device->FmtChans != DevFmtX51)
285 ERROR("Failed to set %s, got 5.1 Surround instead\n", DevFmtChannelsString(device->FmtChans));
286 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
288 device->FmtChans = DevFmtX51;
289 break;
290 case 7:
291 if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
292 device->FmtChans != DevFmtX61)
294 ERROR("Failed to set %s, got 6.1 Surround instead\n", DevFmtChannelsString(device->FmtChans));
295 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
297 device->FmtChans = DevFmtX61;
298 break;
299 case 8:
300 if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
301 device->FmtChans != DevFmtX71)
303 ERROR("Failed to set %s, got 7.1 Surround instead\n", DevFmtChannelsString(device->FmtChans));
304 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
306 device->FmtChans = DevFmtX71;
307 break;
308 default:
309 ERROR("Unhandled channel count (%d), using Stereo\n", streamFormat.mChannelsPerFrame);
310 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
311 device->FmtChans = DevFmtStereo;
312 streamFormat.mChannelsPerFrame = 2;
313 break;
315 SetDefaultWFXChannelOrder(device);
317 /* use channel count and sample rate from the default output unit's current
318 * parameters, but reset everything else */
319 streamFormat.mFramesPerPacket = 1;
320 switch(device->FmtType)
322 case DevFmtUByte:
323 device->FmtType = DevFmtByte;
324 /* fall-through */
325 case DevFmtByte:
326 streamFormat.mBitsPerChannel = 8;
327 streamFormat.mBytesPerPacket = streamFormat.mChannelsPerFrame;
328 streamFormat.mBytesPerFrame = streamFormat.mChannelsPerFrame;
329 break;
330 case DevFmtUShort:
331 case DevFmtFloat:
332 device->FmtType = DevFmtShort;
333 /* fall-through */
334 case DevFmtShort:
335 streamFormat.mBitsPerChannel = 16;
336 streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
337 streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
338 break;
340 streamFormat.mFormatID = kAudioFormatLinearPCM;
341 streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
342 kAudioFormatFlagsNativeEndian |
343 kLinearPCMFormatFlagIsPacked;
345 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription));
346 if(err != noErr)
348 ERROR("AudioUnitSetProperty failed\n");
349 return ALC_FALSE;
352 /* setup callback */
353 data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
354 input.inputProc = ca_callback;
355 input.inputProcRefCon = device;
357 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct));
358 if(err != noErr)
360 ERROR("AudioUnitSetProperty failed\n");
361 return ALC_FALSE;
364 return ALC_TRUE;
367 static void ca_stop_playback(ALCdevice *device)
369 ca_data *data = (ca_data*)device->ExtraData;
370 OSStatus err;
372 AudioOutputUnitStop(data->audioUnit);
373 err = AudioUnitUninitialize(data->audioUnit);
374 if(err != noErr)
375 ERROR("-- AudioUnitUninitialize failed.\n");
378 static ALCboolean ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
380 AudioStreamBasicDescription requestedFormat; // The application requested format
381 AudioStreamBasicDescription hardwareFormat; // The hardware format
382 AudioStreamBasicDescription outputFormat; // The AudioUnit output format
383 AURenderCallbackStruct input;
384 ComponentDescription desc;
385 AudioDeviceID inputDevice;
386 UInt32 outputFrameCount;
387 UInt32 propertySize;
388 UInt32 enableIO;
389 Component comp;
390 ca_data *data;
391 OSStatus err;
393 desc.componentType = kAudioUnitType_Output;
394 desc.componentSubType = kAudioUnitSubType_HALOutput;
395 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
396 desc.componentFlags = 0;
397 desc.componentFlagsMask = 0;
399 // Search for component with given description
400 comp = FindNextComponent(NULL, &desc);
401 if(comp == NULL)
403 ERROR("FindNextComponent failed\n");
404 return ALC_FALSE;
407 data = calloc(1, sizeof(*data));
408 device->ExtraData = data;
410 // Open the component
411 err = OpenAComponent(comp, &data->audioUnit);
412 if(err != noErr)
414 ERROR("OpenAComponent failed\n");
415 goto error;
418 // Turn off AudioUnit output
419 enableIO = 0;
420 err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint));
421 if(err != noErr)
423 ERROR("AudioUnitSetProperty failed\n");
424 goto error;
427 // Turn on AudioUnit input
428 enableIO = 1;
429 err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint));
430 if(err != noErr)
432 ERROR("AudioUnitSetProperty failed\n");
433 goto error;
436 // Get the default input device
437 propertySize = sizeof(AudioDeviceID);
438 err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &inputDevice);
439 if(err != noErr)
441 ERROR("AudioHardwareGetProperty failed\n");
442 goto error;
445 if(inputDevice == kAudioDeviceUnknown)
447 ERROR("No input device found\n");
448 goto error;
451 // Track the input device
452 err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID));
453 if(err != noErr)
455 ERROR("AudioUnitSetProperty failed\n");
456 goto error;
459 // set capture callback
460 input.inputProc = ca_capture_callback;
461 input.inputProcRefCon = device;
463 err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct));
464 if(err != noErr)
466 ERROR("AudioUnitSetProperty failed\n");
467 goto error;
470 // Initialize the device
471 err = AudioUnitInitialize(data->audioUnit);
472 if(err != noErr)
474 ERROR("AudioUnitInitialize failed\n");
475 goto error;
478 // Get the hardware format
479 propertySize = sizeof(AudioStreamBasicDescription);
480 err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize);
481 if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription))
483 ERROR("AudioUnitGetProperty failed\n");
484 goto error;
487 // Set up the requested format description
488 switch(device->FmtType)
490 case DevFmtUByte:
491 requestedFormat.mBitsPerChannel = 8;
492 requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
493 break;
494 case DevFmtShort:
495 requestedFormat.mBitsPerChannel = 16;
496 requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
497 break;
498 case DevFmtFloat:
499 requestedFormat.mBitsPerChannel = 32;
500 requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
501 break;
502 case DevFmtByte:
503 case DevFmtUShort:
504 ERROR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
505 goto error;
508 switch(device->FmtChans)
510 case DevFmtMono:
511 requestedFormat.mChannelsPerFrame = 1;
512 break;
513 case DevFmtStereo:
514 requestedFormat.mChannelsPerFrame = 2;
515 break;
517 case DevFmtQuad:
518 case DevFmtX51:
519 case DevFmtX51Side:
520 case DevFmtX61:
521 case DevFmtX71:
522 ERROR("%s not supported\n", DevFmtChannelsString(device->FmtChans));
523 goto error;
526 requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8;
527 requestedFormat.mBytesPerPacket = requestedFormat.mBytesPerFrame;
528 requestedFormat.mSampleRate = device->Frequency;
529 requestedFormat.mFormatID = kAudioFormatLinearPCM;
530 requestedFormat.mReserved = 0;
531 requestedFormat.mFramesPerPacket = 1;
533 // save requested format description for later use
534 data->format = requestedFormat;
535 data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
537 // Use intermediate format for sample rate conversion (outputFormat)
538 // Set sample rate to the same as hardware for resampling later
539 outputFormat = requestedFormat;
540 outputFormat.mSampleRate = hardwareFormat.mSampleRate;
542 // Determine sample rate ratio for resampling
543 data->sampleRateRatio = outputFormat.mSampleRate / device->Frequency;
545 // The output format should be the requested format, but using the hardware sample rate
546 // This is because the AudioUnit will automatically scale other properties, except for sample rate
547 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat));
548 if(err != noErr)
550 ERROR("AudioUnitSetProperty failed\n");
551 goto error;
554 // Set the AudioUnit output format frame count
555 outputFrameCount = device->UpdateSize * data->sampleRateRatio;
556 err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount));
557 if(err != noErr)
559 ERROR("AudioUnitSetProperty failed: %d\n", err);
560 goto error;
563 // Set up sample converter
564 err = AudioConverterNew(&outputFormat, &requestedFormat, &data->audioConverter);
565 if(err != noErr)
567 ERROR("AudioConverterNew failed: %d\n", err);
568 goto error;
571 // Create a buffer for use in the resample callback
572 data->resampleBuffer = malloc(device->UpdateSize * data->frameSize * data->sampleRateRatio);
574 // Allocate buffer for the AudioUnit output
575 data->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * data->frameSize * data->sampleRateRatio);
576 if(data->bufferList == NULL)
578 alcSetError(device, ALC_OUT_OF_MEMORY);
579 goto error;
582 data->ring = CreateRingBuffer(data->frameSize, (device->UpdateSize * data->sampleRateRatio) * device->NumUpdates);
583 if(data->ring == NULL)
585 alcSetError(device, ALC_OUT_OF_MEMORY);
586 goto error;
589 return ALC_TRUE;
591 error:
592 DestroyRingBuffer(data->ring);
593 free(data->resampleBuffer);
594 destroy_buffer_list(data->bufferList);
596 if(data->audioConverter)
597 AudioConverterDispose(data->audioConverter);
598 if(data->audioUnit)
599 CloseComponent(data->audioUnit);
601 free(data);
602 device->ExtraData = NULL;
604 return ALC_FALSE;
607 static void ca_close_capture(ALCdevice *device)
609 ca_data *data = (ca_data*)device->ExtraData;
611 DestroyRingBuffer(data->ring);
612 free(data->resampleBuffer);
613 destroy_buffer_list(data->bufferList);
615 AudioConverterDispose(data->audioConverter);
616 CloseComponent(data->audioUnit);
618 free(data);
619 device->ExtraData = NULL;
622 static void ca_start_capture(ALCdevice *device)
624 ca_data *data = (ca_data*)device->ExtraData;
625 OSStatus err = AudioOutputUnitStart(data->audioUnit);
626 if(err != noErr)
627 ERROR("AudioOutputUnitStart failed\n");
630 static void ca_stop_capture(ALCdevice *device)
632 ca_data *data = (ca_data*)device->ExtraData;
633 OSStatus err = AudioOutputUnitStop(data->audioUnit);
634 if(err != noErr)
635 ERROR("AudioOutputUnitStop failed\n");
638 static ALCuint ca_available_samples(ALCdevice *device)
640 ca_data *data = device->ExtraData;
641 return RingBufferSize(data->ring) / data->sampleRateRatio;
644 static void ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
646 ca_data *data = (ca_data*)device->ExtraData;
648 if(samples <= ca_available_samples(device))
650 AudioBufferList *list;
651 UInt32 frameCount;
652 OSStatus err;
654 // If no samples are requested, just return
655 if(samples == 0)
656 return;
658 // Allocate a temporary AudioBufferList to use as the return resamples data
659 list = alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer));
661 // Point the resampling buffer to the capture buffer
662 list->mNumberBuffers = 1;
663 list->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame;
664 list->mBuffers[0].mDataByteSize = samples * data->frameSize;
665 list->mBuffers[0].mData = buffer;
667 // Resample into another AudioBufferList
668 frameCount = samples;
669 err = AudioConverterFillComplexBuffer(data->audioConverter, ca_capture_conversion_callback, device,
670 &frameCount, list, NULL);
671 if(err != noErr)
673 ERROR("AudioConverterFillComplexBuffer error: %d\n", err);
674 alcSetError(device, ALC_INVALID_VALUE);
677 else
678 alcSetError(device, ALC_INVALID_VALUE);
681 static const BackendFuncs ca_funcs = {
682 ca_open_playback,
683 ca_close_playback,
684 ca_reset_playback,
685 ca_stop_playback,
686 ca_open_capture,
687 ca_close_capture,
688 ca_start_capture,
689 ca_stop_capture,
690 ca_capture_samples,
691 ca_available_samples
694 void alc_ca_init(BackendFuncs *func_list)
696 *func_list = ca_funcs;
699 void alc_ca_deinit(void)
703 void alc_ca_probe(enum DevProbe type)
705 switch(type)
707 case DEVICE_PROBE:
708 AppendDeviceList(ca_device);
709 break;
710 case ALL_DEVICE_PROBE:
711 AppendAllDeviceList(ca_device);
712 break;
713 case CAPTURE_DEVICE_PROBE:
714 AppendCaptureDeviceList(ca_device);
715 break;