Synthetic ERLE metric demo¶
Tutorial goal
Explain ERLE and MSE on a controlled synthetic echo-path identification problem.
Note
New to the terminology? See the lattice DSP concept map and the causality/data-use guide for how online, offline, block, and MIMO examples should be read.
Context¶
This tutorial is intentionally limited: it is a metric demonstration for a synthetic echo path, not a production acoustic echo canceller. It is useful for understanding the two-signal roles: a far-end/reference signal drives the unknown echo path, while a microphone/desired signal is used to measure the residual after subtracting the estimated echo.
Key idea and equations¶
With reference signal \(x[n]\) and microphone signal \(m[n]\), an adaptive echo-path model produces
Echo return loss enhancement is commonly reported as
A causal echo-path filter may use current and past reference samples and previous adaptive state. It must not use future microphone samples to form the current residual.
Causality and data use¶
This is a controlled two-signal synthetic metric demo. It uses reference/far-end and microphone/desired roles, unlike one-signal AR prediction. Real AEC systems require additional delay control, double-talk handling, nonlinear echo handling, and deployment-specific engineering.
How to read the result¶
Higher ERLE and lower MSE indicate better cancellation in this controlled synthetic setup only; they are not product-quality acoustic echo-cancellation claims.
Run command¶
python examples/echo_cancellation_erle_demo.py
Run status¶
Return code: 0
Captured stdout¶
Synthetic echo metric demo
--------------------------
No cancellation ERLE: 0.00 dB
FIR/NLMS ERLE: 24.98 dB
Lattice/IIR ERLE: 16.18 dB
ERLE = 10 log10(input echo/error power / output residual error power).
Positive ERLE means residual error power was reduced. It does not by
itself prove speech quality, especially during double-talk.
Final lattice reflection coefficients:
[ 0.2837 -0.1909 0.1629 -0.1216]
Source code¶
1"""Small synthetic echo-cancellation metric demo.
2
3This example is intentionally modest. It shows how the stable adaptive
4lattice/IIR stage behaves on a known synthetic echo problem and how ERLE is
5computed. It is not a production acoustic echo canceller.
6"""
7
8from __future__ import annotations
9
10import numpy as np
11
12from lattice_dsp import HybridEchoCanceller, echo_metrics, generate_echo_problem
13
14
15def fir_nlms(
16 reference: np.ndarray,
17 desired: np.ndarray,
18 *,
19 order: int = 64,
20 mu: float = 0.5,
21 epsilon: float = 1e-8,
22):
23 """Tiny FIR/NLMS reference baseline for this example."""
24
25 w = np.zeros(order, dtype=np.float64)
26 xbuf = np.zeros(order, dtype=np.float64)
27 y = np.zeros_like(reference, dtype=np.float64)
28 e = np.zeros_like(reference, dtype=np.float64)
29 for n, sample in enumerate(reference):
30 xbuf[1:] = xbuf[:-1]
31 xbuf[0] = sample
32 y_n = float(np.dot(w, xbuf))
33 e_n = float(desired[n] - y_n)
34 w += (mu * e_n / (float(np.dot(xbuf, xbuf)) + epsilon)) * xbuf
35 y[n] = y_n
36 e[n] = e_n
37 return y, e, w
38
39
40def main() -> None:
41 problem = generate_echo_problem(
42 samples=16_000,
43 sample_rate=16_000,
44 seed=123,
45 nonlinear_strength=0.0,
46 near_end_power_ratio=0.0,
47 noise_snr_db=60.0,
48 double_talk=False,
49 )
50
51 no_cancel = echo_metrics(problem.microphone, problem.microphone, problem.clean_target)
52
53 _, fir_residual, _ = fir_nlms(problem.reference, problem.microphone, order=64, mu=0.5)
54 fir_metrics = echo_metrics(problem.microphone, fir_residual, problem.clean_target)
55
56 canceller = HybridEchoCanceller(
57 initial_reflection=[0.0] * 4,
58 initial_taps=[0.0] * 5,
59 mu_taps=0.05,
60 mu_reflection=0.001,
61 reflection_update_period=8,
62 )
63 result = canceller.process(
64 problem.reference, problem.microphone, clean_target=problem.clean_target
65 )
66 lattice_metrics = echo_metrics(problem.microphone, result.residual, problem.clean_target)
67
68 print("Synthetic echo metric demo")
69 print("--------------------------")
70 print(f"No cancellation ERLE: {no_cancel.erle_db:8.2f} dB")
71 print(f"FIR/NLMS ERLE: {fir_metrics.erle_db:8.2f} dB")
72 print(f"Lattice/IIR ERLE: {lattice_metrics.erle_db:8.2f} dB")
73 print()
74 print("ERLE = 10 log10(input echo/error power / output residual error power).")
75 print("Positive ERLE means residual error power was reduced. It does not by")
76 print("itself prove speech quality, especially during double-talk.")
77 print()
78 print("Final lattice reflection coefficients:")
79 print(np.array2string(result.reflection, precision=4))
80
81
82if __name__ == "__main__":
83 main()