Room EQ Wizard(REW)によるスピーカー特性の補正

スピーカーの周波数特性は、どのようにあるのが望ましいだろうか?
これは主観の問題なので一概には言えないが、少なくとも、左右の周波数特性は同じであるべきだという点については合意できるだろう。
しかしながら左右の特性には差が出る。同じ機種の同じロットを使おうがかなり差が出る。それはもうあきれるくらい違う。なぜなら左右のスピーカーが同一だとしてもそれが置かれた部屋の形状や家具の配置は対称と程遠く、放たれた音たちは好き勝手に反射し共鳴し吸収されわたしたちの耳に届く頃には物凄いことになっているのだから。
この恐ろしい周波数特性を救いたい、そのためには(1)部屋の音響特性を変える (2)音声信号に逆フィルタをかける、という手段があり、(1)については他の記事を当たってもらうとして(壁に吸音材を貼るとかだ)、この記事では主に(2)について扱うが、どちらにしても計測なくして改善はないわけで、現在の周波数特性を計測するところから始める。

というわけでRoom EQ Wizard、通称REWが登場する。Mac/Win/Linuxで使えるGUIアプリケーションで、様々な音響特性の測定とフィルタの定義ができる。
REWで作成したフィルタ定義を適用するためにBlackHoleとCamillaDSPを採用した。こちらについても後で触れる。

測定のやり方は検索すると出てくるのでそのようにするとよい。マイクの位置を多少変えつつ何度も計測して平均を取るのがよいとされている。実際やってみると、高周波領域でのディップが測定ごとにかなり変動しているのに気づく。

リスニングポジションによってディップの位置が変動することを検証した記事。このような事情から、高音部分のディップは補正不能なので気にしない方がよさそうである。

左右それぞれ5回測定したところからスタートする。
左ペインに測定結果が並び、メイン画面に周波数特性と位相特性のグラフが表示されている。
グラフの表示範囲をデータにフィットさせるには Limitsボタン→Fit to dataでいける。
Graphメニューからグラフのスムージング手法を選ぶことができる。1/48(1/48オクターブ幅で平滑化)を選ぶとこのようになる。
なお、スムージング手法は画面表示だけでなく実際の演算にも影響する。REWには表示設定と見せかけて演算に影響する系オプションが多いので注意が必要だ。

All SPLタブにはすべてのSPL計測結果を重ねて表示できる。ツールバーのOverlaysボタンを押しても似たようなウィンドウが開くが、こちらはSPL以外に位相なども選べる。あとSPLが何なのかはよくわかってない(サウンドプレッシャーレベルの計測結果(を周波数領域で表示したやつ)という意味だと思われます)。

All SPLタブでActionsボタンを押すとメニューウィンドウが表示される。Apply Smoothing(選択した全データに同じスムージングをかける)やTrace Arithmetic(データどうしを演算する)をよく使います。

引き続きAll SPLタブ。
全データを選択した状態で、ActionsからNo smoothingを適用。
下部のデータ選択部分で右クリック→Clear selectionsしてから左チャネルのデータを全部チェック。ActionsのRMS Averageボタンで、左チャネルの周波数特性を平均したデータが作られる。
右チャネルについても同様に。
生成されたデータは"RMS Average 1"とかの名前になっているので、"L avg"とかに変えておかないと後で後悔します。
グラフの線の太さは、Controlsボタン→Trace optionsボタンで設定可能。線の色は左ペインの各データに筆みたいなアイコン(Trace color)があるのでそこから。
というわけで表示された周波数特性がこのようなありさまになっており、全体的にわけのわからんデコボコがあり左右で10db SPLくらいずれてる箇所もありめちゃめちゃである。まずはこの現実を受け止め、吸音材とかを壁に貼りまくるといいと思う!

音圧のレベルとしてdb SPLという単位があることは今調べました

スムージングについてはREWのERB Smoothingについてという記事がよかったです。

計測結果をERBスムージングした結果。1.3〜4.5kHzあたりの領域がキモい!!

