Commit 80cdee58 authored by David Reid's avatar David Reid

Add ma_data_source_set_looping().

This is used for giving the data source a hint as to whether or not
it'll be used in a looping situations. It's required for some data
sources which need to know about it's looping state for caching or
whatnot.
parent e78ce5e3
...@@ -8264,6 +8264,7 @@ typedef struct ...@@ -8264,6 +8264,7 @@ typedef struct
ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap); ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
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_result (* onSetLooping)(ma_data_source* pDataSource, ma_bool32 isLooping);
} ma_data_source_vtable; } ma_data_source_vtable;
typedef ma_data_source* (* ma_data_source_get_next_proc)(ma_data_source* pDataSource); typedef ma_data_source* (* ma_data_source_get_next_proc)(ma_data_source* pDataSource);
...@@ -8296,6 +8297,7 @@ MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, m ...@@ -8296,6 +8297,7 @@ MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, m
MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap); MA_API ma_result ma_data_source_get_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_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);
...@@ -52565,6 +52567,22 @@ MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSo ...@@ -52565,6 +52567,22 @@ MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSo
return pDataSourceBase->vtable->onGetLength(pDataSource, pLength); return pDataSourceBase->vtable->onGetLength(pDataSource, pLength);
} }
MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool32 isLooping)
{
ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
if (pDataSource == NULL) {
return MA_INVALID_ARGS;
}
/* If there's no callback for this just treat it as a successful no-op. */
if (pDataSourceBase->vtable->onSetLooping == NULL) {
return MA_SUCCESS;
}
return pDataSourceBase->vtable->onSetLooping(pDataSource, 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;
...@@ -52823,7 +52841,8 @@ static ma_data_source_vtable g_ma_audio_buffer_ref_data_source_vtable = ...@@ -52823,7 +52841,8 @@ static ma_data_source_vtable g_ma_audio_buffer_ref_data_source_vtable =
ma_audio_buffer_ref__data_source_on_seek, ma_audio_buffer_ref__data_source_on_seek,
ma_audio_buffer_ref__data_source_on_get_data_format, 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_cursor,
ma_audio_buffer_ref__data_source_on_get_length ma_audio_buffer_ref__data_source_on_get_length,
NULL /* onSetLooping */
}; };
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)
...@@ -53505,7 +53524,8 @@ static ma_data_source_vtable g_ma_paged_audio_buffer_data_source_vtable = ...@@ -53505,7 +53524,8 @@ static ma_data_source_vtable g_ma_paged_audio_buffer_data_source_vtable =
ma_paged_audio_buffer__data_source_on_seek, ma_paged_audio_buffer__data_source_on_seek,
ma_paged_audio_buffer__data_source_on_get_data_format, ma_paged_audio_buffer__data_source_on_get_data_format,
ma_paged_audio_buffer__data_source_on_get_cursor, ma_paged_audio_buffer__data_source_on_get_cursor,
ma_paged_audio_buffer__data_source_on_get_length ma_paged_audio_buffer__data_source_on_get_length,
NULL /* onSetLooping */
}; };
MA_API ma_result ma_paged_audio_buffer_init(const ma_paged_audio_buffer_config* pConfig, ma_paged_audio_buffer* pPagedAudioBuffer) MA_API ma_result ma_paged_audio_buffer_init(const ma_paged_audio_buffer_config* pConfig, ma_paged_audio_buffer* pPagedAudioBuffer)
...@@ -56093,7 +56113,8 @@ static ma_data_source_vtable g_ma_wav_ds_vtable = ...@@ -56093,7 +56113,8 @@ static ma_data_source_vtable g_ma_wav_ds_vtable =
ma_wav_ds_seek, ma_wav_ds_seek,
ma_wav_ds_get_data_format, ma_wav_ds_get_data_format,
ma_wav_ds_get_cursor, ma_wav_ds_get_cursor,
ma_wav_ds_get_length ma_wav_ds_get_length,
NULL /* onSetLooping */
}; };
...@@ -56734,7 +56755,8 @@ static ma_data_source_vtable g_ma_flac_ds_vtable = ...@@ -56734,7 +56755,8 @@ static ma_data_source_vtable g_ma_flac_ds_vtable =
ma_flac_ds_seek, ma_flac_ds_seek,
ma_flac_ds_get_data_format, ma_flac_ds_get_data_format,
ma_flac_ds_get_cursor, ma_flac_ds_get_cursor,
ma_flac_ds_get_length ma_flac_ds_get_length,
NULL /* onSetLooping */
}; };
...@@ -57368,7 +57390,8 @@ static ma_data_source_vtable g_ma_mp3_ds_vtable = ...@@ -57368,7 +57390,8 @@ static ma_data_source_vtable g_ma_mp3_ds_vtable =
ma_mp3_ds_seek, ma_mp3_ds_seek,
ma_mp3_ds_get_data_format, ma_mp3_ds_get_data_format,
ma_mp3_ds_get_cursor, ma_mp3_ds_get_cursor,
ma_mp3_ds_get_length ma_mp3_ds_get_length,
NULL /* onSetLooping */
}; };
...@@ -58055,7 +58078,8 @@ static ma_data_source_vtable g_ma_stbvorbis_ds_vtable = ...@@ -58055,7 +58078,8 @@ static ma_data_source_vtable g_ma_stbvorbis_ds_vtable =
ma_stbvorbis_ds_seek, ma_stbvorbis_ds_seek,
ma_stbvorbis_ds_get_data_format, ma_stbvorbis_ds_get_data_format,
ma_stbvorbis_ds_get_cursor, ma_stbvorbis_ds_get_cursor,
ma_stbvorbis_ds_get_length ma_stbvorbis_ds_get_length,
NULL /* onSetLooping */
}; };
...@@ -58810,7 +58834,8 @@ static ma_data_source_vtable g_ma_decoder_data_source_vtable = ...@@ -58810,7 +58834,8 @@ static ma_data_source_vtable g_ma_decoder_data_source_vtable =
ma_decoder__data_source_on_seek, ma_decoder__data_source_on_seek,
ma_decoder__data_source_on_get_data_format, ma_decoder__data_source_on_get_data_format,
ma_decoder__data_source_on_get_cursor, ma_decoder__data_source_on_get_cursor,
ma_decoder__data_source_on_get_length ma_decoder__data_source_on_get_length,
NULL /* onSetLooping */
}; };
static ma_result ma_decoder__preinit(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, ma_decoder_tell_proc onTell, 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, ma_decoder_tell_proc onTell, void* pUserData, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
...@@ -60391,7 +60416,8 @@ static ma_data_source_vtable g_ma_waveform_data_source_vtable = ...@@ -60391,7 +60416,8 @@ static ma_data_source_vtable g_ma_waveform_data_source_vtable =
ma_waveform__data_source_on_seek, ma_waveform__data_source_on_seek,
ma_waveform__data_source_on_get_data_format, ma_waveform__data_source_on_get_data_format,
ma_waveform__data_source_on_get_cursor, ma_waveform__data_source_on_get_cursor,
NULL /* onGetLength. There's no notion of a length in waveforms. */ NULL, /* onGetLength. There's no notion of a length in waveforms. */
NULL /* onSetLooping */
}; };
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)
...@@ -60812,7 +60838,8 @@ static ma_data_source_vtable g_ma_noise_data_source_vtable = ...@@ -60812,7 +60838,8 @@ static ma_data_source_vtable g_ma_noise_data_source_vtable =
ma_noise__data_source_on_seek, /* No-op for noise. */ ma_noise__data_source_on_seek, /* No-op for noise. */
ma_noise__data_source_on_get_data_format, ma_noise__data_source_on_get_data_format,
NULL, /* onGetCursor. No notion of a cursor for noise. */ NULL, /* onGetCursor. No notion of a cursor for noise. */
NULL /* onGetLength. No notion of a length for noise. */ NULL, /* onGetLength. No notion of a length for noise. */
NULL /* onSetLooping */
}; };
...@@ -63408,7 +63435,8 @@ static ma_data_source_vtable g_ma_resource_manager_data_buffer_vtable = ...@@ -63408,7 +63435,8 @@ static ma_data_source_vtable g_ma_resource_manager_data_buffer_vtable =
ma_resource_manager_data_buffer_cb__seek_to_pcm_frame, ma_resource_manager_data_buffer_cb__seek_to_pcm_frame,
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 */
}; };
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)
...@@ -64088,13 +64116,19 @@ static ma_result ma_resource_manager_data_stream_cb__get_length_in_pcm_frames(ma ...@@ -64088,13 +64116,19 @@ 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_result ma_resource_manager_data_stream_cb__set_looping(ma_data_source* pDataSource, ma_bool32 isLooping)
{
return ma_resource_manager_data_stream_set_looping((ma_resource_manager_data_stream*)pDataSource, isLooping);
}
static ma_data_source_vtable g_ma_resource_manager_data_stream_vtable = 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__read_pcm_frames,
ma_resource_manager_data_stream_cb__seek_to_pcm_frame, ma_resource_manager_data_stream_cb__seek_to_pcm_frame,
ma_resource_manager_data_stream_cb__get_data_format, 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_cursor_in_pcm_frames,
ma_resource_manager_data_stream_cb__get_length_in_pcm_frames ma_resource_manager_data_stream_cb__get_length_in_pcm_frames,
ma_resource_manager_data_stream_cb__set_looping
}; };
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_uint64 initialSeekPoint, const ma_resource_manager_pipeline_notifications* pNotifications, 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_uint64 initialSeekPoint, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_stream* pDataStream)
...@@ -66234,7 +66268,7 @@ static ma_result ma_node_input_bus_read_pcm_frames(ma_node* pInputNode, ma_node_ ...@@ -66234,7 +66268,7 @@ static ma_result ma_node_input_bus_read_pcm_frames(ma_node* pInputNode, ma_node_
are both critical to our lock-free thread-safety system. We can only call ma_node_input_bus_first() are both critical to our lock-free thread-safety system. We can only call ma_node_input_bus_first()
once per iteration, however we have an optimization to checks whether or not it's the first item in once per iteration, however we have an optimization to checks whether or not it's the first item in
the list. We therefore need to store a pointer to the first item rather than repeatedly calling the list. We therefore need to store a pointer to the first item rather than repeatedly calling
ma_node_input_bus_first(). It's safe to keep hold of this point, so long as we don't dereference it ma_node_input_bus_first(). It's safe to keep hold of this pointer, so long as we don't dereference it
after calling ma_node_input_bus_next(), which we won't be. after calling ma_node_input_bus_next(), which we won't be.
*/ */
pFirst = ma_node_input_bus_first(pInputBus); pFirst = ma_node_input_bus_first(pInputBus);
...@@ -67106,7 +67140,6 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde ...@@ -67106,7 +67140,6 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde
frameCountIn = 0; frameCountIn = 0;
frameCountOut = frameCount; /* Just read as much as we can. The callback will return what was actually read. */ frameCountOut = frameCount; /* Just read as much as we can. The callback will return what was actually read. */
/* Don't do anything if our read counter is ahead of the node graph. That means we're */
ppFramesOut[0] = pFramesOut; ppFramesOut[0] = pFramesOut;
ma_node_process_pcm_frames_internal(pNode, NULL, &frameCountIn, ppFramesOut, &frameCountOut); ma_node_process_pcm_frames_internal(pNode, NULL, &frameCountIn, ppFramesOut, &frameCountOut);
totalFramesRead = frameCountOut; totalFramesRead = frameCountOut;
...@@ -70683,16 +70716,10 @@ MA_API void ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping) ...@@ -70683,16 +70716,10 @@ MA_API void ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping)
c89atomic_exchange_32(&pSound->isLooping, isLooping); c89atomic_exchange_32(&pSound->isLooping, isLooping);
/* /*
This is a little bit of a hack, but basically we need to set the looping flag at the data source level if we are running a data source managed by Some data sources, in particular resource managed streams, need to know about the looping state
the resource manager, and that is backed by a data stream. The reason for this is that the data stream itself needs to be aware of the looping so they can do clean loop transitions.
requirements so that it can do seamless loop transitions. The better solution for this is to add ma_data_source_set_looping() and just call this
generically.
*/ */
#ifndef MA_NO_RESOURCE_MANAGER ma_data_source_set_looping(pSound->pDataSource, isLooping);
if (pSound->pDataSource == pSound->pResourceManagerDataSource) {
ma_resource_manager_data_source_set_looping(pSound->pResourceManagerDataSource, isLooping);
}
#endif
} }
MA_API ma_bool32 ma_sound_is_looping(const ma_sound* pSound) MA_API ma_bool32 ma_sound_is_looping(const ma_sound* pSound)
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