ディレイラインの実装


ディレイライン

 ディレイライン (Tapped Delay-Line, タップ付き遅延線) は、 現在および過去の信号を蓄えておく記憶装置です。 FIRフィルタにおいて入力信号を蓄えておくなど、 信号処理では多用されます。 そのため、ほとんどのDSPは、 ディレイラインを効率よく実装できる仕掛けを持っています。

Tapped delay line
ディレイライン

Block diagram of an FIR filter
FIRフィルタ


コピーによる実装

 最も単純な実装方法は、 タップ数と同じサイズの配列を用意して、 次の時刻に移る際にデータをコピーするものです。 この方式では、Nタップのディレイに対して、 N回の書き込みとN-1回の読み出しが必要になります。 乗算が極端に遅いプロセッサではコピーしてもかまいませんが、 乗算を高速に実行できるプロセッサではコピーの演算量は無視できません。 多くのDSPのようにNタップの畳み込みをN+α命令で処理できるプロセッサでは、 コピーの方が演算量が多くなってしまいます。

Implementation by copying
コピーによる実装


リングバッファ (循環バッファ) による実装

 リングバッファとは、配列の始点と終点を連結してしまったものです。 端からはみ出すと、反対側の端に入ります。 これを利用すると、コピー無しでディレイラインを実装できます。 下図にその例を示します。 配列の先頭は0と書かれた要素です。 青線のところで 配列の始点と終点を連結しています。 左側が時刻nにおけるディレイラインで、 要素1のx(n)が ディレイラインの先頭になります。 ディレイラインの先頭から順にデータを読み出す時は、 ポインタを1から順に進めていき、 終端であるN-1を超えると始点の0に戻ります。 時刻n+1には、始点を0にずらして、 ここにx(n+1)を書き込みます。

Implementation by ring buffer
リングバッファによる実装

 ほとんど全てのDSPが この方式をサポートするハードウェアや命令を持っています。 初期のDSP (例えばNECのμPD77230) は、

という制限が付いているものが多かったようです。 この場合、アドレスレジスタは一本以上あればじゅうぶんで、 下位Nビット目からN+1ビット目へのキャリー/ボローを止めて アドレスレジスタの加減算を行うだけで済みます。 最近のDSP (例えばAnalog DevicesのSHARC) では、制限は大幅に緩和され、 になっています。 ただし、SHARC DSPはアドレスレジスタ3本を一組にして、 ディレイラインの先頭アドレス、サイズ、現在のポインタを保持しています。 dsPICは2本のレジスタを一組にして、 ディレイラインの先頭アドレスと最終アドレスを保持しています。 アドレス演算器も相当複雑になっています。

 汎用プロセッサでリングバッファを処理する場合は、 例えば下記のようなプログラムになります。

int delay_top;
double delay[TAPNUM];
double coef[TAPNUM];

double FIR()
{
  int i, p;
  double sum;

  if (--delay_top < 0)
    delay_top += TAPNUM;

  delay[delay_top] = input();
  sum = 0.0;
  p = delay_top;
  for (i = 0; i < TAPNUM; i++) {
    sum += coef[i] * delay[p];
    p = ++p % TAPNUM;
  }

  return sum;
}
剰余演算子%を使いたくない場合には、
    if (++p == TAPNUM) p = 0;
としても良いでしょう。


2倍サイズの配列による実装

 主な計算は積和演算 (最近はスループット1命令で実行可能) しかないようなループの中に、 剰余や条件分岐のような時間のかかる計算は入れたくない、 ということで開発された汎用プロセッサ向きの実装方法です。 配列のサイズを2倍にすると、ループ内では剰余や条件分岐が不要になります。

 この方法の原理を下図に示します。 Nタップのディレイラインに対して、サイズ2Nの配列を作ります。 後半N要素には、前半N要素と同じ値を格納します。 時刻nでは、配列の先頭から2番目がディレイラインの先頭になります。 時刻n+1では、配列の先頭がディレイラインの先頭になります。 時刻n+2では、先頭からはみ出してしまうので、 配列のN番目をディレイラインの先頭にします。

Implementation by double-sized array
2倍サイズの配列による実装


[上へ] [目次]