なんとなく

誰得感満載な記事が多いかも。Mono関係とLinuxのサーバ関係、レビューとか。

OpenALでのカスタムHRTFファイルの作成と適用

はじめに

takeshich.hatenablog.com

の続き。

前回は、Xamarin.Androidでの

  • OpenAL
    • OpenALAndroid用のビルド
    • HRTFを有効にした際にOpenALにビルトインされているHRTFの定義ファイルで再生

について見た。

今回は、

  • HRTFとは何か
  • OpenAL用のカスタムHRTFファイルの作り方
  • PCでのカスタムHRTFファイルの適用方法
  • Xamarin.AndroidでのカスタムHRTFファイルの適用

について見ていく。

HRTF(頭部伝達関数)とは

前回HRTFという単語を使っていたが説明を全くしていなかったので、軽く触れていきたい。

人は、音源から両耳に届く音の変化や差異を知覚しているらしい。 その音の変化や差異がHRTF(頭部伝達関数)で、経験的に方向や距離を認知しているらしいのだ*1。 そして、そのHRTF(頭部伝達関数)は人それぞれのようだ。

一定の方位角ごとのHRTF(頭部伝達関数)を計測し、3Dの音場作成時に適宜補間し適用(計算して)することで、立体感を得られるようになる。 現実的には計測するには、計測できる施設に行ってなどいろいろと手間がかかるので、個々に合わせる際には近似しているものを探して使ったり、平均的なものを作成して使用するようだ。

今回は、近似しているものを探して使う。

HRTFとHRIR

頭部伝達関数についてWikipediaをみるとHRTFとHRIRの記述がある。

頭部伝達関数 (とうぶでんたつかんすう、Head-Related Transfer Function, HRTF) とは、耳殻、人頭および肩までふくめた周辺物によって生じる音の変化を伝達関数として表現したものである。

HRTF ということばは周波数領域における表現に対してつかわれるが、これをフーリエ変換して時間領域において表現したものを頭部インパルス応答 (Head-Related Impulse Response, HRIR) という。これは、1個のインパルスを発生させたときの応答特性である。

頭部伝達関数 - Wikipedia

とある。

HRIRをフーリエ逆変換するとHRTFになる。HRTFをフーリエ変換するとHRIRになる。 表記については、HRIRではなくHRTF(インパルス応答)とする場合もあり、注意が必要である。

計算方法

どう計算されているかというと説明してあるサイトを以下に引用する。

HRTF または HRIR を使用してある音源からのモノーラル信号を 3D 化するには,その音源の方向によってことなる,すなわち方位角ごと仰角ごとにことなる HRTF (または HRIR) を選択し,ちょうどその方向のものがなければ補間をおこない,そうしてえられた HRTF によってもとの信号とを入力して複数のチャネル (たとえばバイノーラルにおいては左耳のためのチャネルと右耳のためのチャネル) に関してフィルタリング計算をおこない,結果としてえられた複数チャネルの信号をヘッドフォンまたはスピーカーによって再生する. 頭部伝達関数 (HRTF) (調査と解説)

手法は計算方法を減らすようなものもあるらしいが、詳しくは追えていない。

f:id:takeshich:20180916143345p:plain:w300

カスタムHRTFファイルの作り方

OpenALにおいては、公開されている測定結果からOpenAL用のHRTFファイルを作成し、適用することもできる。

makehrtfに対応している公開データ

makehrtfを用いることで、公開されている測定結果からOpenAL用のHRTFファイルを作成することができる。 makehrtfで対応している定義ファイルは確認できる範囲では3つある。

  • CIAIR.def
  • IRC_1005.def
  • MIT_KEMAR.def

CIAIR.defは、 名古屋大学統合音響情報拠点*2のデータベース*3をもとにカスタムHRTFファイルを作るための定義ファイルである。 公開されているデータはテキストデータなので、自分に似たものを見つけることは難しい。Matlabという物を使うとWAVにできるような記述があるが試していない。

IRC_1005.defは、 フランス国立音響音楽研究所*4のデータベース*5をもとにカスタムHRTFファイルを作るための定義ファイルである。

