[Astro] #181 ブラウザだけで動く音量そろえツール — 曲の音量を、まとめて同じにする

[Astro] #181 ブラウザだけで動く音量そろえツール — 曲の音量を、まとめて同じにする

はじめに

前回は、音声ファイルを切ってつなぐ、Audio Cutter を作りました。

今回は、音量をそろえるツールです。Audio 系のツールを作ってきて、最後に欲しかったのが、これでした。

曲を集めると、ファイルごとに、音の大きさがばらばらです。1 曲ごとに、再生しながら音量を直すのは、手間がかかります。そこで、複数のファイルを、まとめてドロップして、全部を同じ大きさにそろえて書き出すツールを、作りました。名前は Audio Gain です。

ファイルは、サーバーに送られません。

画面

全体

Audio Gain の全体。2 つのファイルが -14.0 LUFS にそろった一覧と、右の設定

左がファイルの一覧、右が設定です。ファイルを入れると、すぐに音量を測ります。「現在の音量」「ピーク」「調整」「変換後」が、1 行に並びます。

ノイズ対策

右の設定。音量、ノイズ対策、書き出し、保存の方法

右の設定は、上から「音量」「ノイズ対策」「書き出し」「保存の方法」です。ふだんは、目標の音量を決めて、「変換して保存」を押すだけです。

F1 ヘルプ

F1 キーで、「やりたいこと → やり方」を検索できます。Audio Cutter と同じ作りです。

F1 キーで、「やりたいこと → やり方」を検索できます。 F1 キーで、「やりたいこと → やり方」を検索できます。

作ったもの

  • 複数のファイルや、フォルダごとドロップして、自動で音量を測ります
  • 目標の音量(初期値は −14 LUFS)を決めると、ファイルごとに、上げ下げする量を計算します。すぐに、全部同じ大きさにそろいます
  • 音が割れないように、音量の上限(初期値 −1 dBTP)を守るリミッターを入れています
  • 読み込みは、MP3、M4A(AAC)、WAV、OGG、FLAC、Opus と、動画ファイルの音声です
  • 書き出しは、元の形式のまま、MP3、M4A、Opus、FLAC、WAV(16bit・24bit)。保存は、ZIP でまとめて、フォルダに保存、1 つずつダウンロード
  • 低音の雑音カットと、電源ハムの除去
  • タグ・ジャケット画像の引き継ぎ、試聴、F1 ヘルプ

作り方

「聴こえる大きさ」を測る

音量をそろえるとき、波形の一番高い所(ピーク)をそろえても、聴いた感じはそろいません。ピークが同じでも、音がずっと鳴っている曲と、たまに鳴る曲では、聴こえる大きさが違うからです。

そこで、人の耳に近づけた音量の単位、LUFS(ラウドネス)を使います。規格は、ITU-R BS.1770-4(放送の基準で、EBU R128 の元になったもの)です。

測り方は、次のとおりです。

  1. 音に、2 段のフィルタ(K 特性)をかけます。高い音を少し持ち上げて、低い音を削って、耳の感じ方に近づけます
  2. 400 ミリ秒の窓を、100 ミリ秒ずつずらして、窓ごとの大きさを出します
  3. −70 LUFS より小さい窓を捨てます(ほぼ無音の所)
  4. 残りの平均から、10 LU 以上小さい窓を、もう一度捨てて(ゲート)、その平均を、全体の音量にします

フィルタの係数は、サンプルレートごとに、計算し直しています。44.1kHz、48kHz、22.05kHz などで、同じ結果になります。

確かめるために、ffmpeg の ebur128 と、同じ音を比べました。6 種類の音(正弦波、ノイズ、混ぜた音、サンプルレートの違い)で、差は 0.05 dB 以内でした(ffmpeg の表示が 0.1 単位なので、それ以上は比べられません)。

上げすぎて、割れないように

音量を上げると、波形の一番高い所が、0 dB を超えます。超えた部分は、潰れて、音が割れます。

