mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
SRC/Speex: Add support for querying required input frame counts.
This commit is contained in:
@@ -6,6 +6,8 @@
|
|||||||
#define RANDOM_PREFIX ma_speex
|
#define RANDOM_PREFIX ma_speex
|
||||||
#include "thirdparty/speex_resampler.h"
|
#include "thirdparty/speex_resampler.h"
|
||||||
|
|
||||||
|
int ma_speex_resampler_get_required_input_frame_count(SpeexResamplerState* st, spx_uint32_t out_len, spx_uint32_t* in_len);
|
||||||
|
|
||||||
#endif /* ma_speex_resampler_h */
|
#endif /* ma_speex_resampler_h */
|
||||||
|
|
||||||
#if defined(MINIAUDIO_SPEEX_RESAMPLER_IMPLEMENTATION)
|
#if defined(MINIAUDIO_SPEEX_RESAMPLER_IMPLEMENTATION)
|
||||||
@@ -23,4 +25,31 @@
|
|||||||
#else
|
#else
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
EXPORT int ma_speex_resampler_get_required_input_frame_count(SpeexResamplerState* st, spx_uint32_t out_len, spx_uint32_t* in_len)
|
||||||
|
{
|
||||||
|
spx_uint32_t count;
|
||||||
|
|
||||||
|
if (st == NULL || in_len == NULL) {
|
||||||
|
return RESAMPLER_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
*in_len = 0;
|
||||||
|
|
||||||
|
if (out_len == 0) {
|
||||||
|
return RESAMPLER_ERR_SUCCESS; /* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* miniaudio only uses interleaved APIs so we can safely just use channel index 0 for the calculations. */
|
||||||
|
if (st->nb_channels == 0) {
|
||||||
|
return RESAMPLER_ERR_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = out_len * st->int_advance;
|
||||||
|
count += (st->samp_frac_num[0] + (out_len * st->frac_advance)) / st->den_rate;
|
||||||
|
|
||||||
|
*in_len = count;
|
||||||
|
|
||||||
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
+39
-6
@@ -59,6 +59,9 @@ typedef struct
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
void* pSpeexResamplerState; /* SpeexResamplerState* */
|
void* pSpeexResamplerState; /* SpeexResamplerState* */
|
||||||
|
ma_uint64 runningTimeIn;
|
||||||
|
ma_uint64 runningTimeOut;
|
||||||
|
double t; /* For tracking the input time so we can query required input and expected output frame counts. */
|
||||||
} speex;
|
} speex;
|
||||||
} state;
|
} state;
|
||||||
} ma_resampler;
|
} ma_resampler;
|
||||||
@@ -137,7 +140,7 @@ Implementation
|
|||||||
#define MA_RESAMPLER_MAX_RATIO 48.0
|
#define MA_RESAMPLER_MAX_RATIO 48.0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SPEEX_RESAMPLER_H)
|
#if defined(ma_speex_resampler_h)
|
||||||
#define MA_HAS_SPEEX_RESAMPLER
|
#define MA_HAS_SPEEX_RESAMPLER
|
||||||
|
|
||||||
static ma_result ma_result_from_speex_err(int err)
|
static ma_result ma_result_from_speex_err(int err)
|
||||||
@@ -497,36 +500,44 @@ static ma_result ma_resampler_process__read__linear(ma_resampler* pResampler, co
|
|||||||
#if defined(MA_HAS_SPEEX_RESAMPLER)
|
#if defined(MA_HAS_SPEEX_RESAMPLER)
|
||||||
static ma_result ma_resampler_process__read__speex(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
|
static ma_result ma_resampler_process__read__speex(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
|
||||||
{
|
{
|
||||||
/* To do this we just read using the non-filtered linear pipeline, and then do an in-place filter on the output buffer. */
|
|
||||||
int speexErr;
|
int speexErr;
|
||||||
ma_uint64 frameCountOut;
|
ma_uint64 frameCountOut;
|
||||||
ma_uint64 frameCountIn;
|
ma_uint64 frameCountIn;
|
||||||
ma_uint64 framesProcessedOut;
|
ma_uint64 framesProcessedOut;
|
||||||
ma_uint64 framesProcessedIn;
|
ma_uint64 framesProcessedIn;
|
||||||
|
unsigned int framesPerIteration = 32768;
|
||||||
|
double ratioInOut;
|
||||||
|
|
||||||
MA_ASSERT(pResampler != NULL);
|
MA_ASSERT(pResampler != NULL);
|
||||||
MA_ASSERT(pFramesOut != NULL);
|
MA_ASSERT(pFramesOut != NULL);
|
||||||
MA_ASSERT(pFrameCountOut != NULL);
|
MA_ASSERT(pFrameCountOut != NULL);
|
||||||
MA_ASSERT(pFrameCountIn != NULL);
|
MA_ASSERT(pFrameCountIn != NULL);
|
||||||
|
|
||||||
/* Speex uses unsigned int counts, whereas miniaudio uses 64-bit. We'll need to process in a loop. */
|
/*
|
||||||
|
Reading from the Speex resampler requires a bit of dancing around for a few reasons. The first thing is that it's frame counts
|
||||||
|
are in unsigned int's whereas ours is in ma_uint64. We therefore need to run the conversion in a loop. The other, more complicated
|
||||||
|
problem, is that we need to keep track of the input time, similar to what we do with the linear resampler. The reason we need to
|
||||||
|
do this is for ma_resampler_get_required_input_frame_count() and ma_resampler_get_expected_output_frame_count().
|
||||||
|
*/
|
||||||
frameCountOut = *pFrameCountOut;
|
frameCountOut = *pFrameCountOut;
|
||||||
frameCountIn = *pFrameCountIn;
|
frameCountIn = *pFrameCountIn;
|
||||||
framesProcessedOut = 0;
|
framesProcessedOut = 0;
|
||||||
framesProcessedIn = 0;
|
framesProcessedIn = 0;
|
||||||
|
|
||||||
|
ratioInOut = (double)pResampler->config.sampleRateIn / (double)pResampler->config.sampleRateOut;
|
||||||
|
|
||||||
while (framesProcessedOut < frameCountOut && framesProcessedIn < frameCountIn) {
|
while (framesProcessedOut < frameCountOut && framesProcessedIn < frameCountIn) {
|
||||||
unsigned int frameCountInThisIteration;
|
unsigned int frameCountInThisIteration;
|
||||||
unsigned int frameCountOutThisIteration;
|
unsigned int frameCountOutThisIteration;
|
||||||
const void* pFramesInThisIteration;
|
const void* pFramesInThisIteration;
|
||||||
void* pFramesOutThisIteration;
|
void* pFramesOutThisIteration;
|
||||||
|
|
||||||
frameCountInThisIteration = UINT_MAX;
|
frameCountInThisIteration = framesPerIteration;
|
||||||
if ((ma_uint64)frameCountInThisIteration > (frameCountIn - framesProcessedIn)) {
|
if ((ma_uint64)frameCountInThisIteration > (frameCountIn - framesProcessedIn)) {
|
||||||
frameCountInThisIteration = (unsigned int)(frameCountIn - framesProcessedIn);
|
frameCountInThisIteration = (unsigned int)(frameCountIn - framesProcessedIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
frameCountOutThisIteration = UINT_MAX;
|
frameCountOutThisIteration = framesPerIteration;
|
||||||
if ((ma_uint64)frameCountOutThisIteration > (frameCountOut - framesProcessedOut)) {
|
if ((ma_uint64)frameCountOutThisIteration > (frameCountOut - framesProcessedOut)) {
|
||||||
frameCountOutThisIteration = (unsigned int)(frameCountOut - framesProcessedOut);
|
frameCountOutThisIteration = (unsigned int)(frameCountOut - framesProcessedOut);
|
||||||
}
|
}
|
||||||
@@ -550,8 +561,14 @@ static ma_result ma_resampler_process__read__speex(ma_resampler* pResampler, con
|
|||||||
|
|
||||||
framesProcessedIn += frameCountInThisIteration;
|
framesProcessedIn += frameCountInThisIteration;
|
||||||
framesProcessedOut += frameCountOutThisIteration;
|
framesProcessedOut += frameCountOutThisIteration;
|
||||||
|
|
||||||
|
pResampler->state.speex.t += frameCountOutThisIteration * ratioInOut;
|
||||||
|
//pResampler->state.speex.t = pResampler->state.speex.t - floor(pResampler->state.speex.t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pResampler->state.speex.runningTimeOut += framesProcessedOut;
|
||||||
|
pResampler->state.speex.runningTimeIn += framesProcessedIn;
|
||||||
|
|
||||||
*pFrameCountOut = framesProcessedOut;
|
*pFrameCountOut = framesProcessedOut;
|
||||||
*pFrameCountIn = framesProcessedIn;
|
*pFrameCountIn = framesProcessedIn;
|
||||||
|
|
||||||
@@ -726,7 +743,22 @@ ma_uint64 ma_resampler_get_required_input_frame_count(ma_resampler* pResampler,
|
|||||||
case ma_resample_algorithm_speex:
|
case ma_resample_algorithm_speex:
|
||||||
{
|
{
|
||||||
#if defined(MA_HAS_SPEEX_RESAMPLER)
|
#if defined(MA_HAS_SPEEX_RESAMPLER)
|
||||||
return 0;
|
#if 0
|
||||||
|
ma_uint64 count;
|
||||||
|
double t = pResampler->state.speex.t;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
count = (ma_uint64)floor(t + (outputFrameCount * ratioInOut) + 0.00000001);
|
||||||
|
#else
|
||||||
|
count = (ma_uint64)(floor(t + (outputFrameCount * ratioInOut)) - floor(t));
|
||||||
|
#endif
|
||||||
|
return count;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ma_uint32 count;
|
||||||
|
ma_speex_resampler_get_required_input_frame_count((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, (unsigned int)outputFrameCount, &count);
|
||||||
|
|
||||||
|
return count;
|
||||||
#else
|
#else
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -774,6 +806,7 @@ ma_uint64 ma_resampler_get_expected_output_frame_count(ma_resampler* pResampler,
|
|||||||
{
|
{
|
||||||
#if defined(MA_HAS_SPEEX_RESAMPLER)
|
#if defined(MA_HAS_SPEEX_RESAMPLER)
|
||||||
/* TODO: Implement me. */
|
/* TODO: Implement me. */
|
||||||
|
return 0;
|
||||||
#else
|
#else
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user