Commit 11acb0ca authored by David Reid's avatar David Reid

Prep work in preparation for some changes to data sources.

Public issue https://github.com/mackron/miniaudio/issues/290
parent 1897c599
...@@ -5895,23 +5895,55 @@ typedef struct ...@@ -5895,23 +5895,55 @@ typedef struct
ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate); ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
ma_result (* onGetCursor)(ma_data_source* pDataSource, ma_uint64* pCursor); ma_result (* onGetCursor)(ma_data_source* pDataSource, ma_uint64* pCursor);
ma_result (* onGetLength)(ma_data_source* pDataSource, ma_uint64* pLength); ma_result (* onGetLength)(ma_data_source* pDataSource, ma_uint64* pLength);
} ma_data_source_callbacks; } ma_data_source_vtable, ma_data_source_callbacks; /* TODO: Remove ma_data_source_callbacks in version 0.11. */
typedef ma_data_source* (* ma_data_source_get_next_proc)(ma_data_source* pDataSource);
typedef struct
{
const ma_data_source_vtable* vtable; /* Can be null, which is useful for proxies. */
ma_uint64 rangeBegInFrames;
ma_uint64 rangeEndInFrames; /* Set to -1 for unranged (default). */
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_get_next_proc onGetNext; /* Will be used when pNext is NULL. If both are NULL, no next will be used. */
} ma_data_source_config;
MA_API ma_data_source_config ma_data_source_config_init(void);
typedef struct
{
ma_data_source_callbacks cb; /* TODO: Remove this. */
/* Variables below are placeholder and not yet used. */
const ma_data_source_vtable* vtable; /* Can be NULL, which might be useful for proxy data sources. */
ma_uint64 rangeBegInFrames;
ma_uint64 rangeEndInFrames;
ma_data_source* pCurrent;
ma_data_source* pNext;
ma_data_source_get_next_proc onGetNext;
} ma_data_source_base;
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 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, ma_bool32 loop); /* 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); */ 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); */
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_map(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount); MA_API ma_result ma_data_source_map(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount); /* Returns MA_NOT_IMPLEMENTED if mapping is not supported. */
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_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_uint32* pSampleRate); MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
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. */
#if MA_VERSION_MINOR >= 11
MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBeg, ma_uint64 rangeLen);
MA_API ma_result ma_data_source_get_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pRangeBeg, ma_uint64* pRangeLen);
#endif
typedef struct typedef struct
{ {
ma_data_source_callbacks ds; ma_data_source_base ds;
ma_format format; ma_format format;
ma_uint32 channels; ma_uint32 channels;
ma_uint64 cursor; ma_uint64 cursor;
...@@ -5920,6 +5952,7 @@ typedef struct ...@@ -5920,6 +5952,7 @@ typedef struct
} ma_audio_buffer_ref; } ma_audio_buffer_ref;
MA_API ma_result ma_audio_buffer_ref_init(ma_format format, ma_uint32 channels, const void* pData, ma_uint64 sizeInFrames, ma_audio_buffer_ref* pAudioBufferRef); MA_API ma_result ma_audio_buffer_ref_init(ma_format format, ma_uint32 channels, const void* pData, ma_uint64 sizeInFrames, ma_audio_buffer_ref* pAudioBufferRef);
MA_API void ma_audio_buffer_ref_uninit(ma_audio_buffer_ref* pAudioBufferRef);
MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames); MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames);
MA_API ma_uint64 ma_audio_buffer_ref_read_pcm_frames(ma_audio_buffer_ref* pAudioBufferRef, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop); MA_API ma_uint64 ma_audio_buffer_ref_read_pcm_frames(ma_audio_buffer_ref* pAudioBufferRef, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop);
MA_API ma_result ma_audio_buffer_ref_seek_to_pcm_frame(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameIndex); MA_API ma_result ma_audio_buffer_ref_seek_to_pcm_frame(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameIndex);
...@@ -6074,7 +6107,7 @@ typedef struct ...@@ -6074,7 +6107,7 @@ typedef struct
struct ma_decoder struct ma_decoder
{ {
ma_data_source_callbacks ds; ma_data_source_base ds;
ma_decoder_read_proc onRead; ma_decoder_read_proc onRead;
ma_decoder_seek_proc onSeek; ma_decoder_seek_proc onSeek;
void* pUserData; void* pUserData;
...@@ -6288,13 +6321,14 @@ MA_API ma_waveform_config ma_waveform_config_init(ma_format format, ma_uint32 ch ...@@ -6288,13 +6321,14 @@ MA_API ma_waveform_config ma_waveform_config_init(ma_format format, ma_uint32 ch
typedef struct typedef struct
{ {
ma_data_source_callbacks ds; ma_data_source_base ds;
ma_waveform_config config; ma_waveform_config config;
double advance; double advance;
double time; double time;
} ma_waveform; } ma_waveform;
MA_API ma_result ma_waveform_init(const ma_waveform_config* pConfig, ma_waveform* pWaveform); MA_API ma_result ma_waveform_init(const ma_waveform_config* pConfig, ma_waveform* pWaveform);
MA_API void ma_waveform_uninit(ma_waveform* pWaveform);
MA_API ma_uint64 ma_waveform_read_pcm_frames(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount); MA_API ma_uint64 ma_waveform_read_pcm_frames(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount);
MA_API ma_result ma_waveform_seek_to_pcm_frame(ma_waveform* pWaveform, ma_uint64 frameIndex); MA_API ma_result ma_waveform_seek_to_pcm_frame(ma_waveform* pWaveform, ma_uint64 frameIndex);
MA_API ma_result ma_waveform_set_amplitude(ma_waveform* pWaveform, double amplitude); MA_API ma_result ma_waveform_set_amplitude(ma_waveform* pWaveform, double amplitude);
...@@ -6323,7 +6357,7 @@ MA_API ma_noise_config ma_noise_config_init(ma_format format, ma_uint32 channels ...@@ -6323,7 +6357,7 @@ MA_API ma_noise_config ma_noise_config_init(ma_format format, ma_uint32 channels
typedef struct typedef struct
{ {
ma_data_source_callbacks ds; ma_data_source_vtable ds;
ma_noise_config config; ma_noise_config config;
ma_lcg lcg; ma_lcg lcg;
union union
...@@ -6342,6 +6376,7 @@ typedef struct ...@@ -6342,6 +6376,7 @@ typedef struct
} ma_noise; } ma_noise;
MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise); MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise);
MA_API void ma_noise_uninit(ma_noise* pNoise);
MA_API ma_uint64 ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount); MA_API ma_uint64 ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount);
MA_API ma_result ma_noise_set_amplitude(ma_noise* pNoise, double amplitude); MA_API ma_result ma_noise_set_amplitude(ma_noise* pNoise, double amplitude);
MA_API ma_result ma_noise_set_seed(ma_noise* pNoise, ma_int32 seed); MA_API ma_result ma_noise_set_seed(ma_noise* pNoise, ma_int32 seed);
...@@ -43105,6 +43140,58 @@ MA_API ma_uint32 ma_get_bytes_per_sample(ma_format format) ...@@ -43105,6 +43140,58 @@ MA_API ma_uint32 ma_get_bytes_per_sample(ma_format format)
MA_API ma_data_source_config ma_data_source_config_init(void)
{
ma_data_source_config config;
MA_ZERO_OBJECT(&config);
config.rangeEndInFrames = ~((ma_uint64)0);
return config;
}
MA_API ma_result ma_data_source_init(const ma_data_source_config* pConfig, ma_data_source* pDataSource)
{
ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
if (pDataSource == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pDataSourceBase);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
pDataSourceBase->vtable = pConfig->vtable;
pDataSourceBase->rangeBegInFrames = pConfig->rangeBegInFrames;
pDataSourceBase->rangeEndInFrames = pConfig->rangeEndInFrames;
pDataSourceBase->pCurrent = pConfig->pCurrent;
pDataSourceBase->pNext = pConfig->pNext;
pDataSourceBase->onGetNext = pConfig->onGetNext;
/* Compatibility: Need to make a copy of the callbacks. This will be removed in version 0.11. */
if (pConfig->vtable != NULL) {
pDataSourceBase->cb = *pConfig->vtable;
}
return MA_SUCCESS;
}
MA_API void ma_data_source_uninit(ma_data_source* pDataSource)
{
if (pDataSource == NULL) {
return;
}
/*
This is placeholder in case we need this later. Data sources need to call this in their
uninitialization routine to ensure things work later on if something is added here.
*/
}
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_bool32 loop)
{ {
ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource; ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
...@@ -43184,30 +43271,42 @@ MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_ ...@@ -43184,30 +43271,42 @@ 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_seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex)
{ {
ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource; ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
if (pCallbacks == NULL || pCallbacks->onSeek == NULL) { if (pCallbacks == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pCallbacks->onSeek == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onSeek(pDataSource, frameIndex); return pCallbacks->onSeek(pDataSource, 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_map(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount)
{ {
ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource; ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
if (pCallbacks == NULL || pCallbacks->onMap == NULL) { if (pCallbacks == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pCallbacks->onMap == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onMap(pDataSource, ppFramesOut, pFrameCount); return pCallbacks->onMap(pDataSource, ppFramesOut, pFrameCount);
} }
MA_API ma_result ma_data_source_unmap(ma_data_source* pDataSource, ma_uint64 frameCount) MA_API ma_result ma_data_source_unmap(ma_data_source* pDataSource, ma_uint64 frameCount)
{ {
ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource; ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
if (pCallbacks == NULL || pCallbacks->onUnmap == NULL) { if (pCallbacks == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pCallbacks->onUnmap == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onUnmap(pDataSource, frameCount); return pCallbacks->onUnmap(pDataSource, frameCount);
} }
...@@ -43231,10 +43330,14 @@ MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_ ...@@ -43231,10 +43330,14 @@ MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_
*pSampleRate = 0; *pSampleRate = 0;
} }
if (pCallbacks == NULL || pCallbacks->onGetDataFormat == NULL) { if (pCallbacks == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pCallbacks->onGetDataFormat == NULL) {
return MA_NOT_IMPLEMENTED;
}
result = pCallbacks->onGetDataFormat(pDataSource, &format, &channels, &sampleRate); result = pCallbacks->onGetDataFormat(pDataSource, &format, &channels, &sampleRate);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
...@@ -43357,30 +43460,54 @@ static ma_result ma_audio_buffer_ref__data_source_on_get_length(ma_data_source* ...@@ -43357,30 +43460,54 @@ static ma_result ma_audio_buffer_ref__data_source_on_get_length(ma_data_source*
return MA_SUCCESS; return MA_SUCCESS;
} }
static ma_data_source_vtable g_ma_audio_buffer_ref_data_source_vtable =
{
ma_audio_buffer_ref__data_source_on_read,
ma_audio_buffer_ref__data_source_on_seek,
ma_audio_buffer_ref__data_source_on_map,
ma_audio_buffer_ref__data_source_on_unmap,
ma_audio_buffer_ref__data_source_on_get_data_format,
ma_audio_buffer_ref__data_source_on_get_cursor,
ma_audio_buffer_ref__data_source_on_get_length
};
MA_API ma_result ma_audio_buffer_ref_init(ma_format format, ma_uint32 channels, const void* pData, ma_uint64 sizeInFrames, ma_audio_buffer_ref* pAudioBufferRef) MA_API ma_result ma_audio_buffer_ref_init(ma_format format, ma_uint32 channels, const void* pData, ma_uint64 sizeInFrames, ma_audio_buffer_ref* pAudioBufferRef)
{ {
ma_result result;
ma_data_source_config dataSourceConfig;
if (pAudioBufferRef == NULL) { if (pAudioBufferRef == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
MA_ZERO_OBJECT(pAudioBufferRef); MA_ZERO_OBJECT(pAudioBufferRef);
pAudioBufferRef->ds.onRead = ma_audio_buffer_ref__data_source_on_read; dataSourceConfig = ma_data_source_config_init();
pAudioBufferRef->ds.onSeek = ma_audio_buffer_ref__data_source_on_seek; dataSourceConfig.vtable = &g_ma_audio_buffer_ref_data_source_vtable;
pAudioBufferRef->ds.onMap = ma_audio_buffer_ref__data_source_on_map;
pAudioBufferRef->ds.onUnmap = ma_audio_buffer_ref__data_source_on_unmap; result = ma_data_source_init(&dataSourceConfig, &pAudioBufferRef->ds);
pAudioBufferRef->ds.onGetDataFormat = ma_audio_buffer_ref__data_source_on_get_data_format; if (result != MA_SUCCESS) {
pAudioBufferRef->ds.onGetCursor = ma_audio_buffer_ref__data_source_on_get_cursor; return result;
pAudioBufferRef->ds.onGetLength = ma_audio_buffer_ref__data_source_on_get_length; }
pAudioBufferRef->format = format;
pAudioBufferRef->channels = channels; pAudioBufferRef->format = format;
pAudioBufferRef->cursor = 0; pAudioBufferRef->channels = channels;
pAudioBufferRef->sizeInFrames = sizeInFrames; pAudioBufferRef->cursor = 0;
pAudioBufferRef->pData = pData; pAudioBufferRef->sizeInFrames = sizeInFrames;
pAudioBufferRef->pData = pData;
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API void ma_audio_buffer_ref_uninit(ma_audio_buffer_ref* pAudioBufferRef)
{
if (pAudioBufferRef == NULL) {
return;
}
ma_data_source_uninit(&pAudioBufferRef->ds);
}
MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames) MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames)
{ {
if (pAudioBufferRef == NULL) { if (pAudioBufferRef == NULL) {
...@@ -43618,6 +43745,8 @@ static void ma_audio_buffer_uninit_ex(ma_audio_buffer* pAudioBuffer, ma_bool32 d ...@@ -43618,6 +43745,8 @@ static void ma_audio_buffer_uninit_ex(ma_audio_buffer* pAudioBuffer, ma_bool32 d
if (doFree) { if (doFree) {
ma__free_from_callbacks(pAudioBuffer, &pAudioBuffer->allocationCallbacks); ma__free_from_callbacks(pAudioBuffer, &pAudioBuffer->allocationCallbacks);
} }
ma_audio_buffer_ref_uninit(&pAudioBuffer->ref);
} }
MA_API ma_result ma_audio_buffer_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer) MA_API ma_result ma_audio_buffer_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer)
...@@ -46673,9 +46802,21 @@ static ma_result ma_decoder__data_source_on_get_length(ma_data_source* pDataSour ...@@ -46673,9 +46802,21 @@ static ma_result ma_decoder__data_source_on_get_length(ma_data_source* pDataSour
return MA_SUCCESS; return MA_SUCCESS;
} }
static ma_data_source_vtable g_ma_decoder_data_source_vtable =
{
ma_decoder__data_source_on_read,
ma_decoder__data_source_on_seek,
NULL, /* onMap */
NULL, /* onUnmap */
ma_decoder__data_source_on_get_data_format,
ma_decoder__data_source_on_get_cursor,
ma_decoder__data_source_on_get_length
};
static ma_result ma_decoder__preinit(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void* pUserData, const ma_decoder_config* pConfig, ma_decoder* pDecoder) static ma_result ma_decoder__preinit(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void* pUserData, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
{ {
ma_result result; ma_result result;
ma_data_source_config dataSourceConfig;
MA_ASSERT(pConfig != NULL); MA_ASSERT(pConfig != NULL);
...@@ -46689,11 +46830,13 @@ static ma_result ma_decoder__preinit(ma_decoder_read_proc onRead, ma_decoder_see ...@@ -46689,11 +46830,13 @@ static ma_result ma_decoder__preinit(ma_decoder_read_proc onRead, ma_decoder_see
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
pDecoder->ds.onRead = ma_decoder__data_source_on_read; dataSourceConfig = ma_data_source_config_init();
pDecoder->ds.onSeek = ma_decoder__data_source_on_seek; dataSourceConfig.vtable = &g_ma_decoder_data_source_vtable;
pDecoder->ds.onGetDataFormat = ma_decoder__data_source_on_get_data_format;
pDecoder->ds.onGetCursor = ma_decoder__data_source_on_get_cursor; result = ma_data_source_init(&dataSourceConfig, &pDecoder->ds);
pDecoder->ds.onGetLength = ma_decoder__data_source_on_get_length; if (result != MA_SUCCESS) {
return result;
}
pDecoder->onRead = onRead; pDecoder->onRead = onRead;
pDecoder->onSeek = onSeek; pDecoder->onSeek = onSeek;
...@@ -46701,6 +46844,7 @@ static ma_result ma_decoder__preinit(ma_decoder_read_proc onRead, ma_decoder_see ...@@ -46701,6 +46844,7 @@ static ma_result ma_decoder__preinit(ma_decoder_read_proc onRead, ma_decoder_see
result = ma_decoder__init_allocation_callbacks(pConfig, pDecoder); result = ma_decoder__init_allocation_callbacks(pConfig, pDecoder);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_data_source_uninit(&pDecoder->ds);
return result; return result;
} }
...@@ -47829,6 +47973,7 @@ MA_API ma_result ma_decoder_uninit(ma_decoder* pDecoder) ...@@ -47829,6 +47973,7 @@ MA_API ma_result ma_decoder_uninit(ma_decoder* pDecoder)
} }
ma_data_converter_uninit(&pDecoder->converter); ma_data_converter_uninit(&pDecoder->converter);
ma_data_source_uninit(&pDecoder->ds);
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -48479,25 +48624,52 @@ static void ma_waveform__update_advance(ma_waveform* pWaveform) ...@@ -48479,25 +48624,52 @@ static void ma_waveform__update_advance(ma_waveform* pWaveform)
pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency); pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency);
} }
static ma_data_source_vtable g_ma_waveform_data_source_vtable =
{
ma_waveform__data_source_on_read,
ma_waveform__data_source_on_seek,
NULL, /* onMap */
NULL, /* onUnmap */
ma_waveform__data_source_on_get_data_format,
ma_waveform__data_source_on_get_cursor,
NULL /* onGetLength. There's no notion of a length in waveforms. */
};
MA_API ma_result ma_waveform_init(const ma_waveform_config* pConfig, ma_waveform* pWaveform) MA_API ma_result ma_waveform_init(const ma_waveform_config* pConfig, ma_waveform* pWaveform)
{ {
ma_result result;
ma_data_source_config dataSourceConfig;
if (pWaveform == NULL) { if (pWaveform == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
MA_ZERO_OBJECT(pWaveform); MA_ZERO_OBJECT(pWaveform);
pWaveform->ds.onRead = ma_waveform__data_source_on_read;
pWaveform->ds.onSeek = ma_waveform__data_source_on_seek; dataSourceConfig = ma_data_source_config_init();
pWaveform->ds.onGetDataFormat = ma_waveform__data_source_on_get_data_format; dataSourceConfig.vtable = &g_ma_waveform_data_source_vtable;
pWaveform->ds.onGetCursor = ma_waveform__data_source_on_get_cursor;
pWaveform->ds.onGetLength = NULL; /* Intentionally set to NULL since there's no notion of a length in waveforms. */ result = ma_data_source_init(&dataSourceConfig, &pWaveform->ds);
pWaveform->config = *pConfig; if (result != MA_SUCCESS) {
pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency); return result;
pWaveform->time = 0; }
pWaveform->config = *pConfig;
pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency);
pWaveform->time = 0;
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API void ma_waveform_uninit(ma_waveform* pWaveform)
{
if (pWaveform == NULL) {
return;
}
ma_data_source_uninit(&pWaveform->ds);
}
MA_API ma_result ma_waveform_set_amplitude(ma_waveform* pWaveform, double amplitude) MA_API ma_result ma_waveform_set_amplitude(ma_waveform* pWaveform, double amplitude)
{ {
if (pWaveform == NULL) { if (pWaveform == NULL) {
...@@ -48872,8 +49044,22 @@ static ma_result ma_noise__data_source_on_get_data_format(ma_data_source* pDataS ...@@ -48872,8 +49044,22 @@ static ma_result ma_noise__data_source_on_get_data_format(ma_data_source* pDataS
return MA_SUCCESS; return MA_SUCCESS;
} }
static ma_data_source_vtable g_ma_noise_data_source_vtable =
{
ma_noise__data_source_on_read,
ma_noise__data_source_on_seek, /* No-op for noise. */
NULL, /* onMap */
NULL, /* onUnmap */
ma_noise__data_source_on_get_data_format,
NULL, /* onGetCursor. No notion of a cursor for noise. */
NULL /* onGetLength. No notion of a length for noise. */
};
MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise) MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise)
{ {
ma_result result;
ma_data_source_config dataSourceConfig;
if (pNoise == NULL) { if (pNoise == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
...@@ -48888,12 +49074,15 @@ MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise) ...@@ -48888,12 +49074,15 @@ MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise)
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
pNoise->ds.onRead = ma_noise__data_source_on_read; dataSourceConfig = ma_data_source_config_init();
pNoise->ds.onSeek = ma_noise__data_source_on_seek; /* <-- No-op for noise. */ dataSourceConfig.vtable = &g_ma_noise_data_source_vtable;
pNoise->ds.onGetDataFormat = ma_noise__data_source_on_get_data_format;
pNoise->ds.onGetCursor = NULL; /* No notion of a cursor for noise. */ result = ma_data_source_init(&dataSourceConfig, &pNoise->ds);
pNoise->ds.onGetLength = NULL; /* No notion of a length for noise. */ if (result != MA_SUCCESS) {
pNoise->config = *pConfig; return result;
}
pNoise->config = *pConfig;
ma_lcg_seed(&pNoise->lcg, pConfig->seed); ma_lcg_seed(&pNoise->lcg, pConfig->seed);
if (pNoise->config.type == ma_noise_type_pink) { if (pNoise->config.type == ma_noise_type_pink) {
...@@ -48914,6 +49103,15 @@ MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise) ...@@ -48914,6 +49103,15 @@ MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise)
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API void ma_noise_uninit(ma_noise* pNoise)
{
if (pNoise == NULL) {
return;
}
ma_data_source_uninit(&pNoise->ds);
}
MA_API ma_result ma_noise_set_amplitude(ma_noise* pNoise, double amplitude) MA_API ma_result ma_noise_set_amplitude(ma_noise* pNoise, double amplitude)
{ {
if (pNoise == NULL) { if (pNoise == NULL) {
...@@ -64801,6 +64999,16 @@ REVISION HISTORY ...@@ -64801,6 +64999,16 @@ REVISION HISTORY
================ ================
0.10.36 - TBD 0.10.36 - TBD
- Silence some warnings when compiling with MA_DEBUG_OUTPUT - Silence some warnings when compiling with MA_DEBUG_OUTPUT
- Prep work for some upcoming changes to data sources. These changes are still compatible with
existing code, however code will need to be updated in preparation for version 0.11 which will
be breaking. You should make these changes now for any custom data sources:
- Change your base data source object from `ma_data_source_callbacks` to `ma_data_source_base`.
- Call `ma_data_source_init()` for your base object in your custom data source's initialization
routine. This takes a config object which includes a pointer to a vtable which is now where
your custom callbacks are defined.
- Call `ma_data_source_uninit()` in your custom data source's uninitialization routine. This
doesn't currently do anything, but it placeholder in case some future uninitialization code
is required to be added at a later date.
v0.10.35 - 2021-04-27 v0.10.35 - 2021-04-27
- Fix the C++ build. - Fix the C++ build.
...@@ -1282,7 +1282,7 @@ struct ma_resource_manager_data_buffer_node ...@@ -1282,7 +1282,7 @@ struct ma_resource_manager_data_buffer_node
struct ma_resource_manager_data_buffer struct ma_resource_manager_data_buffer
{ {
ma_data_source_callbacks ds; /* Data source callbacks. A data buffer is a data source. */ ma_data_source_base ds; /* Base data source. A data buffer is a data source. */
ma_resource_manager* pResourceManager; /* A pointer to the resource manager that owns this buffer. */ ma_resource_manager* pResourceManager; /* A pointer to the resource manager that owns this buffer. */
ma_uint32 flags; /* The flags that were passed used to initialize the buffer. */ ma_uint32 flags; /* The flags that were passed used to initialize the buffer. */
ma_resource_manager_data_buffer_node* pNode; /* The data node. This is reference counted. */ ma_resource_manager_data_buffer_node* pNode; /* The data node. This is reference counted. */
...@@ -1300,7 +1300,7 @@ struct ma_resource_manager_data_buffer ...@@ -1300,7 +1300,7 @@ struct ma_resource_manager_data_buffer
struct ma_resource_manager_data_stream struct ma_resource_manager_data_stream
{ {
ma_data_source_callbacks ds; /* Data source callbacks. A data stream is a data source. */ ma_data_source_base ds; /* Base data source. A data stream is a data source. */
ma_resource_manager* pResourceManager; /* A pointer to the resource manager that owns this data stream. */ ma_resource_manager* pResourceManager; /* A pointer to the resource manager that owns this data stream. */
ma_uint32 flags; /* The flags that were passed used to initialize the stream. */ ma_uint32 flags; /* The flags that were passed used to initialize the stream. */
ma_decoder decoder; /* Used for filling pages with data. This is only ever accessed by the job thread. The public API should never touch this. */ ma_decoder decoder; /* Used for filling pages with data. This is only ever accessed by the job thread. The public API should never touch this. */
...@@ -6086,15 +6086,6 @@ static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_mana ...@@ -6086,15 +6086,6 @@ static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_mana
} }
} }
/*
We can only do mapping if the data source's backend is an audio buffer. If it's not, clear out the callbacks thereby preventing the mixer from attempting
memory map mode, only to fail.
*/
if (pDataBuffer->connectorType != ma_resource_manager_data_buffer_connector_buffer) {
pDataBuffer->ds.onMap = NULL;
pDataBuffer->ds.onUnmap = NULL;
}
/* /*
Initialization of the connector is when we can fire the MA_NOTIFICATION_COMPLETE notification. This will give the application access to Initialization of the connector is when we can fire the MA_NOTIFICATION_COMPLETE notification. This will give the application access to
the format/channels/rate of the data source. the format/channels/rate of the data source.
...@@ -6197,9 +6188,21 @@ static ma_result ma_resource_manager_data_buffer_cb__get_length_in_pcm_frames(ma ...@@ -6197,9 +6188,21 @@ 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_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__seek_to_pcm_frame,
ma_resource_manager_data_buffer_cb__map,
ma_resource_manager_data_buffer_cb__unmap,
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_length_in_pcm_frames
};
static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 hashedName32, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer) static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 hashedName32, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer)
{ {
ma_result result; ma_result result;
ma_data_source_config dataSourceConfig;
ma_resource_manager_data_buffer_node* pInsertPoint; ma_resource_manager_data_buffer_node* pInsertPoint;
char* pFilePathCopy = NULL; /* Allocated here, freed in the job thread. */ char* pFilePathCopy = NULL; /* Allocated here, freed in the job thread. */
wchar_t* pFilePathWCopy = NULL; wchar_t* pFilePathWCopy = NULL;
...@@ -6210,16 +6213,17 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -6210,16 +6213,17 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
MA_ASSERT(pDataBuffer != NULL); MA_ASSERT(pDataBuffer != NULL);
MA_ZERO_OBJECT(pDataBuffer); MA_ZERO_OBJECT(pDataBuffer);
pDataBuffer->ds.onRead = ma_resource_manager_data_buffer_cb__read_pcm_frames;
pDataBuffer->ds.onSeek = ma_resource_manager_data_buffer_cb__seek_to_pcm_frame;
pDataBuffer->ds.onMap = ma_resource_manager_data_buffer_cb__map;
pDataBuffer->ds.onUnmap = ma_resource_manager_data_buffer_cb__unmap;
pDataBuffer->ds.onGetDataFormat = ma_resource_manager_data_buffer_cb__get_data_format;
pDataBuffer->ds.onGetCursor = ma_resource_manager_data_buffer_cb__get_cursor_in_pcm_frames;
pDataBuffer->ds.onGetLength = ma_resource_manager_data_buffer_cb__get_length_in_pcm_frames;
pDataBuffer->pResourceManager = pResourceManager; dataSourceConfig = ma_data_source_config_init();
pDataBuffer->flags = flags; dataSourceConfig.vtable = &g_ma_resource_manager_data_buffer_vtable;
result = ma_data_source_init(&dataSourceConfig, &pDataBuffer->ds);
if (result != MA_SUCCESS) {
return result;
}
pDataBuffer->pResourceManager = pResourceManager;
pDataBuffer->flags = flags;
/* The backend type hasn't been determined yet - that happens when it's initialized properly by the job thread. */ /* The backend type hasn't been determined yet - that happens when it's initialized properly by the job thread. */
pDataBuffer->connectorType = ma_resource_manager_data_buffer_connector_unknown; pDataBuffer->connectorType = ma_resource_manager_data_buffer_connector_unknown;
...@@ -6617,6 +6621,9 @@ static ma_result ma_resource_manager_data_buffer_uninit_internal(ma_resource_man ...@@ -6617,6 +6621,9 @@ static ma_result ma_resource_manager_data_buffer_uninit_internal(ma_resource_man
} }
ma_resource_manager_data_buffer_bst_unlock(pDataBuffer->pResourceManager); ma_resource_manager_data_buffer_bst_unlock(pDataBuffer->pResourceManager);
/* The base data source needs to be uninitialized as well. */
ma_data_source_uninit(&pDataBuffer->ds);
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -7152,9 +7159,21 @@ static ma_result ma_resource_manager_data_stream_cb__get_length_in_pcm_frames(ma ...@@ -7152,9 +7159,21 @@ static ma_result ma_resource_manager_data_stream_cb__get_length_in_pcm_frames(ma
return ma_resource_manager_data_stream_get_length_in_pcm_frames((ma_resource_manager_data_stream*)pDataSource, pLength); return ma_resource_manager_data_stream_get_length_in_pcm_frames((ma_resource_manager_data_stream*)pDataSource, pLength);
} }
static ma_data_source_vtable g_ma_resource_manager_data_stream_vtable =
{
ma_resource_manager_data_stream_cb__read_pcm_frames,
ma_resource_manager_data_stream_cb__seek_to_pcm_frame,
ma_resource_manager_data_stream_cb__map,
ma_resource_manager_data_stream_cb__unmap,
ma_resource_manager_data_stream_cb__get_data_format,
ma_resource_manager_data_stream_cb__get_cursor_in_pcm_frames,
ma_resource_manager_data_stream_cb__get_length_in_pcm_frames
};
static ma_result ma_resource_manager_data_stream_init_internal(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_stream* pDataStream) static ma_result ma_resource_manager_data_stream_init_internal(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_stream* pDataStream)
{ {
ma_result result; ma_result result;
ma_data_source_config dataSourceConfig;
char* pFilePathCopy = NULL; char* pFilePathCopy = NULL;
wchar_t* pFilePathWCopy = NULL; wchar_t* pFilePathWCopy = NULL;
ma_job job; ma_job job;
...@@ -7170,17 +7189,18 @@ static ma_result ma_resource_manager_data_stream_init_internal(ma_resource_manag ...@@ -7170,17 +7189,18 @@ static ma_result ma_resource_manager_data_stream_init_internal(ma_resource_manag
} }
MA_ZERO_OBJECT(pDataStream); MA_ZERO_OBJECT(pDataStream);
pDataStream->ds.onRead = ma_resource_manager_data_stream_cb__read_pcm_frames;
pDataStream->ds.onSeek = ma_resource_manager_data_stream_cb__seek_to_pcm_frame; dataSourceConfig = ma_data_source_config_init();
pDataStream->ds.onMap = ma_resource_manager_data_stream_cb__map; dataSourceConfig.vtable = &g_ma_resource_manager_data_stream_vtable;
pDataStream->ds.onUnmap = ma_resource_manager_data_stream_cb__unmap;
pDataStream->ds.onGetDataFormat = ma_resource_manager_data_stream_cb__get_data_format; result = ma_data_source_init(&dataSourceConfig, &pDataStream->ds);
pDataStream->ds.onGetCursor = ma_resource_manager_data_stream_cb__get_cursor_in_pcm_frames; if (result != MA_SUCCESS) {
pDataStream->ds.onGetLength = ma_resource_manager_data_stream_cb__get_length_in_pcm_frames; return result;
}
pDataStream->pResourceManager = pResourceManager;
pDataStream->flags = flags; pDataStream->pResourceManager = pResourceManager;
pDataStream->result = MA_BUSY; pDataStream->flags = flags;
pDataStream->result = MA_BUSY;
if (pResourceManager == NULL || (pFilePath == NULL && pFilePathW == NULL)) { if (pResourceManager == NULL || (pFilePath == NULL && pFilePathW == NULL)) {
if (pNotification != NULL) { if (pNotification != NULL) {
...@@ -8535,6 +8555,8 @@ static ma_result ma_resource_manager_process_job__free_data_stream(ma_resource_m ...@@ -8535,6 +8555,8 @@ static ma_result ma_resource_manager_process_job__free_data_stream(ma_resource_m
pDataStream->pPageData = NULL; /* Just in case... */ pDataStream->pPageData = NULL; /* Just in case... */
} }
ma_data_source_uninit(&pDataStream->ds);
/* The event needs to be signalled last. */ /* The event needs to be signalled last. */
if (pJob->freeDataStream.pNotification != NULL) { if (pJob->freeDataStream.pNotification != NULL) {
ma_async_notification_signal(pJob->freeDataStream.pNotification, MA_NOTIFICATION_COMPLETE); ma_async_notification_signal(pJob->freeDataStream.pNotification, MA_NOTIFICATION_COMPLETE);
......
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