しかも、デジタルの音は、サンプルの点と点の間で、実際の波形が、点よりも高くなることがあります。それも含めた、本当のピークが、True Peak です。4 倍に細かくして調べています。

最初は、補間の窓関数に Blackman-Harris(16 タップ)を使いました。ところが、測ると、15kHz の信号のピークを、0.3 dB 以上、低く見積もっていました。窓が狭くて、高い音を、正しく補間できていなかったためです。Kaiser 窓(β=4)の 24 タップに、直しました。

上限を超える所には、リミッターをかけます。作りは、こうです。

  • 上限を超えそうな所を、2 ミリ秒先読みして、必要な下げ量を出します
  • 前後 2 ミリ秒の最小値を取って、移動平均で、滑らかにします。これで、音量が急に変わらず、下げ始めの「ブチッ」というノイズを避けられます
  • 戻るときは、80 ミリ秒かけて、ゆっくり戻します
  • 書き出した結果は、元と同じ長さです(最後に、残りを出し切ります)

3 種類の音を、0 / +6 / +12 dB 上げて通したところ、どれも、書き出したあとの True Peak が、上限の −1.000 dBTP を超えませんでした。

書き出し

読み込みと書き出しは、Audio Cutter と同じ、Mediabunny(1.61.6)です。MP3 と FLAC の WASM エンコーダも、Audio Cutter のものを、そのまま使っています。

16bit の WAV にするときだけ、丸める前に、ごく小さなノイズ(TPDF ディザ)を足して、小さい音の歪みを防いでいます。

目標との差が、0.05 dB 未満のファイルは、再エンコードしないで、そのままコピーします。音質が変わらないためです。ほぼ無音のファイルは、測れないので、変えません。上げる量は、最大 +24 dB までです。それ以上は、背景のノイズが、大きくなりすぎます。

ノイズ対策(段階 1)

音量を上げると、もともと入っていた背景のノイズも、同じだけ大きくなります。そこで、ノイズ対策も、入れることにしました。ただし、一度に全部は作らないで、軽い所から、1 つずつです。

今回は、いちばん軽い、2 種類だけです。

  • 低音の雑音をカット: 40Hz より下を削ります。風の音、マイクを触った振動、床の揺れなどが、対象です
  • ハム除去: 電源由来の「ブーン」という音(50Hz か 60Hz と、その倍の高さ)を、細いフィルタで削ります

どちらも、2 次のフィルタ(Biquad)を、つないだものです。低音カットは、4 次の Butterworth(2 段)で、20Hz で −24 dB、60Hz でも −0.2 dB なので、ふつうの低音は、ほとんど変わりません。ハム除去は、基本波と、2 倍、3 倍の、3 本のノッチです。

順番が大事です。ノイズ対策を先にかけて、そのあとで、音量を測って、ゲインをかけます。 逆だと、ノイズを含んだ音量で、そろえてしまうためです。ノイズ対策を選ぶと、全部のファイルを、測り直します。

確認として、50Hz・100Hz・150Hz のハムと、18Hz のゴロゴロを混ぜた、合成の音楽で、変換してみました。ハムは、−24〜−34 dB から、約 −100 dB に下がりました。18Hz は、26 dB 下がりました。ほかの音(220Hz、440Hz)は、変わっていません。

ただし、これは、合成の音です。本物のハムは、周波数が、少しずれます。50Hz から 0.2Hz ずれると、効きは −12 dB ほどに、落ちます。そして、「サーッ」というノイズ(ヒスノイズ)や、声の背景ノイズは、この機能では、消えません。

初期値は、「なし」です。ふつうの音楽にかけると、50Hz や 60Hz のベースの音が、少し細くなるためです。

詰まったこと

AAC の書き出しで、エラー

実機(Windows の Chrome)で、ネットで見つけた AAC のサンプルを入れたところ、読み込みと再生はできたのに、変換でエラーになりました。

