mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-21 15:56:58 +02:00
Updates to ring buffers.
This commit is contained in:
@@ -282,15 +282,16 @@ miniaudio_h("/\* c89atomic.h begin \*/\R":"\R/\* c89atomic.h end \*/") = convert
|
||||
rename_c89atomic_ring_buffer_namespace :: function(src:string) string
|
||||
{
|
||||
return rename_c89atomic_namespace(src)
|
||||
["\bma_atomic_ring_buffer"] <= "ma_ring_buffer"
|
||||
["\bMA_ATOMIC"] <= "MA"
|
||||
["\bMA_RING_BUFFER_API"] <= "MA_API"
|
||||
["\bMA_RING_BUFFER_ASSERT"] <= "MA_ASSERT"
|
||||
["\bMA_RING_BUFFER_COPY_MEMORY"] <= "MA_COPY_MEMORY"
|
||||
["\bMA_RING_BUFFER_OFFSET_PTR"] <= "ma_offset_ptr"
|
||||
["\bma_atomic_ring_buffer"] <= "ma_ring_buffer"
|
||||
["\bMA_ATOMIC"] <= "MA"
|
||||
["\bMA_RING_BUFFER_API"] <= "MA_API"
|
||||
["\bMA_RING_BUFFER_ASSERT"] <= "MA_ASSERT"
|
||||
["\bMA_RING_BUFFER_COPY_MEMORY"] <= "MA_COPY_MEMORY"
|
||||
["\bMA_RING_BUFFER_OFFSET_PTR"] <= "ma_offset_ptr"
|
||||
["\bMA_RING_BUFFER_CACHE_LINE_SIZE"] <= "MA_CACHE_LINE_SIZE"
|
||||
|
||||
// Alignment hack.
|
||||
["void\* pBuffer; "] <= "void* pBuffer;"
|
||||
["void\* pBuffer; "] <= "void* pBuffer;"
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
+125
-73
@@ -3560,7 +3560,8 @@ as an error when returned by `ma_audio_buffer_unmap()`.
|
||||
miniaudio supports lock free (single producer, single consumer) ring buffers which are exposed via
|
||||
the `ma_ring_buffer` and `ma_audio_ring_buffer` APIs. The `ma_ring_buffer` API is a lowever level,
|
||||
generic ring buffer, whereas the `ma_audio_ring_buffer` is designed for PCM audio data and can be
|
||||
used as a data source.
|
||||
used as a data source. Ring buffers are 32-bit oriented. If you want to support 64-bit capacities
|
||||
you will need to use something else.
|
||||
|
||||
The examples below use the PCM frame variant of the ring buffer since that's most likely the one
|
||||
you will want to use. To initialize a ring buffer, do something like the following:
|
||||
@@ -3600,8 +3601,8 @@ To read and write data you map and unmap a pointer. For writing, you can do some
|
||||
|
||||
```c
|
||||
void* pMappedBuffer;
|
||||
ma_uint64 desiredFrameCount = 128;
|
||||
ma_uint64 mappedFrameCount = ma_audio_ring_buffer_map_produce(&rb, desiredFrameCount, &pMappedBuffer);
|
||||
ma_uint32 desiredFrameCount = 128;
|
||||
ma_uint32 mappedFrameCount = ma_audio_ring_buffer_map_produce(&rb, desiredFrameCount, &pMappedBuffer);
|
||||
|
||||
do_something(pMappedBuffer, mappedFrameCount);
|
||||
|
||||
@@ -3618,8 +3619,8 @@ Reading works the same way as writing:
|
||||
|
||||
```c
|
||||
void* pMappedBuffer;
|
||||
ma_uint64 desiredFrameCount = 128;
|
||||
ma_uint64 mappedFrameCount = ma_audio_ring_buffer_map_consume(&rb, desiredFrameCount, pMappedBuffer);
|
||||
ma_uint32 desiredFrameCount = 128;
|
||||
ma_uint32 mappedFrameCount = ma_audio_ring_buffer_map_consume(&rb, desiredFrameCount, pMappedBuffer);
|
||||
|
||||
do_something(pMappedBuffer, mappedFrameCount);
|
||||
|
||||
@@ -4141,8 +4142,18 @@ typedef ma_uint16 wchar_t;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MA_CACHE_LINE_SIZE
|
||||
#if defined(__powerpc64__) || defined(__ppc64__) || defined(_ARCH_PPC64)
|
||||
#define MA_CACHE_LINE_SIZE 128
|
||||
#elif defined(__APPLE__) && (defined(__aarch64__) || defined(__arm64__)) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED)
|
||||
#define MA_CACHE_LINE_SIZE 128
|
||||
#else
|
||||
#define MA_CACHE_LINE_SIZE 64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* SIMD alignment in bytes. Currently set to 32 bytes in preparation for future AVX optimizations. */
|
||||
#define MA_SIMD_ALIGNMENT 32
|
||||
#define MA_SIMD_ALIGNMENT 32
|
||||
|
||||
/*
|
||||
Special wchar_t type to ensure any structures in the public sections that reference it have a
|
||||
@@ -6304,7 +6315,13 @@ Ring Buffer
|
||||
typedef struct ma_ring_buffer
|
||||
{
|
||||
ma_uint32 head; /* Atomic. Most significant bit is a loop flag. When the head is equal to the tail (including the flag) it means the buffer is empty. If the only difference is the flag, it means the buffer is full. */
|
||||
#if MA_CACHE_LINE_SIZE > 4
|
||||
ma_uint8 pad0[MA_CACHE_LINE_SIZE - 4]; /* The head will be modified by the producer, but untouched by the consumer. The reverse is true for the tail. The idea here is to ensure the head and tail are on their own cache lines thereby improving cache coherency. */
|
||||
#endif
|
||||
ma_uint32 tail; /* Atomic. Most significant bit is a loop flag. */
|
||||
#if MA_CACHE_LINE_SIZE > 4
|
||||
ma_uint8 pad1[MA_CACHE_LINE_SIZE - 4];
|
||||
#endif
|
||||
ma_uint32 capacity; /* Capacity of the buffer, in elements. */
|
||||
ma_uint32 stride; /* Size of an element in bytes. */
|
||||
ma_uint32 flags;
|
||||
@@ -6312,11 +6329,11 @@ typedef struct ma_ring_buffer
|
||||
} ma_ring_buffer;
|
||||
|
||||
MA_API void ma_ring_buffer_init(ma_uint32 capacity, ma_uint32 stride, ma_uint32 flags, void* pBuffer, ma_ring_buffer* pRingBuffer); /* Buffer must be `2 * capacity * stride`. That is twice the capacity. You can use a mirrored buffer, in which case specify the MA_RING_BUFFER_FLAG_MIRRORED flag. */
|
||||
MA_API size_t ma_ring_buffer_map_produce(ma_ring_buffer* pRingBuffer, size_t count, void** ppMappedBuffer); /* Returns the number of elements actually mapped. */
|
||||
MA_API void ma_ring_buffer_unmap_produce(ma_ring_buffer* pRingBuffer, size_t count);
|
||||
MA_API size_t ma_ring_buffer_map_consume(ma_ring_buffer* pRingBuffer, size_t count, void** ppMappedBuffer); /* Returns the number of elements actually mapped. */
|
||||
MA_API void ma_ring_buffer_unmap_consume(ma_ring_buffer* pRingBuffer, size_t count);
|
||||
MA_API ma_uint32 ma_ring_buffer_length(const ma_ring_buffer* pRingBuffer); /* Returns the number of elements currently in the ring buffer. If something is in the middle of producing or consuming data on the ring buffer than the returned value may already be out of date. */
|
||||
MA_API ma_uint32 ma_ring_buffer_map_produce(ma_ring_buffer* pRingBuffer, ma_uint32 count, void** ppMappedBuffer); /* Returns the number of elements actually mapped. */
|
||||
MA_API void ma_ring_buffer_unmap_produce(ma_ring_buffer* pRingBuffer, ma_uint32 count);
|
||||
MA_API ma_uint32 ma_ring_buffer_map_consume(ma_ring_buffer* pRingBuffer, ma_uint32 count, void** ppMappedBuffer); /* Returns the number of elements actually mapped. */
|
||||
MA_API void ma_ring_buffer_unmap_consume(ma_ring_buffer* pRingBuffer, ma_uint32 count);
|
||||
MA_API ma_uint32 ma_ring_buffer_length(const ma_ring_buffer* pRingBuffer); /* Returns the number of elements currently in the ring buffer. Should only be called from the producer or consumer thread. If something is in the middle of producing or consuming data on the ring buffer than the returned value may already be out of date. */
|
||||
MA_API ma_uint32 ma_ring_buffer_capacity(const ma_ring_buffer* pRingBuffer);
|
||||
/* END ma_ring_buffer.h */
|
||||
|
||||
@@ -6336,13 +6353,13 @@ typedef struct ma_audio_ring_buffer
|
||||
MA_API ma_result ma_audio_ring_buffer_init_ex(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 capacityInFrames, ma_uint32 flags, void* pBuffer, ma_audio_ring_buffer* pRingBuffer);
|
||||
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);
|
||||
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);
|
||||
MA_API ma_uint32 ma_audio_ring_buffer_map_consume(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_consume(ma_audio_ring_buffer* pRingBuffer, ma_uint32 frameCount);
|
||||
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);
|
||||
MA_API ma_result ma_audio_ring_buffer_read_pcm_frames(ma_audio_ring_buffer* pRingBuffer, void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesRead);
|
||||
MA_API ma_result ma_audio_ring_buffer_get_length_in_pcm_frames(ma_audio_ring_buffer* pRingBuffer, ma_uint32* pLength);
|
||||
|
||||
|
||||
/*
|
||||
@@ -32542,7 +32559,7 @@ static void ma_stream_event_process__pipewire(void* pUserData, ma_device_type de
|
||||
if (ma_device_get_threading_mode(pDeviceStatePipeWire->pDevice) == MA_THREADING_MODE_MULTI_THREADED) {
|
||||
ma_device_handle_backend_data_callback(pDeviceStatePipeWire->pDevice, pBuffer->buffer->datas[0].data, NULL, frameCount);
|
||||
} else {
|
||||
ma_uint64 framesRead;
|
||||
ma_uint32 framesRead;
|
||||
|
||||
ma_audio_ring_buffer_read_pcm_frames(&pStreamState->rb, pBuffer->buffer->datas[0].data, frameCount, &framesRead);
|
||||
if (framesRead < frameCount) {
|
||||
@@ -32556,7 +32573,7 @@ static void ma_stream_event_process__pipewire(void* pUserData, ma_device_type de
|
||||
if (ma_device_get_threading_mode(pDeviceStatePipeWire->pDevice) == MA_THREADING_MODE_MULTI_THREADED) {
|
||||
ma_device_handle_backend_data_callback(pDeviceStatePipeWire->pDevice, NULL, pBuffer->buffer->datas[0].data, frameCount);
|
||||
} else {
|
||||
ma_uint64 framesWritten;
|
||||
ma_uint32 framesWritten;
|
||||
|
||||
ma_audio_ring_buffer_write_pcm_frames(&pStreamState->rb, pBuffer->buffer->datas[0].data, frameCount, &framesWritten);
|
||||
if (framesWritten < frameCount) {
|
||||
@@ -63357,6 +63374,19 @@ MA_API void ma_ring_buffer_init(ma_uint32 capacity, ma_uint32 stride, ma_uint32
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
When offsetting pointers when mapping we multiply our cursors by the stride. Cursors are clamped to the
|
||||
capacity. We therefore want to make sure the multiplication of the capacity by the stride does not
|
||||
overflow our 32-bit range. We could use the maximum value of a size_t here instead, but then there is
|
||||
slightly different behaviour between 32- and 64-bit builds. For the purpose of this ring buffer, I would
|
||||
prefer this be totally consistent between architectures so I'm enforcing a 32-bit maximum.
|
||||
*/
|
||||
if (capacity > (0xFFFFFFFF / stride)) {
|
||||
MA_ASSERT(!"Ring buffer capacity multiplied by the stride exceeds the enforced 32-bit limit of 0xFFFFFFFF.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
pRingBuffer->capacity = capacity;
|
||||
pRingBuffer->stride = stride;
|
||||
pRingBuffer->flags = flags;
|
||||
@@ -63401,7 +63431,7 @@ static MA_INLINE ma_uint32 ma_ring_buffer_calculate_remaining(ma_uint32 head, ma
|
||||
return capacity - ma_ring_buffer_calculate_length(head, tail, capacity);
|
||||
}
|
||||
|
||||
MA_API size_t ma_ring_buffer_map_produce(ma_ring_buffer* pRingBuffer, size_t count, void** ppMappedBuffer)
|
||||
MA_API ma_uint32 ma_ring_buffer_map_produce(ma_ring_buffer* pRingBuffer, ma_uint32 count, void** ppMappedBuffer)
|
||||
{
|
||||
ma_uint32 head;
|
||||
ma_uint32 tail;
|
||||
@@ -63418,13 +63448,12 @@ MA_API size_t ma_ring_buffer_map_produce(ma_ring_buffer* pRingBuffer, size_t cou
|
||||
}
|
||||
|
||||
/*
|
||||
For the head, only the producer will be making modifications to it so we can just use relaxed. For the tail,
|
||||
it is indeed modified by the consumer, but since the producer does not actually have a data dependency on
|
||||
anything done by the consumer the tail is essentially just a cursor for us to determine how much data we can
|
||||
produce. It can therefore be relaxed as well.
|
||||
For the head, only the producer will be making modifications to it so we can just use relaxed. For the tail
|
||||
we need to ensure the producer does not overwrite anything that the consumer is still reading so we'll need
|
||||
to use acquire semantics here (it will be released when the consumer is unmapped).
|
||||
*/
|
||||
head = ma_atomic_load_explicit_32(&pRingBuffer->head, ma_atomic_memory_order_relaxed);
|
||||
tail = ma_atomic_load_explicit_32(&pRingBuffer->tail, ma_atomic_memory_order_relaxed);
|
||||
tail = ma_atomic_load_explicit_32(&pRingBuffer->tail, ma_atomic_memory_order_acquire);
|
||||
|
||||
/* Now we need to clamp the count to ensure it never goes beyond our capacity. */
|
||||
remaining = ma_ring_buffer_calculate_remaining(head, tail, pRingBuffer->capacity);
|
||||
@@ -63432,13 +63461,15 @@ MA_API size_t ma_ring_buffer_map_produce(ma_ring_buffer* pRingBuffer, size_t cou
|
||||
count = remaining;
|
||||
}
|
||||
|
||||
/* Our pointer will always just be where our head is pointing. */
|
||||
*ppMappedBuffer = ma_offset_ptr(pRingBuffer->pBuffer, (head & 0x7FFFFFFF) * pRingBuffer->stride);
|
||||
if (count > 0) {
|
||||
/* Our pointer will always just be where our head is pointing. */
|
||||
*ppMappedBuffer = ma_offset_ptr(pRingBuffer->pBuffer, (head & 0x7FFFFFFF) * pRingBuffer->stride);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
MA_API void ma_ring_buffer_unmap_produce(ma_ring_buffer* pRingBuffer, size_t count)
|
||||
MA_API void ma_ring_buffer_unmap_produce(ma_ring_buffer* pRingBuffer, ma_uint32 count)
|
||||
{
|
||||
ma_uint32 head;
|
||||
ma_uint32 tail;
|
||||
@@ -63447,6 +63478,8 @@ MA_API void ma_ring_buffer_unmap_produce(ma_ring_buffer* pRingBuffer, size_t cou
|
||||
return;
|
||||
}
|
||||
|
||||
MA_ASSERT(count <= pRingBuffer->capacity);
|
||||
|
||||
head = ma_atomic_load_explicit_32(&pRingBuffer->head, ma_atomic_memory_order_relaxed);
|
||||
tail = ma_atomic_load_explicit_32(&pRingBuffer->tail, ma_atomic_memory_order_relaxed);
|
||||
|
||||
@@ -63481,7 +63514,7 @@ MA_API void ma_ring_buffer_unmap_produce(ma_ring_buffer* pRingBuffer, size_t cou
|
||||
ma_atomic_store_explicit_32(&pRingBuffer->head, head, ma_atomic_memory_order_release);
|
||||
}
|
||||
|
||||
MA_API size_t ma_ring_buffer_map_consume(ma_ring_buffer* pRingBuffer, size_t count, void** ppMappedBuffer)
|
||||
MA_API ma_uint32 ma_ring_buffer_map_consume(ma_ring_buffer* pRingBuffer, ma_uint32 count, void** ppMappedBuffer)
|
||||
{
|
||||
ma_uint32 head;
|
||||
ma_uint32 tail;
|
||||
@@ -63510,25 +63543,27 @@ MA_API size_t ma_ring_buffer_map_consume(ma_ring_buffer* pRingBuffer, size_t cou
|
||||
count = length;
|
||||
}
|
||||
|
||||
/* Our pointer will always just be where our tail is pointing. */
|
||||
*ppMappedBuffer = ma_offset_ptr(pRingBuffer->pBuffer, (tail & 0x7FFFFFFF) * pRingBuffer->stride);
|
||||
if (count > 0) {
|
||||
/* Our pointer will always just be where our tail is pointing. */
|
||||
*ppMappedBuffer = ma_offset_ptr(pRingBuffer->pBuffer, (tail & 0x7FFFFFFF) * pRingBuffer->stride);
|
||||
|
||||
/*
|
||||
If the buffer is not mirrored we may need to copy some data from the start of the buffer to the overflow
|
||||
part so the caller has a contiguous block to work with.
|
||||
*/
|
||||
if ((pRingBuffer->flags & MA_RING_BUFFER_FLAG_MIRRORED) == 0) {
|
||||
ma_uint32 newTail = (tail & 0x7FFFFFFF) + count;
|
||||
if (newTail > pRingBuffer->capacity) {
|
||||
newTail -= pRingBuffer->capacity;
|
||||
MA_COPY_MEMORY(ma_offset_ptr(pRingBuffer->pBuffer, pRingBuffer->capacity * pRingBuffer->stride), pRingBuffer->pBuffer, newTail * pRingBuffer->stride);
|
||||
/*
|
||||
If the buffer is not mirrored we may need to copy some data from the start of the buffer to the overflow
|
||||
part so the caller has a contiguous block to work with.
|
||||
*/
|
||||
if ((pRingBuffer->flags & MA_RING_BUFFER_FLAG_MIRRORED) == 0) {
|
||||
ma_uint32 newTail = (tail & 0x7FFFFFFF) + count;
|
||||
if (newTail > pRingBuffer->capacity) {
|
||||
newTail -= pRingBuffer->capacity;
|
||||
MA_COPY_MEMORY(ma_offset_ptr(pRingBuffer->pBuffer, pRingBuffer->capacity * pRingBuffer->stride), pRingBuffer->pBuffer, newTail * pRingBuffer->stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
MA_API void ma_ring_buffer_unmap_consume(ma_ring_buffer* pRingBuffer, size_t count)
|
||||
MA_API void ma_ring_buffer_unmap_consume(ma_ring_buffer* pRingBuffer, ma_uint32 count)
|
||||
{
|
||||
ma_uint32 head;
|
||||
ma_uint32 tail;
|
||||
@@ -63537,6 +63572,8 @@ MA_API void ma_ring_buffer_unmap_consume(ma_ring_buffer* pRingBuffer, size_t cou
|
||||
return;
|
||||
}
|
||||
|
||||
MA_ASSERT(count <= pRingBuffer->capacity);
|
||||
|
||||
/*
|
||||
When we first mapped the buffer with `map_consume()` we used acquire semantics for the head. Since we won't
|
||||
be touching any data that was produced between our map and unmap, we should be able to use relaxed here.
|
||||
@@ -63558,14 +63595,19 @@ MA_API void ma_ring_buffer_unmap_consume(ma_ring_buffer* pRingBuffer, size_t cou
|
||||
tail ^= 0x80000000; /* Flip the loop flag. */
|
||||
}
|
||||
|
||||
/* The producer doesn't care what we do with the data in the buffer so we should be able to use relaxed semantics here for the tail. */
|
||||
ma_atomic_store_explicit_32(&pRingBuffer->tail, tail, ma_atomic_memory_order_relaxed);
|
||||
/*
|
||||
The producer will be using acquire semantics for the tail, so we'll want to mirror that with a release here. If
|
||||
we were to use relaxed here we would run the risk of the producer overwriting data before the consumer has
|
||||
finished reading it.
|
||||
*/
|
||||
ma_atomic_store_explicit_32(&pRingBuffer->tail, tail, ma_atomic_memory_order_release);
|
||||
}
|
||||
|
||||
MA_API ma_uint32 ma_ring_buffer_length(const ma_ring_buffer* pRingBuffer)
|
||||
{
|
||||
ma_uint32 head;
|
||||
ma_uint32 tail;
|
||||
ma_uint32 length;
|
||||
|
||||
if (pRingBuffer == NULL) {
|
||||
return 0;
|
||||
@@ -63574,7 +63616,14 @@ MA_API ma_uint32 ma_ring_buffer_length(const ma_ring_buffer* pRingBuffer)
|
||||
head = ma_atomic_load_explicit_32(&pRingBuffer->head, ma_atomic_memory_order_relaxed);
|
||||
tail = ma_atomic_load_explicit_32(&pRingBuffer->tail, ma_atomic_memory_order_relaxed);
|
||||
|
||||
return ma_ring_buffer_calculate_length(head, tail, pRingBuffer->capacity);
|
||||
length = ma_ring_buffer_calculate_length(head, tail, pRingBuffer->capacity);
|
||||
|
||||
/* Do a clamp just in case the caller violates the API contract and calls this from a non-consumer and non-producer thread. */
|
||||
if (length > pRingBuffer->capacity) {
|
||||
length = pRingBuffer->capacity;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
MA_API ma_uint32 ma_ring_buffer_capacity(const ma_ring_buffer* pRingBuffer)
|
||||
@@ -63592,10 +63641,13 @@ static ma_result ma_audio_ring_buffer__data_source_on_read(ma_data_source* pData
|
||||
{
|
||||
ma_audio_ring_buffer* pRingBuffer = (ma_audio_ring_buffer*)pDataSource;
|
||||
ma_result result;
|
||||
ma_uint64 framesRead;
|
||||
ma_uint32 framesRead;
|
||||
|
||||
if (frameCount > 0xFFFFFFFF) {
|
||||
frameCount = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
result = ma_audio_ring_buffer_read_pcm_frames(pRingBuffer, pFrames, frameCount, &framesRead);
|
||||
result = ma_audio_ring_buffer_read_pcm_frames(pRingBuffer, pFrames, (ma_uint32)frameCount, &framesRead); /* Safe cast due to the check above. */
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
@@ -63605,9 +63657,9 @@ static ma_result ma_audio_ring_buffer__data_source_on_read(ma_data_source* pData
|
||||
count we'll need to pad with silence. If we don't do this, framesRead might equal 0 which will result in
|
||||
the data source layer at a higher level translating this to MA_AT_END which is incorrect for a ring buffer.
|
||||
*/
|
||||
if (framesRead < frameCount) {
|
||||
if (framesRead < (ma_uint32)frameCount) {
|
||||
ma_silence_pcm_frames(ma_offset_pcm_frames_ptr(pFrames, framesRead, pRingBuffer->format, pRingBuffer->channels), (frameCount - framesRead), pRingBuffer->format, pRingBuffer->channels);
|
||||
framesRead = frameCount;
|
||||
framesRead = (ma_uint32)frameCount;
|
||||
}
|
||||
|
||||
*pFramesRead = framesRead;
|
||||
@@ -63629,7 +63681,17 @@ static ma_result ma_audio_ring_buffer__data_source_on_get_data_format(ma_data_so
|
||||
|
||||
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);
|
||||
ma_result result;
|
||||
ma_uint32 length;
|
||||
|
||||
result = ma_audio_ring_buffer_get_length_in_pcm_frames((ma_audio_ring_buffer*)pDataSource, &length);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
*pLength = length;
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_data_source_vtable ma_gDataSourceVTable_AudioRingBuffer =
|
||||
@@ -63735,53 +63797,43 @@ MA_API void ma_audio_ring_buffer_uninit(ma_audio_ring_buffer* pRingBuffer)
|
||||
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)
|
||||
MA_API ma_uint32 ma_audio_ring_buffer_map_produce(ma_audio_ring_buffer* pRingBuffer, ma_uint32 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);
|
||||
return ma_ring_buffer_map_produce(&pRingBuffer->rb, frameCount, ppMappedBuffer);
|
||||
}
|
||||
|
||||
MA_API void ma_audio_ring_buffer_unmap_produce(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount)
|
||||
MA_API void ma_audio_ring_buffer_unmap_produce(ma_audio_ring_buffer* pRingBuffer, ma_uint32 frameCount)
|
||||
{
|
||||
if (pRingBuffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ma_ring_buffer_unmap_produce(&pRingBuffer->rb, (size_t)frameCount);
|
||||
ma_ring_buffer_unmap_produce(&pRingBuffer->rb, frameCount);
|
||||
}
|
||||
|
||||
MA_API ma_uint64 ma_audio_ring_buffer_map_consume(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount, void** ppMappedBuffer)
|
||||
MA_API ma_uint32 ma_audio_ring_buffer_map_consume(ma_audio_ring_buffer* pRingBuffer, ma_uint32 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);
|
||||
return ma_ring_buffer_map_consume(&pRingBuffer->rb, frameCount, ppMappedBuffer);
|
||||
}
|
||||
|
||||
MA_API void ma_audio_ring_buffer_unmap_consume(ma_audio_ring_buffer* pRingBuffer, ma_uint64 frameCount)
|
||||
MA_API void ma_audio_ring_buffer_unmap_consume(ma_audio_ring_buffer* pRingBuffer, ma_uint32 frameCount)
|
||||
{
|
||||
if (pRingBuffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ma_ring_buffer_unmap_consume(&pRingBuffer->rb, (size_t)frameCount);
|
||||
ma_ring_buffer_unmap_consume(&pRingBuffer->rb, 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_write_pcm_frames(ma_audio_ring_buffer* pRingBuffer, const void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
|
||||
{
|
||||
void* pMappedBuffer;
|
||||
|
||||
@@ -63795,7 +63847,7 @@ MA_API ma_result ma_audio_ring_buffer_write_pcm_frames(ma_audio_ring_buffer* pRi
|
||||
|
||||
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));
|
||||
size_t bytesToCopy = (size_t)frameCount * ma_get_bytes_per_frame(pRingBuffer->format, pRingBuffer->channels);
|
||||
|
||||
if (pFrames != NULL) {
|
||||
MA_COPY_MEMORY(pMappedBuffer, pFrames, bytesToCopy);
|
||||
@@ -63812,7 +63864,7 @@ MA_API ma_result ma_audio_ring_buffer_write_pcm_frames(ma_audio_ring_buffer* pRi
|
||||
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)
|
||||
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;
|
||||
|
||||
@@ -63826,7 +63878,7 @@ MA_API ma_result ma_audio_ring_buffer_read_pcm_frames(ma_audio_ring_buffer* pRin
|
||||
|
||||
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));
|
||||
size_t bytesToCopy = (size_t)frameCount * ma_get_bytes_per_frame(pRingBuffer->format, pRingBuffer->channels);
|
||||
|
||||
if (pFrames != NULL) {
|
||||
MA_COPY_MEMORY(pFrames, pMappedBuffer, bytesToCopy);
|
||||
@@ -63841,7 +63893,7 @@ MA_API ma_result ma_audio_ring_buffer_read_pcm_frames(ma_audio_ring_buffer* pRin
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API ma_result ma_audio_ring_buffer_get_length_in_pcm_frames(ma_audio_ring_buffer* pRingBuffer, ma_uint64* pLength)
|
||||
MA_API ma_result ma_audio_ring_buffer_get_length_in_pcm_frames(ma_audio_ring_buffer* pRingBuffer, ma_uint32* pLength)
|
||||
{
|
||||
if (pLength == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
|
||||
Reference in New Issue
Block a user