なんでも作っちゃう、かも。

Arduino/Make/フィジカルコンピューティング/電子工作あたりで活動しています。スタバの空きカップを使ったスタバカップアンプなど製作。最近はもっぱらArduinoと3Dプリンタの自作に興味があります。

V850付録基板でOgg Vorbisプレイヤー(11)

Posted by arms22 on 2007年07月01日 0  0

Tremorを最適化して22KHz-16bit-monoデータを再生させることができた。22KHz-16bit-stereoはまだデコードが追いつかない。
今回行った最適化はov_read8関数の作成と幾つかの処理をインラインアセンブラにした。
ov_read8関数はov_readの改造版で符号なし8bitデータを返す関数だ。バッファに値をコピーする前に符号あり16bitデータを8bitデータに変換してコピーする。バッファ容量の節約と処理時間の節約に繋がる。
インラインアセンブラはasm_arm.hを参考にMULT32/MULT31_SHIFT15/CLIP_TO_15/CLIP_TO_8の4つの関数をインラインアセンブラ化した。※CLIP_TO_15関数はov_read8関数では使用していない。変わりにCLIP_TO_8関数を使用している。CLIP_TO_8関数はCLIP_TO_15関数に加算とシフトを追加した関数。
今回のインラインアセンブラで書いてて一番面白かったのはCLIP_TO_15関数だ。
CLIP_TO_15関数は入力値を符号あり16bitの最大値、最小値に飽和処理してくれる。C言語で書くと次のようになる。

if(x>32767)x=32767;
if(x<-32768)x=-32768;
return(x);
Tremorはもう少し賢くて次のようなコードで書いている。
int ret=x;
ret-= ((x<=32767)-1)&(x-32767);
ret-= ((x>=-32768)-1)&(x+32768);
return(ret);
しかし上の二つのコードはV850でコンパイルするとどちらも条件分岐を含んだコードを生成する。 V850の飽和加算、飽和減算を使えば上記のコードは条件分岐なしで書く事ができる。
int tmp;
asm volatile("mov	0x7fff8000, %1?n?t"
                   "satadd	%1, %0?n?t"
                    "sub	%1, %0?n?t"
                    "satsub	%1, %0?n?t"
                    "add	%1, %0?n?t"
                    : "+r"(x), "=r"(tmp)
                    :
                    : "cc");
return x;
satadd/satsub命令は飽和処理付きの加算/減算命令で、演算結果が正の最大値0x7fffffffを越えたときは0x7fffffffを、負の最大値0x80000000を越えたときは0x80000000をレジスタに格納する。
正側の飽和処理はsatadd命令で入力値xと0x7fff8000を加算し、その結果から0x7fff8000を引く。するとxが0x7fffを超えていた時は0x7fff、xが0x7fff以下ならxがそのまま返る。
負側の飽和処理は正側の逆で、satsub命令で入力値xから0x7fff8000を減算し、その結果に0x7fff8000を足す。するとxが0x8000を超えていた場合は0x8000、xが0x8000以下ならxがそのまま返る。

今回の成果物OggVorbisPlayerのソースコード
http://xfind.hp.infoseek.co.jp/electric/oggplayer/OggVorbisPlayer_7_1.zip

Ads by Google

Leave a reply






管理者にだけ表示を許可する

該当の記事は見つかりませんでした。