2010年4月12日月曜日

PSPの解析:sceAudiocodec系列関数群編

sceAudiocodec系列の関数の振る舞いを詳しく解析してみようと思います。



sceAudiocodec系列の関数はPSPのサブCPUを使って各種マルチメディアのデコードをする為の関数群であり、DXP内部でも使われています。
DXPのオーディオ関連の挙動が怪しいので、一度ちゃんと調べてみようという運びになりました。

必要なモジュールのロード


これらの関数は呼び出される前に必要なモジュールがロードされていないと実行できません。そこで、以下の関数を呼びます呼び出しには。psputility.hのインクルードが必要です。
sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC);
こうすることでだいたいコーデックが読み込まれるようです。
(注:ユーザーモード、FW2.00以降である必要があります)

デコーダーのリソース確保


目的に応じて必要なメモリ量を見積もり、サブCPU側の専用メモリを確保し、デコーダーを初期化します。

この段階では以下の関数を使います。pspaudiocodec.hのインクルードが必要です。

sceAudiocodecCheckNeedMem
sceAudiocodecGetEDRAM
sceAudiocodecInit

上から順番にメモリ量算出、メモリ確保、初期化を行う関数だと思われます。(名前からして)
引数は共通していて、第一引数がデコーダーの管理データへのポインタ、第二引数がデコードするデータの種類です。
管理データは色々なサイトを見たところ、65個の32bit整数値のようです。
データの種類はPSP_CODEC_で始まる定数を使います。

これらの関数を使うと管理データがどうなるか、ダンプしていきます。
といっても、全てを書くのは無駄以外の何者でも無いので、呼び出した時に変化した部分だけにします。
管理データを32bit整数値の配列としてとらえ、変化した部分を(オフセット:データ)というように表記します。
なお、オフセットは10進数、データは16進数で書いてます。

sceAudiocodecCheckNeedMem関数の呼び出し後

(00:0x05100601)
(02:0x00000000)
(04:0x00003b68) ←データ形式によって異なるようです。

sceAudiocodecGetEDRAM関数の呼出し後

(03:0x0018f7c0)←呼び出す毎に変動するので、おそらくEDRAM上のオフセットか何かだと思います。
(26:0x0018f790)←オフセット03の値より少し小さいです。
sceAudiocodecInit関数の呼出し後

(11:0x0000ac44)←AT3のみ
(12:0x00000000)←AT3のみ
(14:0x0000270f)←MP3のみ。0x270fってゲームの改造やったことある人には馴染み深いと思います。10進数にすると9999ですね。

デコードの処理


デコードする際、管理データの一部にデコードに必要な情報を突っ込みます。
(06:デコード前の圧縮されたデータのバッファへのアドレス)
(07:圧縮されたデータのバッファのバイト長)←MP3は指定なしでもデコード可能です。他の形式は試していません。
(08:デコード後のPCMデータのバッファへのアドレス)
(09:デコード後のPCMデータのバッファのバイト長)
(10:07に同じ)
そうしたら、sceAudiocodecDecode関数を呼びます。引数は他のsceAudiocodec系関数と同じです。

なお、渡すデータの長さにはルールがあるようです。
MP3の場合は1152サンプルの倍数分のデータを渡す必要があります。

sceAudiocodecDecodeを呼び出す時、最初の数回だけデコードに失敗することがあります。(おそらくリピート再生時のブツブツ音はこれが原因)
その時のリターンコードは0x807f00fdです。PSPSDKのエラーコード一覧(pspkerror.hあたりに列挙されてるもの)には同じコードが見当たりません。

そんなこんなで頑張ったけど、結局あんまり成果は無かったorz

とりあえず使ったソースコードをあとでうpしようと思います。

うpしました

1 件のコメント:

  1. 0×807f00fd は PSPエラーコード一覧にもないぞっ

    http://pspbannoukaizou.blog50.fc2.com/blog-entry-157.html

    返信削除