数式の離散表現
数学や信号処理をプログラミングで実装する際,注意すべきは連続と離散の取り違えである.数学などの専門書においては数式は連続型であるが,プログラミングする場合は離散型に適度に読み変える必要がある.今回は簡単に積分の離散表現を示す.
くわしい説明
はこういう形だとする.
これを時間間隔でサンプリングしたのがである.
はグラフの面積を表している.
これを離散的に表現すると,で表される長方形の面積の合計値で近似することになる.
数学や信号処理をプログラミングで実装する際,注意すべきは連続と離散の取り違えである.数学などの専門書においては数式は連続型であるが,プログラミングする場合は離散型に適度に読み変える必要がある.今回は簡単に積分の離散表現を示す.
はこういう形だとする.
これを時間間隔でサンプリングしたのがである.
これを離散的に表現すると,で表される長方形の面積の合計値で近似することになる.
記憶の整理のためにメモ.
記事の正しさに責任は持ちません.
追記。
↓qiitaに記事を投稿した。ブログ記事の焼き直しだが、より詳しく書いてるので良かったら見て欲しい。
qiita.com
ある信号(音響信号など)の周波数の時間変化(変調と言ったりする)を調べたい欲求がある人もいるだろうが,そういうのを調べるのを時間周波数解析という.時間周波数解析において一番知りたいのは「(目的の信号の)周波数の時間変化」であり,これは位相を時間微分することで求められ,これを瞬時周波数と呼ぶことにする.(速度の時間変化は速度を微分すると求められ,これはどうやら加速度と言うらしいのだが,位相を微分したものは瞬時周波数と言う.)
簡単にまとめると,
ある一瞬の周波数を知りたい
↓
位相を時間微分する
という素朴な考え方だ.
周波数が時間変化する信号を考える前に,
まず周波数が一定の信号を考える.
振幅,周波数(一定)である信号
ここで位相を微分するとであり,瞬時周波数は時間変化せず、周波数が一定であることを再確認できる.
次に周波数が時間変化する信号を考える.
瞬時周波数をで表す.
]で],
]で],
と周波数が線形変化する場合,
瞬時周波数の時間-周波数グラフは以下のようになる.
このグラフの式は
周波数の時間変化を見るには位相を微分すれば良かったので,逆向きに考えると,このような周波数の時間変化を持つ位相はを積分すれば求められる.
これをの中に入れると,
周波数が時間変化する信号
が出来上がる.
このスペクトログラムを求めると,
となり,期待通りの信号となった.
ちなみに,このように線形に周波数が変調する信号をLFM信号(Linear Frequency Modulated Signal,線形周波数変調信号)とか線形チャープ信号と言ったりする.
メモ.
検証していないので,情報に対して責任は一切持ちません.
コーエンクラスはウィグナー分布に似た形の関数=曖昧度関数と核関数の畳み込みとなっている.
核関数は何をしてるかっていうと,どうやらクロス項を抑制しているっぽい.
なんでクロス項を抑制できるの?と疑問である.
その辺は現在勉強中であるが,どうやら以下のようなイメージらしい.
核関数はチョイウィリアムス.
値は暗赤色=1,暗青色=0で,原点回りの値を抽出するようなフィルタである.
検証については,
実験的には曖昧度関数などを描いて信号が原点を通る直線になるのか確かめる.
理論的には曖昧度関数の勉強
が必要である.
仕事忙しくなってきたので検証はかなり後になりそう.
自分用メモ.計算が合ってるかは自信が無い.
何かあればコメントいただけるとありがたいです.
時間周波数解析手法の一種であるウィグナー分布において,正負の周波数成分を持つ信号や二つ以上の成分から成る信号を分析してみると,その中間部分にスペクトルが発生し,これをクロス項という.本来信号が無いはずの部分にスペクトルが出ているのはよろしくない(そのためクロス項を抑制するような研究が多くなされている).クロス項抑制のためには実信号を負の周波数を含まないような複素信号に変換してからウィグナー分布の計算を行う.負の周波数を含まない複素信号を解析信号という.今回は実信号から解析信号に変換する計算方法を詳しく書く.
解析信号を,実信号を,のフーリエ変換をとする.
これは普通の逆フーリエ変換である.
次に負の周波数を消し去る.ここの計算が本質部分である.
次にとして入れる.
とをくっつけて,積分順序を入れ替える.
内側のを計算するが,ここで
を用いる.(この計算はここでは詳しく計算しない.結果だけ用いる.)
内側の積分結果を元の式に代入して,第一項と第二項を分離する.
第一項のはについての積分だが,の時のみなので,
第二項のだが,の部分はヒルベルト変換なので,
と書く.
以上をまとめて,
となる.
実験用に正弦信号を作成することがある.例として1~1.5秒部分に5kHzの正弦波,1.5~3秒部分に10kHzの正弦波が含まれる信号の時間-振幅グラフを図1に,スペクトログラムを図2に示す(スペクトログラムを表示する部分までのmatlabコードを下に示す).スペクトログラムを見ると信号の開始時点及び終了時点において,周波数の広い範囲に大きい値が出ている(図3).これは信号が突然0→1に立ち上がる(終了時点では1→0になる)ことから,その時点においてあらゆる周波数が反応するのは当然である.しかしA[Hz]の正弦信号を入力したらA[Hz]のところにだけ値が出て来て欲しいわけで,そういうときは普通ならばスペクトログラムのウィンドウ幅を長くするなど分析側のパラメータを調整する必要がある.今回は理想的な信号が入ってくる場合の分析器の挙動を見たいので,分析側のパラメータを変えずに,実験用の信号を理想的なものに調整して綺麗な結果を出してみる.
% % 信号を生成してスペクトログラムを表示する % clear all; close all; clc Fs = 32000; SNRdB = -10; % 信号を生成する t1 = 1.5; f1 = 5000; N = Fs * t1; t = ((1:N)-1)/Fs; s1 = sin(2*pi*f1*t); t2 = 1.5; f2 = 10000; N = Fs * t2; t = ((1:N)-1)/Fs; s2 = sin(2*pi*f2*t); s0 = horzcat(s1, s2); % 信号の前後にpad_time秒間の無音部分をくっつける pad_time = 1; s = padarray(s0, [0 round(pad_time * Fs)], 0, 'both'); % 時間グラフを描く N = length(s); t = ((1:N)-1)/Fs; figure plot(t, s); title('信号の時間-振幅グラフ'); xlabel('時間(sec)'); ylabel('振幅'); % 信号のスペクトログラムを描画 Nw = 1024; Nol = Nw*3/4; NFFT = Nw; figure; spectrogram(s, Nw, Nol, NFFT, Fs, 'yaxis'); %ハミング窓 title('信号のスペクトログラム'); xlabel('時間(sec)'); colormap 'jet' caxis_max = -20; caxis_min = -120; caxis([caxis_min, caxis_max]);
信号の最初と終わりの部分だけ窓関数を掛けたような形である.ネタバレするとコサインテーパーウィンドウを掛けてやればいいわけだが,最初はハンウィンドウを前半後半に分けて信号の最初と終わりにそれぞれ掛けるというやり方を取っていた.
% % 上のコードの「信号を生成する」 の部分を下に入れ替える % % 信号の両端に少しだけ窓関数をかける single_sided_window_length_sec = 0.2;% 片側窓関数がかけられる時間 single_sided_window_length = single_sided_window_length_sec * Fs;% 窓関数の片側の長さ w = hann(single_sided_window_length * 2);% ハン窓を作成 figure N = length(w); t = ((1:N)-1)/Fs; plot(t, w); title('ハンウィンドウ'); xlabel('時間(sec)'); % 信号を生成する t1 = 1.5; f1 = 5000; N = Fs * t1; t = ((1:N)-1)/Fs; s1 = sin(2*pi*f1*t); % 窓関数をかける s1(1:single_sided_window_length) = w(1:single_sided_window_length)' .* s1(1:single_sided_window_length);% 左側 s1(end-single_sided_window_length+1:end) = w(single_sided_window_length+1:end)' .* s1(end-single_sided_window_length+1:end);% 右側 t2 = 1.5; f2 = 10000; N = Fs * t2; t = ((1:N)-1)/Fs; s2 = sin(2*pi*f2*t); % 窓関数をかける s2(1:single_sided_window_length) = w(1:single_sided_window_length)' .* s2(1:single_sided_window_length);% 左側 s2(end-single_sided_window_length+1:end) = w(single_sided_window_length+1:end)' .* s2(end-single_sided_window_length+1:end);% 右側 s0 = horzcat(s1, s2); % 信号の前後にpad_time秒間の無音部分をくっつける pad_time = 1; s = padarray(s0, [0 round(pad_time * Fs)], 0, 'both');
ハンウィンドウを分割して信号の前後にかけたものの時間-振幅グラフを図7,スペクトログラムを図8にそれぞれ示す.0→1に滑らかに変化しているので,スペクトログラムで欲しいところだけに信号が表示されている.
% % 上のコードの「信号を生成する」 の部分を下に入れ替える % single_sided_window_length_sec = 0.2;% 片側窓関数がかけられる時間 % 信号を生成する t1 = 1.5; f1 = 5000; N = Fs * t1; t = ((1:N)-1)/Fs; s1 = sin(2*pi*f1*t); % 窓関数をかける window_signal_length_ratio = (single_sided_window_length_sec*2)/t1;% 窓関数がかけられる時間の比 w = tukeywin(N, window_signal_length_ratio); figure plot(t, w); title('コサインテーパーウィンドウ'); xlabel('時間(sec)'); s1 = w' .* s1; t2 = 1.5; f2 = 10000; N = Fs * t2; t = ((1:N)-1)/Fs; s2 = sin(2*pi*f2*t); % 窓関数をかける window_signal_length_ratio = (single_sided_window_length_sec*2)/t2;% 窓関数がかけられる時間の比 w = tukeywin(N, window_signal_length_ratio); % 5kHzのコサインテーパーウィンドウと同じなのでグラフは省略 s2 = w' .* s2; s0 = horzcat(s1, s2); % 信号の前後にpad_time秒間の無音部分をくっつける pad_time = 1; s = padarray(s0, [0 round(pad_time * Fs)], 0, 'both');