はじめに
Web Audio APIで音声ビジュアライザーを作っていると、AnalyserNode の fftSize という設定が出てきます。
analyser.fftSize = 2048
最初はなんとなくサンプルコードに書かれている値をそのまま使っていました。
ただ、ビジュアライザーを作っていると、
- 反応が粗い
- 低域の反応が鈍い
- 細かい音に反応しすぎる
- 見た目が落ち着かない
- 処理が少し重い
といった問題が出てきます。
そこで今回は、fftSize を変えると音声ビジュアライザーの反応がどう変わるのかを整理します。
fftSizeとは
fftSize は、周波数解析に使うデータサイズです。
Web Audio APIの AnalyserNode では、音声を周波数成分に分解できます。
そのとき、どれくらいの細かさで解析するかを決めるのが fftSize です。
const audioContext = new AudioContext()
const analyser = audioContext.createAnalyser()
analyser.fftSize = 2048
fftSize に指定できる値は、基本的に2の累乗です。
32
64
128
256
512
1024
2048
4096
8192
16384
32768
ただし、音声ビジュアライザー用途では、まずは 1024、2048、4096 あたりから試すのが扱いやすいです。
frequencyBinCountとの関係
fftSize を設定すると、frequencyBinCount はその半分になります。
analyser.fftSize = 2048
console.log(analyser.frequencyBinCount)
// 1024
周波数データを入れる配列は、この frequencyBinCount に合わせて作ります。
const frequencyData = new Uint8Array(analyser.frequencyBinCount)
周波数解析では、この配列に低い周波数から高い周波数までのエネルギーが入ります。
analyser.getByteFrequencyData(frequencyData)
fftSizeを小さくするとどうなるか
たとえば fftSize = 512 のように小さめにすると、反応は軽くなります。
analyser.fftSize = 512
小さい fftSize の特徴は以下です。
良いところ:
- 反応が軽い
- 処理負荷が少ない
- 動きがキビキビする
気になるところ:
- 周波数の解像度が低い
- 低域・中域・高域の分離が粗くなる
- 細かい帯域解析には向きにくい
音量に合わせてざっくり動けばいい場合は、小さめでも問題ありません。
ただ、bass / mids / highs のように帯域を分けたい場合は、少し粗く感じることがあります。
fftSizeを大きくするとどうなるか
逆に fftSize = 4096 や 8192 のように大きくすると、周波数の解像度が上がります。
analyser.fftSize = 4096
大きい fftSize の特徴は以下です。
良いところ:
- 周波数の分解能が高い
- 低域・中域・高域を分けやすい
- 音の成分を細かく見やすい
気になるところ:
- 処理が重くなりやすい
- 反応が少し遅く感じることがある
- ビジュアルの動きが鈍く見える場合がある
音声解析としては細かくなりますが、ビジュアライザーとして気持ちいいかは別です。
特に高BPMの曲や細かい音が多い曲では、数値が細かくなりすぎて、見た目の調整が必要になります。
よく使いやすいのは2048
個人的には、最初は 2048 が扱いやすいと思いました。
analyser.fftSize = 2048
理由は、軽さと解析の細かさのバランスがよいからです。
512: 軽いが粗い
1024: 軽めで扱いやすい
2048: バランスがよい
4096: 細かいが少し重め
8192以上: 用途によっては過剰
音声ビジュアライザーでは、厳密な音響解析よりも「見た目として気持ちよく反応すること」が大事です。
その意味で、2048 はちょうどよい初期値になりやすいです。
bass / mids / highs を取る場合
周波数帯域を分ける場合、fftSize は見た目に影響します。
たとえば、以下のような帯域に分けるとします。
bass: 20Hz - 250Hz
mids: 250Hz - 2000Hz
highs: 2000Hz - 8000Hz
このとき fftSize が小さすぎると、各帯域の解像度が粗くなります。
特に低域は範囲が狭いので、fftSize が小さいと反応がざっくりしやすいです。
function frequencyToIndex(
frequency: number,
sampleRate: number,
fftSize: number
): number {
return Math.round((frequency / (sampleRate / 2)) * (fftSize / 2))
}
fftSize が大きいほど、周波数を細かいindexに変換できます。
ビジュアライザーでは正確さより気持ちよさも大事
音声解析だけを見ると、fftSize は大きい方がよく見えます。
しかし、ビジュアライザーでは必ずしもそうではありません。
たとえば、
- 低域にすぐ反応してほしい
- キックで瞬間的に膨らんでほしい
- ハイハットで細かく光ってほしい
- 全体の動きを軽くしたい
という場合、解析の細かさよりも反応速度や見た目の調整の方が大事になることがあります。
つまり、fftSize は音響的な正しさだけではなく、表現のパラメータとして見ると扱いやすいです。
smoothingとの組み合わせ
fftSize だけでなく、smoothingTimeConstant も見た目に大きく影響します。
analyser.smoothingTimeConstant = 0.8
smoothingTimeConstant は、値のなめらかさです。
低め: 細かく反応する
高め: ゆっくりなめらかに反応する
たとえば、fftSize を大きくして解析を細かくしつつ、smoothingTimeConstant を高めにすると、落ち着いた反応になります。
逆に、fftSize を小さめにして smoothingTimeConstant を低くすると、かなりキビキビした反応になります。
音楽ジャンルによる調整
音楽ジャンルによっても、気持ちよく見える設定は変わります。
Ambient / Shoegaze:
fftSize: 2048 - 4096
smoothing: 高め
Breakcore / Hyperflip:
fftSize: 1024 - 2048
smoothing: 低〜中
Dubstep / Bass Music:
fftSize: 2048
smoothing: 中
Lo-fi / Chill:
fftSize: 2048 - 4096
smoothing: 高め
もちろん正解ではありません。
ただ、曲の動きに合わせて解析設定も変えると、ビジュアルの印象がかなり変わります。
まとめ
fftSize は、Web Audio APIで周波数解析を行うときの重要な設定です。
小さくすると軽くキビキビ動きますが、周波数の解像度は粗くなります。
大きくすると細かく解析できますが、処理が重くなったり、反応が鈍く見えたりすることがあります。
音声ビジュアライザーでは、まずは以下のように考えると扱いやすいです。
迷ったら2048
軽くしたいなら1024
細かく見たいなら4096
最終的には、数値として正しいかよりも、音楽に対して気持ちよく見えるかが大事だと思いました。