mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-21 15:56:58 +02:00
Update the audio ring buffer to use the standard config/init pattern.
This makes it consistent with everything else in the library.
This commit is contained in:
@@ -53,6 +53,7 @@ int main(int argc, char** argv)
|
||||
ma_data_source_node_config sourceNodeConfig;
|
||||
ma_data_source_node_config exciteNodeConfig;
|
||||
ma_waveform_config waveformConfig;
|
||||
ma_audio_ring_buffer_config ringBufferConfig;
|
||||
|
||||
deviceConfig = ma_device_config_init(ma_device_type_duplex);
|
||||
deviceConfig.capture.pDeviceID = NULL;
|
||||
@@ -115,7 +116,9 @@ int main(int argc, char** argv)
|
||||
|
||||
|
||||
/* Excite/modulator. Attached to input bus 1 of the vocoder node. */
|
||||
result = ma_audio_ring_buffer_init(device.capture.format, device.capture.channels, device.sampleRate, device.capture.internalPeriodSizeInFrames * 3, NULL, &g_exciteData);
|
||||
ringBufferConfig = ma_audio_ring_buffer_config_init(device.capture.format, device.capture.channels, device.sampleRate, device.capture.internalPeriodSizeInFrames * 3);
|
||||
|
||||
result = ma_audio_ring_buffer_init(&ringBufferConfig, &g_exciteData);
|
||||
if (result != MA_SUCCESS) {
|
||||
printf("Failed to initialize audio buffer for source.");
|
||||
goto done2;
|
||||
|
||||
@@ -35,6 +35,7 @@ int main(int argc, char** argv)
|
||||
{
|
||||
ma_result result;
|
||||
ma_device_config deviceConfig;
|
||||
ma_audio_ring_buffer_config ringBufferConfig;
|
||||
|
||||
/*
|
||||
The first thing we'll do is set up the capture side. There are two parts to this. The first is
|
||||
@@ -59,7 +60,9 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
/* Initialize the ring buffer. Make sure the sample rate is set so the engine can resample it if necessary. */
|
||||
result = ma_audio_ring_buffer_init(device.capture.format, device.capture.channels, device.sampleRate, device.capture.internalPeriodSizeInFrames * 3, NULL, &rb);
|
||||
ringBufferConfig = ma_audio_ring_buffer_config_init(device.capture.format, device.capture.channels, device.sampleRate, device.capture.internalPeriodSizeInFrames * 3);
|
||||
|
||||
result = ma_audio_ring_buffer_init(&ringBufferConfig, &rb);
|
||||
if (result != MA_SUCCESS) {
|
||||
printf("Failed to initialize the ring buffer.");
|
||||
return -1;
|
||||
|
||||
+94
-59
@@ -3568,25 +3568,30 @@ you will want to use. To initialize a ring buffer, do something like the followi
|
||||
|
||||
```c
|
||||
ma_audio_ring_buffer rb;
|
||||
ma_result result = ma_audio_ring_buffer_init(FORMAT, CHANNELS, SAMPLE_RATE, BUFFER_SIZE_IN_FRAMES, NULL, &rb);
|
||||
ma_audio_ring_buffer_config rbConfig;
|
||||
|
||||
rbConfig = ma_audio_ring_buffer_config_init(FORMAT, CHANNELS, SAMPLE_RATE, BUFFER_SIZE_IN_FRAMES);
|
||||
|
||||
ma_result result = ma_audio_ring_buffer_init(&rbConfig, &rb);
|
||||
if (result != MA_SUCCESS) {
|
||||
// Error
|
||||
}
|
||||
```
|
||||
|
||||
The `ma_audio_ring_buffer_init()` function takes the sample format, channel count and sample rate
|
||||
as parameters because it's the PCM variant of the ring buffer API. The sample rate is not used by
|
||||
the ring buffer internally and can be set to 0, but it is provided for the purpose of the data
|
||||
source implementation.
|
||||
The `ma_audio_ring_buffer_init()` follows the same config/init pattern used throughout miniaudio.
|
||||
The sample rate is not used by the ring buffer internally and can be set to 0, but it is provided
|
||||
for the purpose of the data source implementation.
|
||||
|
||||
You can allocate your own underlying buffer to act as the backing store in which case you can
|
||||
initialize it like this:
|
||||
initialize specify it in the config:
|
||||
|
||||
```c
|
||||
void* pBuffer = malloc(BUFFER_SIZE_IN_FRAMES * bytesPerFrame * 2); // <-- The 2x is important.
|
||||
|
||||
ma_audio_ring_buffer rb;
|
||||
ma_audio_ring_Buffer_init_ex(FORMAT, CHANNELS, SAMPLE_RATE, BUFFER_SIZE_IN_FRAMES, 0, pBuffer, &rb);
|
||||
rbConfig = ma_audio_ring_buffer_config_init(FORMAT, CHANNELS, SAMPLE_RATE, BUFFER_SIZE_IN_FRAMES);
|
||||
rbConfig.pBuffer = pBuffer;
|
||||
|
||||
ma_audio_ring_Buffer_init(&rbConfig, &rb);
|
||||
```
|
||||
|
||||
The size of the buffer must be 2 times the capacity. It is possible for you to use a mirrored
|
||||
@@ -3594,7 +3599,13 @@ buffer where the second half of the buffer maps to the same physical memory as t
|
||||
this case you can specify the `MA_RING_BUFFER_FLAG_MIRRORED` flag:
|
||||
|
||||
```c
|
||||
ma_audio_ring_buffer_init_ex(FORMAT, CHANNELS, SAMPLE_RATE, BUFFER_SIZE_IN_FRAMES, MA_RING_BUFFER_FLAG_MIRRORED, pBuffer, &rb);
|
||||
void* pBuffer = ...; // <-- Your own OS-specific allocation routine goes here. It must have 2x the addressable space as the the capacity.
|
||||
|
||||
rbConfig = ma_audio_ring_buffer_config_init(FORMAT, CHANNELS, SAMPLE_RATE, BUFFER_SIZE_IN_FRAMES);
|
||||
rbConfig.flags = MA_RING_BUFFER_FLAG_MIRRORED;
|
||||
rbConfig.pBuffer = pBuffer;
|
||||
|
||||
ma_audio_ring_buffer_init(&rbConfig, &rb);
|
||||
```
|
||||
|
||||
To read and write data you map and unmap a pointer. For writing, you can do something like this:
|
||||
@@ -6284,6 +6295,20 @@ MA_API ma_uint32 ma_ring_buffer_capacity(const ma_ring_buffer* pRingBuffer);
|
||||
/* END ma_ring_buffer.h */
|
||||
|
||||
|
||||
typedef struct ma_audio_ring_buffer_config
|
||||
{
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate; /* Can be zero. Not used for the actual function of the ring buffer. Stored for the purpose of the data source abstraction. */
|
||||
ma_uint32 sizeInFrames; /* The capacity of the ring buffer in frames. */
|
||||
ma_uint32 flags;
|
||||
void* pBuffer; /* Can be null in which case it'll be allocated internally. */
|
||||
const ma_allocation_callbacks* pAllocationCallbacks;
|
||||
} ma_audio_ring_buffer_config;
|
||||
|
||||
MA_API ma_audio_ring_buffer_config ma_audio_ring_buffer_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 sizeInFrames);
|
||||
|
||||
|
||||
typedef struct ma_audio_ring_buffer
|
||||
{
|
||||
ma_data_source_base ds;
|
||||
@@ -6296,8 +6321,7 @@ typedef struct ma_audio_ring_buffer
|
||||
ma_allocation_callbacks allocationCallbacks;
|
||||
} 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 ma_result ma_audio_ring_buffer_init(const ma_audio_ring_buffer_config* pConfig, ma_audio_ring_buffer* pRingBuffer);
|
||||
MA_API void ma_audio_ring_buffer_uninit(ma_audio_ring_buffer* pRingBuffer);
|
||||
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);
|
||||
@@ -32474,7 +32498,10 @@ static void ma_stream_event_process__pipewire(void* pUserData, ma_device_type de
|
||||
pStreamState->rbSizeInFrames = (ma_uint32)time.size;
|
||||
|
||||
if (ma_device_get_threading_mode(pDeviceStatePipeWire->pDevice) == MA_THREADING_MODE_SINGLE_THREADED) {
|
||||
ma_audio_ring_buffer_init(pStreamState->format, pStreamState->channels, pStreamState->sampleRate, pStreamState->rbSizeInFrames, ma_device_get_allocation_callbacks(pDeviceStatePipeWire->pDevice), &pStreamState->rb);
|
||||
ma_audio_ring_buffer_config ringBufferConfig = ma_audio_ring_buffer_config_init(pStreamState->format, pStreamState->channels, pStreamState->sampleRate, pStreamState->rbSizeInFrames);
|
||||
ringBufferConfig.pAllocationCallbacks = ma_device_get_allocation_callbacks(pDeviceStatePipeWire->pDevice);
|
||||
|
||||
ma_audio_ring_buffer_init(&ringBufferConfig, &pStreamState->rb);
|
||||
}
|
||||
|
||||
pStreamState->initStatus |= MA_PIPEWIRE_INIT_STATUS_HAS_LATENCY;
|
||||
@@ -63666,11 +63693,28 @@ static ma_data_source_vtable ma_gDataSourceVTable_AudioRingBuffer =
|
||||
};
|
||||
|
||||
|
||||
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_audio_ring_buffer_config ma_audio_ring_buffer_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 sizeInFrames)
|
||||
{
|
||||
ma_audio_ring_buffer_config config;
|
||||
|
||||
MA_ZERO_OBJECT(&config);
|
||||
config.format = format;
|
||||
config.channels = channels;
|
||||
config.sampleRate = sampleRate;
|
||||
config.sizeInFrames = sizeInFrames;
|
||||
config.flags = 0;
|
||||
config.pBuffer = NULL;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
MA_API ma_result ma_audio_ring_buffer_init(const ma_audio_ring_buffer_config* pConfig, ma_audio_ring_buffer* pRingBuffer)
|
||||
{
|
||||
ma_result result;
|
||||
ma_data_source_config dataSourceConfig;
|
||||
ma_uint32 bpf;
|
||||
ma_bool32 isOwnerOfBuffer = MA_FALSE;
|
||||
void* pBuffer;
|
||||
|
||||
if (pRingBuffer == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
@@ -63678,11 +63722,15 @@ MA_API ma_result ma_audio_ring_buffer_init_ex(ma_format format, ma_uint32 channe
|
||||
|
||||
MA_ZERO_OBJECT(pRingBuffer);
|
||||
|
||||
if (capacityInFrames == 0) {
|
||||
if (pConfig == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
bpf = ma_get_bytes_per_frame(format, channels);
|
||||
if (pConfig->format == ma_format_unknown || pConfig->channels == 0 || pConfig->sizeInFrames == 0) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
bpf = ma_get_bytes_per_frame(pConfig->format, pConfig->channels);
|
||||
if (bpf == 0) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
@@ -63696,50 +63744,33 @@ MA_API ma_result ma_audio_ring_buffer_init_ex(ma_format format, ma_uint32 channe
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Allocate a buffer if necessary. */
|
||||
if (pConfig->pBuffer == NULL) {
|
||||
size_t bufferSizeInBytes;
|
||||
|
||||
bufferSizeInBytes = pConfig->sizeInFrames * bpf * 2; /* Buffer must 2x the capacity. */
|
||||
MA_ASSERT(bufferSizeInBytes != 0);
|
||||
|
||||
pBuffer = ma_malloc(bufferSizeInBytes, pConfig->pAllocationCallbacks);
|
||||
if (pBuffer == NULL) {
|
||||
ma_data_source_uninit(&pRingBuffer->ds);
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
isOwnerOfBuffer = MA_TRUE;
|
||||
} else {
|
||||
pBuffer = pConfig->pBuffer;
|
||||
isOwnerOfBuffer = MA_FALSE;
|
||||
}
|
||||
|
||||
/* Now for the ring buffer. */
|
||||
ma_ring_buffer_init(capacityInFrames, bpf, flags, pBuffer, &pRingBuffer->rb);
|
||||
pRingBuffer->format = format;
|
||||
pRingBuffer->channels = channels;
|
||||
pRingBuffer->sampleRate = sampleRate;
|
||||
pRingBuffer->pBuffer = pBuffer;
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
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_result result;
|
||||
ma_uint32 bpf;
|
||||
void* pBuffer;
|
||||
|
||||
if (pRingBuffer == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
MA_ZERO_OBJECT(pRingBuffer);
|
||||
|
||||
if (capacityInFrames == 0) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
bpf = ma_get_bytes_per_frame(format, channels);
|
||||
if (bpf == 0) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
pBuffer = ma_malloc(capacityInFrames * bpf * 2, pAllocationCallbacks);
|
||||
if (pBuffer == NULL) {
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
result = ma_audio_ring_buffer_init_ex(format, channels, sampleRate, capacityInFrames, 0, pBuffer, pRingBuffer);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_free(pBuffer, pAllocationCallbacks);
|
||||
return result;
|
||||
}
|
||||
|
||||
ma_allocation_callbacks_init_copy(&pRingBuffer->allocationCallbacks, pAllocationCallbacks);
|
||||
pRingBuffer->isOwnerOfBuffer = MA_TRUE;
|
||||
ma_ring_buffer_init(pConfig->sizeInFrames, bpf, pConfig->flags, pBuffer, &pRingBuffer->rb);
|
||||
pRingBuffer->format = pConfig->format;
|
||||
pRingBuffer->channels = pConfig->channels;
|
||||
pRingBuffer->sampleRate = pConfig->sampleRate;
|
||||
pRingBuffer->isOwnerOfBuffer = isOwnerOfBuffer;
|
||||
pRingBuffer->pBuffer = pBuffer;
|
||||
ma_allocation_callbacks_init_copy(&pRingBuffer->allocationCallbacks, pConfig->pAllocationCallbacks);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
@@ -63907,13 +63938,17 @@ MA_API ma_result ma_duplex_rb_init(ma_format captureFormat, ma_uint32 captureCha
|
||||
{
|
||||
ma_result result;
|
||||
ma_uint32 sizeInFrames;
|
||||
ma_audio_ring_buffer_config ringBufferConfig;
|
||||
|
||||
sizeInFrames = (ma_uint32)ma_calculate_frame_count_after_resampling(sampleRate, captureInternalSampleRate, captureInternalPeriodSizeInFrames * 3);
|
||||
if (sizeInFrames == 0) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
result = ma_audio_ring_buffer_init(captureFormat, captureChannels, sampleRate, sizeInFrames, pAllocationCallbacks, &pRB->rb);
|
||||
ringBufferConfig = ma_audio_ring_buffer_config_init(captureFormat, captureChannels, sampleRate, sizeInFrames);
|
||||
ringBufferConfig.pAllocationCallbacks = pAllocationCallbacks;
|
||||
|
||||
result = ma_audio_ring_buffer_init(&ringBufferConfig, &pRB->rb);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user