DelphiでOggVorbis

INDEX

はじめに


ここでは、DelphiでOggVorbisを使う方法を考えてみようと思います。
AlphaBitmap3 / buinGLと合わせてガンガン使ってゲームを作ってください。


TOBYさんが製作した、Delphi用OggVorbisのヘッダーです。
BSDライセンスなので、超緩やかです。販売もOKですし、ソース公開やライセンス書類の義務などがありません。

これを、TStream形式で読み出せるように私が改悪しましたので、それを含めて公開します。QuadrupleDでOggVorbisをストリーミング再生するテスト。(ついでに手抜きリピートつき)

サンプルをダウンロード


入っている、OggVorbisUnitは、TOBYさん、ならびに、Xiphophorus(OggVorbis開発元)にあります。
BSDライセンスですので、この2つの記述(例は一番下のライセンス記述)を忘れないようにしてください。


今まで私が見てきたものは
・妙に使いにくい
・アヤシイ
・わけわからん
でしたが、TOBYさんのは率直過ぎて分かりやすかったです。

サンプルを見て、使い方を覚えました。
まあ、サンプルは読みにくいんで、慣れていない人は分かりにくいでしょう・・・。

手順1(準備・生成・開放)


usesにOggVorbisUnitを入れておきましょう。

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ddsd,OggVorbisUnit, ComCtrls, Menus, ExtCtrls, Buttons;


DDSDのTDDSDWaveDataとかをOnCreateで生成しておいて下さい。

OggVorbisUnitのロードは、変に面倒なので関数があったのでTOBYさんのサンプルから拝借。

class function TForm1.LoadOggVorbisLibraryFrom(Directory: string): Boolean;
begin
Result := True;
Directory := ExcludeTrailingPathDelimiter(Directory) + '\';
if not OggVorbisUnit.LoadOggLibraryFrom(Directory + OggVorbisUnit.DefaultOggLibraryName) then
Result := False;
if not OggVorbisUnit.LoadVorbisLibraryFrom(Directory + OggVorbisUnit.DefaultVorbisLibraryName) then
Result := False;
if not OggVorbisUnit.LoadVorbisFileLibraryFrom(Directory + OggVorbisUnit.DefaultVorbisFileLibraryName) then
Result := False;
end;

privateにでも宣言しておいて、FormCreate時に実行ファイルの置いてあるディレクトリを指定しましょう。


procedure TForm1.FormCreate(Sender: TObject);
begin

//OggVorbisUnitの動的DLLリンクを行う。
If not LoadOggVorbisLibraries then begin
ShowMessage('OggVorbisのDLLをロードできません!');
halt;
end;


//WAVE出力を44100/16/STEREOに設定
DDSD1.SetPrimaryBufferFotmat(44100, 16, True);
//ストリーミング再生用に作る
wav := TDDSDWaveData.CreateStream(DDSD1, 44100, 16, TRUE, 44100*4);
wav.OnUpdate := UpdateWav;
DDSD1[0].WaveData := wav;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin

wav.Free;

UnloadOggVorbisLibraries;

end;

こんな風にですね。
UpDateWavは、バッファーがなくなったら読みに行くときの関数イベントです。

public宣言等にOggのデータ保持用の構造体とかの変数を宣言しておきます。

F: TFileStream;
vf: OggVorbis_File;
wav : TDDSDWaveData;

Buffer: array[0..BufferSize-1] of Byte;

ユニットの頭に、

const BufferSize = 44100*4;
とやっておきます。バッファーサイズは、一応こう定義します。大きいほうがいいでしょうし。Wavのバッファーサイズと同じにしておきましょう。

手順2 再生


まず、Oggファイルの読み込みですが、TFileStreamを使ってみます。

F:=TFIleStream.Create(Label1.Caption,fmOpenRead);
ov_open_callbacks(F, VF, nil, 0, ops_callbacks);


・・・。簡単すぎ。そのままコピペでオッケーです。

DDSD1[0].LoopPlay;


・・・。再生。簡単すぎ。

さて、バッファーがなくなったとき用のUpDataWavを考えます。


procedure TForm1.UpdateWav(Sender:TDDSDGenWave; Player:TDDSDChannel; ofs,len:Cardinal);
var
BytesRead,SizeToRead: Longword;
CurrentSection,pos,Change: Integer;
Return: Integer;
time:Double;