This specific encoder configuration (mp4a.40.2, 256000 bps, 2 channels, 44100 Hz) is not supported

原因は、音質(ビットレート)でした。元のファイルが高いビットレートだったので、「元に近い値」として、256 kbps を選んでいました。ところが、Windows の AAC エンコーダは、ステレオで 96〜192 kbps までしか、受け付けません。

確かめずに、選んでいたのが、間違いでした。ヘッドレスのブラウザ(画面なしのテスト環境)には、AAC がなく、試せていませんでした。

直しは、変換の前に、canEncodeAudio を、ビットレートつきで確かめて、使えない値は、近い値に下げる、というものです。256 は 192 になります。それでも失敗したときは、英語のエラーを、日本語の説明にします。直したあとで、同じファイルが、変換できました。−17.8 LUFS が −14.0 LUFS になり、ビットレートは 192 kbps でした。

圧縮すると、音量が少しずれる

測った値は、圧縮する前の音量です。MP3 や AAC にすると、エンコーダの癖で、書き出した結果の音量が、±0.5 dB ほど、ずれます。128 kbps の MP3 では、−14.0 が −14.5 LUFS になりました(ffmpeg の LAME でも同じでした)。

これは、仕様です。ずれが気になる場合は、WAV や FLAC に書き出すか、ビットレートを上げてください。ヘルプにも、書いています。

目標まで、上がらないファイル

音が尖っているファイル(ドラムや、ピアノのアタックが強い曲)は、目標まで上げると、一番高い所が、上限を超えます。リミッターで抑えると、全体の音量は、上がりきりません。テストの音では、−14 を目指して、−17.7 になりました。

画面には、リミッターの下げ量の最大値を、出しています。強くかかったファイルは、そこで分かります。

実機で確認できたこと

Windows 11 の Chrome で、確認しました。

  • 音量の違う MP3 を、複数入れて、一括で変換しました。再生して、音がそろっていました
  • 「フォルダに保存」は、問題なく動きました
  • AAC は、読み込み、再生、変換ができました。M4A の 256 kbps を選んでも、通りました(ビットレートは、192 kbps に下がります)
  • ノイズ対策を選んで変換しても、問題なく動きました。ただし、実際のノイズが入ったファイルは、手元になく、効き目は、確かめていません

ヘッドレスのブラウザと、ffmpeg では、次のことを確認しました。

  • LUFS の測定は、ffmpeg と一致(上のとおり)
  • リミッターは、どの条件でも、上限を超えない
  • MP3、WAV、FLAC、OGG、Opus を一括で変換して、ZIP にまとめ、測り直して、目標の −14.0 LUFS(WAV・FLAC・Opus)
  • ZIP の中身の整合性

未確認のこと・制限

  • 聴いた感じの良し悪し: リミッターで音が潰れて聴こえないか、80 ミリ秒の戻りが音楽に合うかは、聴いて決める部分です。強くかけたファイルは、特に、聴いて確かめてください
  • ノイズの入った実際の録音: ノイズ対策の効き目は、合成の音でしか、確かめていません
  • フォルダごとのドロップの動作、数百 MB のファイルや、数十本のバッチでの、時間とメモリ。ZIP でまとめる場合は、変換結果を、全部メモリに持ちます
  • Safari と Firefox
  • 3ch 以上の音声は、先頭の 2ch だけを使います
  • 試聴は、簡易です。リミッターは、ブラウザの簡易なもので、代わりにしています。ノイズ対策は、試聴にはかかりません

おわりに

「音量をそろえる」だけに見えて、測り方の規格、割れない上限の考え方、圧縮したときのずれと、考えることが、思ったより、ありました。

ノイズ対策は、軽い 2 種類だけ入れました。「サーッ」というノイズを、周波数ごとに引く方法(スペクトルゲート)や、声に強い AI の方法(RNNoise)は、あとで、ひとつずつ、足していくつもりです。

今は、v1.0 です。