web-dev-qa-db-ja.com

MATLABのwavファイルからノイズを除去

私はMATLABを電卓としてしか使用していませんので、プログラムにあまり詳しくありません。現在Googleは私の友人であるnotであるため、親切な人が道を案内してくれることを願っています。

下のリンクにwavファイルがありますが、背景には人間の声とノイズがあります。ノイズを除去したい。 MATLABでそれを行う方法を教えてくれる人はいますか?

https://www.dropbox.com/s/3vtd5ehjt2zfuj7/Hold.wav

14
user3338501

これはかなり不完全なソリューションです。特に、ノイズの一部はファイルで聞こえる音声と同じ周波数範囲に埋め込まれているため、ここでは何もしません。周波数スペクトルに関して私が話していたのは、音を聞くと、背景雑音のハムが非常に低いということです。これはスペクトルの低周波数範囲に存在しますが、音声はより高い周波数を持ちます。そのため、bandpassフィルターを適用して低ノイズを除去し、ほとんどの音声をキャプチャすると、高音側のノイズの多い周波数もキャンセルされます。

ここに私がした手順があります:

  1. audioread を使用してオーディオファイルを読み込みます。
  2. オリジナルのサウンドを再生して、使用する音が聞こえるようにします。これを行うには、 audioplayer オブジェクトを作成します。
  3. 左右のチャンネルの両方をプロットして、時間領域で音声信号を見てみましょう...手掛かりがあれば。チャンネルを見ると、どちらも同じように見えるので、両方のチャンネルにマッピングされた単一のマイクのように見えます。
  4. フーリエ変換を使用して、周波数分布を見ました。
  5. (4)を使用して、周波数をカットする場所の大まかな近似を見つけました。
  6. これらの周波数を遮断するバンドパスフィルターを設計しました。
  7. 信号をフィルタリングし、別のaudioplayerオブジェクトを作成して再生しました。

じゃあ、行きましょう!


ステップ1

%% Read in the file
clearvars;
close all;
[f,fs] = audioread('Hold.wav');

audioreadは音声ファイルを読み込みます。 ''内で必要なファイルを指定するだけです。また、作業ディレクトリをこのファイルが保存されている場所に設定してください。 clearvars, close allただクリーンアップしてください。すべてのウィンドウを閉じ(開いている場合)、MATLABワークスペース内のすべての変数をクリアします。 fはMATLABに読み込まれる信号で、fsは信号のサンプリング周波数です。 fは2Dマトリックスです。最初の列は左チャンネルで、2番目の列は右チャンネルです。一般に、オーディオファイルのチャネルの総数は、audioreadを介して読み込まれるこのマトリックスの列の総数で示されます。

ステップ2

%% Play original file
pOrig = audioplayer(f,fs);
pOrig.play;

この手順では、サンプリング周波数(audioplayer)で読み取り信号(f)を取り、fsに格納されているオブジェクトを出力するpOrigオブジェクトを作成できます。次に、pOrig.playを使用して、MATLABでファイルを再生し、聞こえるようにします。

ステップ#3

%% Plot both audio channels
N = size(f,1); % Determine total number of samples in audio file
figure;
subplot(2,1,1);
stem(1:N, f(:,1));
title('Left Channel');
subplot(2,1,2);
stem(1:N, f(:,2));
title('Right Channel');

stem は、MATLABで離散点をプロットする方法です。各時点には、その時点で描かれた円があり、水平軸からその時点までの垂直線が描かれています。 subplot は、同じウィンドウに複数の図を配置する方法です。ここでは取り上げませんが、subplotの詳細な動作については、ここで書いた このStackOverflowの投稿を参照することで読むことができます 。上記のコードは、以下に示すプロットを生成します。

signals

上記のコードは非常に単純です。各サブプロットで各チャンネルを個別にプロットしています。

ステップ#4

%% Plot the spectrum
df = fs / N;
w = (-(N/2):(N/2)-1)*df;
y = fft(f(:,1), N) / N; % For normalizing, but not needed for our analysis
y2 = fftshift(y);
figure;
plot(w,abs(y2));

