Commit c3a9ab9b authored by David Reid's avatar David Reid

Version 0.11.6

parent 13f1d31a
/*
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio - v0.11.5 - 2022-01-16
miniaudio - v0.11.6 - 2022-01-22
David Reid - mackron@gmail.com
......@@ -4535,7 +4535,6 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority
static void ma_thread_wait__posix(ma_thread* pThread)
{
pthread_join((pthread_t)*pThread, NULL);
pthread_detach((pthread_t)*pThread);
}
......@@ -9848,9 +9847,23 @@ static ma_result ma_device_uninit__wasapi(ma_device* pDevice)
#endif
if (pDevice->wasapi.pRenderClient) {
if (pDevice->wasapi.pMappedBufferPlayback != NULL) {
ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, pDevice->wasapi.mappedBufferPlaybackCap, 0);
pDevice->wasapi.pMappedBufferPlayback = NULL;
pDevice->wasapi.mappedBufferPlaybackCap = 0;
pDevice->wasapi.mappedBufferPlaybackLen = 0;
}
ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
}
if (pDevice->wasapi.pCaptureClient) {
if (pDevice->wasapi.pMappedBufferCapture != NULL) {
ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, pDevice->wasapi.mappedBufferCaptureCap);
pDevice->wasapi.pMappedBufferCapture = NULL;
pDevice->wasapi.mappedBufferCaptureCap = 0;
pDevice->wasapi.mappedBufferCaptureLen = 0;
}
ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
}
......@@ -10971,7 +10984,7 @@ static ma_result ma_device_read__wasapi(ma_device* pDevice, void* pFrames, ma_ui
continue;
} else {
if (hr == MA_AUDCLNT_S_BUFFER_EMPTY) {
if (hr == MA_AUDCLNT_S_BUFFER_EMPTY || hr == MA_AUDCLNT_E_BUFFER_ERROR) {
/*
No data is available. We need to wait for more. There's two situations to consider
here. The first is normal capture mode. If this times out it probably means the
......@@ -10984,6 +10997,7 @@ static ma_result ma_device_read__wasapi(ma_device* pDevice, void* pFrames, ma_ui
if (pDevice->type == ma_device_type_loopback) {
continue; /* Keep waiting in loopback mode. */
} else {
result = MA_ERROR;
break; /* Wait failed. */
}
}
......@@ -10991,6 +11005,7 @@ static ma_result ma_device_read__wasapi(ma_device* pDevice, void* pFrames, ma_ui
/* At this point we should be able to loop back to the start of the loop and try retrieving a data buffer again. */
} else {
/* An error occured and we need to abort. */
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from capture device in preparation for reading from the device. HRESULT = %d. Stopping device.\n", (int)hr);
result = ma_result_from_HRESULT(hr);
break;
}
......@@ -11019,6 +11034,7 @@ static ma_result ma_device_read__wasapi(ma_device* pDevice, void* pFrames, ma_ui
static ma_result ma_device_write__wasapi(ma_device* pDevice, const void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
{
ma_result result = MA_SUCCESS;
ma_uint32 totalFramesProcessed = 0;
/* Keep writing to the device until it's stopped or we've consumed all of our input. */
......@@ -11063,6 +11079,7 @@ static ma_result ma_device_write__wasapi(ma_device* pDevice, const void* pFrames
*/
if (pDevice->playback.shareMode == ma_share_mode_exclusive) {
if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
result = MA_ERROR;
break; /* Wait failed. Probably timed out. */
}
}
......@@ -11085,14 +11102,16 @@ static ma_result ma_device_write__wasapi(ma_device* pDevice, const void* pFrames
pDevice->wasapi.mappedBufferPlaybackCap = bufferSizeInFrames;
pDevice->wasapi.mappedBufferPlaybackLen = 0;
} else {
if (hr == MA_AUDCLNT_E_BUFFER_TOO_LARGE) {
if (hr == MA_AUDCLNT_E_BUFFER_TOO_LARGE || hr == MA_AUDCLNT_E_BUFFER_ERROR) {
/* Not enough data available. We need to wait for more. */
if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
result = MA_ERROR;
break; /* Wait failed. Probably timed out. */
}
} else {
/* Some error occurred. We'll need to abort. */
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from playback device in preparation for writing to the device.");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from playback device in preparation for writing to the device. HRESULT = %d. Stopping device.\n", (int)hr);
result = ma_result_from_HRESULT(hr);
break;
}
}
......@@ -11103,7 +11122,7 @@ static ma_result ma_device_write__wasapi(ma_device* pDevice, const void* pFrames
*pFramesWritten = totalFramesProcessed;
}
return MA_SUCCESS;
return result;
}
static ma_result ma_device_data_loop_wakeup__wasapi(ma_device* pDevice)
......@@ -13546,7 +13565,7 @@ static ma_result ma_device_init__winmm(ma_device* pDevice, const ma_device_confi
MMRESULT resultMM;
/* We use an event to know when a new fragment needs to be enqueued. */
pDevice->winmm.hEventPlayback = (ma_handle)CreateEvent(NULL, TRUE, TRUE, NULL);
pDevice->winmm.hEventPlayback = (ma_handle)CreateEventW(NULL, TRUE, TRUE, NULL);
if (pDevice->winmm.hEventPlayback == NULL) {
errorMsg = "[WinMM] Failed to create event for fragment enqueing for the playback device.", errorCode = ma_result_from_GetLastError(GetLastError());
goto on_error;
......@@ -17905,16 +17924,26 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
goto on_error2;
}
/* Internal format. */
pActualSS = ((ma_pa_stream_get_sample_spec_proc)pDevice->pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
if (pActualSS != NULL) {
ss = *pActualSS;
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[PulseAudio] Capture sample spec: format=%s, channels=%d, rate=%d\n", ma_get_format_name(ma_format_from_pulse(ss.format)), ss.channels, ss.rate);
} else {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[PulseAudio] Failed to retrieve capture sample spec.\n");
}
pDescriptorCapture->format = ma_format_from_pulse(ss.format);
pDescriptorCapture->channels = ss.channels;
pDescriptorCapture->sampleRate = ss.rate;
if (pDescriptorCapture->format == ma_format_unknown || pDescriptorCapture->channels == 0 || pDescriptorCapture->sampleRate == 0) {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[PulseAudio] Capture sample spec is invalid. Device unusable by miniaudio. format=%s, channels=%d, sampleRate=%d.\n", ma_get_format_name(pDescriptorCapture->format), pDescriptorCapture->channels, pDescriptorCapture->sampleRate);
result = MA_ERROR;
goto on_error4;
}
/* Internal channel map. */
pActualCMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
if (pActualCMap != NULL) {
......@@ -17932,9 +17961,13 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
attr = *pActualAttr;
}
pDescriptorCapture->periodCount = attr.maxlength / attr.fragsize;
pDescriptorCapture->periodSizeInFrames = attr.maxlength / ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) / pDescriptorCapture->periodCount;
if (attr.fragsize > 0) {
pDescriptorPlayback->periodCount = ma_max(attr.maxlength / attr.fragsize, 1);
} else {
pDescriptorPlayback->periodCount = 1;
}
pDescriptorCapture->periodSizeInFrames = attr.maxlength / ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) / pDescriptorCapture->periodCount;
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[PulseAudio] Capture actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; periodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDescriptorCapture->periodSizeInFrames);
}
......@@ -18016,12 +18049,21 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
pActualSS = ((ma_pa_stream_get_sample_spec_proc)pDevice->pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
if (pActualSS != NULL) {
ss = *pActualSS;
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[PulseAudio] Playback sample spec: format=%s, channels=%d, rate=%d\n", ma_get_format_name(ma_format_from_pulse(ss.format)), ss.channels, ss.rate);
} else {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[PulseAudio] Failed to retrieve playback sample spec.\n");
}
pDescriptorPlayback->format = ma_format_from_pulse(ss.format);
pDescriptorPlayback->channels = ss.channels;
pDescriptorPlayback->sampleRate = ss.rate;
if (pDescriptorPlayback->format == ma_format_unknown || pDescriptorPlayback->channels == 0 || pDescriptorPlayback->sampleRate == 0) {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[PulseAudio] Playback sample spec is invalid. Device unusable by miniaudio. format=%s, channels=%d, sampleRate=%d.\n", ma_get_format_name(pDescriptorPlayback->format), pDescriptorPlayback->channels, pDescriptorPlayback->sampleRate);
result = MA_ERROR;
goto on_error4;
}
/* Internal channel map. */
pActualCMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
if (pActualCMap != NULL) {
......@@ -18039,7 +18081,12 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
attr = *pActualAttr;
}
pDescriptorPlayback->periodCount = ma_max(attr.maxlength / attr.tlength, 1);
if (attr.tlength > 0) {
pDescriptorPlayback->periodCount = ma_max(attr.maxlength / attr.tlength, 1);
} else {
pDescriptorPlayback->periodCount = 1;
}
pDescriptorPlayback->periodSizeInFrames = attr.maxlength / ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels) / pDescriptorPlayback->periodCount;
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[PulseAudio] Playback actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalPeriodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDescriptorPlayback->periodSizeInFrames);
}
......@@ -34004,7 +34051,7 @@ static ma_result ma_hpf_get_heap_layout(const ma_hpf_config* pConfig, ma_hpf_hea
pHeapLayout->sizeInBytes = 0;
/* LPF 1 */
/* HPF 1 */
pHeapLayout->hpf1Offset = pHeapLayout->sizeInBytes;
for (ihpf1 = 0; ihpf1 < hpf1Count; ihpf1 += 1) {
size_t hpf1HeapSizeInBytes;
......@@ -34018,7 +34065,7 @@ static ma_result ma_hpf_get_heap_layout(const ma_hpf_config* pConfig, ma_hpf_hea
pHeapLayout->sizeInBytes += sizeof(ma_hpf1) + hpf1HeapSizeInBytes;
}
/* LPF 2*/
/* HPF 2*/
pHeapLayout->hpf2Offset = pHeapLayout->sizeInBytes;
for (ihpf2 = 0; ihpf2 < hpf2Count; ihpf2 += 1) {
size_t hpf2HeapSizeInBytes;
......@@ -34102,7 +34149,7 @@ static ma_result ma_hpf_reinit__internal(const ma_hpf_config* pConfig, void* pHe
result = ma_hpf1_get_heap_size(&hpf1Config, &hpf1HeapSizeInBytes);
if (result == MA_SUCCESS) {
result = ma_hpf1_init_preallocated(&hpf1Config, ma_offset_ptr(pHeap, heapLayout.hpf1Offset + (ihpf1 * (sizeof(ma_hpf1) + hpf1HeapSizeInBytes)) + sizeof(ma_hpf1)), &pHPF->pHPF1[ihpf1]);
result = ma_hpf1_init_preallocated(&hpf1Config, ma_offset_ptr(pHeap, heapLayout.hpf1Offset + (sizeof(ma_hpf1) * hpf1Count) + (ihpf1 * hpf1HeapSizeInBytes)), &pHPF->pHPF1[ihpf1]);
}
} else {
result = ma_hpf1_reinit(&hpf1Config, &pHPF->pHPF1[ihpf1]);
......@@ -34139,7 +34186,7 @@ static ma_result ma_hpf_reinit__internal(const ma_hpf_config* pConfig, void* pHe
result = ma_hpf2_get_heap_size(&hpf2Config, &hpf2HeapSizeInBytes);
if (result == MA_SUCCESS) {
result = ma_hpf2_init_preallocated(&hpf2Config, ma_offset_ptr(pHeap, heapLayout.hpf2Offset + (ihpf2 * (sizeof(ma_hpf2) + hpf2HeapSizeInBytes)) + sizeof(ma_hpf2)), &pHPF->pHPF2[ihpf2]);
result = ma_hpf2_init_preallocated(&hpf2Config, ma_offset_ptr(pHeap, heapLayout.hpf2Offset + (sizeof(ma_hpf2) * hpf2Count) + (ihpf2 * hpf2HeapSizeInBytes)), &pHPF->pHPF2[ihpf2]);
}
} else {
result = ma_hpf2_reinit(&hpf2Config, &pHPF->pHPF2[ihpf2]);
......@@ -34654,7 +34701,7 @@ static ma_result ma_bpf_reinit__internal(const ma_bpf_config* pConfig, void* pHe
result = ma_bpf2_get_heap_size(&bpf2Config, &bpf2HeapSizeInBytes);
if (result == MA_SUCCESS) {
result = ma_bpf2_init_preallocated(&bpf2Config, ma_offset_ptr(pHeap, heapLayout.bpf2Offset + (ibpf2 * (sizeof(ma_bpf2) + bpf2HeapSizeInBytes)) + sizeof(ma_bpf2)), &pBPF->pBPF2[ibpf2]);
result = ma_bpf2_init_preallocated(&bpf2Config, ma_offset_ptr(pHeap, heapLayout.bpf2Offset + (sizeof(ma_bpf2) * bpf2Count) + (ibpf2 * bpf2HeapSizeInBytes)), &pBPF->pBPF2[ibpf2]);
}
} else {
result = ma_bpf2_reinit(&bpf2Config, &pBPF->pBPF2[ibpf2]);
......@@ -43763,6 +43810,60 @@ MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSo
return pDataSourceBase->vtable->onGetLength(pDataSource, pLength);
}
MA_API ma_result ma_data_source_get_cursor_in_seconds(ma_data_source* pDataSource, float* pCursor)
{
ma_result result;
ma_uint64 cursorInPCMFrames;
ma_uint32 sampleRate;
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0;
result = ma_data_source_get_cursor_in_pcm_frames(pDataSource, &cursorInPCMFrames);
if (result != MA_SUCCESS) {
return result;
}
result = ma_data_source_get_data_format(pDataSource, NULL, NULL, &sampleRate, NULL, 0);
if (result != MA_SUCCESS) {
return result;
}
*pCursor = cursorInPCMFrames / (float)sampleRate;
return MA_SUCCESS;
}
MA_API ma_result ma_data_source_get_length_in_seconds(ma_data_source* pDataSource, float* pLength)
{
ma_result result;
ma_uint64 lengthInPCMFrames;
ma_uint32 sampleRate;
if (pLength == NULL) {
return MA_INVALID_ARGS;
}
*pLength = 0;
result = ma_data_source_get_length_in_pcm_frames(pDataSource, &lengthInPCMFrames);
if (result != MA_SUCCESS) {
return result;
}
result = ma_data_source_get_data_format(pDataSource, NULL, NULL, &sampleRate, NULL, 0);
if (result != MA_SUCCESS) {
return result;
}
*pLength = lengthInPCMFrames / (float)sampleRate;
return MA_SUCCESS;
}
MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool32 isLooping)
{
ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
......@@ -56740,6 +56841,28 @@ static ma_bool32 ma_node_graph_is_reading(ma_node_graph* pNodeGraph)
#endif
static void ma_node_graph_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_node_graph* pNodeGraph = (ma_node_graph*)pNode;
ma_uint64 framesRead;
ma_node_graph_read_pcm_frames(pNodeGraph, ppFramesOut[0], *pFrameCountOut, &framesRead);
*pFrameCountOut = (ma_uint32)framesRead; /* Safe cast. */
(void)ppFramesIn;
(void)pFrameCountIn;
}
static ma_node_vtable g_node_graph_node_vtable =
{
ma_node_graph_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
0, /* 0 input buses. */
1, /* 1 output bus. */
0 /* Flags. */
};
static void ma_node_graph_endpoint_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
MA_ASSERT(pNode != NULL);
......@@ -56776,6 +56899,7 @@ static ma_node_vtable g_node_graph_endpoint_vtable =
MA_API ma_result ma_node_graph_init(const ma_node_graph_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_node_graph* pNodeGraph)
{
ma_result result;
ma_node_config baseConfig;
ma_node_config endpointConfig;
if (pNodeGraph == NULL) {
......@@ -56788,6 +56912,19 @@ MA_API ma_result ma_node_graph_init(const ma_node_graph_config* pConfig, const m
pNodeGraph->nodeCacheCapInFrames = MA_DEFAULT_NODE_CACHE_CAP_IN_FRAMES_PER_BUS;
}
/* Base node so we can use the node graph as a node into another graph. */
baseConfig = ma_node_config_init();
baseConfig.vtable = &g_node_graph_node_vtable;
baseConfig.pOutputChannels = &pConfig->channels;
result = ma_node_init(pNodeGraph, &baseConfig, pAllocationCallbacks, &pNodeGraph->base);
if (result != MA_SUCCESS) {
return result;
}
/* Endpoint. */
endpointConfig = ma_node_config_init();
endpointConfig.vtable = &g_node_graph_endpoint_vtable;
endpointConfig.pInputChannels = &pConfig->channels;
......@@ -56795,6 +56932,7 @@ MA_API ma_result ma_node_graph_init(const ma_node_graph_config* pConfig, const m
result = ma_node_init(pNodeGraph, &endpointConfig, pAllocationCallbacks, &pNodeGraph->endpoint);
if (result != MA_SUCCESS) {
ma_node_uninit(&pNodeGraph->base, pAllocationCallbacks);
return result;
}
......@@ -59686,8 +59824,8 @@ static void ma_engine_node_process_pcm_frames__general(ma_engine_node* pEngineNo
framesJustProcessedIn = (ma_uint32)resampleFrameCountIn;
framesJustProcessedOut = (ma_uint32)resampleFrameCountOut;
} else {
framesJustProcessedIn = framesAvailableIn;
framesJustProcessedOut = framesAvailableOut;
framesJustProcessedIn = ma_min(framesAvailableIn, framesAvailableOut);
framesJustProcessedOut = framesJustProcessedIn; /* When no resampling is being performed, the number of output frames is the same as input frames. */
}
/* Fading. */
......@@ -62024,6 +62162,34 @@ MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64*
return ma_data_source_get_length_in_pcm_frames(pSound->pDataSource, pLength);
}
MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor)
{
if (pSound == NULL) {
return MA_INVALID_ARGS;
}
/* The notion of a cursor is only valid for sounds that are backed by a data source. */
if (pSound->pDataSource == NULL) {
return MA_INVALID_OPERATION;
}
return ma_data_source_get_cursor_in_seconds(pSound->pDataSource, pCursor);
}
MA_API ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength)
{
if (pSound == NULL) {
return MA_INVALID_ARGS;
}
/* The notion of a sound length is only valid for sounds that are backed by a data source. */
if (pSound->pDataSource == NULL) {
return MA_INVALID_OPERATION;
}
return ma_data_source_get_length_in_seconds(pSound->pDataSource, pLength);
}
MA_API ma_result ma_sound_group_init(ma_engine* pEngine, ma_uint32 flags, ma_sound_group* pParentGroup, ma_sound_group* pGroup)
{
/*
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio - v0.11.5 - 2022-01-16
miniaudio - v0.11.6 - 2022-01-22
David Reid - mackron@gmail.com
......@@ -20,7 +20,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 5
#define MA_VERSION_REVISION 6
#define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION)
#if defined(_MSC_VER) && !defined(__clang__)
......@@ -5689,6 +5689,8 @@ MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, m
MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_data_source_get_cursor_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pCursor);
MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLength); /* Returns MA_NOT_IMPLEMENTED if the length is unknown or cannot be determined. Decoders can return this. */
MA_API ma_result ma_data_source_get_cursor_in_seconds(ma_data_source* pDataSource, float* pCursor);
MA_API ma_result ma_data_source_get_length_in_seconds(ma_data_source* pDataSource, float* pLength);
MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool32 isLooping);
MA_API ma_bool32 ma_data_source_is_looping(ma_data_source* pDataSource);
MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames);
......@@ -6748,6 +6750,7 @@ MA_API ma_node_graph_config ma_node_graph_config_init(ma_uint32 channels);
struct ma_node_graph
{
/* Immutable. */
ma_node_base base; /* The node graph itself is a node so it can be connected as an input to different node graph. This has zero inputs and calls ma_node_graph_read_pcm_frames() to generate it's output. */
ma_node_base endpoint; /* Special node that all nodes eventually connect to. Data is read from this node in ma_node_graph_read_pcm_frames(). */
ma_uint16 nodeCacheCapInFrames;
......@@ -7308,6 +7311,8 @@ MA_API ma_result ma_sound_seek_to_pcm_frame(ma_sound* pSound, ma_uint64 frameInd
MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64* pCursor);
MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64* pLength);
MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor);
MA_API ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength);
MA_API ma_result ma_sound_group_init(ma_engine* pEngine, ma_uint32 flags, ma_sound_group* pParentGroup, ma_sound_group* pGroup);
MA_API ma_result ma_sound_group_init_ex(ma_engine* pEngine, const ma_sound_group_config* pConfig, ma_sound_group* pGroup);
......
/*
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio - v0.11.5 - 2022-01-16
miniaudio - v0.11.6 - 2022-01-22
David Reid - mackron@gmail.com
......@@ -3637,7 +3637,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 5
#define MA_VERSION_REVISION 6
#define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION)
#if defined(_MSC_VER) && !defined(__clang__)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment