English
SOUND ManualSCSP/DSPアセンブラユーザーズマニュアル
戻る進む
SCSP/DSPアセンブラユーザーズマニュアル

6.dAsmsプログラミングガイド


■プログラミング概要

dAsmsのソースコードのコーディングにおいては、パイプライン処理を意識する必要がなく、すべてのコマンドを逐次処理的な考え方で記述することができます。具体的には、

  1. 演算に必要なデータの準備(LDI/LDY/LDA
  2. 乗加算式の記述(@...
  3. ストア先の指定(>

の手順を1つの単位処理と考え、シグナルフロー図から適当な部分機能を抽出してこの単位処理にあてはめて部分ソースコードを記述します。これを処理順に繰り返すことによってソースコードを記述していきます。

以下に、dAsmsにおけるDSPプログラムのコーディング方法を、比較的簡単な具体例に沿って解説します。

以下のプログラム例は、CD Audio等が入力可能な外部拡張入力 EXTS00、EXTS01をそれぞれLch、Rchの入力とし、Lch、Rch独立にディレイ(エコー)処理を行った結果をそれぞれ EFREG00、EFREG01 に出力しようとするものです。

■シグナルフロー図

■コーディング手順

1.係数シンボルの定義(#COEF)

 1-1 レベルアッテネーション関係の係数の定義

レベルアッテネーション関係の係数として、

ディレイへのセンドレベル     :EffSendLevelL/R
ダイレクト信号のレベル      :DrctLevelL/R
ディレイからのリターンレベル   :EffRtnLevelL/R
ディレイ信号のフィードバックレベル:FbL/R

を定義します。レベルアッテネーションには、1%刻み程度のレベル分解能で良いと仮定して、パーセント表記での定義を行います。定義書式については、「■係数/アドレスシンボルの定義」を参照してください。dAsmsソースコード上の定義記述は以下のようになります。初期値は一例です。

-----------------------------------------------------
     EffSendLevelL=%100
     EffSendLevelR=%100
     DrctLevelL=%50
     DrctLevelR=%50
     EffRtnLevelL=%75
     EffRtnLevelR=%75
     FbL=%50
     FbR=%50
-----------------------------------------------------

 1-2 フィードバック用フィルター関係の係数の定義

シグナルフロー図中に見られる、ディレイ信号のフィードバック経路となる1次IIRフィルタの係数として、

     C0L/R
     C1L/R
     C2L/R

を定義します。フィルター係数は1に正規化された値で与えられていると仮定して、小数表記での定義を行います。適当なカットオフ周波数を考えると、dAsmsソースコード上の定義記述は以下のようになります。

     C0L=0.40893
     C0R=0.40893
     C1L=0.40893
     C1R=0.40893
     C2L=0.18164
     C2R=0.18164

2.アドレス定数シンボルの定義(#ADRS)

 2-1 ディレイ用リングバッファへの書き込みおよび読み出しアドレスの定義
シグナルフロー図中、Lch / Rchそれぞれの部分のほぼ中央にある長方形はディレイを表しています。ディレイはリングバッファによって作られ、ディレイ時間は書き込みアドレスと読み出しアドレスとの差に比例します。1アドレスは1サンプルのディレイ(遅延)に相当します。アドレス定数として、

     waL/R
     raL/R

を定義します。これらのアドレス定数シンボルに対し、初期値として16進または10進整数でリングバッファ上のアドレスを与えることもできますが、dAsmsでは、アドレスを時間(ミリ秒)に変換した表記が使用できますので、適当なディレイタイムを考えると、dAsmsソースコード上の定義記述は以下のようになります。

----------------------------------------------------------------
     waL=ms0.0
     raL=ms149.9
     waR=ms150.0
     raR=ms249.9
----------------------------------------------------------------

3.プログラム部分の記述(#PROG)

 3-1 Lch側のデータの準備
シグナルフロー図を見ると、演算に必要なデータを得るためには、メモリアクセス(リングバッファからの読み込み)が必要であることが分かります。読み出すべきリングバッファ上のアドレスは、

     raL
     raL+1

です。但し、これらのアドレスはリングバッファ上における相対位置でしかないため、外部メモリ読み出し用パラメータ「MR[...]」の「...」部分には、アドレス記述要素「DEC」を加えます。「DEC」は1サンプル毎に1減算されるカウンタを表し、これをアドレス記述要素に加えることによって初めてリングバッファ動作が実現されます。リングバッファ上のraL、raL+1の位置から読み出したデータをそれぞれ

     MEMS00
     MEMS01

にロードするとして、以上のことをdAsmsソースコード上に表現すると以下のようになります。

     LDI MEMS00,MR[raL+DEC]
     LDI MEMS01,MR[raL+DEC+1]

参考までに、上記の2つの「MR[...]」によってアクセスされるリングバッファ上のアドレスは、互いに1アドレスの間隔を保ったまま、「DEC」の作用によって1サンプル毎に1アドレスずつ低位方向にずれて行きます。

 3-2 Lch側フィードバック用フィルタ部分の演算
必要なデータの準備ができたら、次にそれらのデータを使用して演算をするための記述を行います。ディレイ信号のフィードバック経路となる1次IIRフィルタの演算は、次のような手順となります。

  1. MEMS00にロードされている値に係数C0Lを乗算する。

  2. MEMS01にロードされている値に係数C1Lを乗算し、(1)の結果と加え合わせる。

  3. TEMP01の値に係数C2Lを乗算し、(2)の結果と加え合わせる。

  4. (3)の結果をTEMP00にストアする。

ここで重要なのは、TEMPがリングバッファであることです。TEMPxxは、その添字xxがリングバッファとしての相対アドレスを表しており、TEMP00にストアしたデータは、次のサンプルにおいてはTEMP01に現れます。上記(3)と(4)では、これを利用して、1サンプル分のディレイを実現しています。

dAsmsにおいては、それがターゲットとしているSCSP/DSPハードウエアの特性上、計算式の記述方法はやや特殊な形となります。上記(1)〜(4)の内容をdAsmsソースコード上に表現すると以下のようになります。

--------------------------------------------------------------------------
     @ TEMP01 * C2L + ( MEMS01 * C1L + ( MEMS00 * C0L + ) ) > TEMP00
--------------------------------------------------------------------------

このように、上記(1)〜(3)のような連続乗加算を記述するには、各乗算の実際の順序と、記述上の順序を逆にしなければならないことに注意してください。

 3-3 Lch側リングバッファへの書込み
シグナルフロー図から、

  1. 入力であるEXTS00の値に係数EffSendLevelLを乗算したもの

  2. 3-2の(4)でTEMP00にストアした値に係数FbLを乗算したもの

の2つを加算したものをリングバッファに書き込めばよいことが分かります。リングバッファ上の書き込みアドレスはwaLであり、3-1のMR[...]と同様にアドレス記述要素「DEC」を使用します。以上の内容をdAsmsソースコード上に表現すると以下のようになります。

--------------------------------------------------------------------------
     @ TEMP00 * FbL + ( EXTS00 * EffSendLevelL + ) > MW[waL+DEC]
--------------------------------------------------------------------------

 3-4 Lch出力データの生成およびEFREGへの書込み
シグナルフロー図から、

  1. リングバッファ上のアドレスraLから読み出したデータに係数EffRtnLevelLを乗算したもの

  2. 入力であるEXTS00の値に係数DrctLevelLを乗算したもの

の2つを加算したものをEFREG00にストアすればよいことが分かります。ここで、(a)での乗算に必要な(リングバッファから読み出した)データについては3-1においてMEMS00にロードしてあるのでこれを使います。以上の内容をdAsmsソースコード上に表現すると以下のようになります。

--------------------------------------------------------------------------
     @ EXTS00 * DrctLevelL + ( MEMS00 * EffRtnLevelL + ) > EFREG00
--------------------------------------------------------------------------

以上でLch側のソースコードの記述は終了です。

 3-5 Rch側のソースコードの記述
本プログラム例の機能はステレオ(L/R独立)ディレイですが、シグナルフロー図から分かるように、Rch側の処理内容はLch側のそれと同じです。ただし、使用する係数/アドレス定数シンボル名、レジスタ名等が異なっています。したがって、前項までに記述したLch側のソースコードをCopy&Pasteして、変更部分のみを書き換えれば、それがRch側のソースコードとなります。

 3-6 コーディング終了
以上で本プログラム例のソースコードの記述は全て終了です。「3.ソースコードの構成」に従ったソースコードの全体像は次のようになります。

--------------------------------------------------------------------------
     'dAsms sample program.
     'Function:L/R independent delay
     'CD Lch Direct + Delayed -> EFREG00
     'CD Rch Direct + Delayed -> EFREG01
     #COEF

     'Levels
     EffSendLevelL=%100
     EffSendLevelR=%100
     DrctLevelL=%50
     DrctLevelR=%50
     EffRtnLevelL=%75
     EffRtnLevelR=%75
     FbL=%50
     FbR=%50

     'FilterCoefs
     C0L=0.40893
     C0R=0.40893
     C1L=0.40893
     C1R=0.40893
     C2L=0.18164
     C2R=0.18164

     #ADRS
     waL=ms0.0
     raL=ms149.9
     waR=ms150.0
     raR=ms249.9

     #PROG

     'Lch
     LDI MEMS00,MR[raL+DEC]
     LDI MEMS01,MR[raL+DEC+1]
     @ TEMP01 * C2L + ( MEMS01 * C1L + ( MEMS00 * C0L + ) ) > TEMP00
     @ TEMP00 * FbL + ( EXTS00 * EffSendLevelL + ) > MW[waL+DEC]
     @ EXTS00 * DrctLevelL + ( MEMS00 * EffRtnLevelL + ) > EFREG00

'Rch LDI MEMS02,MR[raR+DEC] LDI MEMS03,MR[raR+DEC+1] @ TEMP03 * C2R + ( MEMS03 * C1R + ( MEMS02 * C0R + ) ) > TEMP02 @ TEMP02 * FbR + ( EXTS01 * EffSendLevelR + ) > MW[waR+DEC] @ EXTS01 * DrctLevelR + ( MEMS02 * EffRtnLevelR + ) > EFREG01 #END --------------------------------------------------------------------------


戻る進む
SOUND ManualSCSP/DSPアセンブラユーザーズマニュアル
Copyright SEGA ENTERPRISES, LTD., 1997