by H.Yanase
本講座はMathematicaを利用してフーリエ解析を学び、実際に音声解析をしようとするものである。
Mathematicaを利用する際の注意も記した。
対象は高校卒業程度であるがこだわらない、時として大学程度の数式も登場するが数学や物理に
興味があるもの、手元にMathematicaがあるものは挑戦してほしい。
Mathematicaについて不慣れな人はまず前講座の「Mathematicaの基礎」を一読することを勧める。
まず、このファイルを別な名前で保存しておこう。そうすれば自由に変えたり、失敗もできる。
Mathematicaがない場合でも以下のサイトからMathReaderを無料でダウンロードしてくれば
Mathematicaと同じようにアニメーションや3次元の回転などが可能である。
【はじめに】
パソコンでは音楽や画像などを圧縮したり、再生したりすることができる。これら多くの
情報を処理を解析するのにフーリエ変換の技術が使われる。その基礎をここで見ていこう。
はじめに次のような三角関数の和を描かせてみよう。
xの関数の定義は次のようにする。
ここではf1とf2の2つの関数を作る。
まずf1につてグラフを描かせてみると
![[Graphics:Images/FourieA_gr_1.gif]](Images/FourieA_gr_1.gif)
三角関数を合成すると実に多様な関数ができる。その基本は次の関係にある。
![[Graphics:Images/FourieA_gr_6.gif]](Images/FourieA_gr_6.gif)
このように三角関数には周期2πで積分するとサインやコサイン同士はπ、
ことなったもの同士では0になる性質がある。
これを利用するとサインやコサインがごちゃごちゃ混ざった関数からサインやコサイン
がどの程度の強さで混ざっているかを知ることができる。
たとえば次のようなサインが ,コサインが
の強さで混ざった関数を異なった
周期で足しあわせたものを定義しよう。
![[Graphics:Images/FourieA_gr_12.gif]](Images/FourieA_gr_12.gif)
例えば3つ足しあげると次のようなグラフになる
![[Graphics:Images/FourieA_gr_13.gif]](Images/FourieA_gr_13.gif)
さて、これに次のようにコサイン、サインをかけて積分してみよう。
平均して正しい結果を得るために全体を しておく。
![[Graphics:Images/FourieA_gr_17.gif]](Images/FourieA_gr_17.gif)
みごとにコサイン、サインの前の係数が出てきた。
足しあわせる数を増やしても、また適当に係数を変えても結果は正しく出てくる。
自分でいろいろ試してみよう。
このようにサインとコサインをかけて積分すればその係数がわかるから、そしたら同じように
係数をつけてサイン、コサインの足しあわせをつくれば元の関数が再現できることになる!
えっ!「元の関数がサインやコサインでなければダメだろう?」それはいい質問だね。
ところが先の足しあわせの関数はnをいくらでも大きくできるし、周期も変えられる。
するとほとんどの関数はサインやコサインでできてしまうんだよ。
次にこの様子を見ていこう。
例えば次のような凸凹した関数はさすがにサインやコサインでは表現できないだろうと感じるね?
![[Graphics:Images/FourieA_gr_20.gif]](Images/FourieA_gr_20.gif)
ところが次のようなサインの足しあわせの関数を定義しよう。
![[Graphics:Images/FourieA_gr_23.gif]](Images/FourieA_gr_23.gif)
![[Graphics:Images/FourieA_gr_24.gif]](Images/FourieA_gr_24.gif)
もっとnを大きくしてグラフにしよう。nを大きくしても苦にならないのはPCの魅力である。
![[Graphics:Images/FourieA_gr_27.gif]](Images/FourieA_gr_27.gif)
おみごと!
凸凹関数ができてしまった!。
サインやコサインの係数を積分して求め、次にこの係数でサインやコサインを足しあわせると
どんな関数でも再現できる!?
このサインやコサインを足しあわせた関数をフーリエ級数というよ。
ではフーリエ級数の基本を感じたところで次の練習問題でためして見よう。
【問題1】次の関数を三角関数の和で表現せよ。
![[Graphics:Images/FourieA_gr_30.gif]](Images/FourieA_gr_30.gif)
【例解】
奇関数(-πから0と0からπの対称性)であるから先のサインを用いる。そして範囲を0からπとして2倍する。
まず、元の関数にサインをかけて係数を求めてみよう。
![[Graphics:Images/FourieA_gr_32.gif]](Images/FourieA_gr_32.gif)
そして全体を して足しあわせる関数を次のようにつくる。
![[Graphics:Images/FourieA_gr_35.gif]](Images/FourieA_gr_35.gif)
以下nが3、20、100の場合を図示する。
![[Graphics:Images/FourieA_gr_36.gif]](Images/FourieA_gr_36.gif)
![[Graphics:Images/FourieA_gr_39.gif]](Images/FourieA_gr_39.gif)
![[Graphics:Images/FourieA_gr_42.gif]](Images/FourieA_gr_42.gif)
なんとか再現できたね。
このように元の関数をサインやコサインで分解して適当な係数をかけて
足しあわせたものにすることをフーリエ変換というよ。
でもよく見ると元のグラフの不連続なところ(原点)では
ギザギザがでてくるね。これをギプス現象という。
【問題2】次の関数をフーリエ級数で表せ
![[Graphics:Images/FourieA_gr_45.gif]](Images/FourieA_gr_45.gif)
【例解】
今度は偶関数(y軸対称)であるからコサインを使う。
さてコサインはxが0でも1という値をもつから次のようにa0という項
を余分につけることを忘れないように!
![[Graphics:Images/FourieA_gr_47.gif]](Images/FourieA_gr_47.gif)
係数が求まったから次にコサインの足しあわせを次のように作る。
![[Graphics:Images/FourieA_gr_50.gif]](Images/FourieA_gr_50.gif)
同様にnが3と10の場合を描く。
![[Graphics:Images/FourieA_gr_51.gif]](Images/FourieA_gr_51.gif)
![[Graphics:Images/FourieA_gr_54.gif]](Images/FourieA_gr_54.gif)
元が滑らかで、連続な関数であるためギプス現象が見られない。
つまりフーリエ変換がうまくいく関数はなめらかに連続しているという性質が
あることがわかるね。
フーリエ変換の応用範囲はさらに広い。例えばギターのような弦の振動の解析にも使える。
次のような初期状態から弦をはじくことを最初に考えよう。
例えば弦の長さがここではL=10としxが4のところで1だけ持ち上げる。
![[Graphics:Images/FourieA_gr_57.gif]](Images/FourieA_gr_57.gif)
![[Graphics:Images/FourieA_gr_58.gif]](Images/FourieA_gr_58.gif)
次に前と同じようまず係数を求めよう。上の関数をフーリエサイン変換する。
グラフは2種類あるため場合分けしてその後、加える。
![[Graphics:Images/FourieA_gr_61.gif]](Images/FourieA_gr_61.gif)
結果を簡単にして整理し、係数Aを決める。
![[Graphics:Images/FourieA_gr_62.gif]](Images/FourieA_gr_62.gif)
あとは先と同じようにこの係数にサインをかけて足しあわせればよい。
本当は無限大まで足すのだったけどここでは後で実際に計算させるために
次のように最大jまで足すようにする。
もう一つ、弦の振動は時間的にも振動するそのために次のように
角振動数をωnとして Cos[ωn t]をかけておく。
![[Graphics:Images/FourieA_gr_64.gif]](Images/FourieA_gr_64.gif)
![[Graphics:Images/FourieA_gr_65.gif]](Images/FourieA_gr_65.gif)
![[Graphics:Images/FourieA_gr_66.gif]](Images/FourieA_gr_66.gif)
このノートブックでは上の図の右タグに下矢印がついてある部分を選択してCTRL+Yで動く
さらに時間変化も一緒に3次元のグラフにすることもできる。
自由に回転ができるようにするためにパッケージRealTime3Dをロードしておこう。(Ver4以上)
![[Graphics:Images/FourieA_gr_116.gif]](Images/FourieA_gr_116.gif)
![[Graphics:Images/FourieA_gr_117.gif]](Images/FourieA_gr_117.gif)
これでマウスで回転して好きな方向から眺めることができる。
上の例では実は次のような運動方程式をフーリエ変換を利用して解いている。
![[Graphics:Images/FourieA_gr_120.gif]](Images/FourieA_gr_120.gif)
さらに次のような外力があるときをここでは考えよう。
フーリエ変換はこのような場合でも簡単に解を出すことができる。
ここでは少々数式を用いることになるので
興味ないものはとばしてよい。
![[Graphics:Images/FourieA_gr_121.gif]](Images/FourieA_gr_121.gif)
まず一般的に考えよう。弦の長さをlとする。
外力fが働くとき運動方程式は解uを次のよう変数分離しておく
![[Graphics:Images/FourieA_gr_124.gif]](Images/FourieA_gr_124.gif)
外力fが次のようにフーリエ変換できたとすると係数Fnは次のように与えられる。
![[Graphics:Images/FourieA_gr_125.gif]](Images/FourieA_gr_125.gif)
初期条件を次のように与えると
![[Graphics:Images/FourieA_gr_126.gif]](Images/FourieA_gr_126.gif)
運動方程式からTnについて次が求まる。
![[Graphics:Images/FourieA_gr_127.gif]](Images/FourieA_gr_127.gif)
この解は次のようになる
![[Graphics:Images/FourieA_gr_128.gif]](Images/FourieA_gr_128.gif)
従って解は
![[Graphics:Images/FourieA_gr_129.gif]](Images/FourieA_gr_129.gif)
ここで具体的に先の外力fを用いる。
上の一般解に従って係数Fnと解uを次のようにおく。
ただし、nについては最大jまで足すようにしておく。
![[Graphics:Images/FourieA_gr_130.gif]](Images/FourieA_gr_130.gif)
では適当に数値を代入して図を描かせてみよう。
![[Graphics:Images/FourieA_gr_131.gif]](Images/FourieA_gr_131.gif)
このノートブックでは上の図の右タグに下矢印がついてある部分を選択してCTRL+Yで動く
今度は振動が一定ではないのがわかるね上のωnやωの値を変えるとどうなるか試してみるといい。
さらに上の式のAn、Bnはt=0のはじめの状態での弦の様子を決める。
例えばAn=1としてみよう。
![[Graphics:Images/FourieA_gr_165.gif]](Images/FourieA_gr_165.gif)
最後のにこの様子を3次元にして比較してみよう。
![[Graphics:Images/FourieA_gr_199.gif]](Images/FourieA_gr_199.gif)
パソコンなどで扱うデータはデジタル化されている。
こうしたデータを効率よくフーリエ変換するのがFFTと呼ばれる高速フーリエ変換だ。
Mathematicaには任意のデータをFFT処理するためのコマンド、Fourier[データ]が用意されて
いる。ここではこの関数の性質をみていくことにする。
興味ある人は Fourie のところにカーソルを持っていってf1キーを押してヘルプを見てみよう
なにやらむずかしいことがいっぱい書いてあるようだけどくじけることはない、使いながら理解していこう。
まず離散化したデータをTableコマンドで作成し、ListPlotを利用して作図する。
次の例ではxが1から200までのデータ列を作成している。
点をつなげない例とPlotJoined->Trueを利用し、つなげた例を以下に示す。
![[Graphics:Images/FourieA_gr_204.gif]](Images/FourieA_gr_204.gif)
![[Graphics:Images/FourieA_gr_205.gif]](Images/FourieA_gr_205.gif)
ここで実際に作成したt1の中身を覗いてみよう。10個みるのは次のようにする。
![[Graphics:Images/FourieA_gr_210.gif]](Images/FourieA_gr_210.gif)
では次のようにこのデータをフーリエ変換し、作図させよう。
![[Graphics:Images/FourieA_gr_212.gif]](Images/FourieA_gr_212.gif)
データー数200の中点100を中心に左右対称なグラフができた。
グラフのピークを詳しくするために次のようにレンジを変えてみよう。
![[Graphics:Images/FourieA_gr_215.gif]](Images/FourieA_gr_215.gif)
9のあたりにピークが出ているのがわかるね。
では刻みを2倍にしてデーター数だけ半分にしたらどうなるだろうか。
Mathematicaのマスターのこつは「思いついたらすぐ実行」「困ったときはすぐヘルプ」である。
ではさっそく試行錯誤といこう!
次の例では1から200まで2ずつ増やしてデータを作っている。
![[Graphics:Images/FourieA_gr_218.gif]](Images/FourieA_gr_218.gif)
予想通り先と半分の50のところで対称になっている。
でもピークの位置はかわらないね。ただ強さ(ピークの高さ)は小さくなっている。
これだけでデーターの数がピークの高さに関係していることがわかる。
では次の謎解きはピークの位置は何で決まるのかである。
そのためには先の関数f2を使う。
同じようにやってみよう。
![[Graphics:Images/FourieA_gr_223.gif]](Images/FourieA_gr_223.gif)
今度は11,21,61の3カ所にピークがある。さて、最初は9だった。
これははじめの関数f1,f2をよく見ると出てくる。
データ数は200、f1の振動数は0.04かけると8、1を加えると9となる。
f2の場合もデータ数が200振動数は0.05,0.1,0.3だから
かけて1を加えると11,21,61でぴったりである。
そう、フーリエ変換のあとのグラフのピークは振動数に対応してる。
こうした振動数の表示をスペクトル表示というよ。
逆にいろいろな情報からその振動数ごとの強さがわかってしまうことになる。
これはすごい!なぜって?
例えば録音された声がだれのものかとか、ある色から赤がどれだけ混ざっているのかとかがわかることに
つながるのだ。
しかし、どうもデータ数をかけたり1をたしたりは面倒である。このあたりをうまくできるように
関数を作ってしまおう。
MathematicaのFourie関数は最初のデータを1ではなく0から数えるので1ずれていたのだ、
これらを解消させるため次のような関数をつくろう。
![[Graphics:Images/FourieA_gr_228.gif]](Images/FourieA_gr_228.gif)
SplotとSRplotの2種類をここでは作った。SRplotはx軸の範囲を指定するときに利用する。
上のプログラムでは最大値の半分までをxの値を1ずらして作図するようにしてある。
また、データの最大値と数をあらかじめ求めて目盛りが合うように調節した。
この関数はMathematcaのTable関数でデータを作成したときに便利である。次のように使用する。
Splot[リスト名、刻み幅]
SRplot[リスト名、刻み幅、x軸のはじめの値、x軸の終わりの値]
という書式になっている。刻み幅は通常は1でよいが0.1でxを増やしたいときにはここに10を入れればよい。
さっそく先のt2のデータを使って試してみよう。
![[Graphics:Images/FourieA_gr_229.gif]](Images/FourieA_gr_229.gif)
ピークの位置があったし、同じ形が2つも出てこないのですっきりした。
振動数の値もあっている。
でも、FFTではデータの数がデータの間隔(秒数)を決めていることを知っておこう。
これは次のような問題をやるとき重要になる。
【問題3】理解ができたら次の2つの関数をフーリエ変換してパワースペクトルを表示せよ。
そして、ピークとなる振動数を[Hz]単位で求めてみよ。
![[Graphics:Images/FourieA_gr_232.gif]](Images/FourieA_gr_232.gif)
--略解--
最初のは先の結果がそのまま使える。
![[Graphics:Images/FourieA_gr_233.gif]](Images/FourieA_gr_233.gif)
従って振動数は0.005Hzと0.01Hzだね。
2番目は振動数がとても大きい。従って同じように刻み幅を1にすると問題が生じる。
失敗した人もいるだろう。
繰り返しの周期が出てこないのだ。FFTを正確にするためにはなるべくたくさんの
周期をデータにしなくてはいけない。データの1間隔の位相差が2π以上になったら意味
をもたない。
そこで次のように刻み幅を細かくしよう。間隔を0.01にして刻み幅に100を代入する。
![[Graphics:Images/FourieA_gr_236.gif]](Images/FourieA_gr_236.gif)
これで答え5[Hz]と10[Hz]が見つかったね。
このようにFFTでは重要な定理があることがわかる。
高い振動数の時には刻みを細かくしなくてはいけないということだ。
1秒間にどれだけのデータがとれるかを表すのがサンプリング周波数だ。
ここでの刻みははこの値に一致する。最近のパソコンでは44.1kHzであることが多い。
従ってこのパソコンでFFTを有効にするには最大はその半分の22.05kHz
程度までだということを知っておこう。
FFTの詳しい内容に興味あるものは後記述の参考文献を読んでみるといい。
では次にデータ解析を実際にしてみよう。
このファイルと共にサンプルとして「うなり.wav」を添付したのでこれを利用してもよい。
自分のPCにマイクがあって録音が簡単にできるならサウンドレコーダーを開いて自分の
声を録音して名前を付けて保存しておこう。
1.録音した音声などの解析
サウンドファイルの作成
マイク・スピーカーのあるウィンドズマシンではサウンドレコーダーで簡単に
音を取り込むことができる。
ここではすでに作成した「うなり」というWaveファイルを使おう。
このファイルをダブルクリックして実際に自分の耳でこの音の様子を聞いておこう。
サウンドファイルの取り込み方
パスを表すのは¥ではなくて半角で/といれる。
下の例はDドライブにある「うなり」というWAVEファイルを読み込んでいる。
ファイル名やファイルの場所は異なるので自分の利用する内容に変えよう。
同じ要領で画像ファイルも取り込むことができる。
パッケージの読み込み
Mathematicaは特別な用途のための多くのパッケージを用意している。ここではサウンドに関する次の
パッケージを読み込む
![[Graphics:Images/FourieA_gr_240.gif]](Images/FourieA_gr_240.gif)
次のようにするとファイルの中身の情報を教えてくれる。
![[Graphics:Images/FourieA_gr_241.gif]](Images/FourieA_gr_241.gif)
では次のようにしてサウンドファイルを変数sndに取り込もう。変数名
はなんでもよい。
![[Graphics:Images/FourieA_gr_249.gif]](Images/FourieA_gr_249.gif)
「Show」コマンドでこのwaveファイルを図にしてみよう。
![[Graphics:Images/FourieA_gr_251.gif]](Images/FourieA_gr_251.gif)
減衰していくうなりの様子が見てとれる、これと先ほど聞いた音と比べてみるといい。
次のようにするとMathematicaからも直接音を鳴らせる
![[Graphics:Images/FourieA_gr_254.gif]](Images/FourieA_gr_254.gif)
またMathematicaで作った関数は次のようにして鳴らすことができる。
220Hzの振動を1秒間鳴らすには
![[Graphics:Images/FourieA_gr_255.gif]](Images/FourieA_gr_255.gif)
とする。音楽の得意な人はどれくらいの振動数の差を聞き分けられるか挑戦してみるといい。
次に技術的だがサウンドファイルからデータを例えば44100個抜き出す関数を次のように定義する。
これで以前にやったリストが44100個できたことになる。
![[Graphics:Images/FourieA_gr_256.gif]](Images/FourieA_gr_256.gif)
中身を確認するために;をはずしてこのうちのいくつかみてみよう、後にこの間隔が重要になる。
![[Graphics:Images/FourieA_gr_257.gif]](Images/FourieA_gr_257.gif)
PlotRangeオプションを変更してフーリエ変換してみよう
![[Graphics:Images/FourieA_gr_259.gif]](Images/FourieA_gr_259.gif)
前にみたように真ん中で対称になってるね。これだとあまりに範囲が大きくてよくわからない。
そこで次のようにレンジを変えよう。
![[Graphics:Images/FourieA_gr_261.gif]](Images/FourieA_gr_261.gif)
ピークの一つが360付近に出ているね。
そこでさらにレンジをしぼってみよう。
![[Graphics:Images/FourieA_gr_264.gif]](Images/FourieA_gr_264.gif)
364のあたりがこの音の振動数が一番大きいことがこれでわかった。ではこれは364Hzといって
いいのだろうか?。
先にこの音声ファイルの情報をみたときに
Sampling rate: `44100
があった。実はこの数字にデーター数を合わせたから目盛りの値は正しく振動数を示してくれたのだ。
このサンプリング周波数はとても重要でMathematicaを使わなくてもWindowsでファイルのアイコンを
右クリックしてプロパティの詳細をみることでもわかるよ。
でも、上の図はMathematicaのFourie関数をそのまま利用したからずれが残っている。
正しくは次のように先のSRplotを利用し、刻み幅にはサンプリング周波数を入れればよい。
![[Graphics:Images/FourieA_gr_267.gif]](Images/FourieA_gr_267.gif)
これで正しい振動数がわかった。?
そう、物理を少し知っている君なら不思議に思うだろう。
もともとこの音声ファイルは「うなり」を録音したものだ「うなり」とは
振動数が非常に近い2つの音からできるんだったね。
ところがフーリエ解析したみても振動数のピークは1つしか見えない。
これはおかしい!!。
原因も実は依然の問題演習で経験している。このリストのデータ数はちょうど
44100個、サンプリング周波数も44100Hzだからこれだと1周期分のデータしかない!
そこで多少時間がかかるがこのファイルのデータを次のようにすべて代入する。
![[Graphics:Images/FourieA_gr_269.gif]](Images/FourieA_gr_269.gif)
今度はMathematicaのFourie関数はつかえないから自作したSRplotを次のように利用する。
![[Graphics:Images/FourieA_gr_270.gif]](Images/FourieA_gr_270.gif)
みごと2つのピークが見て取れるこの振動数の差がうなりの振動数になって聞こえる。
上の図から差は約2Hzだからおよそ、1秒間に2回うなりが聞こえることになる。
実際と比べてみるとよい。
これらはドップラー効果としてスピードガンや飛行機、潜水艦の速さを知ることにも応用されているよ。
【問題4】同じように自分で作成したファイルのサンプリング周波数を求めてフーリエ解析し、
振動数成分を求めよ。
他の解析ソフトがあれば同じようにFFT解析した結果と比べてみるとよい。
では次にフ-リエ変換+Mathematica で実験応用例を考えよう.
![[Graphics:Images/FourieA_gr_272.gif]](Images/FourieA_gr_272.gif)
フーリエ変換には上記のようなたたみこみを満たす関数を利用するとフーリエ変換の積にになるという
性質がある。
これは雑音の入ったデータから目的の情報を取り出す「スムージング処理」に応用できる。
例えば波動でおなじみな次のようなベッセル関数を元にする。
![[Graphics:Images/FourieA_gr_273.gif]](Images/FourieA_gr_273.gif)
これにランダム関数を使って人工的に雑音を入れる。
![[Graphics:Images/FourieA_gr_276.gif]](Images/FourieA_gr_276.gif)
たたみこみで利用する次の関数を用意する。
![[Graphics:Images/FourieA_gr_279.gif]](Images/FourieA_gr_279.gif)
離散フーリエ変換のためのたたみこみの核をずらしておく
![[Graphics:Images/FourieA_gr_282.gif]](Images/FourieA_gr_282.gif)
![[Graphics:Images/FourieA_gr_283.gif]](Images/FourieA_gr_283.gif)
![[Graphics:Images/FourieA_gr_284.gif]](Images/FourieA_gr_284.gif)
ランダム関数Random[]は0から1までの数字をランダムに出すここでは-0.5から+0.5までとした。
前の係数0.1をかえると雑音のレベルが変わる。
&circlef; Mathematicaの基礎 Mathematicaで何ができるか,主要なコマンドの解説
Mathmaticaの基礎 http://www.ne.jp/asahi/buturiwa/ai/educationM.htm
Mathematicaハンドブック 秀和システム 木村 広著
&circlef; フ-リエ変換などの数学的基礎
フーリエ解析 岩波書店 福田礼次郎著
偏微分方程式 岩波書店 及川正行著
&circlef; FFTやプログラム関係
Cによる科学技術計算 CQ出版社 小池真一著
◎ Mathematica公式サイト: http://www.wolfram.com
2001.2 H.Yanase http://www.ne.jp/asahi/buturiwa/ai/educationM.htm