aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/backends
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/backends')
-rw-r--r--Alc/backends/coreaudio.cpp317
1 files changed, 136 insertions, 181 deletions
diff --git a/Alc/backends/coreaudio.cpp b/Alc/backends/coreaudio.cpp
index 808e7cb8..c0b6601b 100644
--- a/Alc/backends/coreaudio.cpp
+++ b/Alc/backends/coreaudio.cpp
@@ -29,6 +29,7 @@
#include "alMain.h"
#include "alu.h"
#include "ringbuffer.h"
+#include "converter.h"
#include <unistd.h>
#include <AudioUnit/AudioUnit.h>
@@ -39,10 +40,10 @@ static const ALCchar ca_device[] = "CoreAudio Default";
struct ALCcoreAudioPlayback final : public ALCbackend {
- AudioUnit AudioUnit;
+ AudioUnit mAudioUnit;
- ALuint FrameSize;
- AudioStreamBasicDescription Format; // This is the OpenAL format as a CoreAudio ASBD
+ ALuint mFrameSize{0u};
+ AudioStreamBasicDescription mFormat{}; // This is the OpenAL format as a CoreAudio ASBD
};
static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice *device);
@@ -66,15 +67,12 @@ static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice
new (self) ALCcoreAudioPlayback{};
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
SET_VTABLE2(ALCcoreAudioPlayback, ALCbackend, self);
-
- self->FrameSize = 0;
- self->Format = AudioStreamBasicDescription{};
}
static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback *self)
{
- AudioUnitUninitialize(self->AudioUnit);
- AudioComponentInstanceDispose(self->AudioUnit);
+ AudioUnitUninitialize(self->mAudioUnit);
+ AudioComponentInstanceDispose(self->mAudioUnit);
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
self->~ALCcoreAudioPlayback();
@@ -90,7 +88,7 @@ static OSStatus ALCcoreAudioPlayback_MixerProc(void *inRefCon,
ALCcoreAudioPlayback_lock(self);
aluMixData(device, ioData->mBuffers[0].mData,
- ioData->mBuffers[0].mDataByteSize / self->FrameSize);
+ ioData->mBuffers[0].mDataByteSize / self->mFrameSize);
ALCcoreAudioPlayback_unlock(self);
return noErr;
@@ -127,7 +125,7 @@ static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCch
return ALC_INVALID_VALUE;
}
- err = AudioComponentInstanceNew(comp, &self->AudioUnit);
+ err = AudioComponentInstanceNew(comp, &self->mAudioUnit);
if(err != noErr)
{
ERR("AudioComponentInstanceNew failed\n");
@@ -135,11 +133,11 @@ static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCch
}
/* init and start the default audio unit... */
- err = AudioUnitInitialize(self->AudioUnit);
+ err = AudioUnitInitialize(self->mAudioUnit);
if(err != noErr)
{
ERR("AudioUnitInitialize failed\n");
- AudioComponentInstanceDispose(self->AudioUnit);
+ AudioComponentInstanceDispose(self->mAudioUnit);
return ALC_INVALID_VALUE;
}
@@ -155,13 +153,14 @@ static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self)
OSStatus err;
UInt32 size;
- err = AudioUnitUninitialize(self->AudioUnit);
+ err = AudioUnitUninitialize(self->mAudioUnit);
if(err != noErr)
ERR("-- AudioUnitUninitialize failed.\n");
/* retrieve default output unit's properties (output side) */
size = sizeof(AudioStreamBasicDescription);
- err = AudioUnitGetProperty(self->AudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &size);
+ err = AudioUnitGetProperty(self->mAudioUnit, kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output, 0, &streamFormat, &size);
if(err != noErr || size != sizeof(AudioStreamBasicDescription))
{
ERR("AudioUnitGetProperty failed\n");
@@ -179,7 +178,8 @@ static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self)
#endif
/* set default output unit's input side to match output side */
- err = AudioUnitSetProperty(self->AudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size);
+ err = AudioUnitSetProperty(self->mAudioUnit, kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input, 0, &streamFormat, size);
if(err != noErr)
{
ERR("AudioUnitSetProperty failed\n");
@@ -263,7 +263,8 @@ static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self)
streamFormat.mFormatFlags |= kAudioFormatFlagsNativeEndian |
kLinearPCMFormatFlagIsPacked;
- err = AudioUnitSetProperty(self->AudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription));
+ err = AudioUnitSetProperty(self->mAudioUnit, kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription));
if(err != noErr)
{
ERR("AudioUnitSetProperty failed\n");
@@ -271,11 +272,12 @@ static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self)
}
/* setup callback */
- self->FrameSize = device->frameSizeFromFmt();
+ self->mFrameSize = device->frameSizeFromFmt();
input.inputProc = ALCcoreAudioPlayback_MixerProc;
input.inputProcRefCon = self;
- err = AudioUnitSetProperty(self->AudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct));
+ err = AudioUnitSetProperty(self->mAudioUnit, kAudioUnitProperty_SetRenderCallback,
+ kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct));
if(err != noErr)
{
ERR("AudioUnitSetProperty failed\n");
@@ -283,7 +285,7 @@ static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self)
}
/* init the default audio unit... */
- err = AudioUnitInitialize(self->AudioUnit);
+ err = AudioUnitInitialize(self->mAudioUnit);
if(err != noErr)
{
ERR("AudioUnitInitialize failed\n");
@@ -295,7 +297,7 @@ static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self)
static ALCboolean ALCcoreAudioPlayback_start(ALCcoreAudioPlayback *self)
{
- OSStatus err = AudioOutputUnitStart(self->AudioUnit);
+ OSStatus err = AudioOutputUnitStart(self->mAudioUnit);
if(err != noErr)
{
ERR("AudioOutputUnitStart failed\n");
@@ -307,24 +309,21 @@ static ALCboolean ALCcoreAudioPlayback_start(ALCcoreAudioPlayback *self)
static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback *self)
{
- OSStatus err = AudioOutputUnitStop(self->AudioUnit);
+ OSStatus err = AudioOutputUnitStop(self->mAudioUnit);
if(err != noErr)
ERR("AudioOutputUnitStop failed\n");
}
struct ALCcoreAudioCapture final : public ALCbackend {
- AudioUnit AudioUnit;
+ AudioUnit mAudioUnit{0};
- ALuint FrameSize;
- ALdouble SampleRateRatio; // Ratio of hardware sample rate / requested sample rate
- AudioStreamBasicDescription Format; // This is the OpenAL format as a CoreAudio ASBD
+ ALuint mFrameSize{0u};
+ AudioStreamBasicDescription mFormat{}; // This is the OpenAL format as a CoreAudio ASBD
- AudioConverterRef AudioConverter; // Sample rate converter if needed
- AudioBufferList *BufferList; // Buffer for data coming from the input device
- ALCvoid *ResampleBuffer; // Buffer for returned RingBuffer data when resampling
+ std::unique_ptr<SampleConverter> mConverter;
- RingBufferPtr Ring{nullptr};
+ RingBufferPtr mRing{nullptr};
};
static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device);
@@ -343,56 +342,18 @@ DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioCapture)
DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioCapture);
-static AudioBufferList *allocate_buffer_list(UInt32 channelCount, UInt32 byteSize)
-{
- AudioBufferList *list;
-
- list = static_cast<AudioBufferList*>(calloc(1,
- FAM_SIZE(AudioBufferList, mBuffers, 1) + byteSize));
- if(list)
- {
- list->mNumberBuffers = 1;
-
- list->mBuffers[0].mNumberChannels = channelCount;
- list->mBuffers[0].mDataByteSize = byteSize;
- list->mBuffers[0].mData = &list->mBuffers[1];
- }
- return list;
-}
-
-static void destroy_buffer_list(AudioBufferList *list)
-{
- free(list);
-}
-
-
static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device)
{
new (self) ALCcoreAudioCapture{};
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
SET_VTABLE2(ALCcoreAudioCapture, ALCbackend, self);
-
- self->AudioUnit = 0;
- self->AudioConverter = NULL;
- self->BufferList = NULL;
- self->ResampleBuffer = NULL;
}
static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture *self)
{
- free(self->ResampleBuffer);
- self->ResampleBuffer = NULL;
-
- destroy_buffer_list(self->BufferList);
- self->BufferList = NULL;
-
- if(self->AudioConverter)
- AudioConverterDispose(self->AudioConverter);
- self->AudioConverter = NULL;
-
- if(self->AudioUnit)
- AudioComponentInstanceDispose(self->AudioUnit);
- self->AudioUnit = 0;
+ if(self->mAudioUnit)
+ AudioComponentInstanceDispose(self->mAudioUnit);
+ self->mAudioUnit = 0;
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
self->~ALCcoreAudioCapture();
@@ -405,39 +366,47 @@ static OSStatus ALCcoreAudioCapture_RecordProc(void *inRefCon,
UInt32 inNumberFrames, AudioBufferList* UNUSED(ioData))
{
auto self = static_cast<ALCcoreAudioCapture*>(inRefCon);
- RingBuffer *ring{self->Ring.get()};
+ RingBuffer *ring{self->mRing.get()};
AudioUnitRenderActionFlags flags = 0;
+ union {
+ ALbyte _[sizeof(AudioBufferList) + sizeof(AudioBuffer)];
+ AudioBufferList list;
+ } audiobuf = { { 0 } };
OSStatus err;
- // fill the BufferList with data from the input device
- err = AudioUnitRender(self->AudioUnit, &flags, inTimeStamp, 1, inNumberFrames, self->BufferList);
+ auto rec_vec = ring->getWriteVector();
+
+ // Fill the ringbuffer's first segment with data from the input device
+ size_t total_read{minz(rec_vec.first.len, inNumberFrames)};
+ audiobuf.list.mNumberBuffers = 1;
+ audiobuf.list.mBuffers[0].mNumberChannels = self->mFormat.mChannelsPerFrame;
+ audiobuf.list.mBuffers[0].mData = rec_vec.first.buf;
+ audiobuf.list.mBuffers[0].mDataByteSize = total_read * self->mFormat.mBytesPerFrame;
+ err = AudioUnitRender(self->mAudioUnit, &flags, inTimeStamp, 1, inNumberFrames,
+ &audiobuf.list);
+ if(err == noErr && inNumberFrames > rec_vec.first.len && rec_vec.second.len > 0)
+ {
+ /* If there's still more to get and there's space in the ringbuffer's
+ * second segment, fill that with data too.
+ */
+ const size_t remlen{inNumberFrames - rec_vec.first.len};
+ const size_t toread{minz(rec_vec.second.len, remlen)};
+ total_read += toread;
+
+ audiobuf.list.mNumberBuffers = 1;
+ audiobuf.list.mBuffers[0].mNumberChannels = self->mFormat.mChannelsPerFrame;
+ audiobuf.list.mBuffers[0].mData = rec_vec.second.buf;
+ audiobuf.list.mBuffers[0].mDataByteSize = toread * self->mFormat.mBytesPerFrame;
+ err = AudioUnitRender(self->mAudioUnit, &flags, inTimeStamp, 1, inNumberFrames,
+ &audiobuf.list);
+ }
if(err != noErr)
{
ERR("AudioUnitRender error: %d\n", err);
return err;
}
- ring->write(self->BufferList->mBuffers[0].mData, inNumberFrames);
- return noErr;
-}
-
-static OSStatus ALCcoreAudioCapture_ConvertCallback(AudioConverterRef UNUSED(inAudioConverter),
- UInt32 *ioNumberDataPackets, AudioBufferList *ioData,
- AudioStreamPacketDescription** UNUSED(outDataPacketDescription),
- void *inUserData)
-{
- auto self = reinterpret_cast<ALCcoreAudioCapture*>(inUserData);
- RingBuffer *ring{self->Ring.get()};
-
- // Read from the ring buffer and store temporarily in a large buffer
- ring->read(self->ResampleBuffer, *ioNumberDataPackets);
-
- // Set the input data
- ioData->mNumberBuffers = 1;
- ioData->mBuffers[0].mNumberChannels = self->Format.mChannelsPerFrame;
- ioData->mBuffers[0].mData = self->ResampleBuffer;
- ioData->mBuffers[0].mDataByteSize = (*ioNumberDataPackets) * self->Format.mBytesPerFrame;
-
+ ring->writeAdvance(total_read);
return noErr;
}
@@ -481,29 +450,31 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar
}
// Open the component
- err = AudioComponentInstanceNew(comp, &self->AudioUnit);
+ err = AudioComponentInstanceNew(comp, &self->mAudioUnit);
if(err != noErr)
{
ERR("AudioComponentInstanceNew failed\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
// Turn off AudioUnit output
enableIO = 0;
- err = AudioUnitSetProperty(self->AudioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint));
+ err = AudioUnitSetProperty(self->mAudioUnit, kAudioOutputUnitProperty_EnableIO,
+ kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint));
if(err != noErr)
{
ERR("AudioUnitSetProperty failed\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
// Turn on AudioUnit input
enableIO = 1;
- err = AudioUnitSetProperty(self->AudioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint));
+ err = AudioUnitSetProperty(self->mAudioUnit, kAudioOutputUnitProperty_EnableIO,
+ kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint));
if(err != noErr)
{
ERR("AudioUnitSetProperty failed\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
#if !TARGET_OS_IOS
@@ -520,20 +491,21 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar
if(err != noErr)
{
ERR("AudioObjectGetPropertyData failed\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
if(inputDevice == kAudioDeviceUnknown)
{
ERR("No input device found\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
// Track the input device
- err = AudioUnitSetProperty(self->AudioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID));
+ err = AudioUnitSetProperty(self->mAudioUnit, kAudioOutputUnitProperty_CurrentDevice,
+ kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID));
if(err != noErr)
{
ERR("AudioUnitSetProperty failed\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
}
#endif
@@ -542,28 +514,30 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar
input.inputProc = ALCcoreAudioCapture_RecordProc;
input.inputProcRefCon = self;
- err = AudioUnitSetProperty(self->AudioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct));
+ err = AudioUnitSetProperty(self->mAudioUnit, kAudioOutputUnitProperty_SetInputCallback,
+ kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct));
if(err != noErr)
{
ERR("AudioUnitSetProperty failed\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
// Initialize the device
- err = AudioUnitInitialize(self->AudioUnit);
+ err = AudioUnitInitialize(self->mAudioUnit);
if(err != noErr)
{
ERR("AudioUnitInitialize failed\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
// Get the hardware format
propertySize = sizeof(AudioStreamBasicDescription);
- err = AudioUnitGetProperty(self->AudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize);
+ err = AudioUnitGetProperty(self->mAudioUnit, kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize);
if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription))
{
ERR("AudioUnitGetProperty failed\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
// Set up the requested format description
@@ -589,7 +563,7 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar
case DevFmtUShort:
case DevFmtUInt:
ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
- goto error;
+ return ALC_INVALID_VALUE;
}
switch(device->FmtChans)
@@ -608,7 +582,7 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar
case DevFmtX71:
case DevFmtAmbi3D:
ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans));
- goto error;
+ return ALC_INVALID_VALUE;
}
requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8;
@@ -619,80 +593,61 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar
requestedFormat.mFramesPerPacket = 1;
// save requested format description for later use
- self->Format = requestedFormat;
- self->FrameSize = device->frameSizeFromFmt();
+ self->mFormat = requestedFormat;
+ self->mFrameSize = device->frameSizeFromFmt();
// Use intermediate format for sample rate conversion (outputFormat)
// Set sample rate to the same as hardware for resampling later
outputFormat = requestedFormat;
outputFormat.mSampleRate = hardwareFormat.mSampleRate;
- // Determine sample rate ratio for resampling
- self->SampleRateRatio = outputFormat.mSampleRate / device->Frequency;
-
// The output format should be the requested format, but using the hardware sample rate
// This is because the AudioUnit will automatically scale other properties, except for sample rate
- err = AudioUnitSetProperty(self->AudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat));
+ err = AudioUnitSetProperty(self->mAudioUnit, kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat));
if(err != noErr)
{
ERR("AudioUnitSetProperty failed\n");
- goto error;
+ return ALC_INVALID_VALUE;
}
// Set the AudioUnit output format frame count
- outputFrameCount = device->UpdateSize * self->SampleRateRatio;
- err = AudioUnitSetProperty(self->AudioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount));
- if(err != noErr)
+ ALuint64 FrameCount64{device->UpdateSize};
+ FrameCount64 = (FrameCount64*outputFormat.mSampleRate + device->Frequency-1) /
+ device->Frequency;
+ FrameCount64 += MAX_RESAMPLE_PADDING*2;
+ if(FrameCount64 > std::numeric_limits<uint32_t>::max()/2)
{
- ERR("AudioUnitSetProperty failed: %d\n", err);
- goto error;
+ ERR("FrameCount too large\n");
+ return ALC_INVALID_VALUE;
}
- // Set up sample converter
- err = AudioConverterNew(&outputFormat, &requestedFormat, &self->AudioConverter);
+ outputFrameCount = static_cast<uint32_t>(FrameCount64);
+ err = AudioUnitSetProperty(self->mAudioUnit, kAudioUnitProperty_MaximumFramesPerSlice,
+ kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount));
if(err != noErr)
{
- ERR("AudioConverterNew failed: %d\n", err);
- goto error;
+ ERR("AudioUnitSetProperty failed: %d\n", err);
+ return ALC_INVALID_VALUE;
}
- // Create a buffer for use in the resample callback
- self->ResampleBuffer = malloc(device->UpdateSize * self->FrameSize * self->SampleRateRatio);
+ // Set up sample converter if needed
+ if(outputFormat.mSampleRate != device->Frequency)
+ self->mConverter.reset(CreateSampleConverter(device->FmtType, device->FmtType,
+ self->mFormat.mChannelsPerFrame, hardwareFormat.mSampleRate, device->Frequency,
+ BSinc24Resampler));
- // Allocate buffer for the AudioUnit output
- self->BufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * self->FrameSize * self->SampleRateRatio);
- if(self->BufferList == NULL)
- goto error;
-
- self->Ring.reset(ll_ringbuffer_create(
- (size_t)ceil(device->UpdateSize*self->SampleRateRatio*device->NumUpdates),
- self->FrameSize, false));
- if(!self->Ring) goto error;
+ self->mRing.reset(ll_ringbuffer_create(outputFrameCount, self->mFrameSize, false));
+ if(!self->mRing) return ALC_INVALID_VALUE;
device->DeviceName = name;
return ALC_NO_ERROR;
-
-error:
- self->Ring = nullptr;
- free(self->ResampleBuffer);
- self->ResampleBuffer = NULL;
- destroy_buffer_list(self->BufferList);
- self->BufferList = NULL;
-
- if(self->AudioConverter)
- AudioConverterDispose(self->AudioConverter);
- self->AudioConverter = NULL;
- if(self->AudioUnit)
- AudioComponentInstanceDispose(self->AudioUnit);
- self->AudioUnit = 0;
-
- return ALC_INVALID_VALUE;
}
static ALCboolean ALCcoreAudioCapture_start(ALCcoreAudioCapture *self)
{
- OSStatus err = AudioOutputUnitStart(self->AudioUnit);
+ OSStatus err = AudioOutputUnitStart(self->mAudioUnit);
if(err != noErr)
{
ERR("AudioOutputUnitStart failed\n");
@@ -703,46 +658,46 @@ static ALCboolean ALCcoreAudioCapture_start(ALCcoreAudioCapture *self)
static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture *self)
{
- OSStatus err = AudioOutputUnitStop(self->AudioUnit);
+ OSStatus err = AudioOutputUnitStop(self->mAudioUnit);
if(err != noErr)
ERR("AudioOutputUnitStop failed\n");
}
static ALCenum ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture *self, ALCvoid *buffer, ALCuint samples)
{
- union {
- ALbyte _[sizeof(AudioBufferList) + sizeof(AudioBuffer)];
- AudioBufferList list;
- } audiobuf = { { 0 } };
- UInt32 frameCount;
- OSStatus err;
+ RingBuffer *ring{self->mRing.get()};
- // If no samples are requested, just return
- if(samples == 0) return ALC_NO_ERROR;
+ if(!self->mConverter)
+ {
+ ring->read(buffer, samples);
+ return ALC_NO_ERROR;
+ }
- // Point the resampling buffer to the capture buffer
- audiobuf.list.mNumberBuffers = 1;
- audiobuf.list.mBuffers[0].mNumberChannels = self->Format.mChannelsPerFrame;
- audiobuf.list.mBuffers[0].mDataByteSize = samples * self->FrameSize;
- audiobuf.list.mBuffers[0].mData = buffer;
-
- // Resample into another AudioBufferList
- frameCount = samples;
- err = AudioConverterFillComplexBuffer(self->AudioConverter,
- ALCcoreAudioCapture_ConvertCallback, self, &frameCount, &audiobuf.list, NULL
- );
- if(err != noErr)
+ auto rec_vec = ring->getReadVector();
+ const void *src0{rec_vec.first.buf};
+ auto src0len = static_cast<ALsizei>(rec_vec.first.len);
+ auto got = static_cast<ALuint>(SampleConverterInput(self->mConverter.get(), &src0, &src0len,
+ buffer, samples));
+ size_t total_read{rec_vec.first.len - src0len};
+ if(got < samples && !src0len && rec_vec.second.len > 0)
{
- ERR("AudioConverterFillComplexBuffer error: %d\n", err);
- return ALC_INVALID_VALUE;
+ const void *src1{rec_vec.second.buf};
+ auto src1len = static_cast<ALsizei>(rec_vec.second.len);
+ got += static_cast<ALuint>(SampleConverterInput(self->mConverter.get(), &src1, &src1len,
+ static_cast<char*>(buffer)+got, samples-got));
+ total_read += rec_vec.second.len - src1len;
}
+
+ ring->readAdvance(total_read);
return ALC_NO_ERROR;
}
static ALCuint ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture *self)
{
- RingBuffer *ring{self->Ring.get()};
- return ring->readSpace() / self->SampleRateRatio;
+ RingBuffer *ring{self->mRing.get()};
+
+ if(!self->mConverter) return ring->readSpace();
+ return SampleConverterAvailableOut(self->mConverter.get(), ring->readSpace());
}