SOFAとは?
ここでいうのは、HRTF(頭部伝達関数)の入ったバイノーラル音声処理に用いられるファイルのことだ。
SOFAのファイル形式
Hierarchical Data Format version 5, HDF5と呼ばれるものだ。
Matlabの関連ページにNetCDFだと書いていたがあながち間違いではないらしい。NetCDFはHDF5の拡張であるからだ。だがマジックナンバーはHDFだと言っている。
NetCDF用のncdump(aptのnetcdf-bin内)でも、HDF5用のh5dump(同h5utils内)で中を見ることができる。
以下、例
user@foo:~$ ncdump -h HRIR_CIRC360_NF100.sofa
netcdf HRIR_CIRC360_NF100 {
dimensions:
I = 1 ;
C = 3 ;
R = 2 ;
E = 1 ;
N = 128 ;
M = 360 ;
S = UNLIMITED ; // (0 currently)
variables:
double ListenerPosition(I, C) ;
ListenerPosition:Type = "cartesian" ;
ListenerPosition:Units = "metre" ;
double ReceiverPosition(R, C, I) ;
ReceiverPosition:Type = "cartesian" ;
ReceiverPosition:Units = "metre" ;
double SourcePosition(M, C) ;
SourcePosition:Type = "spherical" ;
SourcePosition:Units = "degree, degree, metre" ;
double EmitterPosition(E, C, I) ;
EmitterPosition:Type = "cartesian" ;
EmitterPosition:Units = "metre" ;
double ListenerUp(I, C) ;
double ListenerView(I, C) ;
ListenerView:Type = "cartesian" ;
ListenerView:Units = "metre" ;
double Data.IR(M, R, N) ;
double Data.SamplingRate(I) ;
Data.SamplingRate:Units = "hertz" ;
double Data.Delay(I, R) ;
// global attributes:
:Conventions = "SOFA" ;
:Version = "1.0" ;
:SOFAConventions = "SimpleFreeFieldHRIR" ;
:SOFAConventionsVersion = "1.0" ;
:APIName = "ARI SOFA API for Matlab/Octave" ;
:APIVersion = "1.0.3" ;
:ApplicationName = "" ;
:ApplicationVersion = "" ;
:AuthorContact = "Johannes.Arend@th-koeln.de" ;
:Comment = "KU100 nearfield HRIRs" ;
:DataType = "FIR" ;
:History = "Converted from the miro file format" ;
:License = "CC 3.0 BY-SA" ;
:Organization = "Technische Hochschule Köln, Germany" ;
:References = "Arend, J.M., Neidhardt, A., Pörschmann, C. (2016). Measurement and Perceptual Evaluation of a Spherical Near-Field HRTF Set. In: Proceedings of the 29th VDT International Convention" ;
:RoomType = "free field" ;
:Origin = "http://audiogroup.web.th-koeln.de" ;
:DateCreated = "2016-05-25 15:04:51" ;
:DateModified = "2018-05-04 14:41:12" ;
:Title = "HRTF" ;
:DatabaseName = "THK" ;
:ListenerShortName = "HRIR_CIRC360_NF100" ;
:Author = "Johannes M. Arend" ;
:ListenerDescription = "Neumann KU100" ;
:ReceiverDescription = "Neumann KU100; Internal RME Firefac UFX Preamps" ;
:SourceDescription = "Geithain RL906" ;
:RoomDescription = "THK ZW8-4 (Anechoic Chamber)" ;
}
中身
ほとんどのSOFAファイルはにはインパルス応答が時間領域で記録されている。
SOFAにはそれ以外の形式もサポートされているようだが、出くわしたことがないので割愛。
以下では、音声処理に必要なところのみ記載する。
N | 一つのIRデータの長さ(サンプル数) |
M | 計測したIRの数 |
Data.IR | インパルス応答のデータ |
SourcePosition | 音源の場所 |
SamplingRate | サンプリングレート |
JavaScriptでの読み込み
WebSofa
使えなくはないが、どうやら壊れている。ある程度の大きさ以上のファイルが読めないし、指定したところから一番近い音源座標のIRを持ってくる機能に不具合があるらしく、どうやっても同じ座標のデータしか取得できない。
netcdfjs
残念ながらnode上でしか使えない。
jsfive
これはブラウザ上でも問題なく使える。
ただし、SourcePositionとIRは1次元の配列として帰ってくる。そのためにサンプル数と測定数を取得するのだが。本当はなにかいい方法があるのか?
var file = await fetch("HRIR_CIRC360_NF100.sofa");
var buffer = file.arrayBuffer();
var f = new hdf5.File(buffer, filename);
f.keys; // (16) ['I', 'C', 'EmitterPosition', 'ListenerUp', 'ListenerView', 'Data.IR', 'Data.SamplingRate', 'Data.Delay', 'R', 'E', 'N', 'M', 'S', 'ListenerPosition', 'ReceiverPosition', 'SourcePosition']
f.get("N").value.length; // 128
var IR = f.get("Data.IR).value;
SofaJS
jsfiveでSOFAを扱いやすくするためにライブラリを自作した。
var file = await fetch("HRIR_CIRC360_NF100.sofa");
var buffer = file.arrayBuffer();
var Sofa = Sofa(buffer);
var IR[L,R] = Sofa.getFilter(Phi, Theta, Radius);
degreeの角度でIRデータを簡単に取得できる。
あとはこれを煮るなり焼くなり、audioBufferにしてConvolverNodeに入れるなりすればいい。・
音声処理のためのメソッドも存在する。詳しくはgithubのページで。
コメントを残す