view finalterm/text/chapter3.texi @ 0:775ef1b35b8c

最終論文
author Masato Tawata <e185761@ie.u-ryukyu.ac.jp>
date Mon, 31 Jan 2022 13:23:13 +0900
parents
children
line wrap: on
line source

\chapter{Kingdom Spatial Audio}
\section{概要}
本章ではリアルタイムで音響を再計算、再生するシステムとして制作したKingdom Spatial Audio(以降、KSA)の構成について説明する。
KSAでは聴覚的な影響が大きい反射と、\ref{intro}で述べた様な音が壁を回り込んでくる回折現象を主に再現するシステムとなっている。
それぞれの音響効果をシミュレートするにあたって、KSAではレイキャストと経路探索を用いてシステムを構築している。

レイキャストを用いることで周囲の遮蔽物の状態を取得する事が可能となり、音の反響時間や反射による音の増幅の計算をすることが可能になる。
経路探索では音が回り込むために生成される回折経路を近似し、音が聞こえる方向を変化させる効果と音の高周波成分が減衰する現象を再現する。

また、経路探索は計算に時間を要するため、メインスレッドで処理を行うと同じくメインスレッドで動作しているUnityの動作が停止し画面が固まってしまうなどの悪影響が発生する。
そのため、経路探索はサブスレッドで処理を行う様にし、複数の経路探索が同時に行われても問題なく実行できるように構築している。

\section{システム構成}
\ref{system_kousei}に構築したシステムの構成を示す。

\section{システムの流れ}
図\ref{ksa_flow}にシステムの大まかなフローチャートを示す。
まずゲーム開始時に初期化処理としてワールドのオブジェクト情報を読み込む。次に、そのオブジェクト情報から8分木を構築する。


\begin{figure}[htbp]
  \begin{center}
   \includegraphics[width=70mm]{./figures/flow.pdf}
   \caption[KSAのフローチャート]{KSAのフローチャート}
   \label{fig:ksa_flow}
   \end{center}
\end{figure}

\section{反射の再現}
音は障害物に衝突すると、一部は吸収され残りは反射されて空間に放出される。それが繰り返された結果、その場にいる人間には音が反響して聴こえる様になる。
これはコンピュータ上ではリバーブエフェクトとして再現される。そこで、KSAではリバーブエフェクトに渡すパラメータを計算することで音の反射を再現する。

リバーブのパラメーターには反射音の遅延時間や反響音の持続時間などを渡す必要がある。
反射音の遅延時間は音が音源から発生し壁に反射した後リスナーに届くまでの時間で計算できる。反響音の持続時間は以下に示されるSabineの式\cite{sabin}を利用して求める事が可能である。

\begin{math}
T=\frac{0.161V}{S*A}

T:残響時間

S:空間の表面積

A:吸音率
\end{math}


どちらのパラメータを求めるにも音源の周囲の環境を測定する必要があり、本システムではレイキャストを用いてこれらの計算を行う。

\ref{}で述べたように空間分割を行わずにレイキャストなどの衝突判定を行うことは計算量が多くなってしまうため最適ではない。そこで、レイキャストを行う前に8分木を用いた空間分割を実行する。

図\ref{fig:quad_div}は4分木の分割の様子を示している。可視化のしやすさのために4分木を用いているが、基本的な考え方は8分木も同様である。
まず空間が空白ブロックと遮蔽ブロックで構成されているとする。分割レベル0では一つの空間に灰色の遮蔽ブロックと空白ブロックが混ざっている。そこでさらに分割数を増やす。分割レベル1では空間1と空間3が同じブロックのみで構成されているためこれ以上分割する必要はない。
分割レベル2では空間0と空間2の分割数をさらに増やし、一種類のブロックのみで空間が構成される様にする。
この様な分割を行うことで、空間1と3関してはその中に含まれる4つのブロックに対して個別に衝突判定を行う必要がなくなり、空間そのものと衝突判定を行えば良くなる。

\begin{figure}[htbp]
  \begin{center}
   \includegraphics[width=70mm]{./figures/quad_div.pdf}
   \caption[4分木の分割の様子]{4分木の分割の様子}
   \label{fig:quad_div}
   \end{center}
\end{figure}