begin
BytesRead := 0;
CurrentSection:=0;

repeat
Change := ov_read(VF, Buffer[BytesRead], len - BytesRead, 0, 2, 1, CurrentSection);
BytesRead := BytesRead + Longword(Change);
until (Change = 0) or (BytesRead = len);

If Change=0 then begin
//バッファの初期化
Zeromemory(@Buffer,BufferSize);
wav.BlockCopy(0,@Buffer, BufferSize);
//シーク
ov_time_seek(vf,0);
end else begin
//レンダリング結果をストリーミングに転送
wav.BlockCopy(ofs,@Buffer, BytesRead);
Time := ov_time_tell(vf);
Label2.Caption:=Format('時間 %f',[time]);
end;


end;


・・・。ちょっと難しいですねえ。
Bufferは配列ですが、ポインタにしてwavにBlockCopyに入るようにぶち込んでます。
repeat〜untilは、どうもOggデータから、現在位置の情報を1バイトずつ読ませてるみたいです。
現在位置とかの指定は特にいらないみたいです。lenには必要な長さが入っているんで、その長さ分読み取ってます。
あと、Changes=0のときは、つまりは空っぽ、つまりは終了ってことなのでリピートさせてます。
普通は、停止命令DDSD1[0].Stopでも入れておけばいいんじゃないでしょーか。


停止は、

DDSD1[0].Stop;



とします。

ファイルを変えたいときは、Oggをいったんクローズします。

ov_clear(VF);

Oggの入ったFileStreamのFは、Freeにする必要はないようです。勝手にライブラリのほうで開放してくれるようで。

ストリーミングの再生は以上のとおり、妙に簡単です。

普通の再生は、LenをとりあえずChangesがゼロになるまで回しまくりつつ、Streamに書き込んでいって最後にTDDSDWaveDataでそのストリームをバッファで読み込めば音声やら効果音が再生できるはず。

QuadrupleDだけではなく、DelphiXや他のWaveラッピングライブラリならどれでも使えるはずです。



関数解説

関数 使い方 説明
ov_read ov_read(TOggVorbisFile構造体,バッファー,取得したいサイズ,0,2,1,適当なInteger型変数); デコードしてバッファに展開してくれる関数。
ov_time_tell ov_time_tell(TOggVorbisFile構造体);
返り値にDouble型の時間データ。
現在の再生時間(秒)をDouble型で返してくれます。
ov_time_seek ov_time_seek(TOggVorbisFile構造体,移動したい位置(Double型の数値で秒)); 指定時間(秒)の位置に移動します。リピートとかの時に使いましょう。
ov_time_total ov_time_total(TOggVorbisFile構造体,-1);
返る値がDouble型の時間。
全部の再生時間を返してくれます。
ov_open_callbacks ov_open_callbacks(ストリーム(TStream型),TOggVorbisFile構造体,nil,0,Callbacks); ファイル(ストリーム)をオープンします。Oggの情報を全部取得してくれるので楽です。
ov_clear ov_clear(TOggVorbisFile構造体); ストリームを開放しつつ、Oggを閉じます。FStream.Free;とやる必要ないので念のため。

TOggVorbisFile構造体には、ov_open_callbacksで呼び出した後、ビットレートやサンプルレート等の情報が書き込まれますんで、PCMバッファの設定に使えます。

QuadrupleD用に作りましたが、DelphiXや、他のWaveバッファをいじれるライブラリにも簡単に移植が可能なはずです。


ライセンス

OggVorbisは、BSDライセンスです。
このライセンスは、非常に緩やかで基本的に著作元を表記するだけでOKです。
表記する場所は、ソフトウェア情報や説明書等です。
まあ、こんなに素晴らしいライブラリを使わせてもらってますし、どんどん普及活動を行うためにもガンガン宣伝も兼ねて説明書に大きく書きましょう!

一応、例はこちら。


Ogg, Vorbis, Xiphophorus and their logos are trademarks (tm) of Xiphophorus.
These DLL are copyright (C) 1994-2001 Xiphophorus. All rights reserved.
OggVorbisUnit for Delphi (C) 2002 TOBY

まあ、一番簡単に書いた例です。
もっと派手に書くと、ベリーグッドです。


INDEX