言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

Ogg Vorbis

Ogg の一番メジャーな応用として Vorbis という音声圧縮方式が提供されている。Vorbis 自体は Ogg に依存しない独立した方式だと書いてあるのだが、ドキュメントがイマイチで純粋に Vorbis だけを使う方法がよく分からないので、サンプルコードを読んで分かる範囲で Ogg Vorbis と libvorbis プログラミングの方法を書く。

OggVorbis の関係

Ogg ファイルの内容は、物理的には適当なサイズの沢山のページの集合になっている。また、論理的には何本かの論理ストリームを入れる事が出来て、その論理ストリームは細かい沢山のパケットの集合という事になっている。Vorbis はそのパケットを順に処理して音声を解凍してゆく。つまり、Vorbis 自体は物理的なファイルやページの切れ目の事は(あまり)考えない。

Vorbis ヘッダ

Vorbis ファイルの最初の三つのパケットはヘッダで、残りが音声情報だ。() の数字は Vorbis_I_spec.html の章番号。

  • 確認ヘッダ (Identification header) : ざっとこのファイルの内容を表す。(4.2.2)。
    • このヘッダだけ一ページに収まる必要がある。
    • vorbis_version : 常に 0
    • audio_channels : チャンネル数
    • audio_sample_rate : サンプルレート
    • bitrate_maximum : 最大ビットレートのヒント
    • bitrate_nominal : 通常ビットレートのヒント
    • bitrate_minimum : 最小ビットレートのヒント
    • blocksize_0 : よくわからない???
    • blocksize_1 : よくわからない???
    • framing_flag : よくわからない???
  • コメントヘッダ (Comment header) : 文字情報 (4.2.3)
    • フィールド名=内容 の列。フィールドには TITLE, VERSION, ALBUM, TRACKNUMBER 等がある。
    • フィールドはアルファベットのみ、内容は utf-8(5.2.2.2)
  • 設定ヘッダ (Setup header) : 色々解凍に必要な情報 (4.2.4)

libvorbis で使う構造体

  • vorbis_info : 設定を保存
  • vorbis_comment : コメントを保存
  • vorbis_dsp_state : パケットを pcm に変換する状態
  • vorbis_block : パケットを pcm に変換する場所

Ogg Vorbis ファイルを解凍する手順 (decoder_example.c の内容)

  • vorbis_synthesis_headerin() を三回読んでパケット三つ分を読む。
    • vorbis_info 構造体と、vorbis_comment 構造体が設定される。
  • vorbis_synthesis_init() で vorbis_info を元に vorbis_dsp_state を設定。
  • vorbis_block_init() で vorbis_dsp_state を元に vorbis_block を設定。
  • 以下パケットごとに繰り返し
    • vorbis_synthesis() : パケットを調べる (synthesis.c)
    • vorbis_synthesis_blockin() : なんかやる (block.c)
    • vorbis_synthesis_pcmout() : 音声を返す (block.c)
    • vorbis_synthesis_read() : 実際どこまで読んだかを知らせる (block.c)