別途、バイノーラルの音が公開されており、今回試した中では、自分と機器にあった近似的な定義ファイルを一番作りやすいと感じた。その作り方を後述する。

MIT_KEMAR.defは、 MIT Media Lab*6のデータベース*7をもとにカスタムHRTFファイルを作るための定義ファイルである。左耳のデータを使っているよう。

バイノーラルの音が公開されているものは、公開されているものすべてを聞いて、自分と機器にあった近似的なものを見つけるという作業がある。

また、バイノーラルの音が伴わないものについては、カスタム定義ファイルを公開されている個数だけ作成し、

takeshich.hatenablog.com

で作ったような、listenPositionを中心に半径と高さを計測時の環境に合わせた円を描くものをつくり、その作成した定義ファイルを適用し、再生し、作成した定義ファイルの個数回聞き、自分のと近似しているか確認する必要がある。OpenALはループバックに対応しているので、WAVを作成するようにするのがいいだろう。

自分と機器にあった近似的なものを見つけるという作業はとてもしんどい。私が試したのは、公開されているバイノーラルの音を聞くだけであったが、51個もあった。 機器が複数台(例えば、カナル型イヤホンとヘッドホンなど)あり、それぞれに適用したいのであれば、機器ごとにしなければならない。 近似のものを見つけるには母集団が多いほうがいいと思うが、準備と確認し比較する作業がかなりの手間で、簡単にHRTFを計測できる施設などがあればいいなぁと思った。 もしくは特性を多方面から分類して、絞り込むようなツールを作成するといった方法も考えられるがこれを作成するのも手間だろう。

作り方

今回は、IRCAMのデータベースにあるものをもとにmakehrtfでHRTFファイルを作成していく。

以下、2つのサイトを参考にした。なお、後者にはHRTFのテストツールもあるので、後述する適用方法を行い確認することもできる。

www.systemshock.org

www.bitoutsidethebox.com

作成の流れは以下のようになる。

  • サイトから音データ(反時計回りに音が回る)ダウンロードし、聞き(51回)、一番自然と感じるものを選ぶ。
  • その音に関連する測定データをダウンロードする。
  • makehrtf用の定義ファイルをその音に関するデータ用に修正する。
  • makehrtfでHRTFファイルを作成する。

機器と自分の耳が関わるので、イヤホンやヘッドホンが複数ある場合には、機器に合わせてHRTFファイルは複数用意する必要がある。

makehrtfの用意

Windowsの場合を記述する。しかし、LinuxMACでもほぼ同じだろうから読み替えてほしい。

  • http://openal-soft.org/#download からバイナリをダウンロードし、展開しておく。
  • 任意のフォルダを作成する。
  • そこに展開した中にあるhrtf_defsフォルダをコピーする。
  • hrtf_defsフォルダの中にmakehrtf.exeをコピーする。
  • hrtf_defsフォルダの中にIRCフォルダを作成する
|--openal(任意)
|  |--hrtf_defs
|  |  |--IRC_1005.def
|  |  |--CIAIR.def
|  |  |--MIT_KEMAR.def
|  |  |--makehrtf.exe
|  |  |--IRC

一番自然と感じるものを選ぶ

例)一番自然と感じる番号が1032の場合

|--openal(任意)
|  |--hrtf_defs
|  |  |--IRC_1005.def
|  |  |--CIAIR.def(使わないので、削除してしまって良い)
|  |  |--MIT_KEMAR.def(使わないので、削除してしまって良い)
|  |  |--makehrtf.exe
|  |  |--IRC
|  |  |  |--RAW
|  |  |  |  |--MAT(使わないので、削除してしまって良い)
|  |  |  |  |--WAV
|  |  |  |  |  |--IRC_1032_R
|  |  |  |  |  |  |--IRC_1032_R_R0195_T000_P000.wav
|  |  |  |  |  |  |--IRC_1032_R_R0195_T000_P015.wav

makehrtf用の定義ファイルをその音に関するデータ用に修正する。

  • IRC_1005.defをコピーし、IRC_????.def ( ????は、一番自然と感じる番号)にリネームする。識別できれば任意のファイル名で構わないがここではわかりやすくしている。
  • リネームした IRC_????.def ( ???? は、一番自然と感じる番号)をテキストエディタで開き、文字列IRC_1005を IRC_???? に置き換える。

