mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 00:34:03 +02:00
Core Audio: Fix some bugs with capture mode.
This commit is contained in:
+34
-9
@@ -3821,7 +3821,8 @@ struct ma_device
|
|||||||
ma_uint32 deviceObjectIDCapture;
|
ma_uint32 deviceObjectIDCapture;
|
||||||
/*AudioUnit*/ ma_ptr audioUnitPlayback;
|
/*AudioUnit*/ ma_ptr audioUnitPlayback;
|
||||||
/*AudioUnit*/ ma_ptr audioUnitCapture;
|
/*AudioUnit*/ ma_ptr audioUnitCapture;
|
||||||
/*AudioBufferList**/ ma_ptr pAudioBufferList; /* Only used for input devices. */
|
/*AudioBufferList**/ ma_ptr pAudioBufferList; /* Only used for input devices. */
|
||||||
|
ma_uint32 audioBufferSizeInBytes; /* Only used for input devices. The size in bytes of each buffer in pAudioBufferList. */
|
||||||
ma_event stopEvent;
|
ma_event stopEvent;
|
||||||
ma_uint32 originalPeriodSizeInFrames;
|
ma_uint32 originalPeriodSizeInFrames;
|
||||||
ma_uint32 originalPeriodSizeInMilliseconds;
|
ma_uint32 originalPeriodSizeInMilliseconds;
|
||||||
@@ -24269,6 +24270,7 @@ static OSStatus ma_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFla
|
|||||||
ma_device* pDevice = (ma_device*)pUserData;
|
ma_device* pDevice = (ma_device*)pUserData;
|
||||||
AudioBufferList* pRenderedBufferList;
|
AudioBufferList* pRenderedBufferList;
|
||||||
ma_stream_layout layout;
|
ma_stream_layout layout;
|
||||||
|
ma_uint32 iBuffer;
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
|
|
||||||
MA_ASSERT(pDevice != NULL);
|
MA_ASSERT(pDevice != NULL);
|
||||||
@@ -24285,6 +24287,18 @@ static OSStatus ma_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFla
|
|||||||
#if defined(MA_DEBUG_OUTPUT)
|
#if defined(MA_DEBUG_OUTPUT)
|
||||||
printf("INFO: Input Callback: busNumber=%d, frameCount=%d, mNumberBuffers=%d\n", busNumber, frameCount, pRenderedBufferList->mNumberBuffers);
|
printf("INFO: Input Callback: busNumber=%d, frameCount=%d, mNumberBuffers=%d\n", busNumber, frameCount, pRenderedBufferList->mNumberBuffers);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
When you call AudioUnitRender(), Core Audio tries to be helpful by setting the mDataByteSize to the number of bytes
|
||||||
|
that were actually rendered. The problem with this is that the next call can fail with -50 due to the size no longer
|
||||||
|
being set to the capacity of the buffer, but instead the size in bytes of the previous render. This will cause a
|
||||||
|
problem when a future call to this callback specifies a larger number of frames.
|
||||||
|
|
||||||
|
To work around this we need to explicitly set the size of each buffer to their respective size in bytes.
|
||||||
|
*/
|
||||||
|
for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
|
||||||
|
pRenderedBufferList->mBuffers[iBuffer].mDataByteSize = pDevice->coreaudio.audioBufferSizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
status = ((ma_AudioUnitRender_proc)pDevice->pContext->coreaudio.AudioUnitRender)((AudioUnit)pDevice->coreaudio.audioUnitCapture, pActionFlags, pTimeStamp, busNumber, frameCount, pRenderedBufferList);
|
status = ((ma_AudioUnitRender_proc)pDevice->pContext->coreaudio.AudioUnitRender)((AudioUnit)pDevice->coreaudio.audioUnitCapture, pActionFlags, pTimeStamp, busNumber, frameCount, pRenderedBufferList);
|
||||||
if (status != noErr) {
|
if (status != noErr) {
|
||||||
@@ -24295,7 +24309,6 @@ static OSStatus ma_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFla
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (layout == ma_stream_layout_interleaved) {
|
if (layout == ma_stream_layout_interleaved) {
|
||||||
UInt32 iBuffer;
|
|
||||||
for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
|
for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
|
||||||
if (pRenderedBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->capture.internalChannels) {
|
if (pRenderedBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->capture.internalChannels) {
|
||||||
if (pDevice->type == ma_device_type_duplex) {
|
if (pDevice->type == ma_device_type_duplex) {
|
||||||
@@ -24347,7 +24360,6 @@ static OSStatus ma_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFla
|
|||||||
*/
|
*/
|
||||||
if ((pRenderedBufferList->mNumberBuffers % pDevice->capture.internalChannels) == 0) {
|
if ((pRenderedBufferList->mNumberBuffers % pDevice->capture.internalChannels) == 0) {
|
||||||
ma_uint8 tempBuffer[4096];
|
ma_uint8 tempBuffer[4096];
|
||||||
UInt32 iBuffer;
|
|
||||||
for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; iBuffer += pDevice->capture.internalChannels) {
|
for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; iBuffer += pDevice->capture.internalChannels) {
|
||||||
ma_uint32 framesRemaining = frameCount;
|
ma_uint32 framesRemaining = frameCount;
|
||||||
while (framesRemaining > 0) {
|
while (framesRemaining > 0) {
|
||||||
@@ -24825,6 +24837,7 @@ typedef struct
|
|||||||
AudioComponent component;
|
AudioComponent component;
|
||||||
AudioUnit audioUnit;
|
AudioUnit audioUnit;
|
||||||
AudioBufferList* pAudioBufferList; /* Only used for input devices. */
|
AudioBufferList* pAudioBufferList; /* Only used for input devices. */
|
||||||
|
ma_uint32 audioBufferSizeInBytes;
|
||||||
ma_format formatOut;
|
ma_format formatOut;
|
||||||
ma_uint32 channelsOut;
|
ma_uint32 channelsOut;
|
||||||
ma_uint32 sampleRateOut;
|
ma_uint32 sampleRateOut;
|
||||||
@@ -24841,6 +24854,7 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev
|
|||||||
UInt32 enableIOFlag;
|
UInt32 enableIOFlag;
|
||||||
AudioStreamBasicDescription bestFormat;
|
AudioStreamBasicDescription bestFormat;
|
||||||
ma_uint32 actualPeriodSizeInFrames;
|
ma_uint32 actualPeriodSizeInFrames;
|
||||||
|
ma_uint32 actualPeriodSizeInFramesSize = sizeof(actualPeriodSizeInFrames);
|
||||||
AURenderCallbackStruct callbackInfo;
|
AURenderCallbackStruct callbackInfo;
|
||||||
#if defined(MA_APPLE_DESKTOP)
|
#if defined(MA_APPLE_DESKTOP)
|
||||||
AudioObjectID deviceObjectID;
|
AudioObjectID deviceObjectID;
|
||||||
@@ -25087,11 +25101,16 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev
|
|||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pData->periodSizeInFramesOut = actualPeriodSizeInFrames;
|
|
||||||
#else
|
#else
|
||||||
actualPeriodSizeInFrames = 2048;
|
/*
|
||||||
pData->periodSizeInFramesOut = actualPeriodSizeInFrames;
|
I don't know how to configure buffer sizes on iOS so for now we're not allowing it to be configured. Instead we're
|
||||||
|
just going to set it to the value of kAudioUnitProperty_MaximumFramesPerSlice.
|
||||||
|
*/
|
||||||
|
status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &actualPeriodSizeInFrames, &actualPeriodSizeInFramesSize);
|
||||||
|
if (status != noErr) {
|
||||||
|
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
|
||||||
|
return ma_result_from_OSStatus(status);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -25120,6 +25139,8 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pData->periodSizeInFramesOut = actualPeriodSizeInFrames;
|
||||||
|
|
||||||
/* We need a buffer list if this is an input device. We render into this in the input callback. */
|
/* We need a buffer list if this is an input device. We render into this in the input callback. */
|
||||||
if (deviceType == ma_device_type_capture) {
|
if (deviceType == ma_device_type_capture) {
|
||||||
ma_bool32 isInterleaved = (bestFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
|
ma_bool32 isInterleaved = (bestFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
|
||||||
@@ -25144,16 +25165,18 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isInterleaved) {
|
if (isInterleaved) {
|
||||||
|
pData->audioBufferSizeInBytes = actualPeriodSizeInFrames * ma_get_bytes_per_frame(pData->formatOut, pData->channelsOut);
|
||||||
pBufferList->mNumberBuffers = 1;
|
pBufferList->mNumberBuffers = 1;
|
||||||
pBufferList->mBuffers[0].mNumberChannels = pData->channelsOut;
|
pBufferList->mBuffers[0].mNumberChannels = pData->channelsOut;
|
||||||
pBufferList->mBuffers[0].mDataByteSize = actualPeriodSizeInFrames * ma_get_bytes_per_frame(pData->formatOut, pData->channelsOut);
|
pBufferList->mBuffers[0].mDataByteSize = pData->audioBufferSizeInBytes;
|
||||||
pBufferList->mBuffers[0].mData = (ma_uint8*)pBufferList + sizeof(AudioBufferList);
|
pBufferList->mBuffers[0].mData = (ma_uint8*)pBufferList + sizeof(AudioBufferList);
|
||||||
} else {
|
} else {
|
||||||
ma_uint32 iBuffer;
|
ma_uint32 iBuffer;
|
||||||
|
pData->audioBufferSizeInBytes = actualPeriodSizeInFrames * ma_get_bytes_per_sample(pData->formatOut);
|
||||||
pBufferList->mNumberBuffers = pData->channelsOut;
|
pBufferList->mNumberBuffers = pData->channelsOut;
|
||||||
for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
|
for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
|
||||||
pBufferList->mBuffers[iBuffer].mNumberChannels = 1;
|
pBufferList->mBuffers[iBuffer].mNumberChannels = 1;
|
||||||
pBufferList->mBuffers[iBuffer].mDataByteSize = actualPeriodSizeInFrames * ma_get_bytes_per_sample(pData->formatOut);
|
pBufferList->mBuffers[iBuffer].mDataByteSize = pData->audioBufferSizeInBytes;
|
||||||
pBufferList->mBuffers[iBuffer].mData = (ma_uint8*)pBufferList + ((sizeof(AudioBufferList) - sizeof(AudioBuffer)) + (sizeof(AudioBuffer) * pData->channelsOut)) + (actualPeriodSizeInFrames * ma_get_bytes_per_sample(pData->formatOut) * iBuffer);
|
pBufferList->mBuffers[iBuffer].mData = (ma_uint8*)pBufferList + ((sizeof(AudioBufferList) - sizeof(AudioBuffer)) + (sizeof(AudioBuffer) * pData->channelsOut)) + (actualPeriodSizeInFrames * ma_get_bytes_per_sample(pData->formatOut) * iBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25278,6 +25301,7 @@ static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_dev
|
|||||||
#endif
|
#endif
|
||||||
pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
|
pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
|
||||||
pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
|
pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
|
||||||
|
pDevice->coreaudio.audioBufferSizeInBytes = data.audioBufferSizeInBytes;
|
||||||
|
|
||||||
pDevice->capture.internalFormat = data.formatOut;
|
pDevice->capture.internalFormat = data.formatOut;
|
||||||
pDevice->capture.internalChannels = data.channelsOut;
|
pDevice->capture.internalChannels = data.channelsOut;
|
||||||
@@ -25354,6 +25378,7 @@ static ma_result ma_device_init__coreaudio(ma_context* pContext, const ma_device
|
|||||||
#endif
|
#endif
|
||||||
pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
|
pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
|
||||||
pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
|
pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
|
||||||
|
pDevice->coreaudio.audioBufferSizeInBytes = data.audioBufferSizeInBytes;
|
||||||
|
|
||||||
pDevice->capture.internalFormat = data.formatOut;
|
pDevice->capture.internalFormat = data.formatOut;
|
||||||
pDevice->capture.internalChannels = data.channelsOut;
|
pDevice->capture.internalChannels = data.channelsOut;
|
||||||
|
|||||||
Reference in New Issue
Block a user