Eliminate quantization in 2-band split filter in WebRTC APM
This CL eliminates the issue of quantization in the 2-band splitfilter in WebRTC APM The code change has been tested offline on recordings and shown to perform well. Change-Id: Ic9b5cf35e040429afb7d0077a8dac6a6e208b4f9 Bug: webrtc:454152425 Change-Id: Ic9b5cf35e040429afb7d0077a8dac6a6e208b4f9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/419200 Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org> Commit-Queue: Per Åhgren <peah@webrtc.org> Reviewed-by: Sam Zackrisson <saza@webrtc.org> Cr-Commit-Position: refs/heads/main@{#46022}
This commit is contained in:
parent
7fc962d0ae
commit
1270f5ce74
@ -997,18 +997,18 @@ void WebRtcSpl_UpsampleBy2(const int16_t* in,
|
||||
/************************************************************
|
||||
* END OF RESAMPLING FUNCTIONS
|
||||
************************************************************/
|
||||
void WebRtcSpl_AnalysisQMF(const int16_t* in_data,
|
||||
void WebRtcSpl_AnalysisQMF(const float* in_data,
|
||||
size_t in_data_length,
|
||||
int16_t* low_band,
|
||||
int16_t* high_band,
|
||||
int32_t* filter_state1,
|
||||
int32_t* filter_state2);
|
||||
void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
||||
const int16_t* high_band,
|
||||
float* low_band,
|
||||
float* high_band,
|
||||
float* filter_state1,
|
||||
float* filter_state2);
|
||||
void WebRtcSpl_SynthesisQMF(const float* low_band,
|
||||
const float* high_band,
|
||||
size_t band_length,
|
||||
int16_t* out_data,
|
||||
int32_t* filter_state1,
|
||||
int32_t* filter_state2);
|
||||
float* out_data,
|
||||
float* filter_state1,
|
||||
float* filter_state2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -21,9 +21,11 @@ enum {
|
||||
kMaxBandFrameLength = 320 // 10 ms at 64 kHz.
|
||||
};
|
||||
|
||||
// QMF filter coefficients in Q16.
|
||||
static const uint16_t WebRtcSpl_kAllPassFilter1[3] = {6418, 36982, 57261};
|
||||
static const uint16_t WebRtcSpl_kAllPassFilter2[3] = {21333, 49062, 63010};
|
||||
// QMF filter coefficients.
|
||||
static const float WebRtcSpl_kAllPassFilter1[3] = {0.0979309082f, 0.5643005371f,
|
||||
0.8737335205f};
|
||||
static const float WebRtcSpl_kAllPassFilter2[3] = {
|
||||
0.32551574707f, 0.74862670898f, 0.96145629882f};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// WebRtcSpl_AllPassQMF(...)
|
||||
@ -31,23 +33,23 @@ static const uint16_t WebRtcSpl_kAllPassFilter2[3] = {21333, 49062, 63010};
|
||||
// Allpass filter used by the analysis and synthesis parts of the QMF filter.
|
||||
//
|
||||
// Input:
|
||||
// - in_data : Input data sequence (Q10)
|
||||
// - in_data : Input data sequence
|
||||
// - data_length : Length of data sequence (>2)
|
||||
// - filter_coefficients : Filter coefficients (length 3, Q16)
|
||||
// - filter_coefficients : Filter coefficients
|
||||
//
|
||||
// Input & Output:
|
||||
// - filter_state : Filter state (length 6, Q10).
|
||||
// - filter_state : Filter state
|
||||
//
|
||||
// Output:
|
||||
// - out_data : Output data sequence (Q10), length equal to
|
||||
// - out_data : Output data sequence, length equal to
|
||||
// `data_length`
|
||||
//
|
||||
|
||||
static void WebRtcSpl_AllPassQMF(int32_t* in_data,
|
||||
static void WebRtcSpl_AllPassQMF(float* in_data,
|
||||
size_t data_length,
|
||||
int32_t* out_data,
|
||||
const uint16_t* filter_coefficients,
|
||||
int32_t* filter_state) {
|
||||
float* out_data,
|
||||
const float* filter_coefficients,
|
||||
float* filter_state) {
|
||||
// The procedure is to filter the input with three first order all pass
|
||||
// filters (cascade operations).
|
||||
//
|
||||
@ -66,7 +68,7 @@ static void WebRtcSpl_AllPassQMF(int32_t* in_data,
|
||||
// `out_data`. Note that the input vector values are changed during the
|
||||
// process.
|
||||
size_t k;
|
||||
int32_t diff;
|
||||
float diff;
|
||||
// First all-pass cascade; filter from in_data to out_data.
|
||||
|
||||
// Let y_i[n] indicate the output of cascade filter i (with filter
|
||||
@ -76,18 +78,16 @@ static void WebRtcSpl_AllPassQMF(int32_t* in_data,
|
||||
// First loop, use the states stored in memory.
|
||||
// "diff" should be safe from wrap around since max values are 2^25
|
||||
// diff = (x[0] - y_1[-1])
|
||||
diff = WebRtcSpl_SubSatW32(in_data[0], filter_state[1]);
|
||||
diff = in_data[0] - filter_state[1];
|
||||
// y_1[0] = x[-1] + a_1 * (x[0] - y_1[-1])
|
||||
out_data[0] =
|
||||
WEBRTC_SPL_SCALEDIFF32(filter_coefficients[0], diff, filter_state[0]);
|
||||
out_data[0] = filter_state[0] + filter_coefficients[0] * diff;
|
||||
|
||||
// For the remaining loops, use previous values.
|
||||
for (k = 1; k < data_length; k++) {
|
||||
// diff = (x[n] - y_1[n-1])
|
||||
diff = WebRtcSpl_SubSatW32(in_data[k], out_data[k - 1]);
|
||||
diff = in_data[k] - out_data[k - 1];
|
||||
// y_1[n] = x[n-1] + a_1 * (x[n] - y_1[n-1])
|
||||
out_data[k] =
|
||||
WEBRTC_SPL_SCALEDIFF32(filter_coefficients[0], diff, in_data[k - 1]);
|
||||
out_data[k] = in_data[k - 1] + filter_coefficients[0] * diff;
|
||||
}
|
||||
|
||||
// Update states.
|
||||
@ -98,16 +98,14 @@ static void WebRtcSpl_AllPassQMF(int32_t* in_data,
|
||||
|
||||
// Second all-pass cascade; filter from out_data to in_data.
|
||||
// diff = (y_1[0] - y_2[-1])
|
||||
diff = WebRtcSpl_SubSatW32(out_data[0], filter_state[3]);
|
||||
diff = out_data[0] - filter_state[3];
|
||||
// y_2[0] = y_1[-1] + a_2 * (y_1[0] - y_2[-1])
|
||||
in_data[0] =
|
||||
WEBRTC_SPL_SCALEDIFF32(filter_coefficients[1], diff, filter_state[2]);
|
||||
in_data[0] = filter_state[2] + filter_coefficients[1] * diff;
|
||||
for (k = 1; k < data_length; k++) {
|
||||
// diff = (y_1[n] - y_2[n-1])
|
||||
diff = WebRtcSpl_SubSatW32(out_data[k], in_data[k - 1]);
|
||||
diff = out_data[k] - in_data[k - 1];
|
||||
// y_2[0] = y_1[-1] + a_2 * (y_1[0] - y_2[-1])
|
||||
in_data[k] =
|
||||
WEBRTC_SPL_SCALEDIFF32(filter_coefficients[1], diff, out_data[k - 1]);
|
||||
in_data[k] = out_data[k - 1] + filter_coefficients[1] * diff;
|
||||
}
|
||||
|
||||
filter_state[2] =
|
||||
@ -117,16 +115,14 @@ static void WebRtcSpl_AllPassQMF(int32_t* in_data,
|
||||
|
||||
// Third all-pass cascade; filter from in_data to out_data.
|
||||
// diff = (y_2[0] - y[-1])
|
||||
diff = WebRtcSpl_SubSatW32(in_data[0], filter_state[5]);
|
||||
diff = in_data[0] - filter_state[5];
|
||||
// y[0] = y_2[-1] + a_3 * (y_2[0] - y[-1])
|
||||
out_data[0] =
|
||||
WEBRTC_SPL_SCALEDIFF32(filter_coefficients[2], diff, filter_state[4]);
|
||||
out_data[0] = filter_state[4] + filter_coefficients[2] * diff;
|
||||
for (k = 1; k < data_length; k++) {
|
||||
// diff = (y_2[n] - y[n-1])
|
||||
diff = WebRtcSpl_SubSatW32(in_data[k], out_data[k - 1]);
|
||||
diff = in_data[k] - out_data[k - 1];
|
||||
// y[n] = y_2[n-1] + a_3 * (y_2[n] - y[n-1])
|
||||
out_data[k] =
|
||||
WEBRTC_SPL_SCALEDIFF32(filter_coefficients[2], diff, in_data[k - 1]);
|
||||
out_data[k] = in_data[k - 1] + filter_coefficients[2] * diff;
|
||||
}
|
||||
filter_state[4] =
|
||||
in_data[data_length - 1]; // y_2[N-1], becomes y_2[-1] next time
|
||||
@ -134,27 +130,26 @@ static void WebRtcSpl_AllPassQMF(int32_t* in_data,
|
||||
out_data[data_length - 1]; // y[N-1], becomes y[-1] next time
|
||||
}
|
||||
|
||||
void WebRtcSpl_AnalysisQMF(const int16_t* in_data,
|
||||
void WebRtcSpl_AnalysisQMF(const float* in_data,
|
||||
size_t in_data_length,
|
||||
int16_t* low_band,
|
||||
int16_t* high_band,
|
||||
int32_t* filter_state1,
|
||||
int32_t* filter_state2) {
|
||||
float* low_band,
|
||||
float* high_band,
|
||||
float* filter_state1,
|
||||
float* filter_state2) {
|
||||
size_t i;
|
||||
int16_t k;
|
||||
int32_t tmp;
|
||||
int32_t half_in1[kMaxBandFrameLength];
|
||||
int32_t half_in2[kMaxBandFrameLength];
|
||||
int32_t filter1[kMaxBandFrameLength];
|
||||
int32_t filter2[kMaxBandFrameLength];
|
||||
float half_in1[kMaxBandFrameLength];
|
||||
float half_in2[kMaxBandFrameLength];
|
||||
float filter1[kMaxBandFrameLength];
|
||||
float filter2[kMaxBandFrameLength];
|
||||
const size_t band_length = in_data_length / 2;
|
||||
RTC_DCHECK_EQ(0, in_data_length % 2);
|
||||
RTC_DCHECK_LE(band_length, kMaxBandFrameLength);
|
||||
|
||||
// Split even and odd samples. Also shift them to Q10.
|
||||
// Split even and odd samples.
|
||||
for (i = 0, k = 0; i < band_length; i++, k += 2) {
|
||||
half_in2[i] = ((int32_t)in_data[k]) * (1 << 10);
|
||||
half_in1[i] = ((int32_t)in_data[k + 1]) * (1 << 10);
|
||||
half_in2[i] = in_data[k];
|
||||
half_in1[i] = in_data[k + 1];
|
||||
}
|
||||
|
||||
// All pass filter even and odd samples, independently.
|
||||
@ -166,36 +161,30 @@ void WebRtcSpl_AnalysisQMF(const int16_t* in_data,
|
||||
// Take the sum and difference of filtered version of odd and even
|
||||
// branches to get upper & lower band.
|
||||
for (i = 0; i < band_length; i++) {
|
||||
tmp = (filter1[i] + filter2[i] + 1024) >> 11;
|
||||
low_band[i] = WebRtcSpl_SatW32ToW16(tmp);
|
||||
|
||||
tmp = (filter1[i] - filter2[i] + 1024) >> 11;
|
||||
high_band[i] = WebRtcSpl_SatW32ToW16(tmp);
|
||||
low_band[i] = (filter1[i] + filter2[i]) * 0.5f;
|
||||
high_band[i] = (filter1[i] - filter2[i]) * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
||||
const int16_t* high_band,
|
||||
void WebRtcSpl_SynthesisQMF(const float* low_band,
|
||||
const float* high_band,
|
||||
size_t band_length,
|
||||
int16_t* out_data,
|
||||
int32_t* filter_state1,
|
||||
int32_t* filter_state2) {
|
||||
int32_t tmp;
|
||||
int32_t half_in1[kMaxBandFrameLength];
|
||||
int32_t half_in2[kMaxBandFrameLength];
|
||||
int32_t filter1[kMaxBandFrameLength];
|
||||
int32_t filter2[kMaxBandFrameLength];
|
||||
float* out_data,
|
||||
float* filter_state1,
|
||||
float* filter_state2) {
|
||||
float half_in1[kMaxBandFrameLength];
|
||||
float half_in2[kMaxBandFrameLength];
|
||||
float filter1[kMaxBandFrameLength];
|
||||
float filter2[kMaxBandFrameLength];
|
||||
size_t i;
|
||||
int16_t k;
|
||||
RTC_DCHECK_LE(band_length, kMaxBandFrameLength);
|
||||
|
||||
// Obtain the sum and difference channels out of upper and lower-band
|
||||
// channels. Also shift to Q10 domain.
|
||||
// channels.
|
||||
for (i = 0; i < band_length; i++) {
|
||||
tmp = (int32_t)low_band[i] + (int32_t)high_band[i];
|
||||
half_in1[i] = tmp * (1 << 10);
|
||||
tmp = (int32_t)low_band[i] - (int32_t)high_band[i];
|
||||
half_in2[i] = tmp * (1 << 10);
|
||||
half_in1[i] = low_band[i] + high_band[i];
|
||||
half_in2[i] = low_band[i] - high_band[i];
|
||||
}
|
||||
|
||||
// all-pass filter the sum and difference channels
|
||||
@ -205,13 +194,11 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
||||
WebRtcSpl_kAllPassFilter1, filter_state2);
|
||||
|
||||
// The filtered signals are even and odd samples of the output. Combine
|
||||
// them. The signals are Q10 should shift them back to Q0 and take care of
|
||||
// saturation.
|
||||
// them and take care of saturation.
|
||||
for (i = 0, k = 0; i < band_length; i++) {
|
||||
tmp = (filter2[i] + 512) >> 10;
|
||||
out_data[k++] = WebRtcSpl_SatW32ToW16(tmp);
|
||||
|
||||
tmp = (filter1[i] + 512) >> 10;
|
||||
out_data[k++] = WebRtcSpl_SatW32ToW16(tmp);
|
||||
out_data[k++] = filter2[i] > -32768.0f ?
|
||||
(filter2[i] < 32767.0f ? filter2[i] : 32767.0f) : -32768.0f;
|
||||
out_data[k++] = filter1[i] > -32768.0f ?
|
||||
(filter1[i] < 32767.0f ? filter1[i] : 32767.0f) : -32768.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,14 +139,8 @@ void RunBitExactnessTest(int sample_rate_hz,
|
||||
// Chromium ARM and ARM64 boths have been identified. This is tracked in the
|
||||
// issue https://bugs.chromium.org/p/webrtc/issues/detail?id=5711.
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono16kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono16kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f};
|
||||
RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 50, 5,
|
||||
@ -154,14 +148,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Stereo16kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Stereo16kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.027313f, -0.015900f, -0.028107f,
|
||||
-0.027313f, -0.015900f, -0.028107f};
|
||||
@ -170,14 +158,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono32kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono32kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.010162f, -0.009155f, -0.008301f};
|
||||
RunBitExactnessTest(32000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 50, 5,
|
||||
@ -185,14 +167,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono48kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono48kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.010162f, -0.009155f, -0.008301f};
|
||||
RunBitExactnessTest(32000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 50, 5,
|
||||
@ -200,14 +176,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono16kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono16kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.003967f, -0.002777f, -0.001770f};
|
||||
RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveDigital, 10, 50, 5,
|
||||
@ -215,14 +185,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Stereo16kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Stereo16kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.015411f, -0.008972f, -0.015839f,
|
||||
-0.015411f, -0.008972f, -0.015839f};
|
||||
@ -231,14 +195,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono32kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono32kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.006134f, -0.005524f, -0.005005f};
|
||||
RunBitExactnessTest(32000, 1, GainControl::Mode::kAdaptiveDigital, 10, 50, 5,
|
||||
@ -246,14 +204,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono48kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono48kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.006134f, -0.005524f, -0.005005};
|
||||
RunBitExactnessTest(32000, 1, GainControl::Mode::kAdaptiveDigital, 10, 50, 5,
|
||||
@ -261,14 +213,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono16kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono16kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.011749f, -0.008270f, -0.005219f};
|
||||
RunBitExactnessTest(16000, 1, GainControl::Mode::kFixedDigital, 10, 50, 5,
|
||||
@ -276,14 +222,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Stereo16kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Stereo16kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.048896f, -0.028479f, -0.050345f,
|
||||
-0.048896f, -0.028479f, -0.050345f};
|
||||
@ -292,14 +232,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono32kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono32kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.018158f, -0.016357f, -0.014832f};
|
||||
RunBitExactnessTest(32000, 1, GainControl::Mode::kFixedDigital, 10, 50, 5,
|
||||
@ -307,14 +241,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono48kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono48kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 50;
|
||||
const float kOutputReference[] = {-0.018158f, -0.016357f, -0.014832f};
|
||||
RunBitExactnessTest(32000, 1, GainControl::Mode::kFixedDigital, 10, 50, 5,
|
||||
@ -322,14 +250,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono16kHz_AdaptiveAnalog_Tl10_SL10_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono16kHz_AdaptiveAnalog_Tl10_SL10_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 12;
|
||||
const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f};
|
||||
RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 10, 5,
|
||||
@ -337,14 +259,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono16kHz_AdaptiveAnalog_Tl10_SL100_CG5_Lim_AL70_80) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono16kHz_AdaptiveAnalog_Tl10_SL100_CG5_Lim_AL70_80) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 100;
|
||||
const float kOutputReference[] = {-0.003998f, -0.002808f, -0.001770f};
|
||||
RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 100, 5,
|
||||
@ -352,14 +268,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono16kHz_AdaptiveDigital_Tl10_SL100_CG5_NoLim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono16kHz_AdaptiveDigital_Tl10_SL100_CG5_NoLim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 100;
|
||||
const float kOutputReference[] = {-0.004028f, -0.002838f, -0.001770f};
|
||||
RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveDigital, 10, 100, 5,
|
||||
@ -367,14 +277,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono16kHz_AdaptiveDigital_Tl40_SL100_CG5_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono16kHz_AdaptiveDigital_Tl40_SL100_CG5_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 100;
|
||||
const float kOutputReference[] = {-0.008728f, -0.006134f, -0.003845f};
|
||||
RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveDigital, 40, 100, 5,
|
||||
@ -382,14 +286,8 @@ TEST(GainControlBitExactnessTest,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
#if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \
|
||||
defined(WEBRTC_ANDROID))
|
||||
TEST(GainControlBitExactnessTest,
|
||||
Mono16kHz_AdaptiveDigital_Tl10_SL100_CG30_Lim_AL0_100) {
|
||||
#else
|
||||
TEST(GainControlBitExactnessTest,
|
||||
DISABLED_Mono16kHz_AdaptiveDigital_Tl10_SL100_CG30_Lim_AL0_100) {
|
||||
#endif
|
||||
const int kStreamAnalogLevelReference = 100;
|
||||
const float kOutputReference[] = {-0.005859f, -0.004120f, -0.002594f};
|
||||
RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveDigital, 10, 100,
|
||||
|
||||
@ -12,11 +12,10 @@
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "common_audio/channel_buffer.h"
|
||||
#include "common_audio/include/audio_util.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "modules/audio_processing/three_band_filter_bank.h"
|
||||
#include "rtc_base/checks.h"
|
||||
@ -72,15 +71,15 @@ void SplittingFilter::TwoBandsAnalysis(const ChannelBuffer<float>* data,
|
||||
RTC_DCHECK_EQ(data->num_frames(), kTwoBandFilterSamplesPerFrame);
|
||||
|
||||
for (size_t i = 0; i < two_bands_states_.size(); ++i) {
|
||||
std::array<std::array<int16_t, kSamplesPerBand>, 2> bands16;
|
||||
std::array<int16_t, kTwoBandFilterSamplesPerFrame> full_band16;
|
||||
FloatS16ToS16(data->channels(0)[i], full_band16.size(), full_band16.data());
|
||||
WebRtcSpl_AnalysisQMF(full_band16.data(), data->num_frames(),
|
||||
std::array<std::array<float, kSamplesPerBand>, 2> bands16;
|
||||
WebRtcSpl_AnalysisQMF(data->channels(0)[i], data->num_frames(),
|
||||
bands16[0].data(), bands16[1].data(),
|
||||
two_bands_states_[i].analysis_state1,
|
||||
two_bands_states_[i].analysis_state2);
|
||||
S16ToFloatS16(bands16[0].data(), bands16[0].size(), bands->channels(0)[i]);
|
||||
S16ToFloatS16(bands16[1].data(), bands16[1].size(), bands->channels(1)[i]);
|
||||
memcpy(bands->channels(0)[i], bands16[0].data(),
|
||||
kSamplesPerBand * sizeof(float));
|
||||
memcpy(bands->channels(1)[i], bands16[1].data(),
|
||||
kSamplesPerBand * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,15 +88,15 @@ void SplittingFilter::TwoBandsSynthesis(const ChannelBuffer<float>* bands,
|
||||
RTC_DCHECK_LE(data->num_channels(), two_bands_states_.size());
|
||||
RTC_DCHECK_EQ(data->num_frames(), kTwoBandFilterSamplesPerFrame);
|
||||
for (size_t i = 0; i < data->num_channels(); ++i) {
|
||||
std::array<std::array<int16_t, kSamplesPerBand>, 2> bands16;
|
||||
std::array<int16_t, kTwoBandFilterSamplesPerFrame> full_band16;
|
||||
FloatS16ToS16(bands->channels(0)[i], bands16[0].size(), bands16[0].data());
|
||||
FloatS16ToS16(bands->channels(1)[i], bands16[1].size(), bands16[1].data());
|
||||
std::array<std::array<float, kSamplesPerBand>, 2> bands16;
|
||||
memcpy(bands16[0].data(), bands->channels(0)[i],
|
||||
kSamplesPerBand * sizeof(float));
|
||||
memcpy(bands16[1].data(), bands->channels(1)[i],
|
||||
kSamplesPerBand * sizeof(float));
|
||||
WebRtcSpl_SynthesisQMF(bands16[0].data(), bands16[1].data(),
|
||||
bands->num_frames_per_band(), full_band16.data(),
|
||||
bands->num_frames_per_band(), data->channels(0)[i],
|
||||
two_bands_states_[i].synthesis_state1,
|
||||
two_bands_states_[i].synthesis_state2);
|
||||
S16ToFloatS16(full_band16.data(), full_band16.size(), data->channels(0)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -28,10 +28,10 @@ struct TwoBandsStates {
|
||||
}
|
||||
|
||||
static const int kStateSize = 6;
|
||||
int analysis_state1[kStateSize];
|
||||
int analysis_state2[kStateSize];
|
||||
int synthesis_state1[kStateSize];
|
||||
int synthesis_state2[kStateSize];
|
||||
float analysis_state1[kStateSize];
|
||||
float analysis_state2[kStateSize];
|
||||
float synthesis_state1[kStateSize];
|
||||
float synthesis_state2[kStateSize];
|
||||
};
|
||||
|
||||
// Splitting filter which is able to split into and merge from 2 or 3 frequency
|
||||
|
||||
@ -1 +1 @@
|
||||
8d8c2cbec8325f4d323030eba4dbab1c4aad79e9
|
||||
cb2632961797127bb5ff4e523bee98da4af68e3f
|
||||
@ -1 +1 @@
|
||||
b1755a6258421b38d35fe8767ada159833aeee1c
|
||||
f55d225edb02f2ebd0e0a716968296c4aa7a3a7a
|
||||
Loading…
Reference in New Issue
Block a user