From 198b844d8b1a642b03e8459e003e3e8a50cf58c9 Mon Sep 17 00:00:00 2001 From: David Reid Date: Thu, 21 Feb 2019 17:55:35 +1000 Subject: [PATCH] Add mal_pcm_rb to the ring buffer research code. This is the same as the normal ring buffer except everything is done in terms of PCM frames instead of bytes. This is useful to simplify the case of using the ring buffer for storing PCM audio data. --- research/mal_ring_buffer.h | 184 +++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) diff --git a/research/mal_ring_buffer.h b/research/mal_ring_buffer.h index ffefb388..dd542ede 100644 --- a/research/mal_ring_buffer.h +++ b/research/mal_ring_buffer.h @@ -74,6 +74,29 @@ size_t mal_rb_get_subbuffer_stride(mal_rb* pRB); size_t mal_rb_get_subbuffer_offset(mal_rb* pRB, size_t subbufferIndex); void* mal_rb_get_subbuffer_ptr(mal_rb* pRB, size_t subbufferIndex, void* pBuffer); + +typedef struct +{ + mal_rb rb; + mal_format format; + mal_uint32 channels; +} mal_pcm_rb; + +mal_result mal_pcm_rb_init_ex(mal_format format, mal_uint32 channels, size_t subbufferSizeInFrames, size_t subbufferCount, size_t subbufferStrideInFrames, void* pOptionalPreallocatedBuffer, mal_pcm_rb* pRB); +mal_result mal_pcm_rb_init(mal_format format, mal_uint32 channels, size_t bufferSizeInFrames, void* pOptionalPreallocatedBuffer, mal_pcm_rb* pRB); +void mal_pcm_rb_uninit(mal_pcm_rb* pRB); +mal_result mal_pcm_rb_acquire_read(mal_pcm_rb* pRB, size_t* pSizeInFrames, void** ppBufferOut); +mal_result mal_pcm_rb_commit_read(mal_pcm_rb* pRB, size_t sizeInFrames, void* pBufferOut); +mal_result mal_pcm_rb_acquire_write(mal_pcm_rb* pRB, size_t* pSizeInFrames, void** ppBufferOut); +mal_result mal_pcm_rb_commit_write(mal_pcm_rb* pRB, size_t sizeInFrames, void* pBufferOut); +mal_result mal_pcm_rb_seek_read(mal_pcm_rb* pRB, size_t offsetInFrames); +mal_result mal_pcm_rb_seek_write(mal_pcm_rb* pRB, size_t offsetInFrames); +mal_int32 mal_pcm_rb_pointer_disance(mal_pcm_rb* pRB); /* Return value is in frames. */ +size_t mal_pcm_rb_get_subbuffer_stride(mal_pcm_rb* pRB); +size_t mal_pcm_rb_get_subbuffer_offset(mal_pcm_rb* pRB, size_t subbufferIndex); +void* mal_pcm_rb_get_subbuffer_ptr(mal_pcm_rb* pRB, size_t subbufferIndex, void* pBuffer); + + #endif // mal_ring_buffer_h #ifdef MINI_AL_IMPLEMENTATION @@ -450,4 +473,165 @@ void* mal_rb_get_subbuffer_ptr(mal_rb* pRB, size_t subbufferIndex, void* pBuffer return mal_offset_ptr(pBuffer, mal_rb_get_subbuffer_offset(pRB, subbufferIndex)); } + + +/* mal_pcm_rb */ + +mal_uint32 mal_pcm_rb_get_bpf(mal_pcm_rb* pRB) +{ + mal_assert(pRB != NULL); + + return mal_get_bytes_per_frame(pRB->format, pRB->channels); +} + +mal_result mal_pcm_rb_init_ex(mal_format format, mal_uint32 channels, size_t subbufferSizeInFrames, size_t subbufferCount, size_t subbufferStrideInFrames, void* pOptionalPreallocatedBuffer, mal_pcm_rb* pRB) +{ + if (pRB == NULL) { + return MAL_INVALID_ARGS; + } + + mal_zero_object(pRB); + + mal_uint32 bpf = mal_get_bytes_per_frame(format, channels); + if (bpf == 0) { + return MAL_INVALID_ARGS; + } + + mal_result result = mal_rb_init_ex(subbufferSizeInFrames*bpf, subbufferCount, subbufferStrideInFrames*bpf, pOptionalPreallocatedBuffer, &pRB->rb); + if (result != MAL_SUCCESS) { + return result; + } + + pRB->format = format; + pRB->channels = channels; + + return MAL_SUCCESS; +} + +mal_result mal_pcm_rb_init(mal_format format, mal_uint32 channels, size_t bufferSizeInFrames, void* pOptionalPreallocatedBuffer, mal_pcm_rb* pRB) +{ + return mal_pcm_rb_init_ex(format, channels, bufferSizeInFrames, 1, 0, pOptionalPreallocatedBuffer, pRB); +} + +void mal_pcm_rb_uninit(mal_pcm_rb* pRB) +{ + if (pRB == NULL) { + return; + } + + mal_rb_uninit(&pRB->rb); +} + +mal_result mal_pcm_rb_acquire_read(mal_pcm_rb* pRB, size_t* pSizeInFrames, void** ppBufferOut) +{ + size_t sizeInBytes; + mal_result result; + + if (pRB == NULL || pSizeInFrames == NULL) { + return MAL_INVALID_ARGS; + } + + sizeInBytes = *pSizeInFrames * mal_pcm_rb_get_bpf(pRB); + + result = mal_rb_acquire_read(&pRB->rb, &sizeInBytes, ppBufferOut); + if (result != MAL_SUCCESS) { + return result; + } + + *pSizeInFrames = sizeInBytes / mal_pcm_rb_get_bpf(pRB); + return MAL_SUCCESS; +} + +mal_result mal_pcm_rb_commit_read(mal_pcm_rb* pRB, size_t sizeInFrames, void* pBufferOut) +{ + if (pRB == NULL) { + return MAL_INVALID_ARGS; + } + + return mal_rb_commit_read(&pRB->rb, sizeInFrames * mal_pcm_rb_get_bpf(pRB), pBufferOut); +} + +mal_result mal_pcm_rb_acquire_write(mal_pcm_rb* pRB, size_t* pSizeInFrames, void** ppBufferOut) +{ + size_t sizeInBytes; + mal_result result; + + if (pRB == NULL) { + return MAL_INVALID_ARGS; + } + + sizeInBytes = *pSizeInFrames * mal_pcm_rb_get_bpf(pRB); + + result = mal_rb_acquire_write(&pRB->rb, &sizeInBytes, ppBufferOut); + if (result != MAL_SUCCESS) { + return result; + } + + *pSizeInFrames = sizeInBytes / mal_pcm_rb_get_bpf(pRB); + return MAL_SUCCESS; +} + +mal_result mal_pcm_rb_commit_write(mal_pcm_rb* pRB, size_t sizeInFrames, void* pBufferOut) +{ + if (pRB == NULL) { + return MAL_INVALID_ARGS; + } + + return mal_rb_commit_write(&pRB->rb, sizeInFrames * mal_pcm_rb_get_bpf(pRB), pBufferOut); +} + +mal_result mal_pcm_rb_seek_read(mal_pcm_rb* pRB, size_t offsetInFrames) +{ + if (pRB == NULL) { + return MAL_INVALID_ARGS; + } + + return mal_rb_seek_read(&pRB->rb, offsetInFrames * mal_pcm_rb_get_bpf(pRB)); +} + +mal_result mal_pcm_rb_seek_write(mal_pcm_rb* pRB, size_t offsetInFrames) +{ + if (pRB == NULL) { + return MAL_INVALID_ARGS; + } + + return mal_rb_seek_write(&pRB->rb, offsetInFrames * mal_pcm_rb_get_bpf(pRB)); +} + +mal_int32 mal_pcm_rb_pointer_disance(mal_pcm_rb* pRB) +{ + if (pRB == NULL) { + return MAL_INVALID_ARGS; + } + + return mal_rb_pointer_distance(&pRB->rb) / mal_pcm_rb_get_bpf(pRB); +} + +size_t mal_pcm_rb_get_subbuffer_stride(mal_pcm_rb* pRB) +{ + if (pRB == NULL) { + return 0; + } + + return mal_rb_get_subbuffer_stride(&pRB->rb) / mal_pcm_rb_get_bpf(pRB); +} + +size_t mal_pcm_rb_get_subbuffer_offset(mal_pcm_rb* pRB, size_t subbufferIndex) +{ + if (pRB == NULL) { + return 0; + } + + return mal_rb_get_subbuffer_offset(&pRB->rb, subbufferIndex) / mal_pcm_rb_get_bpf(pRB); +} + +void* mal_pcm_rb_get_subbuffer_ptr(mal_pcm_rb* pRB, size_t subbufferIndex, void* pBuffer) +{ + if (pRB == NULL) { + return NULL; + } + + return mal_rb_get_subbuffer_ptr(&pRB->rb, subbufferIndex, pBuffer); +} + #endif // MINI_AL_IMPLEMENTATION