IRC_1005.defの中身を見ると

[  3,  0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P315.wav" left
           + wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P315.wav" right
[  3,  1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P315.wav" left
           + wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P315.wav" right

のようにデータのパスを指定しているので、文字列IRC_1005を相応のもの(例示ではIRC_1032)に置き換える必要がある。

例)一番自然と感じる番号が1032の場合

|--openal(任意)
|  |--hrtf_defs
|  |  |--IRC_1005.def
|  |  |--IRC_1032.def
|  |  |--CIAIR.def(使わないので、削除してしまって良い)
|  |  |--MIT_KEMAR.def(使わないので、削除してしまって良い)
|  |  |--makehrtf.exe
|  |  |--IRC
|  |  |  |--RAW
|  |  |  |  |--MAT(使わないので、削除してしまって良い)
|  |  |  |  |--WAV
|  |  |  |  |  |--IRC_1032_R
|  |  |  |  |  |  |--IRC_1032_R_R0195_T000_P000.wav
|  |  |  |  |  |  |--IRC_1032_R_R0195_T000_P015.wav

makehrtfでHRTFファイルを作成

修正した定義ファイルを指定し、makehrtfを実行する。

f:id:takeshich:20180916142932p:plain

makehrtf.exe -i=.\IRC_????.def -o=.\irc_????.mhr

例)

makehrtf.exe -i=.\IRC_1032.def -o=.\irc_1032.mhr

作成に少し時間はかかるので、注意。応じたメッセージが表示される。

例)一番自然と感じる番号が1032の場合

|--openal(任意)
|  |--hrtf_defs
|  |  |--IRC_1005.def
|  |  |--IRC_1032.def
|  |  |--CIAIR.def(使わないので、削除してしまって良い)
|  |  |--MIT_KEMAR.def(使わないので、削除してしまって良い)
|  |  |--makehrtf.exe
|  |  |--irc_1032.mhr

作成したカスタムHRTFファイルの適用

makehrtfで作成したカスタムHRTFファイルの適用についてみていく。

  • コンフィグファイルを作成し、その中でパス及びその名前指定し、明示的に適用する方法
  • コンフィグファイルを作成ぜずにOpenALのデフォルトの検索パスにカスタムHRTFファイルを置き、適用する方法

がある。

OpenALのコンフィグ

# The system-wide settings can be put in /etc/openal/alsoft.conf and user-
# specific override settings in $HOME/.alsoftrc.
# For Windows, these settings should go into $AppData\alsoft.ini

https://github.com/kcat/openal-soft/blob/master/alsoftrc.sample#L17

とあり、ファイル名、各環境でのパスが記されているので、そちらに沿えば良い。

例えば、Windowsであれば、%AppData%にalsoft.iniというファイル名のファイルを作成すると設定ファイルとして認識される。

C:\Users\takeshich\AppData\Roaming\alsoft.ini

コンフィグファイルを作成し、その中でパス及びその名前指定し、明示的に適用する方法としては、 hrtf-pathsを明示的に指定し、そこにカスタムHRTFファイルを置くか、デフォルトのパスにカスタムHRTFファイルを置く。 そして、default-hrtfでその名前を明示的に指定すればよい。なお、default-hrtfで指定するものは、拡張子なしのもの。

## default-hrtf:
#  Specifies the default HRTF to use. When multiple HRTFs are available, this
#  determines the preferred one to use if none are specifically requested. Note
#  that this is the enumerated HRTF name, not necessarily the filename.

https://github.com/kcat/openal-soft/blob/master/alsoftrc.sample#L116

とある。

具体例としては、新規の場合だとするとC:\Users\takeshich\AppData\Roaming\alsoft.iniを作成し、編集する。 alsoft.iniについては、C:\Users\takeshich\AppData\Roaming\openal\hrtf_defs\irc_1032.mhrがあるとして、

中身は以下

