適応フィルタによるアコースティックエコーの抑制
アコースティックエコーは、音声通信においてスピーカーから出力された音がマイクに再度入り込むことで発生し、通話品質を低下させる大きな要因となります。この問題を解決するために用いられるのが適応フィルタリング技術です。適応フィルタは、未知の音響環境(インパルス応答)を推定し、擬似的なエコー信号を生成して元の信号から差し引くことでエコーを除去します。
適応アルゴリズムの目的は、目的信号 $d(n)$ とフィルタ出力 $y(n)$ の差である誤差信号 $e(n)$ を最小化するようにフィルタ係数 $w(n)$ を逐次更新することです。代表的な手法として、LMS(Least Mean Square)アルゴリズムとその改良版であるNLMS(Normalized Least Mean Square)アルゴリズムが挙げられます。
LMS(最小平均二乗)アルゴリズム
LMSアルゴリズムは、勾配降下法に基づき、平均二乗誤差を最小化するようにフィルタのタップ係数を更新します。計算負荷が低く、実装が容易であることから、適応フィルタの標準的な手法として広く普及しています。
係数更新式
LMSの更新式は以下のように定義されます:
w(n + 1) = w(n) + 2 * μ * e(n) * x(n)
ここで:
- $w(n)$: 時刻 $n$ におけるフィルタ係数ベクトル
- $x(n)$: 入力信号ベクトル
- $e(n)$: 誤差信号(期待値 $d(n)$ - 出力 $y(n)$)
- $\mu$: ステップサイズ(収束速度と安定性を決定するパラメータ)
MATLABによるLMSの実装
以下に、LMSアルゴリズムを用いたエコーキャンセレーションのシミュレーションコードを示します。変数名や構造を最適化し、可読性を高めています。
% LMSアルゴリズムのシミュレーション
clear; clc;
% パラメータ設定
num_samples = 1000;
filter_order = 8;
learning_rate = 0.02; % ステップサイズ
target_snr = 20;
% 未知の音響系(システム系)の定義
true_impulse_response = [0.8, -0.5, 0.6, -0.3, 0.6, -0.05, 0.3, -0.2];
true_impulse_response = true_impulse_response(1:filter_order);
% 入力信号の生成(白色雑音を想定)
input_signal = sign(rand(num_samples, 1) - 0.5);
% エコー信号の生成(システム系との畳み込み)
echo_signal = filter(true_impulse_response, 1, input_signal);
desired_signal = awgn(echo_signal, target_snr, 'measured');
% 適応フィルタの初期化
adaptive_weights = zeros(filter_order, 1);
error_history = zeros(num_samples, 1);
% 適応処理ループ
for n = filter_order : num_samples
% 入力ベクトルの抽出
x_vector = input_signal(n : -1 : n - filter_order + 1);
% フィルタ出力の計算
estimation = adaptive_weights' * x_vector;
% 誤差の算出
current_error = desired_signal(n) - estimation;
% フィルタ係数の更新
adaptive_weights = adaptive_weights + 2 * learning_rate * current_error * x_vector;
% 誤差の記録(二乗誤差)
error_history(n) = current_error^2;
end
% 結果の可視化
figure;
plot(10 * log10(error_history + eps), 'LineWidth', 1.5);
title('LMSアルゴリズムによる収束特性');
xlabel('サンプル数'); ylabel('誤差 [dB]');
grid on;
NLMS(正規化最小平均二乗)アルゴリズム
標準的なLMSの課題は、入力信号の電力変化に対して収束性能が依存することです。これを改善したのがNLMSです。NLMSでは、入力信号のエネルギーによってステップサイズを正規化し、信号強度の変動に左右されない安定した収束を実現します。
係数更新式
NLMSの更新式は以下の通りです:
w(n + 1) = w(n) + [ α / (||x(n)||^2 + ε) ] * e(n) * x(n)
ここで $\alpha$ は調整用のステップサイズ(通常 0 < $\alpha$ < 2)、$\epsilon$ はゼロ除算を防ぐための微小定数です。入力ベクトルの二乗ノルムで除算することで、更新強度が常に適切に保たれます。
MATLABによるNLMSの実装
NLMSは実環境の音声信号のように強弱が激しい入力に対して、LMSよりも高速かつ安定して収束します。
% NLMSアルゴリズムのシミュレーション
clear; clc;
% 設定
N = 1000;
tap_length = 8;
alpha = 0.5; % 適応定数
epsilon = 1e-6; % 安定化定数
% 未知系の設定
h_system = [0.8, -0.5, 0.6, -0.3, 0.6, -0.05, 0.3, -0.2]';
% 信号生成
u = randn(N, 1); % 入力信号
d = filter(h_system, 1, u) + 0.01 * randn(N, 1); % 観測信号(ノイズ含む)
% 初期化
w_nlms = zeros(tap_length, 1);
ms_error = zeros(N, 1);
% NLMSループ
for k = tap_length : N
u_vector = u(k : -1 : k - tap_length + 1);
% 推定出力と誤差
y_hat = w_nlms' * u_vector;
e_k = d(k) - y_hat;
% 正規化ステップサイズによる更新
norm_factor = u_vector' * u_vector + epsilon;
w_nlms = w_nlms + (alpha / norm_factor) * e_k * u_vector;
ms_error(k) = e_k^2;
end
% 結果表示
figure;
plot(10 * log10(smooth(ms_error, 10) + eps), 'r', 'LineWidth', 1.5);
title('NLMSアルゴリズムの誤差推移');
xlabel('反復回数'); ylabel('MSE [dB]');
grid on;
アルゴリズムの比較と特性
LMSとNLMSの主な違いは、収束速度と入力信号に対する頑健性です。LMSは計算が最もシンプルですが、ステップサイズ $\mu$ の設定を誤ると発散しやすく、また入力信号の振幅が変わるたびに最適な $\mu$ を再調整する必要があります。
対してNLMSは、入力ベクトルのエネルギーでステップサイズを自動的にスケーリングするため、音声信号のようにダイナミックレンジの広い入力に対しても安定して動作します。実世界の適応エコーキャンセラ(AEC)においては、その計算効率と性能のバランスからNLMSが一般的に採用されます。