Work in progress on the new high level API.

* Early work on asynchronously decoding into a memory buffer. This is
    just an early implementation - there are still issues needing to be
    figured out. In particular, sounds do not automatically start until
    the entire file has been decoded. It would be good if they could
    start as soon as the first second or so of data has been decoded.
This commit is contained in:
David Reid
2020-06-10 22:07:16 +10:00
parent 86181dfac8
commit 8734e8f578
3 changed files with 1364 additions and 658 deletions
+6 -3
View File
@@ -28,20 +28,23 @@ int main(int argc, char** argv)
return -1; return -1;
} }
result = ma_engine_sound_init_from_file(&engine, argv[1], MA_DATA_SOURCE_FLAG_DECODE, NULL, &sound); result = ma_engine_sound_init_from_file(&engine, argv[1], MA_DATA_SOURCE_FLAG_DECODE | MA_DATA_SOURCE_FLAG_ASYNC, NULL, &sound);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_engine_uninit(&engine); ma_engine_uninit(&engine);
return -1; return -1;
} }
ma_engine_sound_set_volume(&engine, &sound, 0.25f);
ma_engine_sound_set_pitch(&engine, &sound, 1.0f); ma_engine_sound_set_pitch(&engine, &sound, 1.0f);
ma_engine_sound_set_pan(&engine, &sound, -1.0f); ma_engine_sound_set_pan(&engine, &sound, 0.0f);
ma_engine_sound_set_looping(&engine, &sound, MA_TRUE); ma_engine_sound_set_looping(&engine, &sound, MA_TRUE);
ma_engine_sound_start(&engine, &sound); ma_engine_sound_start(&engine, &sound);
ma_engine_play_sound(&engine, argv[1], NULL); #if 1
/*ma_engine_play_sound(&engine, argv[1], NULL);*/
ma_engine_play_sound(&engine, argv[2], NULL); ma_engine_play_sound(&engine, argv[2], NULL);
ma_engine_play_sound(&engine, argv[3], NULL); ma_engine_play_sound(&engine, argv[3], NULL);
#endif
#if 0 #if 0
float pitch = 1; float pitch = 1;
+1314 -597
View File
File diff suppressed because it is too large Load Diff
+7 -21
View File
@@ -2579,7 +2579,7 @@ static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source*
static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCount, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn, ma_bool32 loop) static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCount, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn, ma_bool32 loop)
{ {
ma_result result; ma_result result = MA_SUCCESS;
ma_uint8 preMixBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; ma_uint8 preMixBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint32 preMixBufferCap; ma_uint32 preMixBufferCap;
ma_uint64 totalFramesProcessed = 0; ma_uint64 totalFramesProcessed = 0;
@@ -2589,7 +2589,6 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
ma_format preMixFormat = ma_format_unknown; ma_format preMixFormat = ma_format_unknown;
ma_uint32 preMixChannels = 0; ma_uint32 preMixChannels = 0;
ma_bool32 preEffectConversionRequired = MA_FALSE; ma_bool32 preEffectConversionRequired = MA_FALSE;
ma_bool32 atEnd = MA_FALSE;
MA_ASSERT(pMixer != NULL); MA_ASSERT(pMixer != NULL);
MA_ASSERT(pDataSource != NULL); MA_ASSERT(pDataSource != NULL);
@@ -2629,13 +2628,8 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
} }
if (pEffect == NULL) { if (pEffect == NULL) {
framesRead = ma_data_source_read_pcm_frames(pDataSource, preMixBuffer, framesToRead, loop); result = ma_data_source_read_pcm_frames(pDataSource, preMixBuffer, framesToRead, &framesRead, loop);
ma_mix_pcm_frames_ex(pRunningAccumulationBuffer, pMixer->format, pMixer->channels, preMixBuffer, formatIn, channelsIn, framesRead, volume); ma_mix_pcm_frames_ex(pRunningAccumulationBuffer, pMixer->format, pMixer->channels, preMixBuffer, formatIn, channelsIn, framesRead, volume);
/* We need to check if we've reached the end so we know whether or not we need to loop. */
if (framesRead < framesToRead) {
atEnd = MA_TRUE;
}
} else { } else {
ma_uint8 callbackBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; ma_uint8 callbackBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint8 effectInBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; ma_uint8 effectInBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
@@ -2658,10 +2652,10 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
*/ */
if (preEffectConversionRequired == MA_FALSE) { if (preEffectConversionRequired == MA_FALSE) {
/* Fast path. No need for conversion between the callback and the */ /* Fast path. No need for conversion between the callback and the */
framesReadFromCallback = ma_data_source_read_pcm_frames(pDataSource, effectInBuffer, framesToReadFromCallback, loop); result = ma_data_source_read_pcm_frames(pDataSource, effectInBuffer, framesToReadFromCallback, &framesReadFromCallback, loop);
} else { } else {
/* Slow path. Conversion between the callback and the effect required. */ /* Slow path. Conversion between the callback and the effect required. */
framesReadFromCallback = ma_data_source_read_pcm_frames(pDataSource, callbackBuffer, framesToReadFromCallback, loop); result = ma_data_source_read_pcm_frames(pDataSource, callbackBuffer, framesToReadFromCallback, &framesReadFromCallback, loop);
ma_convert_pcm_frames_format_and_channels(effectInBuffer, effectFormatIn, effectChannelsIn, callbackBuffer, formatIn, channelsIn, framesReadFromCallback, ma_dither_mode_none); ma_convert_pcm_frames_format_and_channels(effectInBuffer, effectFormatIn, effectChannelsIn, callbackBuffer, formatIn, channelsIn, framesReadFromCallback, ma_dither_mode_none);
} }
@@ -2674,11 +2668,6 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
framesRead = (ma_uint32)effectFrameCountOut; /* Safe cast. */ framesRead = (ma_uint32)effectFrameCountOut; /* Safe cast. */
ma_mix_pcm_frames_ex(pRunningAccumulationBuffer, pMixer->format, pMixer->channels, preMixBuffer, preMixFormat, preMixChannels, framesRead, volume); ma_mix_pcm_frames_ex(pRunningAccumulationBuffer, pMixer->format, pMixer->channels, preMixBuffer, preMixFormat, preMixChannels, framesRead, volume);
/* We need to check if we've reached the end so we know whether or not we need to loop. */
if (framesReadFromCallback < framesToReadFromCallback) {
atEnd = MA_TRUE;
}
/* An emergency failure case. Abort if we didn't consume any input nor any output frames. */ /* An emergency failure case. Abort if we didn't consume any input nor any output frames. */
if (framesRead == 0 && framesReadFromCallback == 0) { if (framesRead == 0 && framesReadFromCallback == 0) {
break; break;
@@ -2688,16 +2677,13 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
totalFramesProcessed += framesRead; totalFramesProcessed += framesRead;
pRunningAccumulationBuffer = ma_offset_ptr(pRunningAccumulationBuffer, framesRead * ma_get_accumulation_bytes_per_frame(pMixer->format, pMixer->channels)); pRunningAccumulationBuffer = ma_offset_ptr(pRunningAccumulationBuffer, framesRead * ma_get_accumulation_bytes_per_frame(pMixer->format, pMixer->channels));
if (atEnd) { /* If the data source is busy we need to end mixing now. */
if (result == MA_BUSY || result == MA_AT_END) {
break; break;
} }
} }
if (atEnd) { return result;
return MA_AT_END;
} else {
return MA_SUCCESS;
}
} }
MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCountIn, float volume, ma_effect* pEffect, ma_bool32 loop) MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCountIn, float volume, ma_effect* pEffect, ma_bool32 loop)