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