Commit 6d9379f6 authored by David Reid's avatar David Reid

Try getting sample exact seeking working with stb_vorbis.

parent a8682c36
......@@ -62675,34 +62675,10 @@ static ma_result ma_stbvorbis_post_init(ma_stbvorbis* pVorbis)
return MA_SUCCESS;
}
#endif
MA_API ma_result ma_stbvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_stbvorbis* pVorbis)
static ma_result ma_stbvorbis_init_internal_decoder_push(ma_stbvorbis* pVorbis)
{
ma_result result;
result = ma_stbvorbis_init_internal(pConfig, pVorbis);
if (result != MA_SUCCESS) {
return result;
}
if (onRead == NULL || onSeek == NULL) {
return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
}
pVorbis->onRead = onRead;
pVorbis->onSeek = onSeek;
pVorbis->onTell = onTell;
pVorbis->pReadSeekTellUserData = pReadSeekTellUserData;
ma_allocation_callbacks_init_copy(&pVorbis->allocationCallbacks, pAllocationCallbacks);
#if !defined(MA_NO_VORBIS)
{
/*
stb_vorbis lacks a callback based API for it's pulling API which means we're stuck with the
pushing API. In order for us to be able to successfully initialize the decoder we need to
supply it with enough data. We need to keep loading data until we have enough.
*/
stb_vorbis* stb;
size_t dataSize = 0;
size_t dataCapacity = 0;
......@@ -62716,9 +62692,9 @@ MA_API ma_result ma_stbvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_
/* Allocate memory for the new chunk. */
dataCapacity += MA_VORBIS_DATA_CHUNK_SIZE;
pNewData = (ma_uint8*)ma_realloc(pData, dataCapacity, pAllocationCallbacks);
pNewData = (ma_uint8*)ma_realloc(pData, dataCapacity, &pVorbis->allocationCallbacks);
if (pNewData == NULL) {
ma_free(pData, pAllocationCallbacks);
ma_free(pData, &pVorbis->allocationCallbacks);
return MA_OUT_OF_MEMORY;
}
......@@ -62729,13 +62705,13 @@ MA_API ma_result ma_stbvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_
dataSize += bytesRead;
if (result != MA_SUCCESS) {
ma_free(pData, pAllocationCallbacks);
ma_free(pData, &pVorbis->allocationCallbacks);
return result;
}
/* We have a maximum of 31 bits with stb_vorbis. */
if (dataSize > INT_MAX) {
ma_free(pData, pAllocationCallbacks);
ma_free(pData, &pVorbis->allocationCallbacks);
return MA_TOO_BIG;
}
......@@ -62760,7 +62736,7 @@ MA_API ma_result ma_stbvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_
if (vorbisError == VORBIS_need_more_data) {
continue;
} else {
ma_free(pData, pAllocationCallbacks);
ma_free(pData, &pVorbis->allocationCallbacks);
return MA_ERROR; /* Failed to open the stb_vorbis decoder. */
}
}
......@@ -62772,12 +62748,47 @@ MA_API ma_result ma_stbvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_
pVorbis->push.dataSize = dataSize;
pVorbis->push.dataCapacity = dataCapacity;
return MA_SUCCESS;
}
#endif
MA_API ma_result ma_stbvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_stbvorbis* pVorbis)
{
ma_result result;
result = ma_stbvorbis_init_internal(pConfig, pVorbis);
if (result != MA_SUCCESS) {
return result;
}
if (onRead == NULL || onSeek == NULL) {
return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
}
pVorbis->onRead = onRead;
pVorbis->onSeek = onSeek;
pVorbis->onTell = onTell;
pVorbis->pReadSeekTellUserData = pReadSeekTellUserData;
ma_allocation_callbacks_init_copy(&pVorbis->allocationCallbacks, pAllocationCallbacks);
#if !defined(MA_NO_VORBIS)
{
/*
stb_vorbis lacks a callback based API for it's pulling API which means we're stuck with the
pushing API. In order for us to be able to successfully initialize the decoder we need to
supply it with enough data. We need to keep loading data until we have enough.
*/
result = ma_stbvorbis_init_internal_decoder_push(pVorbis);
if (result != MA_SUCCESS) {
return result;
}
pVorbis->usingPushMode = MA_TRUE;
result = ma_stbvorbis_post_init(pVorbis);
if (result != MA_SUCCESS) {
stb_vorbis_close(pVorbis->stb);
ma_free(pData, pAllocationCallbacks);
ma_free(pVorbis->push.pData, pAllocationCallbacks);
return result;
}
......@@ -63079,28 +63090,39 @@ MA_API ma_result ma_stbvorbis_seek_to_pcm_frame(ma_stbvorbis* pVorbis, ma_uint64
ma_result result;
float buffer[4096];
/*
This is terribly inefficient because stb_vorbis does not have a good seeking solution with it's push API. Currently this just performs
a full decode right from the start of the stream. Later on I'll need to write a layer that goes through all of the Ogg pages until we
find the one containing the sample we need. Then we know exactly where to seek for stb_vorbis.
/* If we're seeking backwards, we need to seek back to the start and then brute-force forward. */
if (frameIndex < pVorbis->cursor) {
if (frameIndex > 0x7FFFFFFF) {
return MA_INVALID_ARGS; /* Trying to seek beyond the 32-bit maximum of stb_vorbis. */
}
TODO: Use seeking logic documented for stb_vorbis_flush_pushdata().
/*
This is wildly inefficient due to me having trouble getting sample exact seeking working
robustly with stb_vorbis_flush_pushdata(). The only way I can think to make this work
perfectly is to reinitialize the decoder. Note that we only enter this path when seeking
backwards. This will hopefully be removed once we get our own Vorbis decoder implemented.
*/
stb_vorbis_close(pVorbis->stb);
ma_free(pVorbis->push.pData, &pVorbis->allocationCallbacks);
/* Seek to the start of the audio data in the file to begin with. */
result = pVorbis->onSeek(pVorbis->pReadSeekTellUserData, pVorbis->push.audioStartOffsetInBytes, ma_seek_origin_start);
MA_ZERO_OBJECT(&pVorbis->push);
/* Seek to the start of the file. */
result = pVorbis->onSeek(pVorbis->pReadSeekTellUserData, 0, ma_seek_origin_start);
if (result != MA_SUCCESS) {
return result;
}
stb_vorbis_flush_pushdata(pVorbis->stb);
pVorbis->push.framesConsumed = 0;
pVorbis->push.framesRemaining = 0;
pVorbis->push.dataSize = 0;
result = ma_stbvorbis_init_internal_decoder_push(pVorbis);
if (result != MA_SUCCESS) {
return result;
}
/* Move the cursor back to the start. We'll increment this in the loop below. */
/* At this point we should be sitting on the first frame. */
pVorbis->cursor = 0;
}
/* We're just brute-forcing this for now. */
while (pVorbis->cursor < frameIndex) {
ma_uint64 framesRead;
ma_uint64 framesToRead = ma_countof(buffer)/pVorbis->channels;
......@@ -68467,7 +68489,7 @@ static ma_data_source_vtable g_ma_resource_manager_data_stream_vtable =
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__set_looping,
MA_DATA_SOURCE_SELF_MANAGED_RANGE_AND_LOOP_POINT
0 /*MA_DATA_SOURCE_SELF_MANAGED_RANGE_AND_LOOP_POINT*/
};
static void ma_resource_manager_data_stream_set_absolute_cursor(ma_resource_manager_data_stream* pDataStream, ma_uint64 absoluteCursor)
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