壁に吸音材とか貼りまくるのは面倒なのでおれはソフトウェアだけでいく。
REWで補正データを作る方法は複数あるが、メジャーなやつ(EQボタンからグラフィックイコライザ用の設定を作る)はそのへんに説明があると思うのでここでは扱わない。かわりにマイナーなやつ(Trace ArithmeticでFIRフィルタ用のインパルス応答wavファイルを作る)の説明をします。

なお動画ではタイムアライメントの調整からやっているが今回は省略した。
大まかな流れとしては、
- 左右の音量差を大まかに補正する
- 目標とする周波数特性のカーブを作る
- Trace Arithmeticを使用し、理想カーブになるような補正データを左右チャンネルそれぞれ作成
- 位相を調整
- インパルス応答をwavとしてエクスポート
- 音量差補正+インパルス応答をCamillaDSPに設定
となる。

1. 左右の音量差を補正する
- All SPLタブのMeasurement Actionsで左右チャネルそれぞれのResponse copyを作成
- All SPLタブで左右のコピーを選択して、ActionsのAlign SPLを実行(Use avg SPL of measurements, centre=500Hz, span=3 octave)
- All SPLタブでLとL copyを表示してピーク部分をズーム。ふたつのグラフが一致するように、コピーじゃないほうのデータに対してMeasurement ActionsのSPL Offsetを調整する。一致したところでAdd offset to data。この際に入力した値はあとで使うのでメモしておく。Rチャネルに対しても同様の処置をする。
1で作成したコピーは以降使わないので削除してよい。
このステップにより、左右の音量差が大まかに揃った状態になる。メモしたデータはフィルタの設定時に使う。

2. 目標とする周波数特性のカーブを作る
- All SPLタブで、左右のチャネルを選択してActionsからRMS Averageする。できたデータはL+R avgとでも名付けておくといい
- 左ペインでL+R avgを選択、EQボタンでイコライザ設定ウィンドウを開く
- 周波数特性のカーブを作成する。動画ではHarmon target curveのデータをHouse curveとしてロードしているが、フラットな特性でよければTarget settingsのTarget type/LF cutoff/LF slopeあたりを調整するだけでもよい。
- Calcurate target level from responseをクリックして音量のレベルを実データに合わせる
- Generate measurement from target shapeをクリックして目標カーブデータを生成
このカーブを目標に信号を調整することになるので、元の特性から極端にかけ離れたカーブにはしないほうがよい。

3. Trace Arithmeticを使用し、理想カーブになるような補正データを左右チャンネルそれぞれ作成
目標カーブを実際のカーブで割ってやればよいが、そのままやるとFFT的に問題があるので2段階に分けてやるらしい。
- All SPLで左右チャネルを選択、何らかのsmoothingをかける。
スムージングされたデータを元にフィルタを生成するので、この選択によって結果が変わる。 - All SPLのActionsからTrace arithmeticを選択。Aに左チャネルを、Bに目標カーブを設定してA/BをGenerate(Regularization=0%, Lower/Upper limit=None)。A over Bというデータができる。
- 引き続きTrace arithmeticで、Aに1.のA over Bを、Bは使われないので無視、1/AをGenerate。
動画ではREWの旧バージョンが使われているが、現在のバージョン(5.51.3)では1/Aの設定項目が増えている。
ここの動作はよくわからなくて、Maximum gainに0以外を設定すると反転してくれないといった事象が……
生成されたカーブが期待通りか確認しながらやりましょう。あとドキュメントをちゃんと熟読すべき。 - 生成されたデータがLチャネル用のフィルタ。A over Bは不要なので消してよし。
- 右チャネルも同様にやる。
このようなデータが生成されます:
左右チャネルにかけるスムージングの違いは以下のようになった。ERBでは100Hzあたりの左右差が表現できてないので、今回は1/6を採用。
本当は人間の聴覚特性を考慮しつつ、左右差が重要な周波数領域のみ補正するのがいいかもしれない。
ERB
1/6
1/12

4. 位相を調整
左右それぞれのフィルタデータに対して、All SPLタブのActions→Measurement ActionsでMin.phase versionを作成。
なんか生成されたデータが+49.9dbになるんだけど何これ…… とりあえずSPL offsetを入れて対処。

5. インパルス応答をwavとしてエクスポート
FileメニューのExport→Export Impulse Response as WAV

