[1chipMSX]

波形を補間して滑らかにする

※情報の正確さは保証できません。

SCC音源は、8bit/sample で 32sample の波形を時間軸方向に整数倍することで、音程を作っています。
その整数倍拡大のときに、ニアレストネイバー法(拡大位置に出力されるはずの元波形内最近傍をそのまま出力)
で処理しているために、特に振幅変化が激しい波形で拡大歪みによって現れる高周波成分がノイズとして現れます。


fig.1 ニアレストネイバー法と補間の違い

fig.1 の右上の図が SCC の出力波形です。
fig.1 では3倍に拡大してますが、実際には分周比レジスタで指定した値になるので、数百くらいの値になります。
その数百サイクルごとに、波形は階段状に急に変化するような出力になっています。

ここを補間演算によって滑らかにして、fig.1 の右下の図のようにしてしまおうというのが、このページのテーマです。


しかし、単純に補間すればいいわけでなく、いくつかの注意点があります。

注意点1:
実際のところ、チップチューン等と言われている音源ICの性能を限界まで引き出すことに注力している人たちがいます。
このような人たちは、ニアレストネイバー法によるギザギザ波形を、意図的に利用することによって、音の厚みを作ったり
広がりを表現したりしていることがあります。
単純に補間してしまうと、そのような用途に耐えられなくなります。

注意点2:
OPLL のようにサンプリング位置を固定小数点で保持している場合は、その小数部を重みとした補間演算(たとえば線形補間)を
行うことで、簡単に補間を実現できましたが、SCC は分周比を指定するタイプで、補間用の重みを計算しようとすると、
割り算が必要になってきます。割り算回路は巨大であるため、FPGA の空き容量が少ない 1chipMSX では避けたい回路です。


注意点1に対する対策としては、波形の変化量(微分値)の大きさに応じて、補間のやりかたを変え、急激な変化では、
あえて補間せず、階段状のエッジを意図的に残すことにします。

注意点2に対する対策としては、分数表現を内部に保持して、分子の積分と、分子・分母の比較器によって整数への繰り上げ
を検知して、増分値を調整する方法(ブレゼンハムのアルゴリズム)を採用することにします。
比較器1つだけでは 45度を超える急速な変化には対応できませんが、幸いなことに注意点1への対策がそのケースを避ける役割も
担ってくれそうです。


ということで、早速その補間演算部の回路を設計してみました。

回路図

※回路図相当の VHDLソースは、に戻って最新のデザインデータをダウンロードしてください。

※回路図はあくまで設計資料です、実際の回路は最適化などの影響により、図の通りにならない場合があります。

この補完機能はデフォルトで OFF になっており、SCCカートリッジのメモリ空間に追加した新規レジスタに設定値を書き込むことで
有効にして使います。

追加レジスタは、

アドレス レジスタ名(デフォルト値) 意味
B8E0h REG_EN(00h) bit0〜4 が ch.A〜E の補間有無指定。0=補間しない, 1=補間する。
B8E1h REG_TH1(20h) 補間閾値1。波形内で連続する2値の絶対差がこの値以下の場合は線形補間する。
B8E2h REG_TH2(40h) 補間閾値2。波形内で連続する2値の絶対差が閾値1より大きくこの値以下の場合は、2値の差の1/2まで線形補間する。
B8E3h REG_TH3(80h) 補間閾値3。波形内で連続する2値の絶対差が閾値2より大きくこの値以下の場合は、2値の差の1/4まで線形補間する。
B8E4h〜B8FFh は、回路の都合上で上記4レジスタのミラーが現れているが、利用する場合は上記4アドレスにすることを
強く推奨する(B8E4h〜B8FFh は将来の予約のため、機能を変更する可能性があるため)。
レジスタ設定は、ハードウェアリセットするとデフォルト値に戻ります。

これらを制御するサンプルプログラムを書きに用意しました。

[SCCIC をダウンロード]


[▲上へ]

lastupdate 2007/05/20 t.hara