最も恐ろしく見えるコードは、上記のコードです。信号やシステムから思い出すと、信号で表される最大周波数は、サンプリング周波数を2で割った値です。これは、 ナイキスト周波数と呼ばれます 。オーディオファイルのサンプリング周波数は48000 Hzです。つまり、オーディオファイルで表される最大周波数は24000 Hzです。 fft は、 Fast Fourier Transform を表します。フーリエ変換を計算する非常に効率的な方法と考えてください。従来の式では、出力の各要素に対して複数の合計を実行する必要があります。 FFTは、はるかに少ない操作でこれを効率的に計算し、同じ結果を提供します。

fftを使用して、信号の frequency spectrum を調べています。 fftを呼び出すには、最初のパラメーターとして必要な入力信号を指定し、次に2番目のパラメーターで評価するポイント数を指定します。 FFTのポイント数を信号の長さに指定するのが一般的です。これを行うには、サウンドマトリックスに何行あるかを確認します。周波数スペクトルをプロットするとき、他のチャンネルは同じであるため、物事を簡単にするために1つのチャンネルを使用しました。これは、fftへの最初の入力として機能します。また、Nで除算することは、信号を正規化する適切な方法であるため、注意してください。ただし、周波数ドメインがどのように見えるかのスナップショットを取得するだけなので、実際にこれを行う必要はありません。ただし、後で何かを計算するためにそれを使用することを計画している場合は、間違いなく必要です。

デフォルトではuncenteredであるため、追加のコードをいくつか作成しました。 fftshift を使用して、中心が0 Hzにマッピングされ、左側が0から-24000Hzに、右側が0から24000 Hzにまたがるようにしました。これは直感的に周波数スペクトルを見る方法です。負の周波数は、反対方向に伝播する周波数と考えることができます。理想的には、負の頻度の頻度分布は正の頻度と等しくなければなりません。周波数スペクトルをプロットすると、その周波数が出力にどの程度寄与しているかがわかります。これは、信号のmagnitudeによって定義されます。これを見つけるには、 abs 関数を使用します。得られる出力を以下に示します。

enter image description here

プロットを見ると、低周波数範囲の周囲に多くのスパイクがあります。これはハミングに対応しますが、音声はおそらくより高い周波数範囲にマッピングされ、それほど多くの音声は聞こえないため、それほど多くはありません。

ステップ#5

試行錯誤を繰り返し、ステップ#5を見ると、700 Hz以下のすべてがハミングノイズに対応し、12000 Hz以上のノイズの寄与が大きいことがわかりました。

ステップ6

Signal Processing Toolboxの butter 関数を使用して、バンドパスフィルターを設計できます。ただし、このツールボックスがない場合は、 このStackOverflow post を参照して、同じことを実現するユーザー作成関数を参照してください。ただし、そのフィルターの順序は2のみです。butter関数を使用できると仮定すると、フィルターの順序を把握する必要があります。順序が高いほど、より多くの作業が行われます。 n = 7を選択して開始します。また、周波数をnormalizeして、ナイキスト周波数が1にマッピングされ、他のすべてが0から1にマッピングされるようにする必要があります。それができたら、次のようにbutterを呼び出すことができます。

[b,a] = butter(n, [beginFreq, endFreq], 'bandpass');

bandpassフラグは、バンドパスフィルターを設計することを意味し、beginFreqおよびendFreqは、バンドパスフィルターに使用する正規化された開始および終了周波数にマップします。この例では、beginFreq = 700 / NyquistendFreq = 12000 / Nyquistです。 b,aは、このタスクの実行に役立つフィルターに使用される係数です。これらは次のステップで必要になります。

%% Design a bandpass filter that filters out between 700 to 12000 Hz
n = 7;
beginFreq = 700 / (fs/2);
endFreq = 12000 / (fs/2);
[b,a] = butter(n, [beginFreq, endFreq], 'bandpass');

ステップ7

%% Filter the signal
fOut = filter(b, a, f);

%% Construct audioplayer object and play
p = audioplayer(fOut, fs);
p.play;

filter を使用して、ステップ6で得たものを使用して信号をフィルタリングします。 fOutがフィルター処理された信号になります。再生したい場合は、入力と同じサンプリング周波数で、この出力信号に基づいてaudioplayerを作成できます。次に、p.playを使用して、MATLABでそれを聞きます。

これをすべて試して、それがどのように機能するかを確認してください。おそらく、ステップ6と7で最も多くのことをする必要があります。これは完璧な解決策ではありませんが、開始するには十分です。

幸運を!

41
rayryeng