App-MHFS
view release on metacpan or search on metacpan
share/public_html/static/music_inc/src/miniaudio.h view on Meta::CPAN
totalFramesProcessed += framesToProcessThisIteration;
}
} else {
pDevice->onData(pDevice, pFramesOut, pFramesIn, frameCount);
}
/* Volume control and clipping for playback devices. */
if (pFramesOut != NULL) {
if (masterVolumeFactor < 1) {
if (pFramesIn == NULL) { /* <-- In full-duplex situations, the volume will have been applied to the input samples before the data callback. Applying it again post-callback will incorrectly compound it. */
ma_apply_volume_factor_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels, masterVolumeFactor);
}
}
if (!pDevice->noClip && pDevice->playback.format == ma_format_f32) {
ma_clip_pcm_frames_f32((float*)pFramesOut, frameCount, pDevice->playback.channels);
}
}
}
}
/* A helper function for reading sample data from the client. */
static void ma_device__read_frames_from_client(ma_device* pDevice, ma_uint32 frameCount, void* pFramesOut)
{
MA_ASSERT(pDevice != NULL);
MA_ASSERT(frameCount > 0);
MA_ASSERT(pFramesOut != NULL);
if (pDevice->playback.converter.isPassthrough) {
ma_device__on_data(pDevice, pFramesOut, NULL, frameCount);
} else {
ma_result result;
ma_uint64 totalFramesReadOut;
ma_uint64 totalFramesReadIn;
void* pRunningFramesOut;
totalFramesReadOut = 0;
totalFramesReadIn = 0;
pRunningFramesOut = pFramesOut;
while (totalFramesReadOut < frameCount) {
ma_uint8 pIntermediaryBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In client format. */
ma_uint64 intermediaryBufferCap = sizeof(pIntermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
ma_uint64 framesToReadThisIterationIn;
ma_uint64 framesReadThisIterationIn;
ma_uint64 framesToReadThisIterationOut;
ma_uint64 framesReadThisIterationOut;
ma_uint64 requiredInputFrameCount;
framesToReadThisIterationOut = (frameCount - totalFramesReadOut);
framesToReadThisIterationIn = framesToReadThisIterationOut;
if (framesToReadThisIterationIn > intermediaryBufferCap) {
framesToReadThisIterationIn = intermediaryBufferCap;
}
requiredInputFrameCount = ma_data_converter_get_required_input_frame_count(&pDevice->playback.converter, framesToReadThisIterationOut);
if (framesToReadThisIterationIn > requiredInputFrameCount) {
framesToReadThisIterationIn = requiredInputFrameCount;
}
if (framesToReadThisIterationIn > 0) {
ma_device__on_data(pDevice, pIntermediaryBuffer, NULL, (ma_uint32)framesToReadThisIterationIn);
totalFramesReadIn += framesToReadThisIterationIn;
}
/*
At this point we have our decoded data in input format and now we need to convert to output format. Note that even if we didn't read any
input frames, we still want to try processing frames because there may some output frames generated from cached input data.
*/
framesReadThisIterationIn = framesToReadThisIterationIn;
framesReadThisIterationOut = framesToReadThisIterationOut;
result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, pIntermediaryBuffer, &framesReadThisIterationIn, pRunningFramesOut, &framesReadThisIterationOut);
if (result != MA_SUCCESS) {
break;
}
totalFramesReadOut += framesReadThisIterationOut;
pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesReadThisIterationOut * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
if (framesReadThisIterationIn == 0 && framesReadThisIterationOut == 0) {
break; /* We're done. */
}
}
}
}
/* A helper for sending sample data to the client. */
static void ma_device__send_frames_to_client(ma_device* pDevice, ma_uint32 frameCountInDeviceFormat, const void* pFramesInDeviceFormat)
{
MA_ASSERT(pDevice != NULL);
MA_ASSERT(frameCountInDeviceFormat > 0);
MA_ASSERT(pFramesInDeviceFormat != NULL);
if (pDevice->capture.converter.isPassthrough) {
ma_device__on_data(pDevice, NULL, pFramesInDeviceFormat, frameCountInDeviceFormat);
} else {
ma_result result;
ma_uint8 pFramesInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint64 framesInClientFormatCap = sizeof(pFramesInClientFormat) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
ma_uint64 totalDeviceFramesProcessed = 0;
ma_uint64 totalClientFramesProcessed = 0;
const void* pRunningFramesInDeviceFormat = pFramesInDeviceFormat;
/* We just keep going until we've exhaused all of our input frames and cannot generate any more output frames. */
for (;;) {
ma_uint64 deviceFramesProcessedThisIteration;
ma_uint64 clientFramesProcessedThisIteration;
deviceFramesProcessedThisIteration = (frameCountInDeviceFormat - totalDeviceFramesProcessed);
clientFramesProcessedThisIteration = framesInClientFormatCap;
result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningFramesInDeviceFormat, &deviceFramesProcessedThisIteration, pFramesInClientFormat, &clientFramesProcessedThisIteration);
if (result != MA_SUCCESS) {
break;
}
if (clientFramesProcessedThisIteration > 0) {
ma_device__on_data(pDevice, NULL, pFramesInClientFormat, (ma_uint32)clientFramesProcessedThisIteration); /* Safe cast. */
share/public_html/static/music_inc/src/miniaudio.h view on Meta::CPAN
if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
continue;
}
bits = caps->enc[iEncoding].bits;
bps = caps->enc[iEncoding].bps;
sig = caps->enc[iEncoding].sig;
le = caps->enc[iEncoding].le;
msb = caps->enc[iEncoding].msb;
format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
if (format == ma_format_unknown) {
continue; /* Format not supported. */
}
if (bestFormat == ma_format_unknown) {
bestFormat = format;
} else {
if (ma_get_format_priority_index(bestFormat) > ma_get_format_priority_index(format)) { /* <-- Lower = better. */
bestFormat = format;
}
}
}
}
return bestFormat;
}
static ma_uint32 ma_find_best_channels_from_sio_cap__sndio(struct ma_sio_cap* caps, ma_device_type deviceType, ma_format requiredFormat)
{
ma_uint32 maxChannels;
unsigned int iConfig;
MA_ASSERT(caps != NULL);
MA_ASSERT(requiredFormat != ma_format_unknown);
/* Just pick whatever configuration has the most channels. */
maxChannels = 0;
for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
/* The encoding should be of requiredFormat. */
unsigned int iEncoding;
for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
unsigned int iChannel;
unsigned int bits;
unsigned int bps;
unsigned int sig;
unsigned int le;
unsigned int msb;
ma_format format;
if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
continue;
}
bits = caps->enc[iEncoding].bits;
bps = caps->enc[iEncoding].bps;
sig = caps->enc[iEncoding].sig;
le = caps->enc[iEncoding].le;
msb = caps->enc[iEncoding].msb;
format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
if (format != requiredFormat) {
continue;
}
/* Getting here means the format is supported. Iterate over each channel count and grab the biggest one. */
for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
unsigned int chan = 0;
unsigned int channels;
if (deviceType == ma_device_type_playback) {
chan = caps->confs[iConfig].pchan;
} else {
chan = caps->confs[iConfig].rchan;
}
if ((chan & (1UL << iChannel)) == 0) {
continue;
}
if (deviceType == ma_device_type_playback) {
channels = caps->pchan[iChannel];
} else {
channels = caps->rchan[iChannel];
}
if (maxChannels < channels) {
maxChannels = channels;
}
}
}
}
return maxChannels;
}
static ma_uint32 ma_find_best_sample_rate_from_sio_cap__sndio(struct ma_sio_cap* caps, ma_device_type deviceType, ma_format requiredFormat, ma_uint32 requiredChannels)
{
ma_uint32 firstSampleRate;
ma_uint32 bestSampleRate;
unsigned int iConfig;
MA_ASSERT(caps != NULL);
MA_ASSERT(requiredFormat != ma_format_unknown);
MA_ASSERT(requiredChannels > 0);
MA_ASSERT(requiredChannels <= MA_MAX_CHANNELS);
firstSampleRate = 0; /* <-- If the device does not support a standard rate we'll fall back to the first one that's found. */
bestSampleRate = 0;
for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
/* The encoding should be of requiredFormat. */
unsigned int iEncoding;
for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
unsigned int iChannel;
unsigned int bits;
unsigned int bps;
unsigned int sig;
unsigned int le;
unsigned int msb;
ma_format format;
if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
continue;
}
bits = caps->enc[iEncoding].bits;
bps = caps->enc[iEncoding].bps;
sig = caps->enc[iEncoding].sig;
le = caps->enc[iEncoding].le;
msb = caps->enc[iEncoding].msb;
format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
if (format != requiredFormat) {
continue;
}
/* Getting here means the format is supported. Iterate over each channel count and grab the biggest one. */
for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
unsigned int chan = 0;
unsigned int channels;
unsigned int iRate;
if (deviceType == ma_device_type_playback) {
chan = caps->confs[iConfig].pchan;
} else {
chan = caps->confs[iConfig].rchan;
}
if ((chan & (1UL << iChannel)) == 0) {
continue;
}
if (deviceType == ma_device_type_playback) {
channels = caps->pchan[iChannel];
} else {
channels = caps->rchan[iChannel];
}
if (channels != requiredChannels) {
continue;
}
/* Getting here means we have found a compatible encoding/channel pair. */
for (iRate = 0; iRate < MA_SIO_NRATE; iRate += 1) {
ma_uint32 rate = (ma_uint32)caps->rate[iRate];
ma_uint32 ratePriority;
if (firstSampleRate == 0) {
firstSampleRate = rate;
}
/* Disregard this rate if it's not a standard one. */
ratePriority = ma_get_standard_sample_rate_priority_index__sndio(rate);
if (ratePriority == (ma_uint32)-1) {
continue;
}
if (ma_get_standard_sample_rate_priority_index__sndio(bestSampleRate) > ratePriority) { /* Lower = better. */
bestSampleRate = rate;
}
}
}
}
}
/* If a standard sample rate was not found just fall back to the first one that was iterated. */
if (bestSampleRate == 0) {
bestSampleRate = firstSampleRate;
}
return bestSampleRate;
}
static ma_bool32 ma_context_is_device_id_equal__sndio(ma_context* pContext, const ma_device_id* pID0, const ma_device_id* pID1)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pID0 != NULL);
MA_ASSERT(pID1 != NULL);
(void)pContext;
return ma_strcmp(pID0->sndio, pID1->sndio) == 0;
}
static ma_result ma_context_enumerate_devices__sndio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
{
ma_bool32 isTerminating = MA_FALSE;
struct ma_sio_hdl* handle;
MA_ASSERT(pContext != NULL);
MA_ASSERT(callback != NULL);
/* sndio doesn't seem to have a good device enumeration API, so I'm therefore only enumerating over default devices for now. */
/* Playback. */
if (!isTerminating) {
handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(MA_SIO_DEVANY, MA_SIO_PLAY, 0);
if (handle != NULL) {
/* Supports playback. */
share/public_html/static/music_inc/src/miniaudio.h view on Meta::CPAN
MA_ASSERT(pConverter->resampler.config.channels == pConverter->channelConverter.channelsIn);
MA_ASSERT(pConverter->resampler.config.channels < pConverter->channelConverter.channelsOut);
frameCountIn = 0;
if (pFrameCountIn != NULL) {
frameCountIn = *pFrameCountIn;
}
frameCountOut = 0;
if (pFrameCountOut != NULL) {
frameCountOut = *pFrameCountOut;
}
framesProcessedIn = 0;
framesProcessedOut = 0;
tempBufferInCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
tempBufferMidCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
tempBufferOutCap = sizeof(pTempBufferOut) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsOut);
while (framesProcessedOut < frameCountOut) {
ma_uint64 frameCountInThisIteration;
ma_uint64 frameCountOutThisIteration;
const void* pRunningFramesIn = NULL;
void* pRunningFramesOut = NULL;
const void* pResampleBufferIn;
void* pChannelsBufferOut;
if (pFramesIn != NULL) {
pRunningFramesIn = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
}
if (pFramesOut != NULL) {
pRunningFramesOut = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
}
/* Run input data through the resampler and output it to the temporary buffer. */
frameCountInThisIteration = (frameCountIn - framesProcessedIn);
if (pConverter->hasPreFormatConversion) {
if (frameCountInThisIteration > tempBufferInCap) {
frameCountInThisIteration = tempBufferInCap;
}
}
frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
if (frameCountOutThisIteration > tempBufferMidCap) {
frameCountOutThisIteration = tempBufferMidCap;
}
/* We can't read more frames than can fit in the output buffer. */
if (pConverter->hasPostFormatConversion) {
if (frameCountOutThisIteration > tempBufferOutCap) {
frameCountOutThisIteration = tempBufferOutCap;
}
}
/* We need to ensure we don't try to process too many input frames that we run out of room in the output buffer. If this happens we'll end up glitching. */
{
ma_uint64 requiredInputFrameCount = ma_resampler_get_required_input_frame_count(&pConverter->resampler, frameCountOutThisIteration);
if (frameCountInThisIteration > requiredInputFrameCount) {
frameCountInThisIteration = requiredInputFrameCount;
}
}
if (pConverter->hasPreFormatConversion) {
if (pFramesIn != NULL) {
ma_convert_pcm_frames_format(pTempBufferIn, pConverter->resampler.config.format, pRunningFramesIn, pConverter->config.formatIn, frameCountInThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
pResampleBufferIn = pTempBufferIn;
} else {
pResampleBufferIn = NULL;
}
} else {
pResampleBufferIn = pRunningFramesIn;
}
result = ma_resampler_process_pcm_frames(&pConverter->resampler, pResampleBufferIn, &frameCountInThisIteration, pTempBufferMid, &frameCountOutThisIteration);
if (result != MA_SUCCESS) {
return result;
}
/*
The input data has been resampled so now we need to run it through the channel converter. The input data is always contained in pTempBufferMid. We only need to do
this part if we have an output buffer.
*/
if (pFramesOut != NULL) {
if (pConverter->hasPostFormatConversion) {
pChannelsBufferOut = pTempBufferOut;
} else {
pChannelsBufferOut = pRunningFramesOut;
}
result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pChannelsBufferOut, pTempBufferMid, frameCountOutThisIteration);
if (result != MA_SUCCESS) {
return result;
}
/* Finally we do post format conversion. */
if (pConverter->hasPostFormatConversion) {
ma_convert_pcm_frames_format(pRunningFramesOut, pConverter->config.formatOut, pChannelsBufferOut, pConverter->channelConverter.format, frameCountOutThisIteration, pConverter->channelConverter.channelsOut, pConverter->config.ditherMode...
}
}
framesProcessedIn += frameCountInThisIteration;
framesProcessedOut += frameCountOutThisIteration;
MA_ASSERT(framesProcessedIn <= frameCountIn);
MA_ASSERT(framesProcessedOut <= frameCountOut);
if (frameCountOutThisIteration == 0) {
break; /* Consumed all of our input data. */
}
}
if (pFrameCountIn != NULL) {
*pFrameCountIn = framesProcessedIn;
}
if (pFrameCountOut != NULL) {
*pFrameCountOut = framesProcessedOut;
}
share/public_html/static/music_inc/src/miniaudio.h view on Meta::CPAN
while (framesProcessedOut < frameCountOut) {
ma_uint64 frameCountInThisIteration;
ma_uint64 frameCountOutThisIteration;
const void* pRunningFramesIn = NULL;
void* pRunningFramesOut = NULL;
const void* pChannelsBufferIn;
void* pResampleBufferOut;
if (pFramesIn != NULL) {
pRunningFramesIn = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
}
if (pFramesOut != NULL) {
pRunningFramesOut = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
}
/* Run input data through the channel converter and output it to the temporary buffer. */
frameCountInThisIteration = (frameCountIn - framesProcessedIn);
if (pConverter->hasPreFormatConversion) {
if (frameCountInThisIteration > tempBufferInCap) {
frameCountInThisIteration = tempBufferInCap;
}
if (pRunningFramesIn != NULL) {
ma_convert_pcm_frames_format(pTempBufferIn, pConverter->channelConverter.format, pRunningFramesIn, pConverter->config.formatIn, frameCountInThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
pChannelsBufferIn = pTempBufferIn;
} else {
pChannelsBufferIn = NULL;
}
} else {
pChannelsBufferIn = pRunningFramesIn;
}
/*
We can't convert more frames than will fit in the output buffer. We shouldn't actually need to do this check because the channel count is always reduced
in this case which means we should always have capacity, but I'm leaving it here just for safety for future maintenance.
*/
if (frameCountInThisIteration > tempBufferMidCap) {
frameCountInThisIteration = tempBufferMidCap;
}
/*
Make sure we don't read any more input frames than we need to fill the output frame count. If we do this we will end up in a situation where we lose some
input samples and will end up glitching.
*/
frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
if (frameCountOutThisIteration > tempBufferMidCap) {
frameCountOutThisIteration = tempBufferMidCap;
}
if (pConverter->hasPostFormatConversion) {
ma_uint64 requiredInputFrameCount;
if (frameCountOutThisIteration > tempBufferOutCap) {
frameCountOutThisIteration = tempBufferOutCap;
}
requiredInputFrameCount = ma_resampler_get_required_input_frame_count(&pConverter->resampler, frameCountOutThisIteration);
if (frameCountInThisIteration > requiredInputFrameCount) {
frameCountInThisIteration = requiredInputFrameCount;
}
}
result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pTempBufferMid, pChannelsBufferIn, frameCountInThisIteration);
if (result != MA_SUCCESS) {
return result;
}
/* At this point we have converted the channels to the output channel count which we now need to resample. */
if (pConverter->hasPostFormatConversion) {
pResampleBufferOut = pTempBufferOut;
} else {
pResampleBufferOut = pRunningFramesOut;
}
result = ma_resampler_process_pcm_frames(&pConverter->resampler, pTempBufferMid, &frameCountInThisIteration, pResampleBufferOut, &frameCountOutThisIteration);
if (result != MA_SUCCESS) {
return result;
}
/* Finally we can do the post format conversion. */
if (pConverter->hasPostFormatConversion) {
if (pRunningFramesOut != NULL) {
ma_convert_pcm_frames_format(pRunningFramesOut, pConverter->config.formatOut, pResampleBufferOut, pConverter->resampler.config.format, frameCountOutThisIteration, pConverter->config.channelsOut, pConverter->config.ditherMode);
}
}
framesProcessedIn += frameCountInThisIteration;
framesProcessedOut += frameCountOutThisIteration;
MA_ASSERT(framesProcessedIn <= frameCountIn);
MA_ASSERT(framesProcessedOut <= frameCountOut);
if (frameCountOutThisIteration == 0) {
break; /* Consumed all of our input data. */
}
}
if (pFrameCountIn != NULL) {
*pFrameCountIn = framesProcessedIn;
}
if (pFrameCountOut != NULL) {
*pFrameCountOut = framesProcessedOut;
}
return MA_SUCCESS;
}
MA_API ma_result ma_data_converter_process_pcm_frames(ma_data_converter* pConverter, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
{
if (pConverter == NULL) {
return MA_INVALID_ARGS;
}
if (pConverter->isPassthrough) {
return ma_data_converter_process_pcm_frames__passthrough(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
}
/*
share/public_html/static/music_inc/src/miniaudio.h view on Meta::CPAN
if (pDecoder->onGetLengthInPCMFrames) {
ma_uint64 nativeLengthInPCMFrames = pDecoder->onGetLengthInPCMFrames(pDecoder);
if (pDecoder->internalSampleRate == pDecoder->outputSampleRate) {
return nativeLengthInPCMFrames;
} else {
return ma_calculate_frame_count_after_resampling(pDecoder->outputSampleRate, pDecoder->internalSampleRate, nativeLengthInPCMFrames);
}
}
return 0;
}
MA_API ma_uint64 ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesOut, ma_uint64 frameCount)
{
ma_result result;
ma_uint64 totalFramesReadOut;
ma_uint64 totalFramesReadIn;
void* pRunningFramesOut;
if (pDecoder == NULL) {
return 0;
}
if (pDecoder->onReadPCMFrames == NULL) {
return 0;
}
/* Fast path. */
if (pDecoder->converter.isPassthrough) {
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
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) {
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. */
totalFramesReadOut = 0;
totalFramesReadIn = 0;
pRunningFramesOut = pFramesOut;
while (totalFramesReadOut < frameCount) {
ma_uint8 pIntermediaryBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In internal format. */
ma_uint64 intermediaryBufferCap = sizeof(pIntermediaryBuffer) / ma_get_bytes_per_frame(pDecoder->internalFormat, pDecoder->internalChannels);
ma_uint64 framesToReadThisIterationIn;
ma_uint64 framesReadThisIterationIn;
ma_uint64 framesToReadThisIterationOut;
ma_uint64 framesReadThisIterationOut;
ma_uint64 requiredInputFrameCount;
framesToReadThisIterationOut = (frameCount - totalFramesReadOut);
framesToReadThisIterationIn = framesToReadThisIterationOut;
if (framesToReadThisIterationIn > intermediaryBufferCap) {
framesToReadThisIterationIn = intermediaryBufferCap;
}
requiredInputFrameCount = ma_data_converter_get_required_input_frame_count(&pDecoder->converter, framesToReadThisIterationOut);
if (framesToReadThisIterationIn > requiredInputFrameCount) {
framesToReadThisIterationIn = requiredInputFrameCount;
}
if (requiredInputFrameCount > 0) {
framesReadThisIterationIn = pDecoder->onReadPCMFrames(pDecoder, pIntermediaryBuffer, framesToReadThisIterationIn);
totalFramesReadIn += framesReadThisIterationIn;
}
/*
At this point we have our decoded data in input format and now we need to convert to output format. Note that even if we didn't read any
input frames, we still want to try processing frames because there may some output frames generated from cached input data.
*/
framesReadThisIterationOut = framesToReadThisIterationOut;
result = ma_data_converter_process_pcm_frames(&pDecoder->converter, pIntermediaryBuffer, &framesReadThisIterationIn, pRunningFramesOut, &framesReadThisIterationOut);
if (result != MA_SUCCESS) {
break;
}
totalFramesReadOut += framesReadThisIterationOut;
if (pRunningFramesOut != NULL) {
pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesReadThisIterationOut * ma_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels));
}
if (framesReadThisIterationIn == 0 && framesReadThisIterationOut == 0) {
break; /* We're done. */
}
}
}
}
pDecoder->readPointerInPCMFrames += totalFramesReadOut;
return totalFramesReadOut;
}
MA_API ma_result ma_decoder_seek_to_pcm_frame(ma_decoder* pDecoder, ma_uint64 frameIndex)
{
if (pDecoder == NULL) {
return MA_INVALID_ARGS;
}
if (pDecoder->onSeekToPCMFrame) {
ma_result result;
ma_uint64 internalFrameIndex;
if (pDecoder->internalSampleRate == pDecoder->outputSampleRate) {
internalFrameIndex = frameIndex;
} else {
internalFrameIndex = ma_calculate_frame_count_after_resampling(pDecoder->internalSampleRate, pDecoder->outputSampleRate, frameIndex);
}
result = pDecoder->onSeekToPCMFrame(pDecoder, internalFrameIndex);
if (result == MA_SUCCESS) {
pDecoder->readPointerInPCMFrames = frameIndex;
}
return result;
}
/* Should never get here, but if we do it means onSeekToPCMFrame was not set by the backend. */
return MA_INVALID_ARGS;
( run in 2.722 seconds using v1.01-cache-2.11-cpan-8f98c5d2c55 )