次に、4分木を用いたレイキャストの方法について説明する。
図\ref{raycast1}に示すように、4分木の分割の際と同じ環境を用いて、赤色の直線がオブジェクトに遮られていないかを判定する。
ここでは遮られているかどうかの判定に直線が通っている空間の中に遮蔽ブロックが存在しないことを条件として用いる。
図\ref{raycast2}では、分割レベル1の4つの空間の中から遮蔽オブジェクトが含まれている可能性のある空間0,2,3の空間と交差判定を行っている。実際に交差している空間0にはさらに分割された子空間が存在するため、その子空間に対しても交差判定を行う。
子空間0'~3'の中から遮蔽ブロックが含まれる空間1'と交差判定を行う。直線は空間1'と交差していないため直線が交差している全ての空間の中に遮蔽オブジェクトが含まれていないことが確認できる。よって直線は遮蔽オブジェクトに遮られていないと判定できる。
上記のようなレイキャストの実装を行うことで、通常は遮蔽物の数だけ行う必要があった交差判定が、空間0,2,3,1'の計4回で済むようになり高速化が見込める。

\begin{figure}[htbp]
  \begin{minipage}{0.3\hsize}
  \centering
  \includegraphics[width=20mm]{./figures/raycast_first.pdf}
  \label{raycast1}
  \caption{レイキャストの環境}
\end{minipage}
\begin{minipage}{0.3\hsize}
  \centering
  \includegraphics[width=20mm]{./figures/raycast_second.pdf}
  \caption{空間0,2,3との交差判定}
  \label{raycast2}
\end{minipage}
\begin{minipage}{0.3\hsize}
  \centering
  \includegraphics[width=20mm]{./figures/raycast_third.pdf}
  \caption{空間1'との交差判定}
  \label{raycast3}
\end{minipage}
\end{figure}

これを3次元に拡張し8分木に適応したプログラムをKSAに実装した。
\begin{figure}[htbp]
  \begin{center}
   \includegraphics[width=70mm]{./figures/raycast.png}
   \caption[レイキャスト]{レイキャスト}
   \label{fig:raycast}
   \end{center}
\end{figure}

\section{回折の再現}
音は障害物の端から回り込んで伝播する性質を持っている。高周波の音ほど回折は起こりにくいため、壁を挟んで音源の反対側にいる人物には音が篭って聞こえる。また音の方向も音源自体ではなく回り込んでくる壁の端から聞こえるようになる。
本システムでは経路探索を用いて音の回折経路と回折してきた音の方向を計算する。

回折経路を算出する際、通常のグラフ探索アルゴリズムでは計算された経路がグラフの離散化された位置に依存してしまうため、図\ref{astar_path}のようにギザギザの経路が算出されてしまい、期待する結果よりも経路長が長くなってしまう。
そこでKSAではAny-angle path planningアルゴリズムとedge-corner graphを用いた最短経路探索を行う。

\subsection{edge-corner graph}

\subsection{Any-angle path planning}
Any-angle path planningアルゴリズムの一つであるTheta\*\cite{ThetaStar}はA*アルゴリズムをベースに、間に障害物がないノード同士を接続することで図\ref{thetastar_path}のような直線的で自然な経路を生成している。

\begin{figure}[htbp]
  \begin{minipage}{0.44\hsize}
  \centering
  \includegraphics[width=40mm]{./figures/astarpath.pdf}
  \label{astar_path}
  \caption{A*による経路生成}
\end{minipage}
\begin{minipage}{0.44\hsize}
  \centering
  \includegraphics[width=40mm]{./figures/thetastarpath.pdf}
  \caption{Theta*による経路生成}
  \label{thetastar_path}
\end{minipage}
\end{figure}

\section{経路探索のサブスレッド化}
経路探索は本システムの計算処理の中でもかなり計算量が多いアルゴリズムとなっている。
グラフのサイズが128の場合、経路探索に27msかかっている。一般的なゲームが最低60fps(1フレーム16.6ms)で動作することを鑑みると、この計算時間はフレーム落ちやフレームレートの不安定化の原因になるため避けたい現象である。
そこでKSAでは経路探索をサブスレッドで行うようにし、メインスレッド動作しているUnityの処理を停止させないようにする。
\begin{table}[H]
\caption{経路探索の計算時間}
\label{pathfinding_time}
\centering
\begin{tabular}{|r|r|r|r|}
  \hline
  グラフの一辺のサイズ(m) & 計算時間(ms) & 経路長(m)\\
  \hline
  128&27.8668&341\\
  \hline
  64&5.7981&170\\
  \hline
  32&4.5226&88\\
  \hline
  16&1.5909&44\\
  \hline
\end{tabular}
\end{table}

メインスレッドで行っていた処理をサブスレッドに移行するにあたって、複数のサブスレッドから同時にアクセスされる可能性を考慮する必要がある。
複数のスレッドから同時に書き込みが発生すると、最後に書き込まれた情報以外は消失してしまうことでデータの整合性が取れなくなったり、プログラム上で意図しないエラーが発生する。
これを解決するために、経路探索のために用いていたグラフに、スタートノードとゴールノードを書き込んでいた処理を削除し、グラフ