From 75b3f7dddc4e13505929844327553b5b08bcf5fb Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 27 Jan 2026 17:04:22 +1000 Subject: [PATCH] Update to the audio ring buffer. This changes `write_pcm_frames()` so that when `pFramesWritten` is null, the write is treated as all or nothing. If the entire write cannot be performed, nothing at all will be written and `MA_NO_SPACE` will be returned. The same applies with `read_pcm_frames()` and `pFramesRead` in which case `MA_NO_DATA_AVAILABLE` will be returned. The reason for this change is that if the called passes in null for these values, they'll have no way to know how many frames were actually written or read. Therefore the most practical way to treat it is as all or nothing. --- miniaudio.h | 60 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/miniaudio.h b/miniaudio.h index 1a561a66..8371b822 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -63796,6 +63796,7 @@ MA_API void ma_audio_ring_buffer_unmap_consume(ma_audio_ring_buffer* pRingBuffer MA_API ma_result ma_audio_ring_buffer_write_pcm_frames(ma_audio_ring_buffer* pRingBuffer, const void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten) { void* pMappedBuffer; + ma_uint32 mappedFrameCount; if (pFramesWritten != NULL) { *pFramesWritten = 0; @@ -63805,20 +63806,35 @@ MA_API ma_result ma_audio_ring_buffer_write_pcm_frames(ma_audio_ring_buffer* pRi return MA_INVALID_ARGS; } - frameCount = ma_ring_buffer_map_produce(&pRingBuffer->rb, frameCount, &pMappedBuffer); + mappedFrameCount = ma_ring_buffer_map_produce(&pRingBuffer->rb, frameCount, &pMappedBuffer); { - size_t bytesToCopy = (size_t)frameCount * ma_get_bytes_per_frame(pRingBuffer->format, pRingBuffer->channels); + /* + When pFramesWritten is null it means the caller has no way of knowing how many frames were actually written. The most + practical thing to do in this case is to treat it as all or nothing. + */ + if (pFramesWritten == NULL && mappedFrameCount != frameCount) { + mappedFrameCount = 0; + } + + if (mappedFrameCount > 0) { + size_t bytesToCopy = (size_t)mappedFrameCount * ma_get_bytes_per_frame(pRingBuffer->format, pRingBuffer->channels); - if (pFrames != NULL) { - MA_COPY_MEMORY(pMappedBuffer, pFrames, bytesToCopy); - } else { - MA_ZERO_MEMORY(pMappedBuffer, bytesToCopy); + if (pFrames != NULL) { + MA_COPY_MEMORY(pMappedBuffer, pFrames, bytesToCopy); + } else { + MA_ZERO_MEMORY(pMappedBuffer, bytesToCopy); + } } } - ma_ring_buffer_unmap_produce(&pRingBuffer->rb, frameCount); + ma_ring_buffer_unmap_produce(&pRingBuffer->rb, mappedFrameCount); if (pFramesWritten != NULL) { - *pFramesWritten = frameCount; + *pFramesWritten = mappedFrameCount; + } else { + /* When pFramesWritten is null we need to treat it as all or nothing. */ + if (mappedFrameCount != frameCount) { + return MA_NO_SPACE; + } } return MA_SUCCESS; @@ -63827,6 +63843,7 @@ MA_API ma_result ma_audio_ring_buffer_write_pcm_frames(ma_audio_ring_buffer* pRi MA_API ma_result ma_audio_ring_buffer_read_pcm_frames(ma_audio_ring_buffer* pRingBuffer, void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesRead) { void* pMappedBuffer; + ma_uint32 mappedFrameCount; if (pFramesRead != NULL) { *pFramesRead = 0; @@ -63836,18 +63853,33 @@ MA_API ma_result ma_audio_ring_buffer_read_pcm_frames(ma_audio_ring_buffer* pRin return MA_INVALID_ARGS; } - frameCount = ma_ring_buffer_map_consume(&pRingBuffer->rb, frameCount, &pMappedBuffer); + mappedFrameCount = ma_ring_buffer_map_consume(&pRingBuffer->rb, frameCount, &pMappedBuffer); { - size_t bytesToCopy = (size_t)frameCount * ma_get_bytes_per_frame(pRingBuffer->format, pRingBuffer->channels); + /* + When pFramesRead is null it means the caller has no way of knowing how many frames were actually read. The most + practical thing to do in this case is to treat it as all or nothing. + */ + if (pFramesRead == NULL && mappedFrameCount != frameCount) { + mappedFrameCount = 0; + } - if (pFrames != NULL) { - MA_COPY_MEMORY(pFrames, pMappedBuffer, bytesToCopy); + if (mappedFrameCount > 0) { + size_t bytesToCopy = (size_t)mappedFrameCount * 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); + ma_ring_buffer_unmap_consume(&pRingBuffer->rb, mappedFrameCount); if (pFramesRead != NULL) { - *pFramesRead = frameCount; + *pFramesRead = mappedFrameCount; + } else { + /* When pFramesRead is null we need to treat it as all or nothing. */ + if (mappedFrameCount != frameCount) { + return MA_NO_DATA_AVAILABLE; + } } return MA_SUCCESS;