0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Web Audio APIでMP3をWAVに書き出すときの落とし穴:decodeAudioDataのリサンプリング、ビット深度、先頭の無音

0
Posted at

「MP3をWAVにしたい」という要件は、DAWや動画編集ソフトへの取り込み、音声認識APIへの入力などでよく出てきます。ブラウザだけで実装しようとすると、decodeAudioData でデコードしてPCMをWAVヘッダー付きで書き出す、という流れになります。シンプルに見えて、いくつかハマりどころがありました。

1. decodeAudioDataは勝手にリサンプリングする

AudioContext はデバイスの出力サンプルレート(48kHzが多い)で作られます。そして decodeAudioData は、元ファイルが44.1kHzでもコンテキストのサンプルレートに変換して返します。

const ctx = new AudioContext();          // 48000Hz の環境が多い
const buf = await ctx.decodeAudioData(arrayBuffer);
console.log(buf.sampleRate);              // 44100 ではなく 48000

元のサンプルレートを保ちたい場合は、事前にMP3のフレームヘッダーからサンプルレートを読み、そのレートで OfflineAudioContext を作ってデコードします。

const off = new OfflineAudioContext(2, 1, srcSampleRate);
const buf = await off.decodeAudioData(arrayBuffer);

2. 先頭と末尾の無音(エンコーダーディレイ)

MP3には仕様上、先頭に数十ms程度の無音(エンコーダーディレイ)と末尾のパディングがあります。LAMEでエンコードされたファイルなら、XingヘッダーのLAMEタグに正確なサンプル数が書かれているので、それを読んでトリミングできます。

ループ素材やギャップレス再生が必要な音源では、これを放置すると「つなぎ目でプチッと鳴る」原因になります。

3. ビット深度とクリッピング

AudioBuffer の中身は-1.0〜1.0のFloat32です。16bit PCMに変換するときは必ずクランプします。

for (let i = 0; i < src.length; i++) {
  const s = Math.max(-1, Math.min(1, src[i]));
  view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
  offset += 2;
}

MP3は音圧の高い曲だとデコード後に1.0を超えるサンプルが出ることがあります。クランプしないと、オーバーフローして大きなノイズになります。用途によっては32bit floatのWAV(フォーマットコード3)で書き出すのも選択肢です。

4. 大きなファイルとメモリ

1時間のステレオ音声を48kHz・Float32で保持すると約1.4GBになります。モバイルでは落ちます。長尺ファイルは、デコードをチャンク単位で行い、WAVのデータチャンクをストリームで書き出す方が安全です。

5. 「MP3→WAVで音質は良くならない」

最後に仕様ではなく説明の話です。ユーザーには「WAVにしても失われた情報は戻らない。編集ソフトに取り込みやすくなるだけ」と明記しておくと、問い合わせが減ります。

実装の確認用に

自分の実装の出力と比較するのに、ブラウザ内で変換が完結するNibboのMP3→WAV変換を使っています。ファイルをアップロードしないので、手元の音源で気軽に試せます。

まとめ

  • decodeAudioData はコンテキストのレートにリサンプリングする
  • エンコーダーディレイを考慮する
  • Float32→Int16はクランプ必須
  • 長尺はストリーム処理

— Vitalii

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?