mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
Add some APIs for ma_audio_buffer and ma_decoder.
* ma_audio_buffer_get_available_frames() * ma_decoder_get_available_frames()
This commit is contained in:
+81
-12
@@ -5288,7 +5288,7 @@ MA_API ma_result ma_audio_buffer_seek_to_pcm_frame(ma_audio_buffer* pAudioBuffer
|
|||||||
MA_API ma_result ma_audio_buffer_map(ma_audio_buffer* pAudioBuffer, void** ppFramesOut, ma_uint64* pFrameCount);
|
MA_API ma_result ma_audio_buffer_map(ma_audio_buffer* pAudioBuffer, void** ppFramesOut, ma_uint64* pFrameCount);
|
||||||
MA_API ma_result ma_audio_buffer_unmap(ma_audio_buffer* pAudioBuffer, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
|
MA_API ma_result ma_audio_buffer_unmap(ma_audio_buffer* pAudioBuffer, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
|
||||||
MA_API ma_result ma_audio_buffer_at_end(ma_audio_buffer* pAudioBuffer);
|
MA_API ma_result ma_audio_buffer_at_end(ma_audio_buffer* pAudioBuffer);
|
||||||
|
MA_API ma_result ma_audio_buffer_get_available_frames(ma_audio_buffer* pAudioBuffer, ma_uint64* pAvailableFrames);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -5407,7 +5407,8 @@ struct ma_decoder
|
|||||||
ma_decoder_read_proc onRead;
|
ma_decoder_read_proc onRead;
|
||||||
ma_decoder_seek_proc onSeek;
|
ma_decoder_seek_proc onSeek;
|
||||||
void* pUserData;
|
void* pUserData;
|
||||||
ma_uint64 readPointer; /* Used for returning back to a previous position after analysing the stream or whatnot. */
|
ma_uint64 readPointerInBytes; /* In internal encoded data. */
|
||||||
|
ma_uint64 readPointerInPCMFrames; /* In output sample rate. Used for keeping track of how many frames are available for decoding. */
|
||||||
ma_format internalFormat;
|
ma_format internalFormat;
|
||||||
ma_uint32 internalChannels;
|
ma_uint32 internalChannels;
|
||||||
ma_uint32 internalSampleRate;
|
ma_uint32 internalSampleRate;
|
||||||
@@ -5511,6 +5512,17 @@ This is not thread safe without your own synchronization.
|
|||||||
*/
|
*/
|
||||||
MA_API ma_result ma_decoder_seek_to_pcm_frame(ma_decoder* pDecoder, ma_uint64 frameIndex);
|
MA_API ma_result ma_decoder_seek_to_pcm_frame(ma_decoder* pDecoder, ma_uint64 frameIndex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Retrieves the number of frames that can be read before reaching the end.
|
||||||
|
|
||||||
|
This calls `ma_decoder_get_length_in_pcm_frames()` so you need to be aware of the rules for that function, in
|
||||||
|
particular ensuring you do not call it on streams of an undefined length, such as internet radio.
|
||||||
|
|
||||||
|
If the total length of the decoder cannot be retrieved, such as with Vorbis decoders, `MA_NOT_IMPLEMENTED` will be
|
||||||
|
returned.
|
||||||
|
*/
|
||||||
|
MA_API ma_result ma_decoder_get_available_frames(ma_decoder* pDecoder, ma_uint64* pAvailableFrames);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Helper for opening and decoding a file into a heap allocated block of memory. Free the returned pointer with ma_free(). On input,
|
Helper for opening and decoding a file into a heap allocated block of memory. Free the returned pointer with ma_free(). On input,
|
||||||
pConfig should be set to what you want. On output it will be set to what you got.
|
pConfig should be set to what you want. On output it will be set to what you got.
|
||||||
@@ -41616,6 +41628,27 @@ MA_API ma_result ma_audio_buffer_at_end(ma_audio_buffer* pAudioBuffer)
|
|||||||
return pAudioBuffer->cursor == pAudioBuffer->sizeInFrames;
|
return pAudioBuffer->cursor == pAudioBuffer->sizeInFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_audio_buffer_get_available_frames(ma_audio_buffer* pAudioBuffer, ma_uint64* pAvailableFrames)
|
||||||
|
{
|
||||||
|
if (pAvailableFrames == NULL) {
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pAvailableFrames = 0;
|
||||||
|
|
||||||
|
if (pAudioBuffer == NULL) {
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pAudioBuffer->sizeInFrames <= pAudioBuffer->cursor) {
|
||||||
|
*pAvailableFrames = 0;
|
||||||
|
} else {
|
||||||
|
*pAvailableFrames = pAudioBuffer->sizeInFrames - pAudioBuffer->cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************************************************************************************************
|
/**************************************************************************************************************************************************************
|
||||||
@@ -43427,7 +43460,7 @@ static size_t ma_decoder_read_bytes(ma_decoder* pDecoder, void* pBufferOut, size
|
|||||||
MA_ASSERT(pBufferOut != NULL);
|
MA_ASSERT(pBufferOut != NULL);
|
||||||
|
|
||||||
bytesRead = pDecoder->onRead(pDecoder, pBufferOut, bytesToRead);
|
bytesRead = pDecoder->onRead(pDecoder, pBufferOut, bytesToRead);
|
||||||
pDecoder->readPointer += bytesRead;
|
pDecoder->readPointerInBytes += bytesRead;
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
@@ -43441,9 +43474,9 @@ static ma_bool32 ma_decoder_seek_bytes(ma_decoder* pDecoder, int byteOffset, ma_
|
|||||||
wasSuccessful = pDecoder->onSeek(pDecoder, byteOffset, origin);
|
wasSuccessful = pDecoder->onSeek(pDecoder, byteOffset, origin);
|
||||||
if (wasSuccessful) {
|
if (wasSuccessful) {
|
||||||
if (origin == ma_seek_origin_start) {
|
if (origin == ma_seek_origin_start) {
|
||||||
pDecoder->readPointer = (ma_uint64)byteOffset;
|
pDecoder->readPointerInBytes = (ma_uint64)byteOffset;
|
||||||
} else {
|
} else {
|
||||||
pDecoder->readPointer += byteOffset;
|
pDecoder->readPointerInBytes += byteOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45609,17 +45642,15 @@ MA_API ma_uint64 ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO
|
|||||||
|
|
||||||
/* Fast path. */
|
/* Fast path. */
|
||||||
if (pDecoder->converter.isPassthrough) {
|
if (pDecoder->converter.isPassthrough) {
|
||||||
return pDecoder->onReadPCMFrames(pDecoder, pFramesOut, frameCount);
|
totalFramesReadOut = pDecoder->onReadPCMFrames(pDecoder, pFramesOut, frameCount);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Getting here means we need to do data conversion. If we're seeking forward and are _not_ doing resampling we can run this in a fast path. If we're doing resampling we
|
Getting here means we need to do data conversion. If we're seeking forward and are _not_ doing resampling we can run this in a fast path. If we're doing resampling we
|
||||||
need to run through each sample because we need to ensure it's internal cache is updated.
|
need to run through each sample because we need to ensure it's internal cache is updated.
|
||||||
*/
|
*/
|
||||||
if (pFramesOut == NULL && pDecoder->converter.hasResampler == MA_FALSE) {
|
if (pFramesOut == NULL && pDecoder->converter.hasResampler == MA_FALSE) {
|
||||||
return pDecoder->onReadPCMFrames(pDecoder, NULL, frameCount); /* All decoder backends must support passing in NULL for the output buffer. */
|
totalFramesReadOut = pDecoder->onReadPCMFrames(pDecoder, NULL, frameCount); /* All decoder backends must support passing in NULL for the output buffer. */
|
||||||
}
|
} else {
|
||||||
|
|
||||||
/* Slow path. Need to run everything through the data converter. */
|
/* Slow path. Need to run everything through the data converter. */
|
||||||
totalFramesReadOut = 0;
|
totalFramesReadOut = 0;
|
||||||
totalFramesReadIn = 0;
|
totalFramesReadIn = 0;
|
||||||
@@ -45670,6 +45701,10 @@ MA_API ma_uint64 ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO
|
|||||||
break; /* We're done. */
|
break; /* We're done. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pDecoder->readPointerInPCMFrames += totalFramesReadOut;
|
||||||
|
|
||||||
return totalFramesReadOut;
|
return totalFramesReadOut;
|
||||||
}
|
}
|
||||||
@@ -45681,6 +45716,7 @@ MA_API ma_result ma_decoder_seek_to_pcm_frame(ma_decoder* pDecoder, ma_uint64 fr
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pDecoder->onSeekToPCMFrame) {
|
if (pDecoder->onSeekToPCMFrame) {
|
||||||
|
ma_result result;
|
||||||
ma_uint64 internalFrameIndex;
|
ma_uint64 internalFrameIndex;
|
||||||
if (pDecoder->internalSampleRate == pDecoder->outputSampleRate) {
|
if (pDecoder->internalSampleRate == pDecoder->outputSampleRate) {
|
||||||
internalFrameIndex = frameIndex;
|
internalFrameIndex = frameIndex;
|
||||||
@@ -45688,13 +45724,44 @@ MA_API ma_result ma_decoder_seek_to_pcm_frame(ma_decoder* pDecoder, ma_uint64 fr
|
|||||||
internalFrameIndex = ma_calculate_frame_count_after_resampling(pDecoder->internalSampleRate, pDecoder->outputSampleRate, frameIndex);
|
internalFrameIndex = ma_calculate_frame_count_after_resampling(pDecoder->internalSampleRate, pDecoder->outputSampleRate, frameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pDecoder->onSeekToPCMFrame(pDecoder, internalFrameIndex);
|
result = pDecoder->onSeekToPCMFrame(pDecoder, internalFrameIndex);
|
||||||
|
if (result == MA_SUCCESS) {
|
||||||
|
pDecoder->readPointerInPCMFrames = frameIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should never get here, but if we do it means onSeekToPCMFrame was not set by the backend. */
|
/* Should never get here, but if we do it means onSeekToPCMFrame was not set by the backend. */
|
||||||
return MA_INVALID_ARGS;
|
return MA_INVALID_ARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_decoder_get_available_frames(ma_decoder* pDecoder, ma_uint64* pAvailableFrames)
|
||||||
|
{
|
||||||
|
ma_uint64 totalFrameCount;
|
||||||
|
|
||||||
|
if (pAvailableFrames == NULL) {
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pAvailableFrames = 0;
|
||||||
|
|
||||||
|
if (pDecoder == NULL) {
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
totalFrameCount = ma_decoder_get_length_in_pcm_frames(pDecoder);
|
||||||
|
if (totalFrameCount == 0) {
|
||||||
|
return MA_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalFrameCount <= pDecoder->readPointerInPCMFrames) {
|
||||||
|
*pAvailableFrames = 0;
|
||||||
|
} else {
|
||||||
|
*pAvailableFrames = totalFrameCount - pDecoder->readPointerInPCMFrames;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MA_SUCCESS; /* No frames available. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ma_result ma_decoder__full_decode_and_uninit(ma_decoder* pDecoder, ma_decoder_config* pConfigOut, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
|
static ma_result ma_decoder__full_decode_and_uninit(ma_decoder* pDecoder, ma_decoder_config* pConfigOut, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
|
||||||
{
|
{
|
||||||
@@ -62292,6 +62359,8 @@ v0.10.16 - TBD
|
|||||||
- Fix a bug in ma_data_source_read_pcm_frames() where looping doesn't work.
|
- 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 on Windows when both DirectSound and WinMM are disabled.
|
||||||
- Fix some compilation warnings when no decoders are enabled.
|
- Fix some compilation warnings when no decoders are enabled.
|
||||||
|
- Add ma_audio_buffer_get_available_frames()
|
||||||
|
- Add ma_decoder_get_available_frames()
|
||||||
- Updates to documentation.
|
- Updates to documentation.
|
||||||
|
|
||||||
v0.10.15 - 2020-07-15
|
v0.10.15 - 2020-07-15
|
||||||
|
|||||||
Reference in New Issue
Block a user