Раздели аудиопотоки и привяжи AEC к фактическому общему выходу
This commit is contained in:
1 parent
d7fb0c83f9
commit
bd082a26bf
30 files changed
+1839
-412
No files matched your search
+38
-1
@@ -56,7 +56,9 @@ static int test_lifecycle_and_null(void) {
|
||||
CHECK(speex_aec_create(0, FS, FILTER, DELAY_FRAMES) == NULL, "create(rate=0) should fail");
|
||||
CHECK(speex_aec_create(RATE, 0, FILTER, DELAY_FRAMES) == NULL, "create(frame=0) should fail");
|
||||
CHECK(speex_aec_create(RATE, FS, FS - 1, DELAY_FRAMES) == NULL, "create(filter<frame) should fail");
|
||||
CHECK(speex_aec_create(RATE, FS, FILTER, -3) != NULL, "create(delay=-3) should clamp, not fail");
|
||||
speex_aec_t* clamped = speex_aec_create(RATE, FS, FILTER, -3);
|
||||
CHECK(clamped != NULL, "create(delay=-3) should clamp, not fail");
|
||||
speex_aec_destroy(clamped);
|
||||
|
||||
CHECK(speex_aec_process_capture(NULL, pcm, FS, out) == 0, "process(NULL vad) should return 0");
|
||||
CHECK(speex_aec_process_capture(a, NULL, FS, out) == 0, "process(NULL pcm) should return 0");
|
||||
@@ -198,6 +200,40 @@ static int test_echo_suppression(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_stereo_microphones(void) {
|
||||
printf("[speex_aec] independent stereo references + two microphones\n");
|
||||
speex_aec_t* a = speex_aec_create_mc(RATE, FS, FILTER, 1, 2, 2);
|
||||
CHECK(a != NULL, "MC create failed");
|
||||
if (!a) return;
|
||||
int16_t render[FS * 2], input[FS * 2], output[FS * 2];
|
||||
double echo_power = 0, residual_power = 0, speech_power = 0, output_power = 0, cross = 0;
|
||||
for (int frame = 0; frame < 240; ++frame) {
|
||||
int double_talk = frame >= 160 && frame < 180;
|
||||
for (int i = 0; i < FS; ++i) {
|
||||
render[2*i] = aec_noise(); render[2*i+1] = aec_noise();
|
||||
int16_t speech = (int16_t)(3000 * sin(2 * M_PI * 440 * (frame * FS + i) / RATE));
|
||||
for (int ch = 0; ch < 2; ++ch) {
|
||||
int16_t echo = (int16_t)(render[2*i] * (ch ? -0.3 : 0.5) + render[2*i+1] * (ch ? 0.45 : 0.2));
|
||||
input[2*i+ch] = echo + (double_talk ? speech : 0);
|
||||
if (frame >= 180) echo_power += (double)echo * echo;
|
||||
}
|
||||
}
|
||||
speex_aec_feed_playback(a, render, FS * 2);
|
||||
CHECK(speex_aec_process_capture(a, input, FS * 2, output) == FS * 2, "MC capture count");
|
||||
for (int i = 0; i < FS * 2; ++i) {
|
||||
if (frame >= 180) residual_power += (double)output[i] * output[i];
|
||||
if (double_talk) {
|
||||
double speech = 3000 * sin(2 * M_PI * 440 * (frame * FS + i / 2) / RATE);
|
||||
speech_power += speech * speech; output_power += (double)output[i] * output[i]; cross += speech * output[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
printf(" MC residual=%.6f double-talk correlation=%.3f\n", residual_power / echo_power, cross / sqrt(speech_power * output_power));
|
||||
CHECK(residual_power < echo_power * 0.1, "MC echo not suppressed");
|
||||
CHECK(cross / sqrt(speech_power * output_power) > 0.7, "MC near-end speech distorted");
|
||||
speex_aec_destroy(a);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
debug_config_init();
|
||||
debug_set_level(DEBUG_LEVEL_INFO);
|
||||
@@ -208,6 +244,7 @@ int main(void) {
|
||||
test_lifecycle_and_null();
|
||||
test_delay_line();
|
||||
test_echo_suppression();
|
||||
test_stereo_microphones();
|
||||
|
||||
if (g_failures == 0) {
|
||||
printf("TEST PASSED\n");
|
||||
|
||||
Reference in new issue
Block a user