From f68fe8b076837d72a14a67e4a4d11f41f4c055d6 Mon Sep 17 00:00:00 2001 From: David Reid Date: Wed, 29 Apr 2026 15:25:31 +1000 Subject: [PATCH] Add support for copying audio ring buffers. --- miniaudio.h | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/miniaudio.h b/miniaudio.h index 332477ea..a5828bc9 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -6468,6 +6468,7 @@ typedef struct ma_audio_ring_buffer } ma_audio_ring_buffer; MA_API ma_result ma_audio_ring_buffer_init(const ma_audio_ring_buffer_config* pConfig, ma_audio_ring_buffer* pRingBuffer); +MA_API ma_result ma_audio_ring_buffer_init_copy(ma_audio_ring_buffer* pRingBuffer, ma_audio_ring_buffer* pNewRingBuffer); MA_API void ma_audio_ring_buffer_uninit(ma_audio_ring_buffer* pRingBuffer); MA_API ma_uint32 ma_audio_ring_buffer_map_produce(ma_audio_ring_buffer* pRingBuffer, ma_uint32 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_uint32 frameCount); @@ -68310,6 +68311,11 @@ static void ma_audio_ring_buffer__data_source_on_uninit(ma_data_source* pDataSou ma_audio_ring_buffer_uninit((ma_audio_ring_buffer*)pDataSource); } +static ma_result ma_audio_ring_buffer__data_source_on_copy(ma_data_source* pDataSource, ma_data_source* pNewDataSource) +{ + return ma_audio_ring_buffer_init_copy((ma_audio_ring_buffer*)pDataSource, (ma_audio_ring_buffer*)pNewDataSource); +} + static ma_result ma_audio_ring_buffer__data_source_on_read(ma_data_source* pDataSource, void* pFrames, ma_uint64 frameCount, ma_uint64* pFramesRead) { ma_audio_ring_buffer* pRingBuffer = (ma_audio_ring_buffer*)pDataSource; @@ -68371,7 +68377,7 @@ static ma_data_source_vtable ma_gDataSourceVTable_AudioRingBuffer = { ma_audio_ring_buffer__data_source_on_sizeof, ma_audio_ring_buffer__data_source_on_uninit, - NULL, /* onCopy */ + ma_audio_ring_buffer__data_source_on_copy, ma_audio_ring_buffer__data_source_on_read, NULL, /* No seeking in ring buffers. */ ma_audio_ring_buffer__data_source_on_get_data_format, @@ -68463,6 +68469,30 @@ MA_API ma_result ma_audio_ring_buffer_init(const ma_audio_ring_buffer_config* pC return MA_SUCCESS; } +MA_API ma_result ma_audio_ring_buffer_init_copy(ma_audio_ring_buffer* pRingBuffer, ma_audio_ring_buffer* pNewRingBuffer) +{ + ma_audio_ring_buffer_config config; + + if (pNewRingBuffer == NULL || pRingBuffer == NULL) { + return MA_INVALID_ARGS; + } + + config = ma_audio_ring_buffer_config_init(pRingBuffer->format, pRingBuffer->channels, pRingBuffer->sampleRate, pRingBuffer->rb.capacity); + config.pAllocationCallbacks = &pRingBuffer->allocationCallbacks; + + /* + For the buffer, if it's an internally managed we want to make sure the copy is also internally managed. If it's externally + managed we can make the copy also external. + */ + if (pRingBuffer->isOwnerOfBuffer) { + config.pBuffer = NULL; /* Internally managed. Set the buffer to null to trigger the new ring buffer to also allocate it's own buffer. */ + } else { + config.pBuffer = pRingBuffer->pBuffer; /* Externally managed. Just reuse the buffer. */ + } + + return ma_audio_ring_buffer_init(&config, pNewRingBuffer); +} + MA_API void ma_audio_ring_buffer_uninit(ma_audio_ring_buffer* pRingBuffer) { if (pRingBuffer == NULL) {