LoginSignup
6
3

More than 5 years have passed since last update.

liboggとlibvorbisを使ってPCMエンコーディング

Posted at

libogg, libvorbisを使ってPCM音源をoggに変換するやり方を調べてみました。

OggとVorbis

とりあえず知っときたいのは、

  • Oggは音声ファイル自体のことではなくて、様々なメディアを格納するコンテナフォーマット(FLAC,Theoraなど)
  • Vorbisが実際の音声圧縮のフォーマットで、Ogg以外にも格納できる(Matroskaとか)
  • OggにVorbisで圧縮した音声を格納したものをOgg Vorbisファイルという(拡張子.oggまたは.oga)

このため、.oggファイルを作るにはoggとvorbisの両方のライブラリが必要になります。

Oggの概要

Oggにデータを格納するには、

  1. データをパケット(ogg_packet)に分ける
  2. ogg_packetをストリーム(ogg_stream)に送り込む
  3. ある程度データがたまるとストリームからページ(ogg_page)単位でデータが取り出せる
  4. ページにはヘッダとボディがあるのでそれぞれをoggファイルに書き込む

という手順をとります。
最初から最後までページ単位でデータを書き込みます。(ファイル単位のヘッダはコーデック自体がogg_streamに書き込む)

Vorbisの概要

こっちはOggほど単純ではありません。

まず、Vorbisには以下のようなデータがあるので、これらをOggに詰めていきます。

  • Vorbisのヘッダ
    • Ogg用のヘッダ
    • コメントヘッダ(曲名、作曲者などの楽曲情報)
    • コードブックヘッダ(Vorbisの圧縮に関する情報らしい)
  • 圧縮された音声データ

Vorbisヘッダについては関数一つでポンとすべてogg_packetにできてしまいますので、
ここでは音声の圧縮について流れを見てみます。

  1. VorbisInfo(圧縮音声に関する情報を格納した構造体)を初期化する
  2. 圧縮モードやサンプリングレート、ビットレートなどをVorbisInfoに設定する
  3. VorbisAnalysis(Vorbisの音声圧縮器)の圧縮コンテキスト(圧縮中の状態を保持する構造体)を初期化する
  4. VorbisBlock(圧縮作業に必要なメモリ領域)を確保する
  5. 以下6~11をPCMデータが残っている限り行う
  6. 元のPCMデータを、チャンネルごとに浮動小数点数のPCMデータに変換する(各サンプルの変位を-1.0f~1.0fで表す)
  7. 変換したデータをVorbisAnalysisが用意したバッファに詰める(通常6と7は同時にする)
  8. 圧縮用のブロック(VorbisBlock)をVorbisAnalysisから取得する
  9. 取得したブロックを圧縮し、VorbisBitrate(ビットレートの管理をするもの)に圧縮したブロックを送る
  10. VorbisBitrateに圧縮したデータがたまるので、データがなくなるまでogg_packetとして取り出す
  11. 取り出したogg_packetをOggに詰める
  12. データがなくなったら、圧縮用に使っていた領域を解放する

わざわざ8で圧縮用のブロックを取得するのは、並列化できるようにするためらしいです。

実際のコード

libvorbisにエンコーダのサンプルがくっついているのでそちらを参考にするとよいかと思います。
一応ソースへのリンクを貼っときます。

書くのも疲れたのでこの辺で。

参考文献

Wikipedia - Vorbis
https://ja.wikipedia.org/wiki/Vorbis

libvorbis/libogg Documentation
https://www.xiph.org/vorbis/doc/libvorbis/
https://www.xiph.org/ogg/doc/libogg/

6
3
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
6
3