mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Remove ma_audio_queue.
This commit is contained in:
@@ -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_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. */
|
#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_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_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_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_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_vocoder_node g_vocoderNode; /* The vocoder node. */
|
||||||
static ma_node_graph g_nodeGraph;
|
static ma_node_graph g_nodeGraph;
|
||||||
|
|
||||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
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
|
the data source is our `pInput` buffer. We need to update the underlying data source so that it
|
||||||
read data from `pInput`.
|
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. */
|
/* 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);
|
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 sourceNodeConfig;
|
||||||
ma_data_source_node_config exciteNodeConfig;
|
ma_data_source_node_config exciteNodeConfig;
|
||||||
ma_waveform_config waveformConfig;
|
ma_waveform_config waveformConfig;
|
||||||
ma_audio_queue_config audioQueueConfig;
|
|
||||||
|
|
||||||
deviceConfig = ma_device_config_init(ma_device_type_duplex);
|
deviceConfig = ma_device_config_init(ma_device_type_duplex);
|
||||||
deviceConfig.capture.pDeviceID = NULL;
|
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. */
|
/* 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_ring_buffer_init(device.capture.format, device.capture.channels, device.sampleRate, device.capture.internalPeriodSizeInFrames * 3, NULL, &g_exciteData);
|
||||||
|
|
||||||
result = ma_audio_queue_init(&audioQueueConfig, &g_exciteData);
|
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
printf("Failed to initialize audio buffer for source.");
|
printf("Failed to initialize audio buffer for source.");
|
||||||
goto done2;
|
goto done2;
|
||||||
|
|||||||
-324
@@ -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
|
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
|
VFS
|
||||||
|
|||||||
Reference in New Issue
Block a user