Variousible ホーム Programming Room トップ

Ogg Vorbis を奏でる

2004/03/14

SDK のビルドが完了すれば、今度は実際に再生プログラムを作成してみます。 ファイルから再生するだけのコマンドラインプログラムですので、 使用するのは vorbisfile というライブラリです。 なお、Windows API を使用した方法を紹介していますが、紹介している本人は 根っからの非 Windows プログラマーなので、誤っていればご指摘ください。 また、不具合として、バッファの切り替え時に再生が一瞬途切れることがありますが、 これについてはよくわかりません。切れて当然のような気もしますが...

コードリスト

まずは手っ取り早く、コード全体を紹介します。必要な説明は後に つけていきたいと思います。なお、StdAfx.h と StdAfx.cpp は、 Visual Studio でコンソールアプリケーションのプロジェクトを作成するときに 自動生成されるファイルにインクルードファイルを追加したものです。

Visual Studio VC++ プロジェクトについて

コードの説明の前に、プロジェクト作成時の注意をまとめておきます。

Ogg Vorbis SDK を使用するプロジェクト

libogg や libvorbis を使用する場合、ビルドしたライブラリを適切に 使用するようにプロジェクトを設定する必要があります。

まず必要なのはインクルードファイルで、libogg と libvorbis の include ディレクトリをプロジェクトの全般設定で指定してください。 vorbisfile を使用する場合、直接必要なのは、libvorbis のヘッダファイルですが、内部で libogg のヘッダを参照しているため、 両方のインクルードファイルが必要となります。

もちろんリンクするためにはライブラリが必要です。アプリケーションを 作成する場合は、デバッグビルド、リリースビルドそれぞれに対して、 ogg/vorbis ライブラリもデバッグビルド、 リリースビルドを使用すると良いかもしれません。今回のプログラムで必要なのは、 vorbisfile_static_d.lib、ogg_static_d.lib winmm.lib です。 winmm.lib は Windows のマルチメディアライブラリです。 なお、"_d" のつくライブラリはデバッグビルド用、さらに _static がつくのは、 スタティックリンクをするためのライブラリであることをあらわします。 dll を使用する場合は、"_static" のないファイルを使用します。 SDK を自分でビルドした場合であれば、適当な名前のフォルダに それぞれ生成されているので確認してみてください。

ファイルから再生する基本

Web1.cpp は ogg ファイルからデータを読ませて再生するものです。 基本的な Vorbisfile API のみを使用しています。ここでの解説における コードは Web1.cpp のものと完全に同等ではありません。より一般的な (Windows に依存した書き方ではない) コード断片を使って解説します。 したがって、ここでは Windows 関連の API については解説しません。

デコーダの準備

ファイルからデータを読ませて再生するための準備が必要です。 以下のコードが該当します。

Vorbisfile の準備
FILE *fp; OggVorbis_File vf; /* Ogg ファイルのオープン */ fp = fopen(OGG_FILE, "rb"); if (NULL == fp) { fprintf(stderr, "ERROR: Can not open file.\n"); exit(1); } /* OggVorbils_File 構造体 */ ret = ov_open(fp, &vf, NULL, 0); if (ret < 0) { fprintf(stderr, "ERROR: ov_open()\n"); fclose(fp); exit(1); }

標準入出力を使用していますので、<stdio.h> が必要になります。 また、libvorblis を使用するため、<vorbis/vorbisfile.h> も必要です。

OggVorbis_File 構造体がリソースの管理など、再生に必要な情報を管理する 構造体です。ogg ファイル (ここではファイル名を OGG_FILE としています) を開いた後、OggVorbis_File 構造体を ov_open() 関数により初期化します。 正しく構造体を初期化できれば、必要最低限の初期化は完了です。

ov_open() 関数の後の 2 つの引数は、 すでにファイルからデータを読み込み済みのバッファがある場合に使用します。

Vorbis の情報

コーデックにより取得された情報を格納する vorbis_info 構造体があります。 PCM へのデコード後に、その PCM を処理 (例えば再生) するためには、チャンネル数、またサンプリングレートも必要となります。 これらは vorbis_info 構造体から取得します。ov_info() 関数は、 指定した OggVorbis_File 構造体に関する vorbis_info 構造体を返します。

Vorbisfile の準備
/* Vorbis 情報 */ vi = ov_info(&vf, -1); if (NULL == vi) { fprintf(stderr, "ERROR: ov_info()\n"); fclose(fp); ov_clear(&vf); exit(1); }

一つ目の引数は OggVorbis_File 構造体へのポインタです。2 つめは、 ビットストリームを指定するということですが、まだこのビットストリームとは ? というのがよくわかってませんが、現在のビットストリームをあらわす -1 を指定します。

デコード処理

デコードをおこなうために、まず、バッファを用意する必要があります。 デコードされた PCM を格納するためのバッファです。

デコード
#define BUFFER_SIZE 4026 ... char buffer[BUFFER_SIZE]; int bitstream; while (1) { int read = ov_read(&vf, buffer, BUFFER_SIZE, 0, 2, 1, &bitstream); if (read <= 0) { break; } /* 再生などの PCM の処理 */ }

ov_read 関数は、ストリームをデコードし、PCM をバッファ buffer に格納します。ここで、BUFFER_SIZE にはデコード後の PCM データの要求バイト数を指定します。戻り値として、実際に得られた PCM のバイト数が返されます。ここで、戻り値は必ず BUFFER_SIZE 以下になります。 BUFFER_SIZE と等しくなることは保障されません。

残りの引数は、取得する PCM のエンディアン、PCM サンプルのサイズ、 符号付か否かを指定します。PCM の用途によって指定する値が決まります。 通常は、リトルエンディアン (0 を指定)、2 バイト (1 サンプルが 2 バイトからなる)、符号付 (1 を指定) を指定します。 bitstream には、現在のビットストリームを表す値が格納されます。 この値を使って、ov_info() 他の問い合わせ関数を使用することができます。

後処理

デコードが終了すれば、後処理を行う必要があります。 後処理は ov_clear() 関数を呼び出すだけで完了です。

後処理
ov_clear(&vf);
Variousible ホーム Programming Room トップ
※Java およびすべての Java に関する標章は、米国およびその他の国における米国 Sun Microsystems, Inc. の商標または登録商標です。
※その他の登場する製品名は、各社の商標または登録商標です。
本サイトについて
Copyright © 2004 KURIHARA, Yusuke