Skip to content

Commit aa214d0

Browse files
committed
One more test and aec3 access from config
1 parent 9f568d8 commit aa214d0

File tree

5 files changed

+83
-23
lines changed

5 files changed

+83
-23
lines changed

examples/aec-configs/config.json5

-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
{
2-
num_capture_channels: 1,
3-
num_render_channels: 2,
4-
52
config: {
63
echo_canceller: {
74
Full: {

examples/config_karaoke.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ struct Args {
2828
#[derive(Debug, Deserialize)]
2929
#[serde(default)]
3030
struct AppConfig {
31-
#[serde(default = "default_channels")]
3231
num_capture_channels: u16,
33-
#[serde(default = "default_channels")]
3432
num_render_channels: u16,
3533
#[serde(default)]
3634
config: Config,
@@ -41,8 +39,8 @@ struct AppConfig {
4139
impl Default for AppConfig {
4240
fn default() -> Self {
4341
Self {
44-
num_capture_channels: default_channels(),
45-
num_render_channels: default_channels(),
42+
num_capture_channels: 1,
43+
num_render_channels: 1,
4644
config: Config::default(),
4745
aec3: EchoCanceller3Config::default(),
4846
}
@@ -61,10 +59,6 @@ impl AppConfig {
6159
}
6260
}
6361

64-
fn default_channels() -> u16 {
65-
1
66-
}
67-
6862
fn create_processor(config: &AppConfig) -> Result<Processor, Error> {
6963
let mut processor = Processor::with_aec3_config(
7064
&InitializationConfig {

src/config.rs

+4
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,10 @@ pub struct Config {
368368
/// Toggles reporting of selected fields in [`Stats`].
369369
#[serde(default)]
370370
pub reporting: ReportingConfig,
371+
372+
/// Fine-grained AEC3 configuration parameters.
373+
#[serde(default)]
374+
pub aec3_config: Option<EchoCanceller3Config>,
371375
}
372376

373377
impl From<Config> for ffi::AudioProcessing_Config {

src/lib.rs

+75-7
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ mod tests {
394394
}
395395
}
396396

397+
/// A context to put abstracted methods commonly reused for tests.
397398
struct TestContext {
398399
processor: Processor,
399400
num_samples: usize,
@@ -441,6 +442,7 @@ mod tests {
441442
final_erl - initial_erl
442443
}
443444

445+
/// Warm up the AEC and then measure ERL
444446
fn measure_steady_state_performance(
445447
&mut self,
446448
render_frame: &[f32],
@@ -456,7 +458,7 @@ mod tests {
456458
warmup_iterations,
457459
);
458460

459-
// Measure steady state
461+
// Measure steady state and sum up the ERL reduction
460462
let mut total_reduction = 0.0;
461463
for _ in 0..measurement_count {
462464
let mut test_capture = capture_frame.clone();
@@ -608,9 +610,7 @@ mod tests {
608610
/// Measures baseline echo cancellation performance using industry metrics.
609611
///
610612
/// Uses a pure sine wave to create ideal test conditions. Verifies the AEC
611-
/// achieves at least 18dB Echo Return Loss Enhancement (ERLE)
612-
///
613-
/// Most echo cancellers are able to apply 18 to 35 dB ERLE.
613+
/// achieves at least 18dB ERL.
614614
#[test]
615615
fn test_echo_cancellation_effectiveness() {
616616
let mut context = TestContext::new(1);
@@ -635,7 +635,6 @@ mod tests {
635635

636636
/// Verifies that different AEC configurations produce measurably different results.
637637
///
638-
/// Compares Mobile vs Full modes under realistic conditions (noise + attenuation).
639638
/// These modes should have distinct echo cancellation behaviors by design.
640639
#[test]
641640
fn test_aec3_configuration_impact() {
@@ -663,11 +662,80 @@ mod tests {
663662
);
664663
}
665664

665+
/// Verifies that unique AEC configurations produce measurably different results.
666+
///
667+
/// This test is used to verify that a AEC3 configuration will apply and output
668+
/// different results (in this case, 4dB of ERL).
669+
#[test]
670+
fn test_aec3_configuration_tuning() {
671+
// Strong suppression configuration
672+
let strong_config = Config {
673+
echo_canceller: Some(EchoCanceller::default()),
674+
aec3_config: Some(EchoCanceller3Config {
675+
suppressor: Suppressor {
676+
dominant_nearend_detection: DominantNearendDetection {
677+
enr_threshold: 0.75,
678+
snr_threshold: 20.0,
679+
..Default::default()
680+
},
681+
high_bands_suppression: HighBandsSuppression {
682+
enr_threshold: 0.8,
683+
max_gain_during_echo: 0.3,
684+
..Default::default()
685+
},
686+
..Default::default()
687+
},
688+
..Default::default()
689+
}),
690+
..Default::default()
691+
};
692+
693+
// Light suppression configuration
694+
let light_config = Config {
695+
echo_canceller: Some(EchoCanceller::default()),
696+
aec3_config: Some(EchoCanceller3Config {
697+
suppressor: Suppressor {
698+
dominant_nearend_detection: DominantNearendDetection {
699+
enr_threshold: 0.25,
700+
snr_threshold: 30.0,
701+
..Default::default()
702+
},
703+
high_bands_suppression: HighBandsSuppression {
704+
enr_threshold: 1.2,
705+
max_gain_during_echo: 0.8,
706+
..Default::default()
707+
},
708+
..Default::default()
709+
},
710+
..Default::default()
711+
}),
712+
..Default::default()
713+
};
714+
715+
let mut context = TestContext::new(2);
716+
let render_frame = context.generate_sine_frame(440.0);
717+
718+
// Test strong suppression
719+
context.processor.set_config(strong_config);
720+
let strong_reduction = context.measure_steady_state_performance(&render_frame, 50, 10);
721+
722+
// Test light suppression
723+
context.processor.set_config(light_config);
724+
let light_reduction = context.measure_steady_state_performance(&render_frame, 50, 10);
725+
726+
// Verify the configurations produce measurably different results
727+
assert!(
728+
strong_reduction > light_reduction + 3.0,
729+
"Strong suppression ({:.1} dB) should achieve at least 3dB more reduction than light suppression ({:.1} dB)",
730+
strong_reduction,
731+
light_reduction
732+
);
733+
}
734+
666735
/// Validates AEC configuration state management across processing modes.
667736
///
668737
/// Tests that AEC metrics and behavior remain consistent when switching
669-
/// between different modes (Full vs Mobile). Ensures configuration changes
670-
/// are properly applied and maintained during audio processing.
738+
/// between different modes (Full vs Mobile).
671739
#[test]
672740
fn test_aec3_configuration_behavior() {
673741
let mut context = TestContext::new(2);

webrtc-audio-processing-sys/src/lib.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ mod tests {
233233
fn test_config_bindings_coverage() {
234234
use std::collections::HashSet;
235235

236-
// Helper to normalize field names into groups
236+
// Helper to normalize field names into groups - very ugly
237237
fn normalize_group_name(field: &str) -> Option<String> {
238238
let field = field.trim_matches(|c: char| c == '{' || c == '}' || c == ',' || c == ' ');
239239
if field.is_empty()
@@ -243,6 +243,7 @@ mod tests {
243243
}
244244

245245
// Handle special cases and normalize the field name
246+
// There might be some easier way to do this.
246247
let group = if field.contains("echo_audibility") {
247248
"echo_audibility"
248249
} else if field.contains("render_levels") {
@@ -278,10 +279,6 @@ mod tests {
278279
}
279280
}
280281

281-
// Debug output
282-
println!("Debug representation:\n{:#?}", config);
283-
println!("Found groups: {:?}", found_groups);
284-
285282
// Define expected groups based on C++ header
286283
let expected_groups = [
287284
"buffering",

0 commit comments

Comments
 (0)