[general]
default-hrtf ="irc_1032"
hrtf-paths = "C:\Users\takeshich\AppData\Roaming\openal\hrtf_defs"

ファイル構成としては以下

|--%AppData%
|  |--openal
|  |  |--hrtf_defs
|  |  |  |--irc_1032.mhr
|--alsoft.ini

なお、HRTFファイルを検索するデフォルトのパスは

 ## hrtf-paths:
 #  Specifies a comma-separated list of paths containing HRTF data sets. The
 #  format of the files are described in docs/hrtf.txt. The files within the
 #  directories must have the .mhr file extension to be recognized. By default,
 #  OS-dependent data paths will be used. They will also be used if the list
 #  ends with a comma. On Windows this is:
 #  $AppData\openal\hrtf
 #  And on other systems, it's (in order):
 #  $XDG_DATA_HOME/openal/hrtf  (defaults to $HOME/.local/share/openal/hrtf)
 #  $XDG_DATA_DIRS/openal/hrtf  (defaults to /usr/local/share/openal/hrtf and
 #                               /usr/share/openal/hrtf)

https://github.com/kcat/openal-soft/blob/master/alsoftrc.sample#L122

とあり、各環境でのデフォルトのパスにカスタムHRTFファイルを設置すればよい。

コンフィグファイルを作成ぜずにOpenALのデフォルトの検索パスにカスタムHRTFファイルを置き、適用する方法は、 今回の場合は、Windowsなので、作成したカスタムHRTFファイルをデフォルトのパスの%AppData%\openal\hrtfにコピーすれば良い。 通常はフォルダが存在しないので、作成する。

なお、カスタムHRTFファイルが複数の場合は、default-hrtfでその名前を明示的にしない場合、ファイルのソート順の一番先頭が適用されるようだ。

Xamarin.AndroidでのカスタムHRTFファイルの適用

Xamarin.AndroidでのカスタムHRTFファイルの適用であるが、makehrtfでカスタムHRTFファイルを作成するのは、WindowsLinux,MACのデスクトップ環境で行い、作成されたカスタムHRTFファイルをAssetにして実行時に展開してあげるという方法で試してみた。

  • コンフィグファイルを作成し、その中でパス及びその名前指定し、明示的に適用する方法
  • コンフィグファイルを作成ぜずにOpenALのデフォルトの検索パスにカスタムHRTFファイルを置き、適用する方法

の2つを行ってみたが、どちらも問題なくカスタムHRTFファイルを適用させることができた。

Assetsに必要なファイルを置き、それを実行時に当該フォルダにコピーして適用させた。

以下に、コンフィグファイルを作成し、その中でパス及びその名前指定し、明示的に適用する方法の場合を示す。 他方はalsoftrcを削除し、DestPathを変更する。.alsoftrcを設置しないようにする。

private void CopyFromAssetToFiles()
{
    //hrtfの定義リストを作成
    String[] mhrlist = Resources.Assets.List("hrtf");

    //デフォルトのパス
    //string DestPath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), ".local/share/openal/hrtf");

    string DestPath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "hrtf");
    if (!System.IO.Directory.Exists(DestPath))
    {
        System.IO.Directory.CreateDirectory(DestPath);

    }

    foreach (string Filename in mhrlist)
    {
        using (System.IO.Stream ass = Android.App.Application.Context.Assets.Open("hrtf" +"/" + Filename))
        {
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                ass.CopyTo(ms);
                System.IO.File.WriteAllBytes(DestPath + "/" + Filename, ms.ToArray());
            }
        }
    }

    //alsoftrcを.alsoftrcにして設置
    using (System.IO.Stream assetss = Android.App.Application.Context.Assets.Open("alsoftrc"))
    {
        using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
        {
            assetss.CopyTo(ms);
            System.IO.File.WriteAllBytes(System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal) , ".alsoftrc"), ms.ToArray());
        }
    }
}

Assetsには以下図のようにカスタムHRTFファイルとalsoftrcを設置した。

f:id:takeshich:20180916142900p:plain

alsoftrcの内容は以下

[general]

default-hrtf = "irc_1032_44100"
hrtf-paths = $HOME/hrtf

実行時のログは以下

