Commit efa95d99 authored by David Reid's avatar David Reid

Remove the loop parameter from ma_data_source_read_pcm_frames().

parent 80cdee58
...@@ -417,7 +417,7 @@ static ma_result ma_device_init_internal__sdl(ma_device_ex* pDeviceEx, const ma_ ...@@ -417,7 +417,7 @@ static ma_result ma_device_init_internal__sdl(ma_device_ex* pDeviceEx, const ma_
pDescriptor->format = ma_format_from_sdl(obtainedSpec.format); pDescriptor->format = ma_format_from_sdl(obtainedSpec.format);
pDescriptor->channels = obtainedSpec.channels; pDescriptor->channels = obtainedSpec.channels;
pDescriptor->sampleRate = (ma_uint32)obtainedSpec.freq; pDescriptor->sampleRate = (ma_uint32)obtainedSpec.freq;
ma_get_standard_channel_map(ma_standard_channel_map_default, pDescriptor->channelMap, ma_countof(pDescriptor->channelMap), pDescriptor->channels); ma_channel_map_init_standard(ma_standard_channel_map_default, pDescriptor->channelMap, ma_countof(pDescriptor->channelMap), pDescriptor->channels);
pDescriptor->periodSizeInFrames = obtainedSpec.samples; pDescriptor->periodSizeInFrames = obtainedSpec.samples;
pDescriptor->periodCount = 1; /* SDL doesn't use the notion of period counts, so just set to 1. */ pDescriptor->periodCount = 1; /* SDL doesn't use the notion of period counts, so just set to 1. */
......
...@@ -65,7 +65,7 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ...@@ -65,7 +65,7 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
if you want to loop the chain, like we're doing in this example, you need to set the `loop` if you want to loop the chain, like we're doing in this example, you need to set the `loop`
parameter to false, or else only the current data source will be looped. parameter to false, or else only the current data source will be looped.
*/ */
ma_data_source_read_pcm_frames(&g_pDecoders[0], pOutput, frameCount, NULL, MA_FALSE); ma_data_source_read_pcm_frames(&g_pDecoders[0], pOutput, frameCount, NULL);
/* Unused in this example. */ /* Unused in this example. */
(void)pDevice; (void)pDevice;
......
...@@ -100,7 +100,7 @@ int main(int argc, char** argv) ...@@ -100,7 +100,7 @@ int main(int argc, char** argv)
goto done3; goto done3;
} }
sourceNodeConfig = ma_data_source_node_config_init(&g_sourceData, MA_FALSE); sourceNodeConfig = ma_data_source_node_config_init(&g_sourceData);
result = ma_data_source_node_init(&g_nodeGraph, &sourceNodeConfig, NULL, &g_sourceNode); result = ma_data_source_node_init(&g_nodeGraph, &sourceNodeConfig, NULL, &g_sourceNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
...@@ -118,7 +118,7 @@ int main(int argc, char** argv) ...@@ -118,7 +118,7 @@ int main(int argc, char** argv)
goto done2; goto done2;
} }
exciteNodeConfig = ma_data_source_node_config_init(&g_exciteData, MA_FALSE); exciteNodeConfig = ma_data_source_node_config_init(&g_exciteData);
result = ma_data_source_node_init(&g_nodeGraph, &exciteNodeConfig, NULL, &g_exciteNode); result = ma_data_source_node_init(&g_nodeGraph, &exciteNodeConfig, NULL, &g_exciteNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
......
...@@ -46,7 +46,7 @@ void main_loop__em(void* pUserData) ...@@ -46,7 +46,7 @@ void main_loop__em(void* pUserData)
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)
{ {
ma_data_source_read_pcm_frames((ma_data_source*)pDevice->pUserData, pOutput, frameCount, NULL, MA_TRUE); ma_data_source_read_pcm_frames((ma_data_source*)pDevice->pUserData, pOutput, frameCount, NULL);
(void)pInput; (void)pInput;
} }
...@@ -108,6 +108,7 @@ int main(int argc, char** argv) ...@@ -108,6 +108,7 @@ int main(int argc, char** argv)
&resourceManager, &resourceManager,
argv[1], argv[1],
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM, MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM,
0, /* Initial seek point. */
NULL, /* Async notification. */ NULL, /* Async notification. */
&dataSource); &dataSource);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
...@@ -115,6 +116,9 @@ int main(int argc, char** argv) ...@@ -115,6 +116,9 @@ int main(int argc, char** argv)
return -1; return -1;
} }
/* In this example we'll enable looping. */
ma_data_source_set_looping(&dataSource, MA_TRUE);
/* Now that we have a sound we can start the device. */ /* Now that we have a sound we can start the device. */
result = ma_device_start(&device); result = ma_device_start(&device);
......
...@@ -27,7 +27,7 @@ static ma_uint32 g_dataSourceCount; ...@@ -27,7 +27,7 @@ static ma_uint32 g_dataSourceCount;
TODO: Consider putting these public functions in miniaudio.h. Will depend on ma_mix_pcm_frames_f32() TODO: Consider putting these public functions in miniaudio.h. Will depend on ma_mix_pcm_frames_f32()
being merged into miniaudio.h (it's currently in miniaudio_engine.h). being merged into miniaudio.h (it's currently in miniaudio_engine.h).
*/ */
static ma_result ma_data_source_read_pcm_frames_f32_ex(ma_data_source* pDataSource, float* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, ma_bool32 loop, ma_format dataSourceFormat, ma_uint32 dataSourceChannels) static ma_result ma_data_source_read_pcm_frames_f32_ex(ma_data_source* pDataSource, float* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, ma_format dataSourceFormat, ma_uint32 dataSourceChannels)
{ {
/* /*
This function is intended to be used when the format and channel count of the data source is This function is intended to be used when the format and channel count of the data source is
...@@ -37,7 +37,7 @@ static ma_result ma_data_source_read_pcm_frames_f32_ex(ma_data_source* pDataSour ...@@ -37,7 +37,7 @@ static ma_result ma_data_source_read_pcm_frames_f32_ex(ma_data_source* pDataSour
if (dataSourceFormat == ma_format_f32) { if (dataSourceFormat == ma_format_f32) {
/* Fast path. No conversion necessary. */ /* Fast path. No conversion necessary. */
return ma_data_source_read_pcm_frames(pDataSource, pFramesOut, frameCount, pFramesRead, loop); return ma_data_source_read_pcm_frames(pDataSource, pFramesOut, frameCount, pFramesRead);
} else { } else {
/* Slow path. Conversion necessary. */ /* Slow path. Conversion necessary. */
ma_result result; ma_result result;
...@@ -53,7 +53,7 @@ static ma_result ma_data_source_read_pcm_frames_f32_ex(ma_data_source* pDataSour ...@@ -53,7 +53,7 @@ static ma_result ma_data_source_read_pcm_frames_f32_ex(ma_data_source* pDataSour
framesToRead = tempCapInFrames; framesToRead = tempCapInFrames;
} }
result = ma_data_source_read_pcm_frames(pDataSource, pFramesOut, framesToRead, &framesJustRead, loop); result = ma_data_source_read_pcm_frames(pDataSource, pFramesOut, framesToRead, &framesJustRead);
ma_convert_pcm_frames_format(ma_offset_pcm_frames_ptr_f32(pFramesOut, totalFramesRead, dataSourceChannels), ma_format_f32, temp, dataSourceFormat, framesJustRead, dataSourceChannels, ma_dither_mode_none); ma_convert_pcm_frames_format(ma_offset_pcm_frames_ptr_f32(pFramesOut, totalFramesRead, dataSourceChannels), ma_format_f32, temp, dataSourceFormat, framesJustRead, dataSourceChannels, ma_dither_mode_none);
totalFramesRead += framesJustRead; totalFramesRead += framesJustRead;
...@@ -67,7 +67,7 @@ static ma_result ma_data_source_read_pcm_frames_f32_ex(ma_data_source* pDataSour ...@@ -67,7 +67,7 @@ static ma_result ma_data_source_read_pcm_frames_f32_ex(ma_data_source* pDataSour
} }
} }
MA_API ma_result ma_data_source_read_pcm_frames_f32(ma_data_source* pDataSource, float* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, ma_bool32 loop) MA_API ma_result ma_data_source_read_pcm_frames_f32(ma_data_source* pDataSource, float* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{ {
ma_result result; ma_result result;
ma_format format; ma_format format;
...@@ -78,10 +78,10 @@ MA_API ma_result ma_data_source_read_pcm_frames_f32(ma_data_source* pDataSource, ...@@ -78,10 +78,10 @@ MA_API ma_result ma_data_source_read_pcm_frames_f32(ma_data_source* pDataSource,
return result; /* Failed to retrieve the data format of the data source. */ return result; /* Failed to retrieve the data format of the data source. */
} }
return ma_data_source_read_pcm_frames_f32_ex(pDataSource, pFramesOut, frameCount, pFramesRead, loop, format, channels); return ma_data_source_read_pcm_frames_f32_ex(pDataSource, pFramesOut, frameCount, pFramesRead, format, channels);
} }
MA_API ma_result ma_data_source_read_pcm_frames_and_mix_f32(ma_data_source* pDataSource, float* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, ma_bool32 loop, float volume) MA_API ma_result ma_data_source_read_pcm_frames_and_mix_f32(ma_data_source* pDataSource, float* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, float volume)
{ {
ma_result result; ma_result result;
ma_format format; ma_format format;
...@@ -111,7 +111,7 @@ MA_API ma_result ma_data_source_read_pcm_frames_and_mix_f32(ma_data_source* pDat ...@@ -111,7 +111,7 @@ MA_API ma_result ma_data_source_read_pcm_frames_and_mix_f32(ma_data_source* pDat
framesToRead = tempCapInFrames; framesToRead = tempCapInFrames;
} }
result = ma_data_source_read_pcm_frames_f32_ex(pDataSource, temp, framesToRead, &framesJustRead, loop, format, channels); result = ma_data_source_read_pcm_frames_f32_ex(pDataSource, temp, framesToRead, &framesJustRead, format, channels);
ma_mix_pcm_frames_f32(ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, ma_format_f32, channels), temp, framesJustRead, channels, volume); ma_mix_pcm_frames_f32(ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, ma_format_f32, channels), temp, framesJustRead, channels, volume);
totalFramesRead += framesJustRead; totalFramesRead += framesJustRead;
...@@ -149,7 +149,7 @@ void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uin ...@@ -149,7 +149,7 @@ void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uin
/* For each sound, mix as much data as we can. */ /* For each sound, mix as much data as we can. */
for (iDataSource = 0; iDataSource < g_dataSourceCount; iDataSource += 1) { for (iDataSource = 0; iDataSource < g_dataSourceCount; iDataSource += 1) {
ma_data_source_read_pcm_frames_and_mix_f32(&g_dataSources[iDataSource], (float*)pOutput, frameCount, NULL, MA_TRUE, /* volume = */1); ma_data_source_read_pcm_frames_and_mix_f32(&g_dataSources[iDataSource], (float*)pOutput, frameCount, NULL, /* volume = */1);
} }
} }
...@@ -275,6 +275,7 @@ int main(int argc, char** argv) ...@@ -275,6 +275,7 @@ int main(int argc, char** argv)
&resourceManager, &resourceManager,
argv[iFile+1], argv[iFile+1],
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC /*| MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM*/, MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC /*| MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM*/,
0, /* Initial seek point. */
NULL, /* Async notification. */ NULL, /* Async notification. */
&g_dataSources[iFile]); &g_dataSources[iFile]);
...@@ -282,6 +283,9 @@ int main(int argc, char** argv) ...@@ -282,6 +283,9 @@ int main(int argc, char** argv)
break; break;
} }
/* Use looping in this example. */
ma_data_source_set_looping(&g_dataSources[iFile], MA_TRUE);
g_dataSourceCount += 1; g_dataSourceCount += 1;
} }
......
...@@ -12,18 +12,13 @@ decoder straight into `ma_data_source_read_pcm_frames()` and it will just work. ...@@ -12,18 +12,13 @@ decoder straight into `ma_data_source_read_pcm_frames()` and it will just work.
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)
{ {
ma_bool32 isLooping = MA_TRUE;
ma_decoder* pDecoder = (ma_decoder*)pDevice->pUserData; ma_decoder* pDecoder = (ma_decoder*)pDevice->pUserData;
if (pDecoder == NULL) { if (pDecoder == NULL) {
return; return;
} }
/* /* Reading PCM frames will loop based on what we specified when called ma_data_source_set_looping(). */
A decoder is a data source which means you can seemlessly plug it into the ma_data_source API. We can therefore take advantage ma_data_source_read_pcm_frames(pDecoder, pOutput, frameCount, NULL);
of the "loop" parameter of ma_data_source_read_pcm_frames() to handle looping for us.
*/
ma_data_source_read_pcm_frames(pDecoder, pOutput, frameCount, NULL, isLooping);
(void)pInput; (void)pInput;
} }
...@@ -45,6 +40,12 @@ int main(int argc, char** argv) ...@@ -45,6 +40,12 @@ int main(int argc, char** argv)
return -2; return -2;
} }
/*
A decoder is a data source which means we just use ma_data_source_set_looping() to set the
looping state. We will read data using ma_data_source_read_pcm_frames() in the data callback.
*/
ma_data_source_set_looping(&decoder, MA_TRUE);
deviceConfig = ma_device_config_init(ma_device_type_playback); deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = decoder.outputFormat; deviceConfig.playback.format = decoder.outputFormat;
deviceConfig.playback.channels = decoder.outputChannels; deviceConfig.playback.channels = decoder.outputChannels;
......
...@@ -115,7 +115,7 @@ int main(int argc, char** argv) ...@@ -115,7 +115,7 @@ int main(int argc, char** argv)
/* Data supply. Attached to input bus 0 of the reverb node. */ /* Data supply. Attached to input bus 0 of the reverb node. */
dataSupplyNodeConfig = ma_data_source_node_config_init(&g_decoder, MA_FALSE); dataSupplyNodeConfig = ma_data_source_node_config_init(&g_decoder);
result = ma_data_source_node_init(&g_nodeGraph, &dataSupplyNodeConfig, NULL, &g_dataSupplyNode); result = ma_data_source_node_init(&g_nodeGraph, &dataSupplyNodeConfig, NULL, &g_dataSupplyNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
......
...@@ -84,7 +84,7 @@ int main(int argc, char** argv) ...@@ -84,7 +84,7 @@ int main(int argc, char** argv)
goto done2; goto done2;
} }
dataSupplyNodeConfig = ma_data_source_node_config_init(&g_dataSupply, MA_FALSE); dataSupplyNodeConfig = ma_data_source_node_config_init(&g_dataSupply);
result = ma_data_source_node_init(&g_nodeGraph, &dataSupplyNodeConfig, NULL, &g_dataSupplyNode); result = ma_data_source_node_init(&g_nodeGraph, &dataSupplyNodeConfig, NULL, &g_dataSupplyNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
......
...@@ -85,7 +85,7 @@ int main(int argc, char** argv) ...@@ -85,7 +85,7 @@ int main(int argc, char** argv)
goto done2; goto done2;
} }
dataSupplyNodeConfig = ma_data_source_node_config_init(&g_dataSupply, MA_FALSE); dataSupplyNodeConfig = ma_data_source_node_config_init(&g_dataSupply);
result = ma_data_source_node_init(&g_nodeGraph, &dataSupplyNodeConfig, NULL, &g_dataSupplyNode); result = ma_data_source_node_init(&g_nodeGraph, &dataSupplyNodeConfig, NULL, &g_dataSupplyNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
......
...@@ -100,7 +100,7 @@ int main(int argc, char** argv) ...@@ -100,7 +100,7 @@ int main(int argc, char** argv)
goto done3; goto done3;
} }
sourceNodeConfig = ma_data_source_node_config_init(&g_sourceData, MA_FALSE); sourceNodeConfig = ma_data_source_node_config_init(&g_sourceData);
result = ma_data_source_node_init(&g_nodeGraph, &sourceNodeConfig, NULL, &g_sourceNode); result = ma_data_source_node_init(&g_nodeGraph, &sourceNodeConfig, NULL, &g_sourceNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
...@@ -118,7 +118,7 @@ int main(int argc, char** argv) ...@@ -118,7 +118,7 @@ int main(int argc, char** argv)
goto done2; goto done2;
} }
exciteNodeConfig = ma_data_source_node_config_init(&g_exciteData, MA_FALSE); exciteNodeConfig = ma_data_source_node_config_init(&g_exciteData);
result = ma_data_source_node_init(&g_nodeGraph, &exciteNodeConfig, NULL, &g_exciteNode); result = ma_data_source_node_init(&g_nodeGraph, &exciteNodeConfig, NULL, &g_exciteNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
......
...@@ -8287,17 +8287,19 @@ typedef struct ...@@ -8287,17 +8287,19 @@ typedef struct
ma_data_source* pCurrent; /* When non-NULL, the data source being initialized will act as a proxy and will route all operations to pCurrent. Used in conjunction with pNext/onGetNext for seamless chaining. */ ma_data_source* pCurrent; /* When non-NULL, the data source being initialized will act as a proxy and will route all operations to pCurrent. Used in conjunction with pNext/onGetNext for seamless chaining. */
ma_data_source* pNext; /* When set to NULL, onGetNext will be used. */ ma_data_source* pNext; /* When set to NULL, onGetNext will be used. */
ma_data_source_get_next_proc onGetNext; /* Will be used when pNext is NULL. If both are NULL, no next will be used. */ ma_data_source_get_next_proc onGetNext; /* Will be used when pNext is NULL. If both are NULL, no next will be used. */
MA_ATOMIC ma_bool32 isLooping;
} ma_data_source_base; } ma_data_source_base;
MA_API ma_result ma_data_source_init(const ma_data_source_config* pConfig, ma_data_source* pDataSource); MA_API ma_result ma_data_source_init(const ma_data_source_config* pConfig, ma_data_source* pDataSource);
MA_API void ma_data_source_uninit(ma_data_source* pDataSource); MA_API void ma_data_source_uninit(ma_data_source* pDataSource);
MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, ma_bool32 loop); /* Must support pFramesOut = NULL in which case a forward seek should be performed. */ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); /* Must support pFramesOut = NULL in which case a forward seek should be performed. */
MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked, ma_bool32 loop); /* Can only seek forward. Equivalent to ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, &framesRead, loop); */ MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked); /* Can only seek forward. Equivalent to ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, &framesRead); */
MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex); MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex);
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_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_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_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_set_looping(ma_data_source* pDataSource, ma_bool32 isLooping); 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); MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames);
MA_API void ma_data_source_get_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pRangeBegInFrames, ma_uint64* pRangeEndInFrames); MA_API void ma_data_source_get_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pRangeBegInFrames, ma_uint64* pRangeEndInFrames);
MA_API ma_result ma_data_source_set_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 loopBegInFrames, ma_uint64 loopEndInFrames); MA_API ma_result ma_data_source_set_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 loopBegInFrames, ma_uint64 loopEndInFrames);
...@@ -9199,7 +9201,7 @@ MA_API ma_result ma_resource_manager_data_buffer_get_cursor_in_pcm_frames(ma_res ...@@ -9199,7 +9201,7 @@ MA_API ma_result ma_resource_manager_data_buffer_get_cursor_in_pcm_frames(ma_res
MA_API ma_result ma_resource_manager_data_buffer_get_length_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pLength); MA_API ma_result ma_resource_manager_data_buffer_get_length_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pLength);
MA_API ma_result ma_resource_manager_data_buffer_result(const ma_resource_manager_data_buffer* pDataBuffer); MA_API ma_result ma_resource_manager_data_buffer_result(const ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_set_looping(ma_resource_manager_data_buffer* pDataBuffer, ma_bool32 isLooping); MA_API ma_result ma_resource_manager_data_buffer_set_looping(ma_resource_manager_data_buffer* pDataBuffer, ma_bool32 isLooping);
MA_API ma_result ma_resource_manager_data_buffer_get_looping(const ma_resource_manager_data_buffer* pDataBuffer, ma_bool32* pIsLooping); MA_API ma_bool32 ma_resource_manager_data_buffer_is_looping(const ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pAvailableFrames); MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pAvailableFrames);
/* Data Streams. */ /* Data Streams. */
...@@ -9213,7 +9215,7 @@ MA_API ma_result ma_resource_manager_data_stream_get_cursor_in_pcm_frames(ma_res ...@@ -9213,7 +9215,7 @@ MA_API ma_result ma_resource_manager_data_stream_get_cursor_in_pcm_frames(ma_res
MA_API ma_result ma_resource_manager_data_stream_get_length_in_pcm_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pLength); MA_API ma_result ma_resource_manager_data_stream_get_length_in_pcm_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pLength);
MA_API ma_result ma_resource_manager_data_stream_result(const ma_resource_manager_data_stream* pDataStream); MA_API ma_result ma_resource_manager_data_stream_result(const ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_set_looping(ma_resource_manager_data_stream* pDataStream, ma_bool32 isLooping); MA_API ma_result ma_resource_manager_data_stream_set_looping(ma_resource_manager_data_stream* pDataStream, ma_bool32 isLooping);
MA_API ma_result ma_resource_manager_data_stream_get_looping(const ma_resource_manager_data_stream* pDataStream, ma_bool32* pIsLooping); MA_API ma_bool32 ma_resource_manager_data_stream_is_looping(const ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pAvailableFrames); MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pAvailableFrames);
/* Data Sources. */ /* Data Sources. */
...@@ -9228,7 +9230,7 @@ MA_API ma_result ma_resource_manager_data_source_get_cursor_in_pcm_frames(ma_res ...@@ -9228,7 +9230,7 @@ MA_API ma_result ma_resource_manager_data_source_get_cursor_in_pcm_frames(ma_res
MA_API ma_result ma_resource_manager_data_source_get_length_in_pcm_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pLength); MA_API ma_result ma_resource_manager_data_source_get_length_in_pcm_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pLength);
MA_API ma_result ma_resource_manager_data_source_result(const ma_resource_manager_data_source* pDataSource); MA_API ma_result ma_resource_manager_data_source_result(const ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_set_looping(ma_resource_manager_data_source* pDataSource, ma_bool32 isLooping); MA_API ma_result ma_resource_manager_data_source_set_looping(ma_resource_manager_data_source* pDataSource, ma_bool32 isLooping);
MA_API ma_result ma_resource_manager_data_source_get_looping(const ma_resource_manager_data_source* pDataSource, ma_bool32* pIsLooping); MA_API ma_bool32 ma_resource_manager_data_source_is_looping(const ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_get_available_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pAvailableFrames); MA_API ma_result ma_resource_manager_data_source_get_available_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pAvailableFrames);
/* Job management. */ /* Job management. */
...@@ -9464,22 +9466,20 @@ typedef struct ...@@ -9464,22 +9466,20 @@ typedef struct
{ {
ma_node_config nodeConfig; ma_node_config nodeConfig;
ma_data_source* pDataSource; ma_data_source* pDataSource;
ma_bool32 looping; /* Can be changed after initialization with ma_data_source_node_set_looping(). */
} ma_data_source_node_config; } ma_data_source_node_config;
MA_API ma_data_source_node_config ma_data_source_node_config_init(ma_data_source* pDataSource, ma_bool32 looping); MA_API ma_data_source_node_config ma_data_source_node_config_init(ma_data_source* pDataSource);
typedef struct typedef struct
{ {
ma_node_base base; ma_node_base base;
ma_data_source* pDataSource; ma_data_source* pDataSource;
MA_ATOMIC ma_bool32 looping; /* This can be modified and read across different threads. Must be used atomically. */
} ma_data_source_node; } ma_data_source_node;
MA_API ma_result ma_data_source_node_init(ma_node_graph* pNodeGraph, const ma_data_source_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source_node* pDataSourceNode); MA_API ma_result ma_data_source_node_init(ma_node_graph* pNodeGraph, const ma_data_source_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source_node* pDataSourceNode);
MA_API void ma_data_source_node_uninit(ma_data_source_node* pDataSourceNode, const ma_allocation_callbacks* pAllocationCallbacks); MA_API void ma_data_source_node_uninit(ma_data_source_node* pDataSourceNode, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_data_source_node_set_looping(ma_data_source_node* pDataSourceNode, ma_bool32 looping); MA_API ma_result ma_data_source_node_set_looping(ma_data_source_node* pDataSourceNode, ma_bool32 isLooping);
MA_API ma_bool32 ma_data_source_node_is_looping(ma_data_source_node* pDataSourceNode); MA_API ma_bool32 ma_data_source_node_is_looping(ma_data_source_node* pDataSourceNode);
...@@ -9808,7 +9808,6 @@ struct ma_sound ...@@ -9808,7 +9808,6 @@ struct ma_sound
ma_engine_node engineNode; /* Must be the first member for compatibility with the ma_node API. */ ma_engine_node engineNode; /* Must be the first member for compatibility with the ma_node API. */
ma_data_source* pDataSource; ma_data_source* pDataSource;
ma_uint64 seekTarget; /* The PCM frame index to seek to in the mixing thread. Set to (~(ma_uint64)0) to not perform any seeking. */ ma_uint64 seekTarget; /* The PCM frame index to seek to in the mixing thread. Set to (~(ma_uint64)0) to not perform any seeking. */
MA_ATOMIC ma_bool32 isLooping; /* False by default. */
MA_ATOMIC ma_bool32 atEnd; MA_ATOMIC ma_bool32 atEnd;
ma_bool8 ownsDataSource; ma_bool8 ownsDataSource;
...@@ -52227,11 +52226,12 @@ static ma_result ma_data_source_resolve_current(ma_data_source* pDataSource, ma_ ...@@ -52227,11 +52226,12 @@ static ma_result ma_data_source_resolve_current(ma_data_source* pDataSource, ma_
return MA_SUCCESS; return MA_SUCCESS;
} }
static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, ma_bool32 loop) static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{ {
ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource; ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
ma_result result; ma_result result;
ma_uint64 framesRead = 0; ma_uint64 framesRead = 0;
ma_bool32 loop = ma_data_source_is_looping(pDataSource);
if (pDataSourceBase == NULL) { if (pDataSourceBase == NULL) {
return MA_AT_END; return MA_AT_END;
...@@ -52285,7 +52285,7 @@ static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDa ...@@ -52285,7 +52285,7 @@ static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDa
return result; return result;
} }
MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, ma_bool32 loop) MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{ {
ma_result result = MA_SUCCESS; ma_result result = MA_SUCCESS;
ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource; ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
...@@ -52295,6 +52295,7 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi ...@@ -52295,6 +52295,7 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi
ma_format format; ma_format format;
ma_uint32 channels; ma_uint32 channels;
ma_uint32 emptyLoopCounter = 0; /* Keeps track of how many times 0 frames have been read. For infinite loop detection of sounds with no audio data. */ ma_uint32 emptyLoopCounter = 0; /* Keeps track of how many times 0 frames have been read. For infinite loop detection of sounds with no audio data. */
ma_bool32 loop;
if (pFramesRead != NULL) { if (pFramesRead != NULL) {
*pFramesRead = 0; *pFramesRead = 0;
...@@ -52308,6 +52309,8 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi ...@@ -52308,6 +52309,8 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
loop = ma_data_source_is_looping(pDataSource);
/* /*
We need to know the data format so we can advance the output buffer as we read frames. If this We need to know the data format so we can advance the output buffer as we read frames. If this
fails, chaining will not work and we'll just read as much as we can from the current source. fails, chaining will not work and we'll just read as much as we can from the current source.
...@@ -52318,7 +52321,7 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi ...@@ -52318,7 +52321,7 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi
return result; return result;
} }
return ma_data_source_read_pcm_frames_within_range(pCurrentDataSource, pFramesOut, frameCount, pFramesRead, loop); return ma_data_source_read_pcm_frames_within_range(pCurrentDataSource, pFramesOut, frameCount, pFramesRead);
} }
/* /*
...@@ -52341,7 +52344,7 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi ...@@ -52341,7 +52344,7 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi
break; break;
} }
result = ma_data_source_read_pcm_frames_within_range(pCurrentDataSource, pRunningFramesOut, framesRemaining, &framesProcessed, loop); result = ma_data_source_read_pcm_frames_within_range(pCurrentDataSource, pRunningFramesOut, framesRemaining, &framesProcessed);
totalFramesProcessed += framesProcessed; totalFramesProcessed += framesProcessed;
/* /*
...@@ -52423,9 +52426,9 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi ...@@ -52423,9 +52426,9 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi
return result; return result;
} }
MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked, ma_bool32 loop) MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked)
{ {
return ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, pFramesSeeked, loop); return ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, pFramesSeeked);
} }
MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex) MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex)
...@@ -52575,6 +52578,8 @@ MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool ...@@ -52575,6 +52578,8 @@ MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
c89atomic_exchange_32(&pDataSourceBase->isLooping, isLooping);
/* If there's no callback for this just treat it as a successful no-op. */ /* If there's no callback for this just treat it as a successful no-op. */
if (pDataSourceBase->vtable->onSetLooping == NULL) { if (pDataSourceBase->vtable->onSetLooping == NULL) {
return MA_SUCCESS; return MA_SUCCESS;
...@@ -52583,6 +52588,17 @@ MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool ...@@ -52583,6 +52588,17 @@ MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool
return pDataSourceBase->vtable->onSetLooping(pDataSource, isLooping); return pDataSourceBase->vtable->onSetLooping(pDataSource, isLooping);
} }
MA_API ma_bool32 ma_data_source_is_looping(ma_data_source* pDataSource)
{
ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
if (pDataSource == NULL) {
return MA_FALSE;
}
return c89atomic_load_32(&pDataSourceBase->isLooping);
}
MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames) MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames)
{ {
ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource; ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
...@@ -59657,14 +59673,14 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO ...@@ -59657,14 +59673,14 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO
/* Fast path. */ /* Fast path. */
if (pDecoder->converter.isPassthrough) { if (pDecoder->converter.isPassthrough) {
result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pFramesOut, frameCount, &totalFramesReadOut, MA_FALSE); result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pFramesOut, frameCount, &totalFramesReadOut);
} else { } else {
/* /*
Getting here means we need to do data conversion. If we're seeking forward and are _not_ doing resampling we can run this in a fast path. If we're doing resampling we Getting here means we need to do data conversion. If we're seeking forward and are _not_ doing resampling we can run this in a fast path. If we're doing resampling we
need to run through each sample because we need to ensure it's internal cache is updated. need to run through each sample because we need to ensure it's internal cache is updated.
*/ */
if (pFramesOut == NULL && pDecoder->converter.hasResampler == MA_FALSE) { if (pFramesOut == NULL && pDecoder->converter.hasResampler == MA_FALSE) {
result = ma_data_source_read_pcm_frames(pDecoder->pBackend, NULL, frameCount, &totalFramesReadOut, MA_FALSE); result = ma_data_source_read_pcm_frames(pDecoder->pBackend, NULL, frameCount, &totalFramesReadOut);
} else { } else {
/* Slow path. Need to run everything through the data converter. */ /* Slow path. Need to run everything through the data converter. */
ma_format internalFormat; ma_format internalFormat;
...@@ -59721,7 +59737,7 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO ...@@ -59721,7 +59737,7 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO
if (pDecoder->inputCacheRemaining == 0) { if (pDecoder->inputCacheRemaining == 0) {
pDecoder->inputCacheConsumed = 0; pDecoder->inputCacheConsumed = 0;
result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pDecoder->pInputCache, pDecoder->inputCacheCap, &pDecoder->inputCacheRemaining, MA_FALSE); result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pDecoder->pInputCache, pDecoder->inputCacheCap, &pDecoder->inputCacheRemaining);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
break; break;
} }
...@@ -59750,7 +59766,7 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO ...@@ -59750,7 +59766,7 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO
} }
if (requiredInputFrameCount > 0) { if (requiredInputFrameCount > 0) {
result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pIntermediaryBuffer, framesToReadThisIterationIn, &framesReadThisIterationIn, MA_FALSE); result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pIntermediaryBuffer, framesToReadThisIterationIn, &framesReadThisIterationIn);
} else { } else {
framesReadThisIterationIn = 0; framesReadThisIterationIn = 0;
} }
...@@ -62676,6 +62692,23 @@ static ma_result ma_resource_manager__init_decoder(ma_resource_manager* pResourc ...@@ -62676,6 +62692,23 @@ static ma_result ma_resource_manager__init_decoder(ma_resource_manager* pResourc
return MA_SUCCESS; return MA_SUCCESS;
} }
static ma_data_source* ma_resource_manager_data_buffer_get_connector(ma_resource_manager_data_buffer* pDataBuffer)
{
switch (pDataBuffer->pNode->data.type)
{
case ma_resource_manager_data_supply_type_encoded: return &pDataBuffer->connector.decoder;
case ma_resource_manager_data_supply_type_decoded: return &pDataBuffer->connector.buffer;
case ma_resource_manager_data_supply_type_decoded_paged: return &pDataBuffer->connector.pagedBuffer;
case ma_resource_manager_data_supply_type_unknown:
default:
{
ma_log_postf(ma_resource_manager_get_log(pDataBuffer->pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to retrieve data buffer connector. Unknown data supply type.\n");
return NULL;
};
};
}
static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_manager_data_buffer* pDataBuffer, ma_async_notification* pInitNotification, ma_fence* pInitFence) static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_manager_data_buffer* pDataBuffer, ma_async_notification* pInitNotification, ma_fence* pInitFence)
{ {
ma_result result; ma_result result;
...@@ -62730,6 +62763,12 @@ static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_mana ...@@ -62730,6 +62763,12 @@ static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_mana
the format/channels/rate of the data source. the format/channels/rate of the data source.
*/ */
if (result == MA_SUCCESS) { if (result == MA_SUCCESS) {
/*
Make sure the looping state is set before returning in order to handle the case where the
loop state was set on the data buffer before the connector was initialized.
*/
ma_data_source_set_looping(ma_resource_manager_data_buffer_get_connector(pDataBuffer), ma_resource_manager_data_buffer_is_looping(pDataBuffer));
pDataBuffer->isConnectorInitialized = MA_TRUE; pDataBuffer->isConnectorInitialized = MA_TRUE;
if (pInitNotification != NULL) { if (pInitNotification != NULL) {
...@@ -62784,23 +62823,6 @@ static ma_uint32 ma_resource_manager_data_buffer_node_next_execution_order(ma_re ...@@ -62784,23 +62823,6 @@ static ma_uint32 ma_resource_manager_data_buffer_node_next_execution_order(ma_re
return c89atomic_fetch_add_32(&pDataBufferNode->executionCounter, 1); return c89atomic_fetch_add_32(&pDataBufferNode->executionCounter, 1);
} }
static ma_data_source* ma_resource_manager_data_buffer_get_connector(ma_resource_manager_data_buffer* pDataBuffer)
{
switch (pDataBuffer->pNode->data.type)
{
case ma_resource_manager_data_supply_type_encoded: return &pDataBuffer->connector.decoder;
case ma_resource_manager_data_supply_type_decoded: return &pDataBuffer->connector.buffer;
case ma_resource_manager_data_supply_type_decoded_paged: return &pDataBuffer->connector.pagedBuffer;
case ma_resource_manager_data_supply_type_unknown:
default:
{
ma_log_postf(ma_resource_manager_get_log(pDataBuffer->pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to retrieve data buffer connector. Unknown data supply type.\n");
return NULL;
};
};
}
static ma_result ma_resource_manager_data_buffer_node_init_supply_encoded(ma_resource_manager* pResourceManager, ma_resource_manager_data_buffer_node* pDataBufferNode, const char* pFilePath, const wchar_t* pFilePathW) static ma_result ma_resource_manager_data_buffer_node_init_supply_encoded(ma_resource_manager* pResourceManager, ma_resource_manager_data_buffer_node* pDataBufferNode, const char* pFilePath, const wchar_t* pFilePathW)
{ {
ma_result result; ma_result result;
...@@ -63429,6 +63451,11 @@ static ma_result ma_resource_manager_data_buffer_cb__get_length_in_pcm_frames(ma ...@@ -63429,6 +63451,11 @@ static ma_result ma_resource_manager_data_buffer_cb__get_length_in_pcm_frames(ma
return ma_resource_manager_data_buffer_get_length_in_pcm_frames((ma_resource_manager_data_buffer*)pDataSource, pLength); return ma_resource_manager_data_buffer_get_length_in_pcm_frames((ma_resource_manager_data_buffer*)pDataSource, pLength);
} }
static ma_result ma_resource_manager_data_buffer_cb__set_looping(ma_data_source* pDataSource, ma_bool32 isLooping)
{
return ma_resource_manager_data_buffer_set_looping((ma_resource_manager_data_buffer*)pDataSource, isLooping);
}
static ma_data_source_vtable g_ma_resource_manager_data_buffer_vtable = static ma_data_source_vtable g_ma_resource_manager_data_buffer_vtable =
{ {
ma_resource_manager_data_buffer_cb__read_pcm_frames, ma_resource_manager_data_buffer_cb__read_pcm_frames,
...@@ -63436,7 +63463,7 @@ static ma_data_source_vtable g_ma_resource_manager_data_buffer_vtable = ...@@ -63436,7 +63463,7 @@ static ma_data_source_vtable g_ma_resource_manager_data_buffer_vtable =
ma_resource_manager_data_buffer_cb__get_data_format, ma_resource_manager_data_buffer_cb__get_data_format,
ma_resource_manager_data_buffer_cb__get_cursor_in_pcm_frames, ma_resource_manager_data_buffer_cb__get_cursor_in_pcm_frames,
ma_resource_manager_data_buffer_cb__get_length_in_pcm_frames, ma_resource_manager_data_buffer_cb__get_length_in_pcm_frames,
NULL /* onSetLooping */ ma_resource_manager_data_buffer_cb__set_looping
}; };
static ma_result ma_resource_manager_data_buffer_init_internal(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 hashedName32, ma_uint32 flags, ma_uint64 initialSeekPoint, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_buffer* pDataBuffer) static ma_result ma_resource_manager_data_buffer_init_internal(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 hashedName32, ma_uint32 flags, ma_uint64 initialSeekPoint, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_buffer* pDataBuffer)
...@@ -63677,7 +63704,6 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man ...@@ -63677,7 +63704,6 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man
{ {
ma_result result = MA_SUCCESS; ma_result result = MA_SUCCESS;
ma_uint64 framesRead = 0; ma_uint64 framesRead = 0;
ma_bool32 isLooping;
ma_bool32 isDecodedBufferBusy = MA_FALSE; ma_bool32 isDecodedBufferBusy = MA_FALSE;
/* Safety. */ /* Safety. */
...@@ -63709,11 +63735,6 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man ...@@ -63709,11 +63735,6 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man
} }
} }
result = ma_resource_manager_data_buffer_get_looping(pDataBuffer, &isLooping);
if (result != MA_SUCCESS) {
return result;
}
/* /*
For decoded buffers (not paged) we need to check beforehand how many frames we have available. We cannot For decoded buffers (not paged) we need to check beforehand how many frames we have available. We cannot
exceed this amount. We'll read as much as we can, and then return MA_BUSY. exceed this amount. We'll read as much as we can, and then return MA_BUSY.
...@@ -63746,7 +63767,7 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man ...@@ -63746,7 +63767,7 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man
/* Don't attempt to read anything if we've got no frames available. */ /* Don't attempt to read anything if we've got no frames available. */
if (frameCount > 0) { if (frameCount > 0) {
result = ma_data_source_read_pcm_frames(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pFramesOut, frameCount, &framesRead, isLooping); result = ma_data_source_read_pcm_frames(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pFramesOut, frameCount, &framesRead);
} }
/* /*
...@@ -63915,24 +63936,19 @@ MA_API ma_result ma_resource_manager_data_buffer_set_looping(ma_resource_manager ...@@ -63915,24 +63936,19 @@ MA_API ma_result ma_resource_manager_data_buffer_set_looping(ma_resource_manager
c89atomic_exchange_32(&pDataBuffer->isLooping, isLooping); c89atomic_exchange_32(&pDataBuffer->isLooping, isLooping);
/* The looping state needs to be set on the connector as well or else looping won't work when we read audio data. */
ma_data_source_set_looping(ma_resource_manager_data_buffer_get_connector(pDataBuffer), isLooping);
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API ma_result ma_resource_manager_data_buffer_get_looping(const ma_resource_manager_data_buffer* pDataBuffer, ma_bool32* pIsLooping) MA_API ma_bool32 ma_resource_manager_data_buffer_is_looping(const ma_resource_manager_data_buffer* pDataBuffer)
{ {
if (pIsLooping == NULL) {
return MA_INVALID_ARGS;
}
*pIsLooping = MA_FALSE;
if (pDataBuffer == NULL) { if (pDataBuffer == NULL) {
return MA_INVALID_ARGS; return MA_FALSE;
} }
*pIsLooping = c89atomic_load_32((ma_bool32*)&pDataBuffer->isLooping); return c89atomic_load_32((ma_bool32*)&pDataBuffer->isLooping);
return MA_SUCCESS;
} }
MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pAvailableFrames) MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pAvailableFrames)
...@@ -64305,7 +64321,7 @@ static void ma_resource_manager_data_stream_fill_page(ma_resource_manager_data_s ...@@ -64305,7 +64321,7 @@ static void ma_resource_manager_data_stream_fill_page(ma_resource_manager_data_s
pageSizeInFrames = ma_resource_manager_data_stream_get_page_size_in_frames(pDataStream); pageSizeInFrames = ma_resource_manager_data_stream_get_page_size_in_frames(pDataStream);
ma_resource_manager_data_stream_get_looping(pDataStream, &isLooping); /* Won't fail. */ isLooping = ma_resource_manager_data_stream_is_looping(pDataStream); /* Won't fail. */
if (isLooping) { if (isLooping) {
while (totalFramesReadForThisPage < pageSizeInFrames) { while (totalFramesReadForThisPage < pageSizeInFrames) {
...@@ -64716,21 +64732,13 @@ MA_API ma_result ma_resource_manager_data_stream_set_looping(ma_resource_manager ...@@ -64716,21 +64732,13 @@ MA_API ma_result ma_resource_manager_data_stream_set_looping(ma_resource_manager
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API ma_result ma_resource_manager_data_stream_get_looping(const ma_resource_manager_data_stream* pDataStream, ma_bool32* pIsLooping) MA_API ma_bool32 ma_resource_manager_data_stream_is_looping(const ma_resource_manager_data_stream* pDataStream)
{ {
if (pIsLooping == NULL) {
return MA_INVALID_ARGS;
}
*pIsLooping = MA_FALSE;
if (pDataStream == NULL) { if (pDataStream == NULL) {
return MA_INVALID_ARGS; return MA_FALSE;
} }
*pIsLooping = c89atomic_load_32((ma_bool32*)&pDataStream->isLooping); /* Naughty const-cast. Value won't change from here in practice (maybe from another thread). */ return c89atomic_load_32((ma_bool32*)&pDataStream->isLooping); /* Naughty const-cast. Value won't change from here in practice (maybe from another thread). */
return MA_SUCCESS;
} }
MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pAvailableFrames) MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pAvailableFrames)
...@@ -64975,16 +64983,16 @@ MA_API ma_result ma_resource_manager_data_source_set_looping(ma_resource_manager ...@@ -64975,16 +64983,16 @@ MA_API ma_result ma_resource_manager_data_source_set_looping(ma_resource_manager
} }
} }
MA_API ma_result ma_resource_manager_data_source_get_looping(const ma_resource_manager_data_source* pDataSource, ma_bool32* pIsLooping) MA_API ma_bool32 ma_resource_manager_data_source_is_looping(const ma_resource_manager_data_source* pDataSource)
{ {
if (pDataSource == NULL || pIsLooping == NULL) { if (pDataSource == NULL) {
return MA_INVALID_ARGS; return MA_FALSE;
} }
if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) { if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
return ma_resource_manager_data_stream_get_looping(&pDataSource->backend.stream, pIsLooping); return ma_resource_manager_data_stream_is_looping(&pDataSource->backend.stream);
} else { } else {
return ma_resource_manager_data_buffer_get_looping(&pDataSource->backend.buffer, pIsLooping); return ma_resource_manager_data_buffer_is_looping(&pDataSource->backend.buffer);
} }
} }
...@@ -67397,14 +67405,13 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde ...@@ -67397,14 +67405,13 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde
/* Data source node. */ /* Data source node. */
MA_API ma_data_source_node_config ma_data_source_node_config_init(ma_data_source* pDataSource, ma_bool32 looping) MA_API ma_data_source_node_config ma_data_source_node_config_init(ma_data_source* pDataSource)
{ {
ma_data_source_node_config config; ma_data_source_node_config config;
MA_ZERO_OBJECT(&config); MA_ZERO_OBJECT(&config);
config.nodeConfig = ma_node_config_init(); config.nodeConfig = ma_node_config_init();
config.pDataSource = pDataSource; config.pDataSource = pDataSource;
config.looping = looping;
return config; return config;
} }
...@@ -67437,7 +67444,7 @@ static void ma_data_source_node_process_pcm_frames(ma_node* pNode, const float** ...@@ -67437,7 +67444,7 @@ static void ma_data_source_node_process_pcm_frames(ma_node* pNode, const float**
MA_ASSERT(format == ma_format_f32); MA_ASSERT(format == ma_format_f32);
(void)format; /* Just to silence some static analysis tools. */ (void)format; /* Just to silence some static analysis tools. */
ma_data_source_read_pcm_frames(pDataSourceNode->pDataSource, ppFramesOut[0], frameCount, &framesRead, c89atomic_load_32(&pDataSourceNode->looping)); ma_data_source_read_pcm_frames(pDataSourceNode->pDataSource, ppFramesOut[0], frameCount, &framesRead);
} }
*pFrameCountOut = (ma_uint32)framesRead; *pFrameCountOut = (ma_uint32)framesRead;
...@@ -67502,7 +67509,6 @@ MA_API ma_result ma_data_source_node_init(ma_node_graph* pNodeGraph, const ma_da ...@@ -67502,7 +67509,6 @@ MA_API ma_result ma_data_source_node_init(ma_node_graph* pNodeGraph, const ma_da
} }
pDataSourceNode->pDataSource = pConfig->pDataSource; pDataSourceNode->pDataSource = pConfig->pDataSource;
pDataSourceNode->looping = pConfig->looping;
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -67512,15 +67518,13 @@ MA_API void ma_data_source_node_uninit(ma_data_source_node* pDataSourceNode, con ...@@ -67512,15 +67518,13 @@ MA_API void ma_data_source_node_uninit(ma_data_source_node* pDataSourceNode, con
ma_node_uninit(&pDataSourceNode->base, pAllocationCallbacks); ma_node_uninit(&pDataSourceNode->base, pAllocationCallbacks);
} }
MA_API ma_result ma_data_source_node_set_looping(ma_data_source_node* pDataSourceNode, ma_bool32 looping) MA_API ma_result ma_data_source_node_set_looping(ma_data_source_node* pDataSourceNode, ma_bool32 isLooping)
{ {
if (pDataSourceNode == NULL) { if (pDataSourceNode == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
c89atomic_exchange_32(&pDataSourceNode->looping, looping); return ma_data_source_set_looping(pDataSourceNode->pDataSource, isLooping);
return MA_SUCCESS;
} }
MA_API ma_bool32 ma_data_source_node_is_looping(ma_data_source_node* pDataSourceNode) MA_API ma_bool32 ma_data_source_node_is_looping(ma_data_source_node* pDataSourceNode)
...@@ -67529,7 +67533,7 @@ MA_API ma_bool32 ma_data_source_node_is_looping(ma_data_source_node* pDataSource ...@@ -67529,7 +67533,7 @@ MA_API ma_bool32 ma_data_source_node_is_looping(ma_data_source_node* pDataSource
return MA_FALSE; return MA_FALSE;
} }
return c89atomic_load_32(&pDataSourceNode->looping); return ma_data_source_is_looping(pDataSourceNode->pDataSource);
} }
...@@ -68804,7 +68808,7 @@ static void ma_engine_node_process_pcm_frames__sound(ma_node* pNode, const float ...@@ -68804,7 +68808,7 @@ static void ma_engine_node_process_pcm_frames__sound(ma_node* pNode, const float
framesToRead = tempCapInFrames; framesToRead = tempCapInFrames;
} }
result = ma_data_source_read_pcm_frames(pSound->pDataSource, temp, framesToRead, &framesJustRead, ma_sound_is_looping(pSound)); result = ma_data_source_read_pcm_frames(pSound->pDataSource, temp, framesToRead, &framesJustRead);
/* If we reached the end of the sound we'll want to mark it as at the end and stop it. This should never be returned for looping sounds. */ /* If we reached the end of the sound we'll want to mark it as at the end and stop it. This should never be returned for looping sounds. */
if (result == MA_AT_END) { if (result == MA_AT_END) {
...@@ -70713,12 +70717,7 @@ MA_API void ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping) ...@@ -70713,12 +70717,7 @@ MA_API void ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping)
return; return;
} }
c89atomic_exchange_32(&pSound->isLooping, isLooping); /* The looping state needs to be applied to the data source in order for any looping to actually happen. */
/*
Some data sources, in particular resource managed streams, need to know about the looping state
so they can do clean loop transitions.
*/
ma_data_source_set_looping(pSound->pDataSource, isLooping); ma_data_source_set_looping(pSound->pDataSource, isLooping);
} }
...@@ -70733,7 +70732,7 @@ MA_API ma_bool32 ma_sound_is_looping(const ma_sound* pSound) ...@@ -70733,7 +70732,7 @@ MA_API ma_bool32 ma_sound_is_looping(const ma_sound* pSound)
return MA_FALSE; return MA_FALSE;
} }
return c89atomic_load_32(&pSound->isLooping); return ma_data_source_is_looping(pSound->pDataSource);
} }
MA_API ma_bool32 ma_sound_at_end(const ma_sound* pSound) MA_API ma_bool32 ma_sound_at_end(const ma_sound* pSound)
...@@ -87476,6 +87475,9 @@ Breaking API Changes ...@@ -87476,6 +87475,9 @@ Breaking API Changes
-------------------- --------------------
There are many breaking API changes in this release. There are many breaking API changes in this release.
- The "loop" parameter has been removed from ma_data_source_read_pcm_frames(). To enabled looping
you now need to call ma_data_source_set_looping(). The looping state can be retrieved with
ma_data_source_is_looping().
- ma_channel_mix_mode_planar_blend has been removed. Use ma_channel_mix_mode_rectangular instead. - ma_channel_mix_mode_planar_blend has been removed. Use ma_channel_mix_mode_rectangular instead.
- MA_MIN_SAMPLE_RATE and MA_MAX_SAMPLE_RATE have been removed. Use ma_standard_sample_rate_min - MA_MIN_SAMPLE_RATE and MA_MAX_SAMPLE_RATE have been removed. Use ma_standard_sample_rate_min
and ma_standard_sample_rate_max instead. and ma_standard_sample_rate_max instead.
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