posted by rerofumi
2007/7/20 金曜日 0:26:16
波形合成だけでCPU負荷を食いつぶしてしまうのは流石にまずいのでいくらかの高速化を考えてみる。
高速化といえばアセンブラで最適化を目指す方向で。
基本的には、発声させる波形データを加算合成するだけなのだが、加算後の値が上限を超えないように制限する必要がある。(サチュレーション)
V850 には飽和加算と飽和減算の命令があるのだけれども、(当然ながら)32bit レジスタに対して行われる。さらに、音声データは8bitで 0時 0x80、+1 0x81, -1 0x7f といったデータである(データ、出力共に)。レジスタ内では 0 時 0x00000000 で +1 は 0x00000001、-1 は 0xffffffff なわけだから、飽和加算・減算の命令を使おうとするとその前後でレジスタ拡張と値のシフトをする必要がある。これが結構手間となる。
そもそもで、CPUが32bitでデータが8bitなのだからいっぺんに4データを処理できるんじゃないの?という話がある。それができたら単純に4倍速だ。
でまあ、そういったパッキングビットに対し、論理演算を重ねて飽和加算・減算をするアルゴリズムというのはちゃんと存在している。グーグル先生に「飽和加算」と訪ねると即座に見つかる情報だ。
でまあ、そういった技をアセンブラで書いたのが以下のソース。
レジスタが多いので書きやすかったし、おかげでそれなりに早いコードになっているはず。
ld.w 0[r11], r14 -- r14 = buffer data
ld.w 0[r12], r15 -- r15 = wave data
-- add with limit
mov 0x80808080, r16 -- r16 = add mask
and r15, r16
mov r16, r17
shr 7, r17
subr r16, r17
or r17, r16
mov 0x80808080, r17
and r16, r17
subr r15, r17
and r16, r17 -- r17 = add value
mov r14, r18
and r17, r18
mov r14, r19
xor r17, r19
shr 1, r19
and 0x7f7f7f7f, r19
add r19, r18
and 0x80808080, r18
mov r18, r19
shr 7, r19
subr r18, r19
or r19, r18 -- ov mask
add r17, r14
sub r18, r14
or r18, r14
-- sub with limit
xor 0xffffffff, r16 -- r16 = sub mask
mov 0x80808080, r17
sub r15, r17
and r16, r17 -- r17 = sub value
not r14, r18
and r17, r18
not r14, r19
xor r17, r19
shr 1, r19
and 0x7f7f7f7f, r19
add r19, r18
and 0x80808080, r18
mov r18, r19
shr 7, r19
subr r18, r19
or r19, r18 -- ov mask
or r18, r17
or r18, r14
sub r17, r14
-- str
st.w r14, 0[r11]
制限としては、発声するデータのサイズが 4の倍数byteでないとならないところだけれども、そのへんはまあ運用でなんとかするというところで。
Leave a Reply