09-16 03:52:24.727 D/openal  ( 1569): AL lib: alc_initconfig: Initializing library v1.18.2-7d76cbdd master
09-16 03:52:24.727 D/openal  ( 1569): AL lib: alc_initconfig: Supported backends: opensl, null, wave
09-16 03:52:24.727 D/openal  ( 1569): AL lib: ReadALConfig: Loading config /etc/openal/alsoft.conf...
09-16 03:52:24.727 D/openal  ( 1569): AL lib: ReadALConfig: Loading config /etc/xdg/alsoft.conf...
09-16 03:52:24.728 D/openal  ( 1569): AL lib: ReadALConfig: Loading config /data/user/0/OpenALApp.OpenALApp/files/.alsoftrc...
09-16 03:52:24.728 D/openal  ( 1569): AL lib: LoadConfigFromFile: found 'default-hrtf' = 'irc_1032_44100'
09-16 03:52:24.728 D/openal  ( 1569): AL lib: LoadConfigFromFile: found 'hrtf-paths' = '/data/user/0/OpenALApp.OpenALApp/files/hrtf'
09-16 03:52:24.728 D/openal  ( 1569): AL lib: ReadALConfig: Loading config /data/user/0/OpenALApp.OpenALApp/files/.config/alsoft.conf...
~略~
09-16 03:52:24.739 D/openal  ( 1569): AL lib: GetConfigValue: Found hrtf-paths = "/data/user/0/OpenALApp.OpenALApp/files/hrtf"
09-16 03:52:24.739 D/openal  ( 1569): AL lib: DirectorySearch: Searching /data/user/0/OpenALApp.OpenALApp/files/hrtf for *.mhr
09-16 03:52:24.739 D/openal  ( 1569): AL lib: DirectorySearch: Got result /data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1030.mhr
09-16 03:52:24.739 D/openal  ( 1569): AL lib: DirectorySearch: Got result /data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_44100.mhr
09-16 03:52:24.739 D/openal  ( 1569): AL lib: DirectorySearch: Got result /data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_48000.mhr
09-16 03:52:24.739 D/openal  ( 1569): AL lib: DirectorySearch: Got result /data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_96000.mhr
09-16 03:52:24.739 D/openal  ( 1569): AL lib: AddFileEntry: Got new file "/data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1030.mhr"
09-16 03:52:24.739 D/openal  ( 1569): AL lib: AddFileEntry: Adding entry "irc_1030" from file "/data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1030.mhr"
09-16 03:52:24.739 D/openal  ( 1569): AL lib: AddFileEntry: Got new file "/data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_44100.mhr"
09-16 03:52:24.739 D/openal  ( 1569): AL lib: AddFileEntry: Adding entry "irc_1032_44100" from file "/data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_44100.mhr"
09-16 03:52:24.739 D/openal  ( 1569): AL lib: AddFileEntry: Got new file "/data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_48000.mhr"
09-16 03:52:24.739 D/openal  ( 1569): AL lib: AddFileEntry: Adding entry "irc_1032_48000" from file "/data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_48000.mhr"
09-16 03:52:24.739 D/openal  ( 1569): AL lib: AddFileEntry: Got new file "/data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_96000.mhr"
09-16 03:52:24.739 D/openal  ( 1569): AL lib: AddFileEntry: Adding entry "irc_1032_96000" from file "/data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_96000.mhr"
09-16 03:52:24.740 D/openal  ( 1569): AL lib: GetConfigValue: Found default-hrtf = "irc_1032_44100"
09-16 03:52:24.740 D/openal  ( 1569): AL lib: GetLoadedHrtf: Loading /data/user/0/OpenALApp.OpenALApp/files/hrtf/irc_1032_44100.mhr...
09-16 03:52:24.740 D/openal  ( 1569): AL lib: GetLoadedHrtf: Detected data set format v1
09-16 03:52:24.740 D/openal  ( 1569): AL lib: GetLoadedHrtf: Loaded HRTF support for format: Stereo 44100hz
09-16 03:52:24.740 D/openal  ( 1569): AL lib: UpdateDeviceParams: Pre-reset: *Stereo, Float, *44100hz, 1024 update size x3
~略~
09-16 03:52:24.753 D/openal  ( 1569): AL lib: aluInitRenderer: Full HRTF rendering enabled, using "irc_1032_44100"
09-16 03:52:24.753 D/openal  ( 1569): AL lib: BuildBFormatHrtf: Skipped delay: 2, max delay: 25, new FIR length: 80

