From 76a43426deaf604b450cb4bb271e95b604817a38 Mon Sep 17 00:00:00 2001 From: David Reid Date: Sun, 9 Aug 2020 07:27:41 +1000 Subject: [PATCH] Add sample rate to ma_data_source_get_data_format(). --- miniaudio.h | 56 ++++++++++++++++++++++++++------------------ research/ma_engine.h | 31 ++++++++++++------------ research/ma_mixing.h | 9 +++---- 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/miniaudio.h b/miniaudio.h index 6de9e7d7..1580f66a 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -5243,7 +5243,7 @@ typedef struct ma_result (* onSeek)(ma_data_source* pDataSource, ma_uint64 frameIndex); ma_result (* onMap)(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */ ma_result (* onUnmap)(ma_data_source* pDataSource, ma_uint64 frameCount); - ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels); + ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate); } ma_data_source_callbacks; 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. */ @@ -5251,7 +5251,7 @@ MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_ 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_map(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount); MA_API ma_result ma_data_source_unmap(ma_data_source* pDataSource, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */ -MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels); +MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate); typedef struct @@ -41202,7 +41202,8 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi } else { ma_format format; ma_uint32 channels; - if (ma_data_source_get_data_format(pDataSource, &format, &channels) != MA_SUCCESS) { + ma_uint32 sampleRate; + if (ma_data_source_get_data_format(pDataSource, &format, &channels, &sampleRate) != MA_SUCCESS) { return pCallbacks->onRead(pDataSource, pFramesOut, frameCount, pFramesRead); /* We don't have a way to retrieve the data format which means we don't know how to offset the output buffer. Just read as much as we can. */ } else { ma_result result = MA_SUCCESS; @@ -41284,18 +41285,19 @@ MA_API ma_result ma_data_source_unmap(ma_data_source* pDataSource, ma_uint64 fra return pCallbacks->onUnmap(pDataSource, frameCount); } -MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels) +MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate) { ma_result result; ma_format format; ma_uint32 channels; + ma_uint32 sampleRate; ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource; if (pCallbacks == NULL || pCallbacks->onGetDataFormat == NULL) { return MA_INVALID_ARGS; } - result = pCallbacks->onGetDataFormat(pDataSource, &format, &channels); + result = pCallbacks->onGetDataFormat(pDataSource, &format, &channels, &sampleRate); if (result != MA_SUCCESS) { return result; } @@ -41306,6 +41308,9 @@ MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_ if (pChannels != NULL) { *pChannels = channels; } + if (pSampleRate != NULL) { + *pSampleRate = sampleRate; + } return MA_SUCCESS; } @@ -41357,12 +41362,13 @@ static ma_result ma_audio_buffer__data_source_on_unmap(ma_data_source* pDataSour return ma_audio_buffer_unmap((ma_audio_buffer*)pDataSource, frameCount); } -static ma_result ma_audio_buffer__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels) +static ma_result ma_audio_buffer__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate) { ma_audio_buffer* pAudioBuffer = (ma_audio_buffer*)pDataSource; - *pFormat = pAudioBuffer->format; - *pChannels = pAudioBuffer->channels; + *pFormat = pAudioBuffer->format; + *pChannels = pAudioBuffer->channels; + *pSampleRate = 0; /* There is no notion of a sample rate with audio buffers. */ return MA_SUCCESS; } @@ -44416,12 +44422,13 @@ static ma_result ma_decoder__data_source_on_seek(ma_data_source* pDataSource, ma return ma_decoder_seek_to_pcm_frame((ma_decoder*)pDataSource, frameIndex); } -static ma_result ma_decoder__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels) +static ma_result ma_decoder__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate) { ma_decoder* pDecoder = (ma_decoder*)pDataSource; - *pFormat = pDecoder->outputFormat; - *pChannels = pDecoder->outputChannels; + *pFormat = pDecoder->outputFormat; + *pChannels = pDecoder->outputChannels; + *pSampleRate = pDecoder->outputSampleRate; return MA_SUCCESS; } @@ -46202,12 +46209,13 @@ static ma_result ma_waveform__data_source_on_seek(ma_data_source* pDataSource, m return ma_waveform_seek_to_pcm_frame((ma_waveform*)pDataSource, frameIndex); } -static ma_result ma_waveform__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels) +static ma_result ma_waveform__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate) { ma_waveform* pWaveform = (ma_waveform*)pDataSource; - *pFormat = pWaveform->config.format; - *pChannels = pWaveform->config.channels; + *pFormat = pWaveform->config.format; + *pChannels = pWaveform->config.channels; + *pSampleRate = pWaveform->config.sampleRate; return MA_SUCCESS; } @@ -46222,9 +46230,9 @@ MA_API ma_result ma_waveform_init(const ma_waveform_config* pConfig, ma_waveform pWaveform->ds.onRead = ma_waveform__data_source_on_read; pWaveform->ds.onSeek = ma_waveform__data_source_on_seek; pWaveform->ds.onGetDataFormat = ma_waveform__data_source_on_get_data_format; - pWaveform->config = *pConfig; - pWaveform->advance = 1.0 / pWaveform->config.sampleRate; - pWaveform->time = 0; + pWaveform->config = *pConfig; + pWaveform->advance = 1.0 / pWaveform->config.sampleRate; + pWaveform->time = 0; return MA_SUCCESS; } @@ -46581,12 +46589,13 @@ static ma_result ma_noise__data_source_on_seek(ma_data_source* pDataSource, ma_u return MA_SUCCESS; } -static ma_result ma_noise__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels) +static ma_result ma_noise__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate) { ma_noise* pNoise = (ma_noise*)pDataSource; - *pFormat = pNoise->config.format; - *pChannels = pNoise->config.channels; + *pFormat = pNoise->config.format; + *pChannels = pNoise->config.channels; + *pSampleRate = 0; /* There is no notion of sample rate with noise generation. */ return MA_SUCCESS; } @@ -46610,7 +46619,7 @@ MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise) pNoise->ds.onRead = ma_noise__data_source_on_read; pNoise->ds.onSeek = ma_noise__data_source_on_seek; /* <-- No-op for noise. */ pNoise->ds.onGetDataFormat = ma_noise__data_source_on_get_data_format; - pNoise->config = *pConfig; + pNoise->config = *pConfig; ma_lcg_seed(&pNoise->lcg, pConfig->seed); if (pNoise->config.type == ma_noise_type_pink) { @@ -62359,8 +62368,9 @@ v0.10.16 - TBD - Fix a bug in ma_data_source_read_pcm_frames() where looping doesn't work. - Fix some compilation warnings on Windows when both DirectSound and WinMM are disabled. - Fix some compilation warnings when no decoders are enabled. - - Add ma_audio_buffer_get_available_frames() - - Add ma_decoder_get_available_frames() + - Add ma_audio_buffer_get_available_frames(). + - Add ma_decoder_get_available_frames(). + - Add sample rate to ma_data_source_get_data_format(). - Change volume APIs to take 64-bit frame counts. - Updates to documentation. diff --git a/research/ma_engine.h b/research/ma_engine.h index 7e5f9203..f55e2d6b 100644 --- a/research/ma_engine.h +++ b/research/ma_engine.h @@ -665,7 +665,7 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man MA_API ma_result ma_resource_manager_data_buffer_seek_to_pcm_frame(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64 frameIndex); MA_API ma_result ma_resource_manager_data_buffer_map(ma_resource_manager_data_buffer* pDataBuffer, void** ppFramesOut, ma_uint64* pFrameCount); MA_API ma_result ma_resource_manager_data_buffer_unmap(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64 frameCount); -MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_manager_data_buffer* pDataBuffer, ma_format* pFormat, ma_uint32* pChannels); +MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_manager_data_buffer* pDataBuffer, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate); 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_get_looping(const ma_resource_manager_data_buffer* pDataBuffer, ma_bool32* pIsLooping); @@ -678,7 +678,7 @@ MA_API ma_result ma_resource_manager_data_stream_read_pcm_frames(ma_resource_man MA_API ma_result ma_resource_manager_data_stream_seek_to_pcm_frame(ma_resource_manager_data_stream* pDataStream, ma_uint64 frameIndex); MA_API ma_result ma_resource_manager_data_stream_map(ma_resource_manager_data_stream* pDataStream, void** ppFramesOut, ma_uint64* pFrameCount); MA_API ma_result ma_resource_manager_data_stream_unmap(ma_resource_manager_data_stream* pDataStream, ma_uint64 frameCount); -MA_API ma_result ma_resource_manager_data_stream_get_data_format(ma_resource_manager_data_stream* pDataStream, ma_format* pFormat, ma_uint32* pChannels); +MA_API ma_result ma_resource_manager_data_stream_get_data_format(ma_resource_manager_data_stream* pDataStream, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate); 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_get_looping(const ma_resource_manager_data_stream* pDataStream, ma_bool32* pIsLooping); @@ -691,7 +691,7 @@ MA_API ma_result ma_resource_manager_data_source_read_pcm_frames(ma_resource_man MA_API ma_result ma_resource_manager_data_source_seek_to_pcm_frame(ma_resource_manager_data_source* pDataSource, ma_uint64 frameIndex); MA_API ma_result ma_resource_manager_data_source_map(ma_resource_manager_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount); MA_API ma_result ma_resource_manager_data_source_unmap(ma_resource_manager_data_source* pDataSource, ma_uint64 frameCount); -MA_API ma_result ma_resource_manager_data_source_get_data_format(ma_resource_manager_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels); +MA_API ma_result ma_resource_manager_data_source_get_data_format(ma_resource_manager_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate); 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_get_looping(const ma_resource_manager_data_source* pDataSource, ma_bool32* pIsLooping); @@ -2585,7 +2585,7 @@ MA_API ma_result ma_resource_manager_data_buffer_unmap(ma_resource_manager_data_ return result; } -MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_manager_data_buffer* pDataBuffer, ma_format* pFormat, ma_uint32* pChannels) +MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_manager_data_buffer* pDataBuffer, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate) { /* We cannot be using the data source after it's been uninitialized. */ MA_ASSERT(pDataBuffer->pNode->result != MA_UNAVAILABLE); @@ -2595,7 +2595,7 @@ MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_man return MA_BUSY; /* Still loading. */ } - return ma_data_source_get_data_format(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pFormat, pChannels); + return ma_data_source_get_data_format(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pFormat, pChannels, pSampleRate); } MA_API ma_result ma_resource_manager_data_buffer_result(const ma_resource_manager_data_buffer* pDataBuffer) @@ -2990,7 +2990,7 @@ MA_API ma_result ma_resource_manager_data_stream_read_pcm_frames(ma_resource_man return MA_BUSY; } - ma_resource_manager_data_stream_get_data_format(pDataStream, &format, &channels); + ma_resource_manager_data_stream_get_data_format(pDataStream, &format, &channels, NULL); /* Reading is implemented in terms of map/unmap. We need to run this in a loop because mapping is clamped against page boundaries. */ totalFramesProcessed = 0; @@ -3176,7 +3176,7 @@ MA_API ma_result ma_resource_manager_data_stream_seek_to_pcm_frame(ma_resource_m return ma_resource_manager_post_job(pDataStream->pResourceManager, &job); } -MA_API ma_result ma_resource_manager_data_stream_get_data_format(ma_resource_manager_data_stream* pDataStream, ma_format* pFormat, ma_uint32* pChannels) +MA_API ma_result ma_resource_manager_data_stream_get_data_format(ma_resource_manager_data_stream* pDataStream, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate) { /* We cannot be using the data source after it's been uninitialized. */ MA_ASSERT(pDataStream->result != MA_UNAVAILABLE); @@ -3193,7 +3193,7 @@ MA_API ma_result ma_resource_manager_data_stream_get_data_format(ma_resource_man We're being a little bit naughty here and accessing the internal decoder from the public API. The output data format is constant, and we've defined this function such that the application is responsible for ensuring it's not called while uninitializing so it should be safe. */ - return ma_data_source_get_data_format(&pDataStream->decoder, pFormat, pChannels); + return ma_data_source_get_data_format(&pDataStream->decoder, pFormat, pChannels, pSampleRate); } MA_API ma_result ma_resource_manager_data_stream_result(const ma_resource_manager_data_stream* pDataStream) @@ -3350,16 +3350,16 @@ MA_API ma_result ma_resource_manager_data_source_unmap(ma_resource_manager_data_ } } -MA_API ma_result ma_resource_manager_data_source_get_data_format(ma_resource_manager_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels) +MA_API ma_result ma_resource_manager_data_source_get_data_format(ma_resource_manager_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate) { if (pDataSource == NULL) { return MA_INVALID_ARGS; } if ((pDataSource->flags & MA_DATA_SOURCE_FLAG_STREAM) != 0) { - return ma_resource_manager_data_stream_get_data_format(&pDataSource->stream, pFormat, pChannels); + return ma_resource_manager_data_stream_get_data_format(&pDataSource->stream, pFormat, pChannels, pSampleRate); } else { - return ma_resource_manager_data_buffer_get_data_format(&pDataSource->buffer, pFormat, pChannels); + return ma_resource_manager_data_buffer_get_data_format(&pDataSource->buffer, pFormat, pChannels, pSampleRate); } } @@ -4452,14 +4452,15 @@ MA_API ma_result ma_fader_process_pcm_frames(ma_fader* pFader, void* pFramesOut, ma_apply_volume_factor_pcm_frames(pFramesOut, frameCount, pFader->format, pFader->channels, pFader->volumeEnd); } } else { + ma_uint64 lo = pFader->timeInFramesBeg; + ma_uint64 hi = pFader->timeInFramesEnd; + ma_uint64 dt = (pFader->timeInFramesEnd - pFader->timeInFramesBeg); + /* Only supporting f32 for the moment while we figure this out. */ if (pFader->format == ma_format_f32) { const float* pFramesInF32 = (const float*)pFramesIn; /* */ float* pFramesOutF32 = ( float*)pFramesOut; float volumeCur = 1; - ma_uint64 lo = pFader->timeInFramesBeg; - ma_uint64 hi = pFader->timeInFramesEnd; - ma_uint64 dt = (pFader->timeInFramesEnd - pFader->timeInFramesBeg); for (iFrame = 0; iFrame < frameCount; iFrame += 1) { /* The volume to apply is just a mix between the begin and end volume depending on the current time. */ @@ -4842,7 +4843,7 @@ static ma_result ma_engine_effect_init(ma_engine* pEngine, ma_engine_effect* pEf MA_ZERO_OBJECT(pEffect); - pEffect->baseEffect.onProcessPCMFrames = ma_engine_effect__on_process_pcm_frames; + pEffect->baseEffect.onProcessPCMFrames = ma_engine_effect__on_process_pcm_frames; pEffect->baseEffect.onGetRequiredInputFrameCount = ma_engine_effect__on_get_required_input_frame_count; pEffect->baseEffect.onGetExpectedOutputFrameCount = ma_engine_effect__on_get_expected_output_frame_count; pEffect->baseEffect.onGetInputDataFormat = ma_engine_effect__on_get_input_data_format; diff --git a/research/ma_mixing.h b/research/ma_mixing.h index 0a4cdf97..e3068f40 100644 --- a/research/ma_mixing.h +++ b/research/ma_mixing.h @@ -2707,7 +2707,7 @@ MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDat return MA_INVALID_ARGS; } - result = ma_data_source_get_data_format(pDataSource, &formatIn, &channelsIn); + result = ma_data_source_get_data_format(pDataSource, &formatIn, &channelsIn, NULL); if (result != MA_SUCCESS) { return result; } @@ -2767,12 +2767,13 @@ static ma_result ma_rb_data_source__on_unmap(ma_data_source* pDataSource, ma_uin return result; /* We never actually return MA_AT_END here because a ring buffer doesn't have any notion of an end. */ } -static ma_result ma_rb_data_source__on_get_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels) +static ma_result ma_rb_data_source__on_get_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate) { ma_rb_data_source* pRB = (ma_rb_data_source*)pDataSource; - *pFormat = pRB->format; - *pChannels = pRB->channels; + *pFormat = pRB->format; + *pChannels = pRB->channels; + *pSampleRate = 0; /* No sample rate. */ return MA_SUCCESS; }