mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Update the linear resampler in preparation for some optimizing.
This commit is contained in:
+66
-56
@@ -5588,7 +5588,12 @@ MA_API ma_linear_resampler_config ma_linear_resampler_config_init(ma_format form
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_linear_resampler_config config;
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRateIn;
|
||||
ma_uint32 sampleRateOut;
|
||||
ma_uint32 lpfOrder;
|
||||
double lpfNyquistFactor;
|
||||
ma_uint32 inAdvanceInt;
|
||||
ma_uint32 inAdvanceFrac;
|
||||
ma_uint32 inTimeInt;
|
||||
@@ -58939,25 +58944,25 @@ static ma_result ma_linear_resampler_set_rate_internal(ma_linear_resampler* pRes
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
oldSampleRateOut = pResampler->config.sampleRateOut;
|
||||
oldSampleRateOut = pResampler->sampleRateOut;
|
||||
|
||||
pResampler->config.sampleRateIn = sampleRateIn;
|
||||
pResampler->config.sampleRateOut = sampleRateOut;
|
||||
pResampler->sampleRateIn = sampleRateIn;
|
||||
pResampler->sampleRateOut = sampleRateOut;
|
||||
|
||||
/* Simplify the sample rate. */
|
||||
gcf = ma_gcf_u32(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut);
|
||||
pResampler->config.sampleRateIn /= gcf;
|
||||
pResampler->config.sampleRateOut /= gcf;
|
||||
gcf = ma_gcf_u32(pResampler->sampleRateIn, pResampler->sampleRateOut);
|
||||
pResampler->sampleRateIn /= gcf;
|
||||
pResampler->sampleRateOut /= gcf;
|
||||
|
||||
/* Always initialize the low-pass filter, even when the order is 0. */
|
||||
if (pResampler->config.lpfOrder > MA_MAX_FILTER_ORDER) {
|
||||
if (pResampler->lpfOrder > MA_MAX_FILTER_ORDER) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
lpfSampleRate = (ma_uint32)(ma_max(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut));
|
||||
lpfCutoffFrequency = ( double)(ma_min(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut) * 0.5 * pResampler->config.lpfNyquistFactor);
|
||||
lpfSampleRate = (ma_uint32)(ma_max(pResampler->sampleRateIn, pResampler->sampleRateOut));
|
||||
lpfCutoffFrequency = ( double)(ma_min(pResampler->sampleRateIn, pResampler->sampleRateOut) * 0.5 * pResampler->lpfNyquistFactor);
|
||||
|
||||
lpfConfig = ma_lpf_config_init(pResampler->config.format, pResampler->config.channels, lpfSampleRate, lpfCutoffFrequency, pResampler->config.lpfOrder);
|
||||
lpfConfig = ma_lpf_config_init(pResampler->format, pResampler->channels, lpfSampleRate, lpfCutoffFrequency, pResampler->lpfOrder);
|
||||
|
||||
/*
|
||||
If the resampler is already initialized we don't want to do a fresh initialization of the low-pass filter because it will result in the cached frames
|
||||
@@ -58974,11 +58979,11 @@ static ma_result ma_linear_resampler_set_rate_internal(ma_linear_resampler* pRes
|
||||
}
|
||||
|
||||
|
||||
pResampler->inAdvanceInt = pResampler->config.sampleRateIn / pResampler->config.sampleRateOut;
|
||||
pResampler->inAdvanceFrac = pResampler->config.sampleRateIn % pResampler->config.sampleRateOut;
|
||||
pResampler->inAdvanceInt = pResampler->sampleRateIn / pResampler->sampleRateOut;
|
||||
pResampler->inAdvanceFrac = pResampler->sampleRateIn % pResampler->sampleRateOut;
|
||||
|
||||
/* Our timer was based on the old rate. We need to adjust it so that it's based on the new rate. */
|
||||
ma_linear_resampler_adjust_timer_for_new_rate(pResampler, oldSampleRateOut, pResampler->config.sampleRateOut);
|
||||
ma_linear_resampler_adjust_timer_for_new_rate(pResampler, oldSampleRateOut, pResampler->sampleRateOut);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
@@ -59077,7 +59082,12 @@ MA_API ma_result ma_linear_resampler_init_preallocated(const ma_linear_resampler
|
||||
return result;
|
||||
}
|
||||
|
||||
pResampler->config = *pConfig;
|
||||
pResampler->format = pConfig->format;
|
||||
pResampler->channels = pConfig->channels;
|
||||
pResampler->sampleRateIn = pConfig->sampleRateIn;
|
||||
pResampler->sampleRateOut = pConfig->sampleRateOut;
|
||||
pResampler->lpfOrder = pConfig->lpfOrder;
|
||||
pResampler->lpfNyquistFactor = pConfig->lpfNyquistFactor;
|
||||
|
||||
pResampler->_pHeap = pHeap;
|
||||
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
|
||||
@@ -59164,13 +59174,13 @@ static void ma_linear_resampler_interpolate_frame_s16(ma_linear_resampler* pResa
|
||||
{
|
||||
ma_uint32 c;
|
||||
ma_uint32 a;
|
||||
const ma_uint32 channels = pResampler->config.channels;
|
||||
const ma_uint32 channels = pResampler->channels;
|
||||
const ma_uint32 shift = 12;
|
||||
|
||||
MA_ASSERT(pResampler != NULL);
|
||||
MA_ASSERT(pFrameOut != NULL);
|
||||
|
||||
a = (pResampler->inTimeFrac << shift) / pResampler->config.sampleRateOut;
|
||||
a = (pResampler->inTimeFrac << shift) / pResampler->sampleRateOut;
|
||||
|
||||
MA_ASSUME(channels > 0);
|
||||
for (c = 0; c < channels; c += 1) {
|
||||
@@ -59184,7 +59194,7 @@ static void ma_linear_resampler_interpolate_frame_f32(ma_linear_resampler* pResa
|
||||
{
|
||||
ma_uint32 c;
|
||||
float a;
|
||||
const ma_uint32 channels = pResampler->config.channels;
|
||||
const ma_uint32 channels = pResampler->channels;
|
||||
|
||||
MA_ASSERT(pResampler != NULL);
|
||||
MA_ASSERT(pFrameOut != NULL);
|
||||
@@ -59224,20 +59234,20 @@ static ma_result ma_linear_resampler_process_pcm_frames_s16_downsample(ma_linear
|
||||
ma_uint32 iChannel;
|
||||
|
||||
if (pFramesInS16 != NULL) {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
|
||||
pResampler->x1.s16[iChannel] = pFramesInS16[iChannel];
|
||||
}
|
||||
pFramesInS16 += pResampler->config.channels;
|
||||
pFramesInS16 += pResampler->channels;
|
||||
} else {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
|
||||
pResampler->x1.s16[iChannel] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Filter. Do not apply filtering if sample rates are the same or else you'll get dangerous glitching. */
|
||||
if (pResampler->config.sampleRateIn != pResampler->config.sampleRateOut) {
|
||||
if (pResampler->inAdvanceInt == 1 && pResampler->inAdvanceFrac == 0) {
|
||||
ma_lpf_process_pcm_frame_s16(&pResampler->lpf, pResampler->x1.s16, pResampler->x1.s16);
|
||||
}
|
||||
|
||||
@@ -59254,7 +59264,7 @@ static ma_result ma_linear_resampler_process_pcm_frames_s16_downsample(ma_linear
|
||||
MA_ASSERT(pResampler->inTimeInt == 0);
|
||||
ma_linear_resampler_interpolate_frame_s16(pResampler, pFramesOutS16);
|
||||
|
||||
pFramesOutS16 += pResampler->config.channels;
|
||||
pFramesOutS16 += pResampler->channels;
|
||||
}
|
||||
|
||||
framesProcessedOut += 1;
|
||||
@@ -59262,8 +59272,8 @@ static ma_result ma_linear_resampler_process_pcm_frames_s16_downsample(ma_linear
|
||||
/* Advance time forward. */
|
||||
pResampler->inTimeInt += pResampler->inAdvanceInt;
|
||||
pResampler->inTimeFrac += pResampler->inAdvanceFrac;
|
||||
if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
|
||||
pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
|
||||
if (pResampler->inTimeFrac >= pResampler->sampleRateOut) {
|
||||
pResampler->inTimeFrac -= pResampler->sampleRateOut;
|
||||
pResampler->inTimeInt += 1;
|
||||
}
|
||||
}
|
||||
@@ -59300,13 +59310,13 @@ static ma_result ma_linear_resampler_process_pcm_frames_s16_upsample(ma_linear_r
|
||||
ma_uint32 iChannel;
|
||||
|
||||
if (pFramesInS16 != NULL) {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
|
||||
pResampler->x1.s16[iChannel] = pFramesInS16[iChannel];
|
||||
}
|
||||
pFramesInS16 += pResampler->config.channels;
|
||||
pFramesInS16 += pResampler->channels;
|
||||
} else {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
|
||||
pResampler->x1.s16[iChannel] = 0;
|
||||
}
|
||||
@@ -59326,11 +59336,11 @@ static ma_result ma_linear_resampler_process_pcm_frames_s16_upsample(ma_linear_r
|
||||
ma_linear_resampler_interpolate_frame_s16(pResampler, pFramesOutS16);
|
||||
|
||||
/* Filter. Do not apply filtering if sample rates are the same or else you'll get dangerous glitching. */
|
||||
if (pResampler->config.sampleRateIn != pResampler->config.sampleRateOut) {
|
||||
if (pResampler->inAdvanceInt == 1 && pResampler->inAdvanceFrac == 0) {
|
||||
ma_lpf_process_pcm_frame_s16(&pResampler->lpf, pFramesOutS16, pFramesOutS16);
|
||||
}
|
||||
|
||||
pFramesOutS16 += pResampler->config.channels;
|
||||
pFramesOutS16 += pResampler->channels;
|
||||
}
|
||||
|
||||
framesProcessedOut += 1;
|
||||
@@ -59338,8 +59348,8 @@ static ma_result ma_linear_resampler_process_pcm_frames_s16_upsample(ma_linear_r
|
||||
/* Advance time forward. */
|
||||
pResampler->inTimeInt += pResampler->inAdvanceInt;
|
||||
pResampler->inTimeFrac += pResampler->inAdvanceFrac;
|
||||
if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
|
||||
pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
|
||||
if (pResampler->inTimeFrac >= pResampler->sampleRateOut) {
|
||||
pResampler->inTimeFrac -= pResampler->sampleRateOut;
|
||||
pResampler->inTimeInt += 1;
|
||||
}
|
||||
}
|
||||
@@ -59354,7 +59364,7 @@ static ma_result ma_linear_resampler_process_pcm_frames_s16(ma_linear_resampler*
|
||||
{
|
||||
MA_ASSERT(pResampler != NULL);
|
||||
|
||||
if (pResampler->config.sampleRateIn > pResampler->config.sampleRateOut) {
|
||||
if (pResampler->inAdvanceInt > 0) {
|
||||
return ma_linear_resampler_process_pcm_frames_s16_downsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
||||
} else {
|
||||
return ma_linear_resampler_process_pcm_frames_s16_upsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
||||
@@ -59388,20 +59398,20 @@ static ma_result ma_linear_resampler_process_pcm_frames_f32_downsample(ma_linear
|
||||
ma_uint32 iChannel;
|
||||
|
||||
if (pFramesInF32 != NULL) {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
|
||||
pResampler->x1.f32[iChannel] = pFramesInF32[iChannel];
|
||||
}
|
||||
pFramesInF32 += pResampler->config.channels;
|
||||
pFramesInF32 += pResampler->channels;
|
||||
} else {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
|
||||
pResampler->x1.f32[iChannel] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Filter. Do not apply filtering if sample rates are the same or else you'll get dangerous glitching. */
|
||||
if (pResampler->config.sampleRateIn != pResampler->config.sampleRateOut) {
|
||||
if (pResampler->inAdvanceInt == 1 && pResampler->inAdvanceFrac == 0) {
|
||||
ma_lpf_process_pcm_frame_f32(&pResampler->lpf, pResampler->x1.f32, pResampler->x1.f32);
|
||||
}
|
||||
|
||||
@@ -59418,7 +59428,7 @@ static ma_result ma_linear_resampler_process_pcm_frames_f32_downsample(ma_linear
|
||||
MA_ASSERT(pResampler->inTimeInt == 0);
|
||||
ma_linear_resampler_interpolate_frame_f32(pResampler, pFramesOutF32);
|
||||
|
||||
pFramesOutF32 += pResampler->config.channels;
|
||||
pFramesOutF32 += pResampler->channels;
|
||||
}
|
||||
|
||||
framesProcessedOut += 1;
|
||||
@@ -59426,8 +59436,8 @@ static ma_result ma_linear_resampler_process_pcm_frames_f32_downsample(ma_linear
|
||||
/* Advance time forward. */
|
||||
pResampler->inTimeInt += pResampler->inAdvanceInt;
|
||||
pResampler->inTimeFrac += pResampler->inAdvanceFrac;
|
||||
if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
|
||||
pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
|
||||
if (pResampler->inTimeFrac >= pResampler->sampleRateOut) {
|
||||
pResampler->inTimeFrac -= pResampler->sampleRateOut;
|
||||
pResampler->inTimeInt += 1;
|
||||
}
|
||||
}
|
||||
@@ -59464,13 +59474,13 @@ static ma_result ma_linear_resampler_process_pcm_frames_f32_upsample(ma_linear_r
|
||||
ma_uint32 iChannel;
|
||||
|
||||
if (pFramesInF32 != NULL) {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
|
||||
pResampler->x1.f32[iChannel] = pFramesInF32[iChannel];
|
||||
}
|
||||
pFramesInF32 += pResampler->config.channels;
|
||||
pFramesInF32 += pResampler->channels;
|
||||
} else {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
|
||||
pResampler->x1.f32[iChannel] = 0;
|
||||
}
|
||||
@@ -59490,11 +59500,11 @@ static ma_result ma_linear_resampler_process_pcm_frames_f32_upsample(ma_linear_r
|
||||
ma_linear_resampler_interpolate_frame_f32(pResampler, pFramesOutF32);
|
||||
|
||||
/* Filter. Do not apply filtering if sample rates are the same or else you'll get dangerous glitching. */
|
||||
if (pResampler->config.sampleRateIn != pResampler->config.sampleRateOut) {
|
||||
if (pResampler->inAdvanceInt == 1 && pResampler->inAdvanceFrac == 0) {
|
||||
ma_lpf_process_pcm_frame_f32(&pResampler->lpf, pFramesOutF32, pFramesOutF32);
|
||||
}
|
||||
|
||||
pFramesOutF32 += pResampler->config.channels;
|
||||
pFramesOutF32 += pResampler->channels;
|
||||
}
|
||||
|
||||
framesProcessedOut += 1;
|
||||
@@ -59502,8 +59512,8 @@ static ma_result ma_linear_resampler_process_pcm_frames_f32_upsample(ma_linear_r
|
||||
/* Advance time forward. */
|
||||
pResampler->inTimeInt += pResampler->inAdvanceInt;
|
||||
pResampler->inTimeFrac += pResampler->inAdvanceFrac;
|
||||
if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
|
||||
pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
|
||||
if (pResampler->inTimeFrac >= pResampler->sampleRateOut) {
|
||||
pResampler->inTimeFrac -= pResampler->sampleRateOut;
|
||||
pResampler->inTimeInt += 1;
|
||||
}
|
||||
}
|
||||
@@ -59518,7 +59528,7 @@ static ma_result ma_linear_resampler_process_pcm_frames_f32(ma_linear_resampler*
|
||||
{
|
||||
MA_ASSERT(pResampler != NULL);
|
||||
|
||||
if (pResampler->config.sampleRateIn > pResampler->config.sampleRateOut) {
|
||||
if (pResampler->inAdvanceInt > 0) {
|
||||
return ma_linear_resampler_process_pcm_frames_f32_downsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
||||
} else {
|
||||
return ma_linear_resampler_process_pcm_frames_f32_upsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
||||
@@ -59532,9 +59542,9 @@ MA_API ma_result ma_linear_resampler_process_pcm_frames(ma_linear_resampler* pRe
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
/* */ if (pResampler->config.format == ma_format_s16) {
|
||||
/* */ if (pResampler->format == ma_format_s16) {
|
||||
return ma_linear_resampler_process_pcm_frames_s16(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
||||
} else if (pResampler->config.format == ma_format_f32) {
|
||||
} else if (pResampler->format == ma_format_f32) {
|
||||
return ma_linear_resampler_process_pcm_frames_f32(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
||||
} else {
|
||||
/* Should never get here. Getting here means the format is not supported and you didn't check the return value of ma_linear_resampler_init(). */
|
||||
@@ -59589,7 +59599,7 @@ MA_API ma_uint64 ma_linear_resampler_get_output_latency(const ma_linear_resample
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ma_linear_resampler_get_input_latency(pResampler) * pResampler->config.sampleRateOut / pResampler->config.sampleRateIn;
|
||||
return ma_linear_resampler_get_input_latency(pResampler) * pResampler->sampleRateOut / pResampler->sampleRateIn;
|
||||
}
|
||||
|
||||
MA_API ma_result ma_linear_resampler_get_required_input_frame_count(const ma_linear_resampler* pResampler, ma_uint64 outputFrameCount, ma_uint64* pInputFrameCount)
|
||||
@@ -59616,7 +59626,7 @@ MA_API ma_result ma_linear_resampler_get_required_input_frame_count(const ma_lin
|
||||
|
||||
/* The rest of the output frames can be calculated in constant time. */
|
||||
inputFrameCount += outputFrameCount * pResampler->inAdvanceInt;
|
||||
inputFrameCount += (pResampler->inTimeFrac + (outputFrameCount * pResampler->inAdvanceFrac)) / pResampler->config.sampleRateOut;
|
||||
inputFrameCount += (pResampler->inTimeFrac + (outputFrameCount * pResampler->inAdvanceFrac)) / pResampler->sampleRateOut;
|
||||
|
||||
*pInputFrameCount = inputFrameCount;
|
||||
|
||||
@@ -59676,7 +59686,7 @@ MA_API ma_result ma_linear_resampler_get_expected_output_frame_count(const ma_li
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
return ma_linear_resampler_get_expected_output_frame_count_ex(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut, pResampler->inTimeInt, pResampler->inTimeFrac, pResampler->inAdvanceInt, pResampler->inAdvanceFrac, inputFrameCount, pOutputFrameCount);
|
||||
return ma_linear_resampler_get_expected_output_frame_count_ex(pResampler->sampleRateIn, pResampler->sampleRateOut, pResampler->inTimeInt, pResampler->inTimeFrac, pResampler->inAdvanceInt, pResampler->inAdvanceFrac, inputFrameCount, pOutputFrameCount);
|
||||
}
|
||||
|
||||
MA_API ma_result ma_linear_resampler_reset(ma_linear_resampler* pResampler)
|
||||
@@ -59692,13 +59702,13 @@ MA_API ma_result ma_linear_resampler_reset(ma_linear_resampler* pResampler)
|
||||
pResampler->inTimeFrac = 0;
|
||||
|
||||
/* Cached samples need to be cleared. */
|
||||
if (pResampler->config.format == ma_format_f32) {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
if (pResampler->format == ma_format_f32) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.f32[iChannel] = 0;
|
||||
pResampler->x1.f32[iChannel] = 0;
|
||||
}
|
||||
} else {
|
||||
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
|
||||
for (iChannel = 0; iChannel < pResampler->channels; iChannel += 1) {
|
||||
pResampler->x0.s16[iChannel] = 0;
|
||||
pResampler->x1.s16[iChannel] = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user