.alsoftrcが読み込まれ、指定したものが提供されているのを伺える。

コンフィグファイルを作成ぜずにOpenALのデフォルトの検索パスにカスタムHRTFファイルを置き、適用する場合のログは以下

09-16 04:24:10.971 D/openal  ( 3303): AL lib: alc_initconfig: Initializing library v1.18.2-7d76cbdd master
09-16 04:24:10.971 D/openal  ( 3303): AL lib: alc_initconfig: Supported backends: opensl, null, wave
09-16 04:24:10.971 D/openal  ( 3303): AL lib: ReadALConfig: Loading config /etc/openal/alsoft.conf...
09-16 04:24:10.972 D/openal  ( 3303): AL lib: ReadALConfig: Loading config /etc/xdg/alsoft.conf...
09-16 04:24:10.972 D/openal  ( 3303): AL lib: ReadALConfig: Loading config /data/user/0/OpenALApp.OpenALApp/files/.alsoftrc...
09-16 04:24:10.972 D/openal  ( 3303): AL lib: ReadALConfig: Loading config /data/user/0/OpenALApp.OpenALApp/files/.config/alsoft.conf...
09-16 04:24:10.972 D/openal  ( 3303): AL lib: GetProcBinary: Got path: /system/bin
09-16 04:24:10.972 D/openal  ( 3303): AL lib: ReadALConfig: Loading config /system/bin/alsoft.conf...
~略~
09-16 04:24:10.984 D/openal  ( 3303): AL lib: GetConfigValue: Key hrtf-paths not found
09-16 04:24:10.984 D/openal  ( 3303): AL lib: GetConfigValue: Key hrtf_tables not found
09-16 04:24:10.984 D/openal  ( 3303): AL lib: DirectorySearch: Searching / for *.mhr
09-16 04:24:10.985 D/openal  ( 3303): AL lib: DirectorySearch: Searching /data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf for *.mhr
09-16 04:24:10.985 D/openal  ( 3303): AL lib: DirectorySearch: Got result /data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1030.mhr
09-16 04:24:10.985 D/openal  ( 3303): AL lib: DirectorySearch: Got result /data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1032_44100.mhr
09-16 04:24:10.985 D/openal  ( 3303): AL lib: DirectorySearch: Got result /data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1032_48000.mhr
09-16 04:24:10.985 D/openal  ( 3303): AL lib: DirectorySearch: Got result /data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1032_96000.mhr
09-16 04:24:10.985 D/openal  ( 3303): AL lib: DirectorySearch: Searching /usr/local/share/openal/hrtf for *.mhr
09-16 04:24:10.985 D/openal  ( 3303): AL lib: DirectorySearch: Searching /usr/share/openal/hrtf for *.mhr
09-16 04:24:10.985 D/openal  ( 3303): AL lib: AddFileEntry: Got new file "/data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1030.mhr"
09-16 04:24:10.985 D/openal  ( 3303): AL lib: AddFileEntry: Adding entry "irc_1030" from file "/data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1030.mhr"
09-16 04:24:10.985 D/openal  ( 3303): AL lib: AddFileEntry: Got new file "/data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1032_44100.mhr"
09-16 04:24:10.985 D/openal  ( 3303): AL lib: AddFileEntry: Adding entry "irc_1032_44100" from file "/data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1032_44100.mhr"
09-16 04:24:10.985 D/openal  ( 3303): AL lib: AddFileEntry: Got new file "/data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1032_48000.mhr"
09-16 04:24:10.985 D/openal  ( 3303): AL lib: AddFileEntry: Adding entry "irc_1032_48000" from file "/data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1032_48000.mhr"
09-16 04:24:10.985 D/openal  ( 3303): AL lib: AddFileEntry: Got new file "/data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1032_96000.mhr"
09-16 04:24:10.985 D/openal  ( 3303): AL lib: AddFileEntry: Adding entry "irc_1032_96000" from file "/data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1032_96000.mhr"
09-16 04:24:10.986 D/openal  ( 3303): AL lib: AddBuiltInEntry: Got new file "Built-In 44100hz"
09-16 04:24:10.986 D/openal  ( 3303): AL lib: AddBuiltInEntry: Adding built-in entry "Built-In 44100hz"
09-16 04:24:10.986 D/openal  ( 3303): AL lib: AddBuiltInEntry: Got new file "Built-In 48000hz"
09-16 04:24:10.986 D/openal  ( 3303): AL lib: AddBuiltInEntry: Adding built-in entry "Built-In 48000hz"
09-16 04:24:10.986 D/openal  ( 3303): AL lib: GetConfigValue: Key default-hrtf not found
09-16 04:24:10.986 D/openal  ( 3303): AL lib: GetLoadedHrtf: Loading /data/user/0/OpenALApp.OpenALApp/files/.local/share/openal/hrtf/irc_1030.mhr...
09-16 04:24:10.986 D/openal  ( 3303): AL lib: GetLoadedHrtf: Detected data set format v1
09-16 04:24:10.986 D/openal  ( 3303): AL lib: GetLoadedHrtf: Loaded HRTF support for format: Stereo 44100hz
09-16 04:24:10.986 D/openal  ( 3303): AL lib: UpdateDeviceParams: Pre-reset: *Stereo, Float, *44100hz, 1024 update size x3
~略~
09-16 04:24:11.011 D/openal  ( 3303): AL lib: aluInitRenderer: Full HRTF rendering enabled, using "irc_1030"
09-16 04:24:11.011 D/openal  ( 3303): AL lib: BuildBFormatHrtf: Skipped delay: 0, max delay: 28, new FIR length: 88

