From fcd386dd87e7a7cfba8b097c9f058e05542b868b Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 27 Jan 2026 06:17:14 +1000 Subject: [PATCH] Remove `ma_audio_queue`. --- examples/duplex_effect.c | 19 +-- miniaudio.h | 324 --------------------------------------- 2 files changed, 8 insertions(+), 335 deletions(-) diff --git a/examples/duplex_effect.c b/examples/duplex_effect.c index 4a200d80..405223d4 100644 --- a/examples/duplex_effect.c +++ b/examples/duplex_effect.c @@ -14,12 +14,12 @@ effect. #define DEVICE_FORMAT ma_format_f32 /* Must always be f32 for this example because the node graph system only works with this. */ #define DEVICE_CHANNELS 1 /* For this example, always set to 1. */ -static ma_waveform g_sourceData; /* The underlying data source of the source node. */ -static ma_audio_queue g_exciteData; /* The underlying data source of the excite node. */ -static ma_data_source_node g_sourceNode; /* A data source node containing the source data we'll be sending through to the vocoder. This will be routed into the first bus of the vocoder node. */ -static ma_data_source_node g_exciteNode; /* A data source node containing the excite data we'll be sending through to the vocoder. This will be routed into the second bus of the vocoder node. */ -static ma_vocoder_node g_vocoderNode; /* The vocoder node. */ -static ma_node_graph g_nodeGraph; +static ma_waveform g_sourceData; /* The underlying data source of the source node. */ +static ma_audio_ring_buffer g_exciteData; /* The underlying data source of the excite node. */ +static ma_data_source_node g_sourceNode; /* A data source node containing the source data we'll be sending through to the vocoder. This will be routed into the first bus of the vocoder node. */ +static ma_data_source_node g_exciteNode; /* A data source node containing the excite data we'll be sending through to the vocoder. This will be routed into the second bus of the vocoder node. */ +static ma_vocoder_node g_vocoderNode; /* The vocoder node. */ +static ma_node_graph g_nodeGraph; void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { @@ -37,7 +37,7 @@ void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uin the data source is our `pInput` buffer. We need to update the underlying data source so that it read data from `pInput`. */ - ma_audio_queue_push_pcm_frames(&g_exciteData, pInput, frameCount); + ma_audio_ring_buffer_write_pcm_frames(&g_exciteData, pInput, frameCount, NULL); /* With the source buffer configured we can now read directly from the node graph. */ ma_node_graph_read_pcm_frames(&g_nodeGraph, pOutput, frameCount, NULL); @@ -53,7 +53,6 @@ int main(int argc, char** argv) ma_data_source_node_config sourceNodeConfig; ma_data_source_node_config exciteNodeConfig; ma_waveform_config waveformConfig; - ma_audio_queue_config audioQueueConfig; deviceConfig = ma_device_config_init(ma_device_type_duplex); deviceConfig.capture.pDeviceID = NULL; @@ -116,9 +115,7 @@ int main(int argc, char** argv) /* Excite/modulator. Attached to input bus 1 of the vocoder node. */ - audioQueueConfig = ma_audio_queue_config_init(device.capture.format, device.capture.channels, device.sampleRate, 0); - - result = ma_audio_queue_init(&audioQueueConfig, &g_exciteData); + result = ma_audio_ring_buffer_init(device.capture.format, device.capture.channels, device.sampleRate, device.capture.internalPeriodSizeInFrames * 3, NULL, &g_exciteData); if (result != MA_SUCCESS) { printf("Failed to initialize audio buffer for source."); goto done2; diff --git a/miniaudio.h b/miniaudio.h index 0cdac108..1a561a66 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -6250,60 +6250,6 @@ MA_API ma_result ma_paged_audio_buffer_get_length_in_pcm_frames(ma_paged_audio_b -/* -Audio Queue -=========== -The audio queue is a data source that allows you to push data from one thread and then read it from -another. The audio queue can be fixed sized or dynamic. Dynamic is the default. To use a static -queue set the the size to non-0. - -With a static queue, if you attempt to push data but there is no room, the entire data will be rejected -and MA_NO_SPACE will be returned. For a dynamic queue it is restricted by memory capacity. - -There is no seeking and no notion of a cursor. The length will be how many PCM frames are currently -sitting in the queue. - -The total capacity of the queue in PCM frames is restricted to 32-bits. - -This is thread safe, but not currently 100% lock-free. This currently uses a dumb spinlock for thread -safety, but there are plans to improve on this later. -*/ - -typedef struct -{ - ma_format format; - ma_uint32 channels; - ma_uint32 sampleRate; - ma_uint32 sizeInFrames; /* When set to 0 (the default), the queue will be dynamically expanding. When set to non-0, the audio queue will be static. */ - ma_allocation_callbacks allocationCallbacks; -} ma_audio_queue_config; - -MA_API ma_audio_queue_config ma_audio_queue_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 sizeInFrames); - - -typedef struct -{ - ma_data_source_base ds; - ma_format format; - ma_uint32 channels; - ma_uint32 sampleRate; - ma_bool32 isStatic; - ma_uint32 capacityInFrames; - ma_uint64 cursorWrite; - ma_uint64 cursorRead; - void* pBuffer; - ma_allocation_callbacks allocationCallbacks; - ma_spinlock lock; /* Temporary until we get a good lock-free solution working. */ -} ma_audio_queue; - -MA_API ma_result ma_audio_queue_init(const ma_audio_queue_config* pConfig, ma_audio_queue* pAudioQueue); -MA_API void ma_audio_queue_uninit(ma_audio_queue* pAudioQueue); -MA_API ma_result ma_audio_queue_push_pcm_frames(ma_audio_queue* pAudioQueue, const void* pFrames, ma_uint64 frameCount); -MA_API ma_result ma_audio_queue_read_pcm_frames(ma_audio_queue* pAudioQueue, void* pFrames, ma_uint64 frameCount, ma_uint64* pFramesRead); -MA_API ma_result ma_audio_queue_get_length_in_pcm_frames(ma_audio_queue* pAudioQueue, ma_uint64* pLength); - - - /************************************************************************************************************************************************************ Ring Buffer @@ -65923,276 +65869,6 @@ MA_API ma_result ma_paged_audio_buffer_get_length_in_pcm_frames(ma_paged_audio_b - -MA_API ma_audio_queue_config ma_audio_queue_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 sizeInFrames) -{ - ma_audio_queue_config config; - - MA_ZERO_OBJECT(&config); - config.format = format; - config.channels = channels; - config.sampleRate = sampleRate; - config.sizeInFrames = sizeInFrames; - - return config; -} - - -static ma_result ma_audio_queue__data_source_on_read(ma_data_source* pDataSource, void* pFrames, ma_uint64 frameCount, ma_uint64* pFramesRead) -{ - return ma_audio_queue_read_pcm_frames((ma_audio_queue*)pDataSource, pFrames, frameCount, pFramesRead); -} - -static ma_result ma_audio_queue__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_queue* pAudioQueue = (ma_audio_queue*)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_queue__data_source_on_get_length(ma_data_source* pDataSource, ma_uint64* pLength) -{ - return ma_audio_queue_get_length_in_pcm_frames((ma_audio_queue*)pDataSource, pLength); -} - -static ma_data_source_vtable ma_gDataSourceVTable_AudioQueue = -{ - ma_audio_queue__data_source_on_read, - NULL, /* No seeking in audio queues. */ - ma_audio_queue__data_source_on_get_data_format, - NULL, /* No notion of a cursor. */ - ma_audio_queue__data_source_on_get_length, - NULL, /* onSetLooping */ - 0 -}; - -MA_API ma_result ma_audio_queue_init(const ma_audio_queue_config* pConfig, ma_audio_queue* pAudioQueue) -{ - ma_result result; - ma_data_source_config dataSourceConfig; - - if (pAudioQueue == NULL) { - return MA_INVALID_ARGS; - } - - MA_ZERO_OBJECT(pAudioQueue); - - if (pConfig == NULL) { - return MA_INVALID_ARGS; - } - - - /* Initialize the data source first. */ - dataSourceConfig = ma_data_source_config_init(); - dataSourceConfig.pVTable = &ma_gDataSourceVTable_AudioQueue; - - result = ma_data_source_init(&dataSourceConfig, &pAudioQueue->ds); - if (result != MA_SUCCESS) { - return result; - } - - pAudioQueue->format = pConfig->format; - pAudioQueue->channels = pConfig->channels; - pAudioQueue->sampleRate = pConfig->sampleRate; - pAudioQueue->capacityInFrames = pConfig->sizeInFrames; - ma_allocation_callbacks_init_copy(&pAudioQueue->allocationCallbacks, &pConfig->allocationCallbacks); - - if (pAudioQueue->capacityInFrames > 0) { - pAudioQueue->pBuffer = ma_malloc(pAudioQueue->capacityInFrames * ma_get_bytes_per_frame(pAudioQueue->format, pAudioQueue->channels), &pAudioQueue->allocationCallbacks); - if (pAudioQueue->pBuffer == NULL) { - return MA_OUT_OF_MEMORY; - } - - pAudioQueue->isStatic = MA_TRUE; - } - - return MA_SUCCESS; -} - -MA_API void ma_audio_queue_uninit(ma_audio_queue* pAudioQueue) -{ - if (pAudioQueue == NULL) { - return; - } - - 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) -{ - ma_uint64 framesWritten = 0; - - while (framesWritten < frameCount) { - ma_uint64 framesRemaining = (frameCount - framesWritten); - ma_uint64 framesToWriteThisIteration = framesRemaining; - ma_uint64 writeOffset; - - writeOffset = pAudioQueue->cursorWrite % pAudioQueue->capacityInFrames; - - if (framesToWriteThisIteration + writeOffset > pAudioQueue->capacityInFrames) { - framesToWriteThisIteration = pAudioQueue->capacityInFrames - writeOffset; - } - - MA_COPY_MEMORY(ma_offset_ptr(pAudioQueue->pBuffer, writeOffset * bpf), ma_offset_ptr(pFrames, framesWritten * bpf), (size_t)(framesToWriteThisIteration * bpf)); - pAudioQueue->cursorWrite += framesToWriteThisIteration; - framesWritten += framesToWriteThisIteration; - } -} - -static void ma_audio_queue_read_pcm_frames_nolock(ma_audio_queue* pAudioQueue, void* pFrames, ma_uint64 frameCount, ma_uint32 bpf) -{ - ma_uint64 framesRead = 0; - - while (framesRead < frameCount) { - ma_uint64 framesRemaining = (frameCount - framesRead); - ma_uint64 framesToReadThisIteration = framesRemaining; - ma_uint64 readOffset; - - readOffset = pAudioQueue->cursorRead % pAudioQueue->capacityInFrames; - - if (framesToReadThisIteration + readOffset > pAudioQueue->capacityInFrames) { - framesToReadThisIteration = pAudioQueue->capacityInFrames - readOffset; - } - - MA_COPY_MEMORY(ma_offset_ptr(pFrames, framesRead * bpf), ma_offset_ptr(pAudioQueue->pBuffer, readOffset * bpf), (size_t)(framesToReadThisIteration * bpf)); - pAudioQueue->cursorRead += framesToReadThisIteration; - framesRead += framesToReadThisIteration; - } -} - -MA_API ma_result ma_audio_queue_push_pcm_frames(ma_audio_queue* pAudioQueue, const void* pFrames, ma_uint64 frameCount) -{ - ma_result result; - ma_uint64 length; - ma_uint32 bpf; - ma_uint32 newCapacity; - void* pNewBuffer = NULL; - void* pOldBuffer = NULL; - - if (pAudioQueue == NULL) { - return MA_INVALID_ARGS; - } - - if (pFrames == NULL) { - return MA_INVALID_ARGS; /* Push silence instead? */ - } - - result = ma_audio_queue_get_length_in_pcm_frames(pAudioQueue, &length); - if (result != MA_SUCCESS) { - return result; - } - - bpf = ma_get_bytes_per_frame(pAudioQueue->format, pAudioQueue->channels); - - if (frameCount > (pAudioQueue->capacityInFrames - length)) { - if (pAudioQueue->isStatic) { - return MA_NO_SPACE; - } else { - newCapacity = pAudioQueue->capacityInFrames * 2; - if (newCapacity < length + frameCount) { - newCapacity = length + frameCount; - } - - pNewBuffer = ma_malloc(newCapacity * bpf, &pAudioQueue->allocationCallbacks); - if (pNewBuffer == NULL) { - return MA_OUT_OF_MEMORY; - } - } - } - - ma_spinlock_lock(&pAudioQueue->lock); - { - length = pAudioQueue->cursorWrite - pAudioQueue->cursorRead; - - /* If we have a new buffer we need to swap out the old one with the new. */ - if (pNewBuffer != NULL) { - pOldBuffer = pAudioQueue->pBuffer; - - /* Fill the new buffer. */ - ma_audio_queue_read_pcm_frames_nolock(pAudioQueue, pNewBuffer, length, bpf); - - /* Normalize our cursors. */ - pAudioQueue->cursorRead = 0; - pAudioQueue->cursorWrite = length; - - /* Swap out the buffer. */ - pAudioQueue->pBuffer = pNewBuffer; - pAudioQueue->capacityInFrames = newCapacity; - } - - ma_audio_queue_write_pcm_frames_nolock(pAudioQueue, pFrames, frameCount, bpf); - } - ma_spinlock_unlock(&pAudioQueue->lock); - - if (pOldBuffer != NULL) { - ma_free(pOldBuffer, &pAudioQueue->allocationCallbacks); - } - - return MA_SUCCESS; -} - -MA_API ma_result ma_audio_queue_read_pcm_frames(ma_audio_queue* pAudioQueue, void* pFrames, ma_uint64 frameCount, ma_uint64* pFramesRead) -{ - ma_result result; - ma_uint64 length; - ma_uint32 bpf; - - /* Clamp the frame count to the length. */ - result = ma_audio_queue_get_length_in_pcm_frames(pAudioQueue, &length); - if (result != MA_SUCCESS) { - return result; - } - - if (frameCount > length) { - frameCount = length; - } - - bpf = ma_get_bytes_per_frame(pAudioQueue->format, pAudioQueue->channels); - - ma_spinlock_lock(&pAudioQueue->lock); - { - ma_audio_queue_read_pcm_frames_nolock(pAudioQueue, pFrames, frameCount, bpf); - } - ma_spinlock_unlock(&pAudioQueue->lock); - - if (pFramesRead != NULL) { - *pFramesRead = frameCount; - } - - /* Note that we never returning MA_AT_END for a queue because there isn't really a notion of it. */ - return MA_SUCCESS; -} - -MA_API ma_result ma_audio_queue_get_length_in_pcm_frames(ma_audio_queue* pAudioQueue, ma_uint64* pLength) -{ - if (pLength == NULL) { - return MA_INVALID_ARGS; - } - - *pLength = 0; - - if (pAudioQueue == NULL) { - return MA_INVALID_ARGS; - } - - ma_spinlock_lock(&pAudioQueue->lock); - { - *pLength = (pAudioQueue->cursorWrite - pAudioQueue->cursorRead); - } - ma_spinlock_unlock(&pAudioQueue->lock); - - return MA_SUCCESS; -} - - - - /************************************************************************************************************************************************************** VFS