SwiftUIで時間波形に窓関数をかけてグラフ表示する方法

  • このエントリーをはてなブックマークに追加

フーリエ変換をする際、漏れ誤差の改善のために一般的に窓関数を用います。ここではiOSアプリ開発でも窓関数の適用ができるようSwiftによる窓関数の適用方法を紹介し、実際に時間波形に対して適用、グラフ表示まで行います。

こんにちは。wat(@watlablog)です。ここではSwiftUIを使った信号処理コードシリーズとして窓関数の実装を紹介します

窓関数のおさらい

WATLABブログはPythonに関する情報発信を基本としていましたので、窓関数については以下の記事でそれぞれ紹介をしていました。この記事でも窓関数の概要は説明しますが、筆者と同じくPythonの方が得意な読者はこちらの記事を是非参照してみてください。
PythonでFFT!SciPyで窓関数をかける
Pythonで窓関数が無い場合は?指数窓を自作してみる!
窓関数使用時の補正!FFTの時に忘れがちな計算とは?

Advertisements

いつも正しい周期で波形を切り出して分析できれば良いのですが、実際は様々な周波数成分の信号に対して全てキリよく抽出することができません。中途半端な信号をフーリエ変換した場合に振幅スペクトルが分散してしまう漏れ誤差Leakage error)が発生してしまいます。これを軽減するために窓関数が使われます\(^{[1]}\)。

概要の説明はPython記事に任せて、この記事では早速SwiftUIでコーディングを始めたいと思います!

SwiftUIで窓関数を実装する

動作環境

本記事のコードは以下の環境で動作を確認しました。

                                                            
Mac OSmacOS Ventura 13.2.1
CPU1.4[GHz]
メモリ8[GB]
Xcode Version14.3(14E222b)
Swift Version5.8(swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)
iPhone SE2 OSiOS 16.3.1

ハニング窓

まずは最も使用頻度の高いハニング窓(通称ハン窓)を書いてみます。ハニング窓は式(1)で示されます。\(w(t)\)は窓関数計算後の波形です。ハニング窓がよく使われる理由としては、時間波形に含まれる振動数と振幅をともに精度よく分析できるから\(^{[1]}\)だそうです。

\[ w(t) = 0.5 - 0.5 \cos(\frac{2 \pi t}{T}) \tag{1} \]

Swiftの関数で書いたコードがこちらです。データ点数Nを引数とし、ハニング窓をかけた後の波形を返す関数にしてみました。

GUIとしてChartにグラフ表示するところまで書いた全コードを以下に示します。このコードはwavePoints関数で理想的な正弦波を作ってChartに表示させるプログラムに対して、間に窓関数の適用を挟んだ構成で書いています。

下図が実行結果です。Buttonという文字をクリックすると両端が0になった波形が表示されます。

SwiftUIによるハニング窓関数適用結果

フラットトップ窓

続いてよく使われる窓関数の例として、もう一つフラットトップ窓を紹介します。フラットトップ窓は式(2)で示されます。この窓関数は周波数分解能を犠牲にして振幅成分をより精密に分析する時に使います。

\[ w(t) = 1 - 1.93 \cos(\frac{2 \pi t}{T}) + 1.29 \cos(\frac{4 \pi t}{T}) - 0.388 \cos(\frac{2 \pi t}{T}) + 0.032 \cos(\frac{8 \pi t}{T}) \tag{2} \]

こちらが関数です。一度に式を書いたら「The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions」というメッセージが出たので、いくつかの式に分割して最後にまとめるという方法で書いてみました。

以下に実行結果を示します。中心付近の振動成分がより目立つような形になりました。

SwiftUIによるフラットトップ窓関数適用結果

まとめ

本日はここまで。Swift系の記事は一度Pythonでやった内容を書き直すような作業であるため簡単にしています。とはいえ、Pythonでは窓関数もライブラリを使って適用していたのに対し、Swiftでは自分で式を組み込むということをしてみました。

窓関数の式の違いにより周波数波形にどう違いが出てくるかといった細かい話はいずれどこかでまとめるかも知れません。

参考文献

[1]:永井健一, 丸山真一, システム計測工学 ポイントでわかる機械計測の基礎と実践, 森北出版, 2011, pp112-115

Swiftでも窓関数を実装するやり方がわかりました!
Twitter(今はXと呼ぶ?)でも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!

SNSでもご購読できます。

コメントを残す

*