6. 音量差補正+インパルス応答をCamillaDSPに設定
設定ファイルの全体はこんな感じになった。devices
の部分は環境に合わせて適宜調整せよ。
devices:
samplerate: 48000
chunksize: 4096
queuelimit: 2
silence_threshold: -60
silence_timeout: 3.0
target_level: 4096
adjust_period: 10
enable_rate_adjust: true
resampler: null
capture_samplerate: null
capture:
type: CoreAudio
channels: 2
device: "BlackHole 2ch"
format: FLOAT32LE
playback:
type: CoreAudio
channels: 2
device: "USB2.0 Device"
format: S16LE
exclusive: false
filters:
gain_l:
type: Gain
parameters:
gain: 0.4 # ステップ1で計測したゲイン(L)をここに書く
scale: dB
gain_r:
type: Gain
parameters:
gain: -0.4 # ステップ1で計測したゲイン(R)をここに書く
scale: dB
fir_l:
type: Conv
parameters:
type: Wav
filename: &conv_filename "WAVファイルのパス"
channel: 0
fir_r:
type: Conv
parameters:
type: Wav
filename: *conv_filename
channel: 1
pipeline:
- type: Filter
channel: 0
names:
- gain_l
- fir_l
- type: Filter
channel: 1
names:
- gain_r
- fir_r

Camilladspがめちゃめちゃbuffer overrunするので困っていたが、camilladsp 3.0 + Blackhole-2ch 0.6.0( brew install blackhole-2ch
で入るの知らなかった )にしたら安定した!!

皆さんへのアドバイス
デジタル信号処理の知識がないとあらゆる操作を雰囲気でやることになってつらいぞ。いい入門書があったら教えてください。

「やる夫で学ぶディジタル信号処理」を熟読しています http://www.ic.is.tohoku.ac.jp/~swk/lecture/yaruodsp/main.html

フィルタを入れた状態での測定結果。
スムージングなし:
1/24スムージング:
拡大(1/24)
補正前の特性、同じ領域(1/24)
まあまあフラットにはなってるけど補正しきれない山や谷が多い。左右の差は前よりマシになってる。物理的にはクソ環境のわりに健闘したほうではないでしょうか!!!

まあまあ良くなってるように見えるけど計測中にRの出力がクリッピングしてるんですよね。フィルタの作り方に問題がある気がする!!音楽とか聞いてるときはクリッピング発生しないので実用上問題はなさそうですが……

2024-08-16 06:27:20.349432 WARN [src/conversions.rs:65] Clipping detected, 342 samples clipped, peak +4.09 dB (160.2%)
2024-08-16 06:27:20.434999 WARN [src/conversions.rs:65] Clipping detected, 327 samples clipped, peak +4.60 dB (169.8%)
2024-08-16 06:27:20.519601 WARN [src/conversions.rs:65] Clipping detected, 60 samples clipped, peak +2.28 dB (130.1%)
2024-08-16 06:27:20.605745 WARN [src/conversions.rs:65] Clipping detected, 138 samples clipped, peak +2.89 dB (139.4%)
2024-08-16 06:27:36.819020 WARN [src/conversions.rs:65] Clipping detected, 7 samples clipped, peak +0.31 dB (103.7%)
2024-08-16 06:28:28.870104 WARN [src/conversions.rs:65] Clipping detected, 1 samples clipped, peak +0.02 dB (100.3%)
2024-08-16 06:28:31.260302 WARN [src/conversions.rs:65] Clipping detected, 6 samples clipped, peak +0.13 dB (101.5%)
ぜんぜんクリッピングしとるやんけ、雑に両チャンネル-5dbして解決
filters:
gain_common:
type: Gain
parameters:
gain: -5.0
scale: dB
# ...
pipeline:
- type: Filter
channel: 0
names:
- gain_common
- gain_l
- fir_l
- type: Filter
channel: 1
names:
- gain_common
- gain_r
- fir_r

主観的にはどうかというと、低域がフラットになりボワボワした感じがなくなったのは明確なメリットで、あと定位?が向上?したような感じがします!!

遅延が大きいので動画には不向き。10msくらいにできんか?