From 2e5f3d517ee0a7d70d8dad4d363e9b1f273ad306 Mon Sep 17 00:00:00 2001 From: zhouyuxin Date: Tue, 26 Aug 2025 21:08:22 +0800 Subject: [PATCH 1/5] add new algo for 8k - 384khz resamling input Signed-off-by: zhouyuxin Change-Id: I61363c49a61c37fc3a82131ac499cba34b6c8e44 --- .../include/audio_proresampler_process.h | 4 + .../proresampler/audio_proresampler_process.c | 84 +++++++++++++++---- 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/services/audio_engine/plugin/resample/include/audio_proresampler_process.h b/services/audio_engine/plugin/resample/include/audio_proresampler_process.h index a976d310f8..5fec78151c 100644 --- a/services/audio_engine/plugin/resample/include/audio_proresampler_process.h +++ b/services/audio_engine/plugin/resample/include/audio_proresampler_process.h @@ -39,6 +39,8 @@ extern "C" { }; #define MAX_RATIO_INTEGRAL_METHOD 32 + #define MAX_LIMIT_POLYNUM 327680 + #define MAX_DWNSMPLE_FILT_LEN 256 typedef struct SingleStagePolyphaseResamplerState SingleStagePolyphaseResamplerState; @@ -62,6 +64,8 @@ extern "C" { uint32_t bufferSize; /** Number of buffer samples for each channel */ uint32_t quoSamplerateRatio; /** Quotient of (input sampling frequency)/(output sampling frequency) */ uint32_t remSamplerateRatio; /** remainder of (input sampling frequency)/(output sampling frequency) */ + uint32_t polyphaseFactor; /** Number of polyphase factor */ + int32_t gainCorrection; /** gain correction for filter coefficinents */ float cutoff; /** Normalized cutoff frequency of anti-aliasing/imaging filter */ float coshParameter; /** Parameter of cosh window for adjusting side-lobe decay of filter */ int32_t isInitialized; /** If the state is initialized, isInitialized=1. */ diff --git a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c index e6ea84b14b..f62707c297 100644 --- a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c +++ b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c @@ -52,7 +52,7 @@ #define THREE_STEPS 3 #define FOUR_STEPS 4 #define QUALITY_LEVEL_TEN 10 -#define BUFFER_SIZE 160 +#define BUFFER_SIZE 256 // WARNING: Code for support to sudden changes in sampling frequency is deprecated! // It is disabled because it is complex and untested. @@ -153,12 +153,13 @@ static int32_t CalculateFilter(SingleStagePolyphaseResamplerState* state) double w; uint32_t requiredFilterCoefficientsSize; float cutoff = state->cutoff; + uint32_t pFactor = state->polyphaseFactor; - if (INT_MAX / sizeof(float) / state->interpolateFactor < state->filterLength) { + if (INT_MAX / sizeof(float) / pFactor < state->filterLength) { return RESAMPLER_ERR_ALLOC_FAILED; } - requiredFilterCoefficientsSize = state->filterLength * state->interpolateFactor; + requiredFilterCoefficientsSize = state->filterLength * pFactor; if (state->filterCoefficientsSize < requiredFilterCoefficientsSize) { if (state->filterCoefficients == NULL) { @@ -177,15 +178,27 @@ static int32_t CalculateFilter(SingleStagePolyphaseResamplerState* state) } state->filterCoefficientsSize = requiredFilterCoefficientsSize; } - - for (i = 0; i < state->interpolateFactor; i++) { + for (i = 0; i < pFactor; i++) { for (j = 0; j < state->filterLength; j++) { phi = ((int32_t)j - (int32_t)state->filterLength / TWO_STEPS + 1) - phi0; w = CompHyperbolicCosineWindow(fabs((double)TWO_STEPS * phi / state->filterLength), state->coshParameter); state->filterCoefficients[i * state->filterLength + j] = w * cutoff * Sinc(cutoff * phi); } - phi0 += 1.0 / state->interpolateFactor; + phi0 += 1.0 / pFactor; + } + // gain compensation for filter coefficinents, 2025.3.21 + if (state->gainCorrection) { + float gain = 0; + for (i = 0; i < pFactor; i++) { + gain = 0.0; + for (j = 0; j < state->filterLength; j++) { + gain += state->filterCoefficients[i * state->filterLength + j]; + } + for (j = 0; j < state->filterLength; j++) { + state->filterCoefficients[i * state->filterLength + j] /= gain; + } + } } return 0; } @@ -730,12 +743,15 @@ static int32_t PolyphaseResamplerMono(SingleStagePolyphaseResamplerState *state, uint32_t outSample = 0; uint32_t inputIndex = state->inputIndex; uint32_t subfilterNum = state->subfilterNum; + uint32_t indexPhase = 0; const float* filterCoefficients = state->filterCoefficients; const uint32_t quoSamplerateRatio = state->quoSamplerateRatio; const uint32_t remSamplerateRatio = state->remSamplerateRatio; const uint32_t decimateFactor = state->decimateFactor; const uint32_t interpolateFactor = state->interpolateFactor; + const uint32_t polyphaseFactor = state->polyphaseFactor; uint32_t i; + float scalerPhase = (float)(polyphaseFactor - 1) / (float)interpolateFactor; if (inputIndex < (uint32_t)(*inputLength)) { outSample = CompareMin((*outputLength), ((interpolateFactor * ((*inputLength) - inputIndex) - @@ -743,7 +759,13 @@ static int32_t PolyphaseResamplerMono(SingleStagePolyphaseResamplerState *state, } for (i = 0; i < outSample; i++) { - const float* coeffs = &filterCoefficients[subfilterNum * n]; + if (state->gainCorrection) { + indexPhase = (int)(subfilterNum * scalerPhase); + } + else { + indexPhase = subfilterNum; + } + const float* coeffs = &filterCoefficients[indexPhase * n]; const float* inputs = &in[inputIndex * MONO]; MultiplyFilterMono(state, coeffs, inputs, out, subfilterNum); out++; @@ -768,19 +790,28 @@ static int32_t PolyphaseResamplerStereo(SingleStagePolyphaseResamplerState* stat uint32_t outSample = 0; uint32_t inputIndex = state->inputIndex; uint32_t subfilterNum = state->subfilterNum; + uint32_t indexPhase = 0; const float* filterCoefficients = state->filterCoefficients; const uint32_t quoSamplerateRatio = state->quoSamplerateRatio; const uint32_t remSamplerateRatio = state->remSamplerateRatio; const uint32_t decimateFactor = state->decimateFactor; const uint32_t interpolateFactor = state->interpolateFactor; + const uint32_t polyphaseFactor = state->polyphaseFactor; uint32_t i; + float = (float)(polyphaseFactor - 1) / (float)interpolateFactor; if (inputIndex < (uint32_t) (*inputLength)) { outSample = CompareMin((*outputLength), ((interpolateFactor * ((*inputLength) - inputIndex) - subfilterNum) - 1) / decimateFactor + 1); } for (i = 0; i < outSample; i++) { - const float* coeffs = &filterCoefficients[subfilterNum * n]; + if (state->gainCorrection) { + indexPhase = (int)(subfilterNum * scalerPhase); + } + else { + indexPhase = subfilterNum; + } + const float* coeffs = &filterCoefficients[indexPhase * n]; const float* inputs = &in[inputIndex * STEREO]; MultiplyFilterStereo(state, coeffs, inputs, out, subfilterNum); out += STEREO; @@ -805,12 +836,14 @@ static int32_t PolyphaseResamplerMultichannel(SingleStagePolyphaseResamplerState uint32_t outSample = 0; uint32_t inputIndex = state->inputIndex; uint32_t subfilterNum = state->subfilterNum; + uint32_t indexPhase = 0; const float* filterCoefficients = state->filterCoefficients; const uint32_t quoSamplerateRatio = state->quoSamplerateRatio; const uint32_t remSamplerateRatio = state->remSamplerateRatio; const uint32_t decimateFactor = state->decimateFactor; const uint32_t interpolateFactor = state->interpolateFactor; const uint32_t numChannels = state->numChannels; + const uint32_t polyphaseFactor = state->polyphaseFactor; uint32_t i; if (inputIndex < (uint32_t)(*inputLength)) { @@ -819,7 +852,14 @@ static int32_t PolyphaseResamplerMultichannel(SingleStagePolyphaseResamplerState } for (i = 0; i < outSample; i++) { - const float* coeffs = &filterCoefficients[subfilterNum * n]; + float scalerPhase = (float)(polyphaseFactor - 1) / (float)interpolateFactor; + if (state->gainCorrection) { + indexPhase = (int)(subfilterNum * scalerPhase); + } + else { + indexPhase = subfilterNum; + } + const float* coeffs = &filterCoefficients[indexPhase * n]; const float* inputs = &in[inputIndex * numChannels]; MultiplyFilterMultichannel(state, coeffs, inputs, out, subfilterNum); out += numChannels; @@ -1263,18 +1303,30 @@ static int32_t UpdateResamplerState(SingleStagePolyphaseResamplerState* state) if (state->interpolateFactor < state->decimateFactor) { // downsampling state->cutoff = (float)state->interpolateFactor / state->decimateFactor; - state->filterLength = state->filterLength * state->decimateFactor / state->interpolateFactor; - + // updating filter length for downsampling + float filterLength = state->filterLength * state->decimateFactor / state->interpolateFactor; + if (filterLength < MAX_DWNSMPLE_FILT_LEN) { + state->filterLength = filterLength; + } + else { + state->filterLength = MAX_DWNSMPLE_FILT_LEN; + } // Round up to make sure filterLength be multiple of 8 state->filterLength = 8 * ((state->filterLength - 1) / 8) + 8; } else { // upsampling state->cutoff = 1; } - // modified for new requirements (extended i/o sample rate combination) 2025.2.28 - if ((CompareMax(state->decimateFactor, state->interpolateFactor) <= MAX_RATIO_INTEGRAL_METHOD) & - ((state->decimateFactor == 1 || state->interpolateFactor == 1) || - ((float)state->decimateFactor / (float)state->interpolateFactor < 2.0f))) { + // set up the polyphase factor, 2025.3.21 + state->polyphaseFactor = (uint32_t)(MAX_LIMIT_POLYNUM / state->filterLength); + state->gainCorrection = 1; + if (state->interpolateFactor <= state->polyphaseFactor) { + state->polyphaseFactor = state->interpolateFactor; + state->gainCorrection = 0; + } + // coarse (integral) sampling rate ratio + if ((COMPARE_MAX(state->decimateFactor, state->interpolateFactor) <= MAX_RATIO_INTEGRAL_METHOD) & + (state->decimateFactor == 1 || state->interpolateFactor == 1)) { state->resamplerFunction = SetResamplerFunctionCoarse(state); } else { // fine (non-integral) sampling rate ratio switch (state->numChannels) { @@ -1374,6 +1426,8 @@ SingleStagePolyphaseResamplerState* SingleStagePolyphaseResamplerInit(uint32_t n state->isStarted = 0; state->decimateFactor = 0; state->interpolateFactor = 0; + state->polyphaseFactor = 0; + state->gainCorrection = 0; state->quality = -1; state->filterCoefficientsSize = 0; state->inputMemorySize = 0; -- Gitee From bddd6cdb76f4e12d2737d9719259177fa6e38e44 Mon Sep 17 00:00:00 2001 From: zhouyuxin Date: Wed, 27 Aug 2025 18:29:19 +0800 Subject: [PATCH 2/5] fix compile bug Signed-off-by: zhouyuxin Change-Id: Ib0b83523f3a56602f2417afe0acaabb8a61c003b --- .../resample/proresampler/audio_proresampler_process.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c index f62707c297..035c9575d8 100644 --- a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c +++ b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c @@ -799,7 +799,7 @@ static int32_t PolyphaseResamplerStereo(SingleStagePolyphaseResamplerState* stat const uint32_t polyphaseFactor = state->polyphaseFactor; uint32_t i; - float = (float)(polyphaseFactor - 1) / (float)interpolateFactor; + float scalerPhase = (float)(polyphaseFactor - 1) / (float)interpolateFactor; if (inputIndex < (uint32_t) (*inputLength)) { outSample = CompareMin((*outputLength), ((interpolateFactor * ((*inputLength) - inputIndex) - subfilterNum) - 1) / decimateFactor + 1); @@ -1325,7 +1325,7 @@ static int32_t UpdateResamplerState(SingleStagePolyphaseResamplerState* state) state->gainCorrection = 0; } // coarse (integral) sampling rate ratio - if ((COMPARE_MAX(state->decimateFactor, state->interpolateFactor) <= MAX_RATIO_INTEGRAL_METHOD) & + if ((CompareMax(state->decimateFactor, state->interpolateFactor) <= MAX_RATIO_INTEGRAL_METHOD) & (state->decimateFactor == 1 || state->interpolateFactor == 1)) { state->resamplerFunction = SetResamplerFunctionCoarse(state); } else { // fine (non-integral) sampling rate ratio @@ -1474,7 +1474,7 @@ static void ApplyResampler(SingleStagePolyphaseResamplerState* state, uint32_t* /* Call resampler function */ outSample = state->resamplerFunction(state, inputMemory, inputLength, out, outputLength); - if (state->inputIndex < (int32_t)*inputLength) { + if (state->inputIndex < (uint32_t)*inputLength) { *inputLength = state->inputIndex; } *outputLength = outSample; -- Gitee From 14ae5f7cfbedc3d98b5cdb5d52102299d04fef29 Mon Sep 17 00:00:00 2001 From: zyx0106 Date: Wed, 27 Aug 2025 20:05:21 +0800 Subject: [PATCH 3/5] fix long function Signed-off-by: zyx0106 --- .../proresampler/audio_proresampler_process.c | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c index 035c9575d8..22a4f9a143 100644 --- a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c +++ b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c @@ -143,6 +143,23 @@ static float Sinc(float x) return sin(M_PI * x) / (M_PI * x); } +// gain compensation for filter coefficinents, 2025.3.21 +static void GainCompensation(SingleStagePolyphaseResamplerState* state, uint32_t pFactor) +{ + CHECK_AND_RETURN_LOG(state != nullptr, "state is nullptr!"); + if (state->gainCorrection) { + float gain = 0; + for (i = 0; i < pFactor; i++) { + gain = 0.0; + for (j = 0; j < state->filterLength; j++) { + gain += state->filterCoefficients[i * state->filterLength + j]; + } + for (j = 0; j < state->filterLength; j++) { + state->filterCoefficients[i * state->filterLength + j] /= gain; + } + } + } +} static int32_t CalculateFilter(SingleStagePolyphaseResamplerState* state) { @@ -187,19 +204,7 @@ static int32_t CalculateFilter(SingleStagePolyphaseResamplerState* state) } phi0 += 1.0 / pFactor; } - // gain compensation for filter coefficinents, 2025.3.21 - if (state->gainCorrection) { - float gain = 0; - for (i = 0; i < pFactor; i++) { - gain = 0.0; - for (j = 0; j < state->filterLength; j++) { - gain += state->filterCoefficients[i * state->filterLength + j]; - } - for (j = 0; j < state->filterLength; j++) { - state->filterCoefficients[i * state->filterLength + j] /= gain; - } - } - } + GainCompensation(state, pFactor); return 0; } @@ -761,8 +766,7 @@ static int32_t PolyphaseResamplerMono(SingleStagePolyphaseResamplerState *state, for (i = 0; i < outSample; i++) { if (state->gainCorrection) { indexPhase = (int)(subfilterNum * scalerPhase); - } - else { + } else { indexPhase = subfilterNum; } const float* coeffs = &filterCoefficients[indexPhase * n]; @@ -807,8 +811,7 @@ static int32_t PolyphaseResamplerStereo(SingleStagePolyphaseResamplerState* stat for (i = 0; i < outSample; i++) { if (state->gainCorrection) { indexPhase = (int)(subfilterNum * scalerPhase); - } - else { + } else { indexPhase = subfilterNum; } const float* coeffs = &filterCoefficients[indexPhase * n]; @@ -855,8 +858,7 @@ static int32_t PolyphaseResamplerMultichannel(SingleStagePolyphaseResamplerState float scalerPhase = (float)(polyphaseFactor - 1) / (float)interpolateFactor; if (state->gainCorrection) { indexPhase = (int)(subfilterNum * scalerPhase); - } - else { + } else { indexPhase = subfilterNum; } const float* coeffs = &filterCoefficients[indexPhase * n]; @@ -1307,8 +1309,7 @@ static int32_t UpdateResamplerState(SingleStagePolyphaseResamplerState* state) float filterLength = state->filterLength * state->decimateFactor / state->interpolateFactor; if (filterLength < MAX_DWNSMPLE_FILT_LEN) { state->filterLength = filterLength; - } - else { + } else { state->filterLength = MAX_DWNSMPLE_FILT_LEN; } // Round up to make sure filterLength be multiple of 8 -- Gitee From fd03d4c381a765ab46c7fb58a1bdb8b70db0eaa1 Mon Sep 17 00:00:00 2001 From: zyx0106 Date: Wed, 27 Aug 2025 20:22:38 +0800 Subject: [PATCH 4/5] fix compile bug Signed-off-by: zyx0106 --- .../resample/proresampler/audio_proresampler_process.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c index 22a4f9a143..dbb6e8bbe8 100644 --- a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c +++ b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c @@ -149,12 +149,12 @@ static void GainCompensation(SingleStagePolyphaseResamplerState* state, uint32_t CHECK_AND_RETURN_LOG(state != nullptr, "state is nullptr!"); if (state->gainCorrection) { float gain = 0; - for (i = 0; i < pFactor; i++) { + for (uint32_t i = 0; i < pFactor; i++) { gain = 0.0; - for (j = 0; j < state->filterLength; j++) { + for (uint32_t j = 0; j < state->filterLength; j++) { gain += state->filterCoefficients[i * state->filterLength + j]; } - for (j = 0; j < state->filterLength; j++) { + for (uint32_t j = 0; j < state->filterLength; j++) { state->filterCoefficients[i * state->filterLength + j] /= gain; } } -- Gitee From 651f4e7a2161d0d60614e04d00e43ee2ed121fe3 Mon Sep 17 00:00:00 2001 From: zyx0106 Date: Wed, 27 Aug 2025 20:51:30 +0800 Subject: [PATCH 5/5] fix compile bug2 Signed-off-by: zyx0106 --- .../plugin/resample/proresampler/audio_proresampler_process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c index dbb6e8bbe8..346be57942 100644 --- a/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c +++ b/services/audio_engine/plugin/resample/proresampler/audio_proresampler_process.c @@ -146,7 +146,7 @@ static float Sinc(float x) // gain compensation for filter coefficinents, 2025.3.21 static void GainCompensation(SingleStagePolyphaseResamplerState* state, uint32_t pFactor) { - CHECK_AND_RETURN_LOG(state != nullptr, "state is nullptr!"); + CHECK_AND_RETURN_LOG(state != NULL, "state is NULL!"); if (state->gainCorrection) { float gain = 0; for (uint32_t i = 0; i < pFactor; i++) { -- Gitee