デフォルトのパスが検索され、適用されているのが伺える。

複数個のカスタムHRTFファイルがある場合、最初に検索されたものが選ばれている。 この場合は、任意のものを使用するためには、.alsoftrcを設置して、default-hrtfで指定する必要がある。

まとめ

今回は、

  • HRTFとは何か
  • OpenAL用のカスタムHRTFファイルの作り方
  • PCでのカスタムHRTFファイルの適用方法
  • Xamarin.AndroidでのカスタムHRTFファイルの適用

について見てた。

現状、容易に自分のHRTFを計測することはできない。簡単に計測できるようになれば、楽しくなるのになとは思った。 現状できうる近似のものを見つけるということも手間がかかる。 人それぞれ違いがあり、多数の人が使用するアプリケーションにHRTFを使用するのは、ハードルが高いと感じた。 落とし所を見つけるのがとても難しい。

ただ、マニア向けに公開されているデータの多くを用意し、近似のものを見つけるツールを使い選択させ、アプリケーションで選択的に使用できるようになっているのはありのような気がする。

Xamarin.AndroidでのHRTFファイルの適用についても見たが、OpenALのHRTFに関するドキュメントがあるのみで、Android向けのものは特にない状態ではあるもののクロスプラットフォームで使えるだけあって、特にハマることなく調査することができた。 おそらく、私以外にXamarin.AndroidOpenALを使用し、更にHRTFを使用するという人やグループがどれだけいるかと考えるとほんの僅かなのだろう。Xenkoで確認できているが、C#のアプローチではなかった。

一方で、カスタムHRTFファイルの作り方とPCでのカスタムHRTFファイルの適用方法については、OpenALを採用し、HRTFを有効にできるゲームを使用する人にとっては有用なことだと考える。

さて次は、Radegast においてFMODで実装されているものをOpenALでの実装したものをXamarin.Android向けに移植する予定であるが、3DSceneについてはすでに移植してある部分もあり、それと同様に音も鳴らすことができるようにという意図もある。 しかし、かつて実装したもので実装したものの一部が現在対象としているAndroidのバージョンでは動かないようになっているため、先に3DSceneの方から手を付けるかもしれない。

書いた。 takeshich.hatenablog.com