Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

適応線スペクトル強調器 (ALE)

この例では、適応線スペクトル強調器 (ALE) と呼ばれる構造を使用する適応フィルターにより、信号分離を行う方法を示します。適応線スペクトル強調では、測定信号 x(n) には、目的の不明な信号 v(n) とほぼ周期的なノイズ信号 eta(n) の 2 つの信号が含まれます。

この例の目的は、測定信号からノイズ信号を除去して、目的の信号を取得することです。

目的の信号の読み込み

まず、目的の信号 (ヘンデルのハレルヤ コーラスからのショート クリップ) を読み込みます。

audioReader = dsp.AudioFileReader('handel.ogg','SamplesPerFrame',44100);
timeScope = timescope('SampleRate',audioReader.SampleRate,...
    'YLimits',[-1,1],'TimeSpan',1,'TimeSpanOverrunAction','Scroll');

while ~isDone(audioReader)
    x = audioReader() / 2;
    timeScope(x);
end

サウンド クリップの再生

目的の信号はオーディオ デバイス ライターを使用して再生できます。

release(audioReader); 
audioWriter = audioDeviceWriter;
while ~isDone(audioReader)
    x = audioReader() / 2;
    audioWriter(x);
end

ノイズ信号の生成

周期的なノイズ信号 (周波数 1,000 Hz の正弦波) を作成します。

sine = dsp.SineWave('Amplitude',0.5,'Frequency',1000,...
    'SampleRate',audioReader.SampleRate,...
    'SamplesPerFrame',audioReader.SamplesPerFrame);

この正弦波信号の 10 ミリ秒をプロットします。予想どおり、10 ミリ秒で 10 の期間が表示されます。

eta = sine();
Fs  = sine.SampleRate;
plot(1/Fs:1/Fs:0.01,eta(1:floor(0.01*Fs)));
xlabel('Time [sec]');
ylabel('Amplitude');
title('Noise Signal, eta(n)');

Figure contains an axes object. The axes object with title Noise Signal, eta(n), xlabel Time [sec], ylabel Amplitude contains an object of type line.

ノイズの再生

周期的なノイズは純音です。以下のコードは、1 秒のノイズ信号 (1 フレームは 44100 サンプル) を再生します。

eta = sine();
release(audioWriter);
audioWriter(eta);

測定信号

実際に測定する信号は、これらの 2 つの信号の混合信号です。この信号を s(n) とします。s(n) のプロットは、音楽信号の包絡線が大幅に不明瞭であることを示します。測定信号から 3 秒のクリップを再生すると、ノイズが顕著です。

release(audioReader);
release(timeScope);
release(audioWriter);
count = 1;
while count < 4
    s = (audioReader() / 2) + sine();
    timeScope(s);
    audioWriter(s);
    count = count + 1;
end

適応フィルターの設定

適応線スペクトル増幅器 (ALE) は、線形予測のわかりやすい概念に基づいています。ほぼ周期的な信号は、以前のサンプルの線形統合を使用して完璧に予測することができます。非周期的な信号の場合は不可能です。したがって、測定信号 s(n-D) の遅延バージョンを適応フィルターへの基準入力信号 x(n) として使用し、目的の応答信号 d(n) を s(n) と同じにします。そのようなシステムで選択するパラメーターは、適応線形推定で使用する信号遅延 "D" とフィルター長 "L" です。遅延の量は、目的の信号の相関の量によって異なります。この信号がないので、D=100 の値を使用して、後で変更することにします。このような選択は、約 12 ミリ秒以上離れている場合、ハレルヤ コーラスのサンプルは無相関であることを示唆します。また、適応フィルターに L=32 の値を選択します。この値も変更される可能性があります。

D = 100;
delay = dsp.Delay(D);

最後に、x(n) と d(n) のベクトルの長さがブロック長の整数倍である必要のあるいくつかのブロック適応アルゴリズムを使用します。N=49 のブロック長から始めます。

ブロック LMS

使用する最初のアルゴリズムは、ブロック LMS アルゴリズムです。このアルゴリズムは、広く知られている最小平均二乗 (LMS) アルゴリズムと似ていますが、サンプルごとの係数更新ではなく、ブロックでの係数更新が使用されます。ブロック LMS アルゴリズムは、フィルターの長さ、ブロック長 "N" およびステップ サイズ値 "mu" を必要とします。まず mu = 0.0001 から開始して、調整していくことにします。

L  = 32;
N  = 49;
mu = 0.0001;
blockLMSFilter = ...
    dsp.BlockLMSFilter('Length',L,'StepSize',mu,'BlockSize',N);

フィルターの実行

すべてが適切に設定されていれば、出力信号 y(n) には周期的な正弦波が含まれ、誤差信号 e(n) には音楽信号が含まれるはずです。元の音楽信号 v(n) があるので、e(n) と v(n) を残差信号 e(n)-v(n) と共に上記と同じプロットにプロットできます。システムは、このステップ サイズの適応の約 5 秒後に収束するようです。実際に信号を聴いて確かめてください。

release(audioReader);
release(timeScope);
release(audioWriter);
while ~isDone(audioReader)
    x = audioReader() / 2;
    s = x + sine();
    d = delay(s);
    [y,e] = blockLMSFilter(s,d);
    timeScope(e);
    audioWriter(e);
end

正弦波ノイズがゆっくりと減衰することがわかります。この動作は、フィルター係数が最適な値に向かって適応されていることが原因です。

FM ノイズ発信源

目的の正弦波がわかっている場合、正弦波と音楽信号の混在信号から純正弦波を除去することは困難ではありません。シンプルな 2 極の 2 零点のノッチ フィルターを使用できます。そこで、FM 変調した正弦信号をノイズ発生源として追加し、問題を少し難しくしてみます。

eta = 0.5 * sin(2*pi*1000/Fs*(0:396899)' + 10*sin(2*pi/Fs*(0:396899)'));
signalSource = dsp.SignalSource(eta,...
    'SamplesPerFrame',audioReader.SamplesPerFrame,...
    'SignalEndAction','Cyclic repetition');
release(audioReader);
release(timeScope);
release(audioWriter);
while ~isDone(audioReader)
    x = audioReader() / 2;
    s = x + signalSource();
    timeScope(s);
    audioWriter(s);
end

信号内のさえずるような音が聞こえます。固定係数ノッチ フィルターでは、FM 変調された正弦波を除去できません。ブロック LMS ベースの ALE を試してみましょう。ステップ サイズ値を mu=0.005 に増加し、ALE がノイズ信号内のバリエーションをトラックできるようにします。

mu = 0.005;
release(blockLMSFilter);
blockLMSFilter.StepSize = mu;

適応フィルターの実行

ノイズを含む音楽信号を適応フィルターでフィルター処理し、ノイズのない音楽信号と誤差を比較します。

release(audioReader);
release(timeScope);
release(audioWriter);
while ~isDone(audioReader)
    x = audioReader() / 2;
    s = x + signalSource();
    d = delay(s);
    [y,e] = blockLMSFilter(s,d);
    timeScope([x,e]);
    audioWriter(e);
end

release(audioReader);
release(timeScope);

release(audioWriter);