mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-21 15:56:58 +02:00
Add a new ma_audio_ring_buffer data source.
This is a wrapper around `ma_ring_buffer` and is more specialized towards audio. It is a data source and replaces `ma_pcm_rb` which will be removed in a future commit. Public issue https://github.com/mackron/miniaudio/issues/671
This commit is contained in:
+262
-43
@@ -6270,6 +6270,29 @@ MA_API ma_uint32 ma_ring_buffer_length(const ma_ring_buffer* pRingBuffer);
|
||||
MA_API ma_uint32 ma_ring_buffer_capacity(const ma_ring_buffer* pRingBuffer);
|
||||
/* END ma_ring_buffer.h */
|
||||
|
||||
|
||||
typedef struct ma_audio_ring_buffer
|
||||
{
|
||||
ma_data_source_base ds;
|
||||
ma_ring_buffer rb;
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate; /* Not required for the ring buffer itself, but useful for associating the data with some sample rate, particularly for data sources. */
|
||||
void* pBuffer;
|
||||
ma_allocation_callbacks allocationCallbacks;
|
||||
} ma_audio_ring_buffer;
|
||||
|
||||
MA_API ma_result ma_audio_ring_buffer_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 capacityInFrames, const ma_allocation_callbacks* pAllocationCallbacks, ma_audio_ring_buffer* pRingBuffer);
|
||||
MA_API void ma_audio_ring_buffer_uninit(ma_audio_ring_buffer* pRingBuffer);
|
||||
MA_API ma_uint64 ma_audio_ring_buffer_map_produce(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount, void** ppMappedBuffer); /* Returns the number of frames actually mapped. */
|
||||
MA_API void ma_audio_ring_buffer_unmap_produce(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount);
|
||||
MA_API ma_uint64 ma_audio_ring_buffer_map_consume(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount, void** ppMappedBuffer); /* Returns the number of frames actually mapped. */
|
||||
MA_API void ma_audio_ring_buffer_unmap_consume(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount);
|
||||
MA_API ma_result ma_audio_ring_buffer_write_pcm_frames(ma_audio_ring_buffer* pRingBuffer, const void* pFrames, ma_uint64 frameCount, ma_uint64* pFramesWritten);
|
||||
MA_API ma_result ma_audio_ring_buffer_read_pcm_frames(ma_audio_ring_buffer* pRingBuffer, void* pFrames, ma_uint64 frameCount, ma_uint64* pFramesRead);
|
||||
MA_API ma_result ma_audio_ring_buffer_get_length_in_pcm_frames(ma_audio_ring_buffer* pRingBuffer, ma_uint64* pLength);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* pBuffer;
|
||||
@@ -6346,7 +6369,7 @@ in frames. The internal sample rate of the capture device is also needed in orde
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ma_pcm_rb rb;
|
||||
ma_audio_ring_buffer rb;
|
||||
} ma_duplex_rb;
|
||||
|
||||
MA_API ma_result ma_duplex_rb_init(ma_format captureFormat, ma_uint32 captureChannels, ma_uint32 sampleRate, ma_uint32 captureInternalSampleRate, ma_uint32 captureInternalPeriodSizeInFrames, const ma_allocation_callbacks* pAllocationCallbacks, ma_duplex_rb* pRB);
|
||||
@@ -20750,7 +20773,7 @@ static void ma_device__send_frames_to_client(ma_device* pDevice, ma_uint32 frame
|
||||
}
|
||||
}
|
||||
|
||||
static ma_result ma_device__handle_duplex_callback_capture(ma_device* pDevice, ma_uint32 frameCountInDeviceFormat, const void* pFramesInDeviceFormat, ma_pcm_rb* pRB)
|
||||
static ma_result ma_device__handle_duplex_callback_capture(ma_device* pDevice, ma_uint32 frameCountInDeviceFormat, const void* pFramesInDeviceFormat, ma_audio_ring_buffer* pRB)
|
||||
{
|
||||
ma_result result;
|
||||
ma_uint32 totalDeviceFramesProcessed = 0;
|
||||
@@ -20763,22 +20786,15 @@ static ma_result ma_device__handle_duplex_callback_capture(ma_device* pDevice, m
|
||||
|
||||
/* Write to the ring buffer. The ring buffer is in the client format which means we need to convert. */
|
||||
for (;;) {
|
||||
ma_uint32 framesToProcessInDeviceFormat = (frameCountInDeviceFormat - totalDeviceFramesProcessed);
|
||||
ma_uint32 framesToProcessInClientFormat = MA_DATA_CONVERTER_STACK_BUFFER_SIZE / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
|
||||
ma_uint64 framesToProcessInDeviceFormat = (frameCountInDeviceFormat - totalDeviceFramesProcessed);
|
||||
ma_uint64 framesToProcessInClientFormat = MA_DATA_CONVERTER_STACK_BUFFER_SIZE / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
|
||||
ma_uint64 framesProcessedInDeviceFormat;
|
||||
ma_uint64 framesProcessedInClientFormat;
|
||||
void* pFramesInClientFormat;
|
||||
|
||||
result = ma_pcm_rb_acquire_write(pRB, &framesToProcessInClientFormat, &pFramesInClientFormat);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "Failed to acquire capture PCM frames from ring buffer.");
|
||||
break;
|
||||
}
|
||||
|
||||
framesToProcessInClientFormat = ma_audio_ring_buffer_map_produce(pRB, framesToProcessInClientFormat, &pFramesInClientFormat);
|
||||
if (framesToProcessInClientFormat == 0) {
|
||||
if (ma_pcm_rb_pointer_distance(pRB) == (ma_int32)ma_pcm_rb_get_subbuffer_size(pRB)) {
|
||||
break; /* Overrun. Not enough room in the ring buffer for input frame. Excess frames are dropped. */
|
||||
}
|
||||
break; /* Overrun. Not enough room in the ring buffer for input frame. Excess frames are dropped. */
|
||||
}
|
||||
|
||||
/* Convert. */
|
||||
@@ -20789,11 +20805,7 @@ static ma_result ma_device__handle_duplex_callback_capture(ma_device* pDevice, m
|
||||
break;
|
||||
}
|
||||
|
||||
result = ma_pcm_rb_commit_write(pRB, (ma_uint32)framesProcessedInClientFormat); /* Safe cast. */
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "Failed to commit capture PCM frames to ring buffer.");
|
||||
break;
|
||||
}
|
||||
ma_audio_ring_buffer_unmap_produce(pRB, framesProcessedInClientFormat);
|
||||
|
||||
pRunningFramesInDeviceFormat = ma_offset_ptr(pRunningFramesInDeviceFormat, framesProcessedInDeviceFormat * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
|
||||
totalDeviceFramesProcessed += (ma_uint32)framesProcessedInDeviceFormat; /* Safe cast. */
|
||||
@@ -20807,9 +20819,8 @@ static ma_result ma_device__handle_duplex_callback_capture(ma_device* pDevice, m
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device__handle_duplex_callback_playback(ma_device* pDevice, ma_uint32 frameCount, void* pFramesInInternalFormat, ma_pcm_rb* pRB)
|
||||
static ma_result ma_device__handle_duplex_callback_playback(ma_device* pDevice, ma_uint32 frameCount, void* pFramesInInternalFormat, ma_audio_ring_buffer* pRB)
|
||||
{
|
||||
ma_result result;
|
||||
ma_uint8 silentInputFrames[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||
ma_uint32 totalFramesReadOut = 0;
|
||||
|
||||
@@ -20838,38 +20849,29 @@ static ma_result ma_device__handle_duplex_callback_playback(ma_device* pDevice,
|
||||
pDevice->playback.inputCacheConsumed += framesConvertedIn;
|
||||
pDevice->playback.inputCacheRemaining -= framesConvertedIn;
|
||||
|
||||
totalFramesReadOut += (ma_uint32)framesConvertedOut; /* Safe cast. */
|
||||
pFramesInInternalFormat = ma_offset_ptr(pFramesInInternalFormat, framesConvertedOut * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
|
||||
totalFramesReadOut += (ma_uint32)framesConvertedOut; /* Safe cast. */
|
||||
pFramesInInternalFormat = ma_offset_ptr(pFramesInInternalFormat, framesConvertedOut * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
|
||||
}
|
||||
|
||||
/* If there's no more data in the cache we'll need to fill it with some. */
|
||||
if (totalFramesReadOut < frameCount && pDevice->playback.inputCacheRemaining == 0) {
|
||||
ma_uint32 inputFrameCount;
|
||||
ma_uint64 inputFrameCount;
|
||||
void* pInputFrames;
|
||||
|
||||
inputFrameCount = (ma_uint32)pDevice->playback.inputCacheCap;
|
||||
result = ma_pcm_rb_acquire_read(pRB, &inputFrameCount, &pInputFrames);
|
||||
if (result == MA_SUCCESS) {
|
||||
if (inputFrameCount > 0) {
|
||||
ma_device__handle_data_callback(pDevice, pDevice->playback.pInputCache, pInputFrames, inputFrameCount);
|
||||
} else {
|
||||
if (ma_pcm_rb_pointer_distance(pRB) == 0) {
|
||||
break; /* Underrun. */
|
||||
}
|
||||
}
|
||||
inputFrameCount = pDevice->playback.inputCacheCap;
|
||||
inputFrameCount = ma_audio_ring_buffer_map_consume(pRB, inputFrameCount, &pInputFrames);
|
||||
if (inputFrameCount > 0) {
|
||||
ma_device__handle_data_callback(pDevice, pDevice->playback.pInputCache, pInputFrames, inputFrameCount);
|
||||
ma_audio_ring_buffer_unmap_consume(pRB, inputFrameCount);
|
||||
} else {
|
||||
/* No capture data available. Feed in silence. */
|
||||
/* Underrun. No capture data available. Feed in silence. */
|
||||
inputFrameCount = (ma_uint32)ma_min(pDevice->playback.inputCacheCap, sizeof(silentInputFrames) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
|
||||
ma_device__handle_data_callback(pDevice, pDevice->playback.pInputCache, silentInputFrames, inputFrameCount);
|
||||
ma_audio_ring_buffer_unmap_consume(pRB, 0); /* <-- Don't *actually* have to unmap this since it's a count of zero, but it makes me feel better having it be properly paired. */
|
||||
}
|
||||
|
||||
pDevice->playback.inputCacheConsumed = 0;
|
||||
pDevice->playback.inputCacheRemaining = inputFrameCount;
|
||||
|
||||
result = ma_pcm_rb_commit_read(pRB, inputFrameCount);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result; /* Should never happen. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63661,6 +63663,222 @@ MA_API ma_uint32 ma_ring_buffer_capacity(const ma_ring_buffer* pRingBuffer)
|
||||
/* END ma_ring_buffer.c */
|
||||
|
||||
|
||||
static ma_result ma_audio_ring_buffer__data_source_on_read(ma_data_source* pDataSource, void* pFrames, ma_uint64 frameCount, ma_uint64* pFramesRead)
|
||||
{
|
||||
return ma_audio_ring_buffer_read_pcm_frames((ma_audio_ring_buffer*)pDataSource, pFrames, frameCount, pFramesRead);
|
||||
}
|
||||
|
||||
static ma_result ma_audio_ring_buffer__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
|
||||
{
|
||||
ma_audio_ring_buffer* pAudioQueue = (ma_audio_ring_buffer*)pDataSource;
|
||||
|
||||
*pFormat = pAudioQueue->format;
|
||||
*pChannels = pAudioQueue->channels;
|
||||
*pSampleRate = pAudioQueue->sampleRate;
|
||||
ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, pAudioQueue->channels);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_audio_ring_buffer__data_source_on_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
|
||||
{
|
||||
return ma_audio_ring_buffer_get_length_in_pcm_frames((ma_audio_ring_buffer*)pDataSource, pLength);
|
||||
}
|
||||
|
||||
static ma_data_source_vtable ma_gDataSourceVTable_AudioRingBuffer =
|
||||
{
|
||||
ma_audio_ring_buffer__data_source_on_read,
|
||||
NULL, /* No seeking in ring buffers. */
|
||||
ma_audio_ring_buffer__data_source_on_get_data_format,
|
||||
NULL, /* No notion of a cursor. */
|
||||
ma_audio_ring_buffer__data_source_on_get_length,
|
||||
NULL, /* onSetLooping */
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
MA_API ma_result ma_audio_ring_buffer_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 capacityInFrames, const ma_allocation_callbacks* pAllocationCallbacks, ma_audio_ring_buffer* pRingBuffer)
|
||||
{
|
||||
ma_result result;
|
||||
ma_data_source_config dataSourceConfig;
|
||||
ma_uint32 bpf;
|
||||
void* pBuffer;
|
||||
|
||||
if (pRingBuffer == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
MA_ZERO_OBJECT(pRingBuffer);
|
||||
|
||||
if (capacityInFrames == 0) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
bpf = ma_get_bytes_per_frame(format, channels);
|
||||
if (bpf == 0) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
pBuffer = ma_malloc(capacityInFrames * bpf * 2, pAllocationCallbacks);
|
||||
if (pBuffer == NULL) {
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Initialize the data source. */
|
||||
dataSourceConfig = ma_data_source_config_init();
|
||||
dataSourceConfig.vtable = &ma_gDataSourceVTable_AudioRingBuffer;
|
||||
|
||||
result = ma_data_source_init(&dataSourceConfig, &pRingBuffer->ds);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_free(pBuffer, pAllocationCallbacks);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Now for the ring buffer. */
|
||||
ma_ring_buffer_init(capacityInFrames, bpf, 0, pBuffer, &pRingBuffer->rb);
|
||||
pRingBuffer->format = format;
|
||||
pRingBuffer->channels = channels;
|
||||
pRingBuffer->sampleRate = sampleRate;
|
||||
pRingBuffer->pBuffer = pBuffer;
|
||||
ma_allocation_callbacks_init_copy(&pRingBuffer->allocationCallbacks, pAllocationCallbacks);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API void ma_audio_ring_buffer_uninit(ma_audio_ring_buffer* pRingBuffer)
|
||||
{
|
||||
if (pRingBuffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ma_free(pRingBuffer->pBuffer, &pRingBuffer->allocationCallbacks);
|
||||
ma_data_source_uninit(&pRingBuffer->ds);
|
||||
}
|
||||
|
||||
MA_API ma_uint64 ma_audio_ring_buffer_map_produce(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount, void** ppMappedBuffer)
|
||||
{
|
||||
if (pRingBuffer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We're not going to write more than 32-bits worth of frames at a time. */
|
||||
if (frameCount > 0xFFFFFFFF) {
|
||||
frameCount = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return (ma_uint64)ma_ring_buffer_map_produce(&pRingBuffer->rb, (size_t)frameCount, ppMappedBuffer);
|
||||
}
|
||||
|
||||
MA_API void ma_audio_ring_buffer_unmap_produce(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount)
|
||||
{
|
||||
if (pRingBuffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ma_ring_buffer_unmap_produce(&pRingBuffer->rb, (size_t)frameCount);
|
||||
}
|
||||
|
||||
MA_API ma_uint64 ma_audio_ring_buffer_map_consume(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount, void** ppMappedBuffer)
|
||||
{
|
||||
if (pRingBuffer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We're not going to write more than 32-bits worth of frames at a time. */
|
||||
if (frameCount > 0xFFFFFFFF) {
|
||||
frameCount = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return (ma_uint64)ma_ring_buffer_map_consume(&pRingBuffer->rb, (size_t)frameCount, ppMappedBuffer);
|
||||
}
|
||||
|
||||
MA_API void ma_audio_ring_buffer_unmap_consume(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount)
|
||||
{
|
||||
if (pRingBuffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ma_ring_buffer_unmap_consume(&pRingBuffer->rb, (size_t)frameCount);
|
||||
}
|
||||
|
||||
MA_API ma_result ma_audio_ring_buffer_write_pcm_frames(ma_audio_ring_buffer* pRingBuffer, const void* pFrames, ma_uint64 frameCount, ma_uint64* pFramesWritten)
|
||||
{
|
||||
void* pMappedBuffer;
|
||||
|
||||
if (pFramesWritten != NULL) {
|
||||
*pFramesWritten = 0;
|
||||
}
|
||||
|
||||
if (pRingBuffer == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
frameCount = ma_ring_buffer_map_produce(&pRingBuffer->rb, frameCount, &pMappedBuffer);
|
||||
{
|
||||
size_t bytesToCopy = (size_t)(frameCount * ma_get_bytes_per_frame(pRingBuffer->format, pRingBuffer->channels));
|
||||
|
||||
if (pFrames != NULL) {
|
||||
MA_COPY_MEMORY(pMappedBuffer, pFrames, bytesToCopy);
|
||||
} else {
|
||||
MA_ZERO_MEMORY(pMappedBuffer, bytesToCopy);
|
||||
}
|
||||
}
|
||||
ma_ring_buffer_unmap_produce(&pRingBuffer->rb, frameCount);
|
||||
|
||||
if (pFramesWritten != NULL) {
|
||||
*pFramesWritten = frameCount;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API ma_result ma_audio_ring_buffer_read_pcm_frames(ma_audio_ring_buffer* pRingBuffer, void* pFrames, ma_uint64 frameCount, ma_uint64* pFramesRead)
|
||||
{
|
||||
void* pMappedBuffer;
|
||||
|
||||
if (pFramesRead != NULL) {
|
||||
*pFramesRead = 0;
|
||||
}
|
||||
|
||||
if (pRingBuffer == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
frameCount = ma_ring_buffer_map_consume(&pRingBuffer->rb, frameCount, &pMappedBuffer);
|
||||
{
|
||||
size_t bytesToCopy = (size_t)(frameCount * ma_get_bytes_per_frame(pRingBuffer->format, pRingBuffer->channels));
|
||||
|
||||
if (pFrames != NULL) {
|
||||
MA_COPY_MEMORY(pFrames, pMappedBuffer, bytesToCopy);
|
||||
}
|
||||
}
|
||||
ma_ring_buffer_unmap_consume(&pRingBuffer->rb, frameCount);
|
||||
|
||||
if (pFramesRead != NULL) {
|
||||
*pFramesRead = frameCount;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API ma_result ma_audio_ring_buffer_get_length_in_pcm_frames(ma_audio_ring_buffer* pRingBuffer, ma_uint64* pLength)
|
||||
{
|
||||
if (pLength == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
*pLength = 0;
|
||||
|
||||
if (pRingBuffer == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
*pLength = ma_ring_buffer_length(&pRingBuffer->rb);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static MA_INLINE ma_uint32 ma_rb__extract_offset_in_bytes(ma_uint32 encodedOffset)
|
||||
@@ -64460,25 +64678,25 @@ MA_API ma_result ma_duplex_rb_init(ma_format captureFormat, ma_uint32 captureCha
|
||||
ma_result result;
|
||||
ma_uint32 sizeInFrames;
|
||||
|
||||
sizeInFrames = (ma_uint32)ma_calculate_frame_count_after_resampling(sampleRate, captureInternalSampleRate, captureInternalPeriodSizeInFrames * 5);
|
||||
sizeInFrames = (ma_uint32)ma_calculate_frame_count_after_resampling(sampleRate, captureInternalSampleRate, captureInternalPeriodSizeInFrames * 3);
|
||||
if (sizeInFrames == 0) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
result = ma_pcm_rb_init(captureFormat, captureChannels, sizeInFrames, NULL, pAllocationCallbacks, &pRB->rb);
|
||||
result = ma_audio_ring_buffer_init(captureFormat, captureChannels, sampleRate, sizeInFrames, pAllocationCallbacks, &pRB->rb);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Seek forward a bit so we have a bit of a buffer in case of desyncs. */
|
||||
ma_pcm_rb_seek_write((ma_pcm_rb*)pRB, captureInternalPeriodSizeInFrames * 2);
|
||||
ma_audio_ring_buffer_write_pcm_frames(&pRB->rb, NULL, captureInternalPeriodSizeInFrames * 2, NULL);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API ma_result ma_duplex_rb_uninit(ma_duplex_rb* pRB)
|
||||
{
|
||||
ma_pcm_rb_uninit((ma_pcm_rb*)pRB);
|
||||
ma_audio_ring_buffer_uninit(&pRB->rb);
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -66551,6 +66769,7 @@ MA_API void ma_audio_queue_uninit(ma_audio_queue* pAudioQueue)
|
||||
}
|
||||
|
||||
ma_free(pAudioQueue->pBuffer, &pAudioQueue->allocationCallbacks);
|
||||
ma_data_source_uninit(&pAudioQueue->ds);
|
||||
}
|
||||
|
||||
static void ma_audio_queue_write_pcm_frames_nolock(ma_audio_queue* pAudioQueue, const void* pFrames, ma_uint64 frameCount, ma_uint32 bpf)
|
||||
|
||||
Reference in New Issue
Block a user