3

わかりました、C で karplus の強力なアルゴリズムを実装しました。これは、弦をはじいた音をシミュレートする単純なアルゴリズムです。長さ n (n = 必要なサンプリング周波数/周波数) のリング バッファーから始めて、単純な 2 点平均フィルター y[n] = (x[n] + x[n-1])/2 に渡します。それを出力してから、遅延線にフィードバックします。すすいで繰り返します。これにより、時間の経過とともにノイズが滑らかになり、自然な弦の弾き音が生まれます。

しかし、整数の遅延線の長さを使用すると、いくつかの高いピッチが同じ遅延の長さに一致する可能性があることに気付きました。また、整数遅延の長さではピッチを滑らかに変化させることはできません (ビブラートやグリッサンドなど)オールパスフィルター

http://quod.lib.umich.edu/cgi/p/pod/dod-idx?c=icmc;idno=bbp2372.1997.068
http://www.jaffe.com/Jaffe-Smith-Extensions-CMJ-1983 .pdf
http://www.music.mcgill.ca/~gary/courses/projects/618_2009/NickDonaldson/index.html

以前に補間遅延線を実装したことがありますが、波形バッファが変更されないウェーブ テーブルでのみ実装しました。さまざまな速度で遅延をステップスルーするだけです。しかし、私を混乱させているのは、KS アルゴリズムに関して言えば、論文では、ステップ スルーするレートだけでなく、遅延の長さを実際に変更することについて話しているように見えることです。ks アルゴリズムは物事を複雑にします。なぜなら、遅延線に値を常にフィードバックすることになっているからです。

では、これを実装するにはどうすればよいでしょうか。補間された値をフィードバックするのですか、それとも何ですか? 2 点平均ローパス フィルターを完全に削除する必要がありますか?

そして、オールパスフィルターはどのように機能しますか? 2 点平均フィルターをオールパス フィルターに置き換えたほうがよいのでしょうか? 線形補間法またはオールパス フィルター法を使用して、グリッサンドで離れたピッチ間を滑空するにはどうすればよいですか?

4

2 に答える 2

2

デジタル信号処理アルゴリズムは、多くの場合、正当な理由でブロック図として表されます。これは、アルゴリズムについて考える優れた方法です。それらをコーディングするときは、 の各ブロックを、入力と出力が固定された個別のユニットと考えてください。あなたの質問のいくつかは、システムのさまざまな要素を時期尚早に組み合わせようとすることから来ていると思います.

これは、Karplus Strong のブロック図です。

ウィキペディア Karplus Strong ブロック図

遅延ブロックの場合、非整数遅延ラインを実装する必要があります。これには独自のローパス フィルターが含まれますが、これは遅延線の実装方法の詳細です。Karplus Strong エフェクトには、ローパス フィルターも必要です。これらのフィルターの特性は異なります。結合しようとしないでください。ところで、選択した平均化ローパス フィルターの周波数応答は低く、「コム フィルター」効果が発生します。より洗練された FIR または IIR フィルターを設計したい場合があります。

では、これを実装するにはどうすればよいでしょうか。補間された値をフィードバックするのですか、それとも何ですか? 2 点平均ローパス フィルターを完全に削除する必要がありますか?

ブロック ダイアグラムが示すように、補間され、合計されたサンプルを遅延線に戻します。場合によっては、これによりシステムの正味のゲインが増加し始める可能性があり、それが心配な場合は、制御不能にならないように遅延の出力を「正規化」する必要がある場合があります。

あなたが言及したように、補間やオールパスフィルタリングなど、非整数遅延線を実装するための多くの有効な戦略があります。アイデアは、遅延ラインを維持readしてインデックスを作成することです。write遅延線の長さは、メモリ バッファーの全長ではなく、遅延線の全長を法とするインデックス間の差です。遅延線を必要なだけ大きくし、サイズ変更について心配する必要はありません。

読み取りと書き込みを、ラップアラウンドや期限切れのないフリーランニングカウンターとして扱うのが最も便利だと思います。

current_delay_length = (write - read) % total_delay_length
current_read_sample = delay_line[read % total_delay_length]

どこ%でモジュラスです。書き込みカウンターと読み取りカウンターは、浮動小数点値であるか固定小数点として設定されている場合、小数部の長さを含むこともあります。いずれにせよ、これにより、遅延線の長さを簡単に変更できます。最小限の遅延が適用されるようにすることが重要です (書き込み > 読み取り)。

信じられないかもしれませんが、遅延線の長さは、固定長のバッファーと同じように、通過するレートを変更することで変更できます。通常、読み取りインデックスを少し調整します。バッファー長を超えて書き込みポインターに遅れたり、進んだりしてはいけません。そうしないと、グリッチが発生します。ただし、書き込みポインターの後に読み取りポインターを自由に移動できます。変調を変更すると、さまざまな効果が得られます。

グリッサンドなどの効果は、遅延ラインの読み取りおよび書き込みインデックスがどのように実装されているかではなく、どのように操作されているかに起因することを強調します。オールパス フィルターまたは線形補間されたディレイ ラインから同様のサウンドが得られます。より優れた部分遅延線は、エイリアシング ノイズを低減し、たとえば、読み取りポインターのより迅速な変化をサポートします。

于 2011-07-27T19:44:51.867 に答える
1

私は 3 つのバリエーションを実装しました。すべてに長所と短所がありますが、私が望むほど完璧なものはありません。多分誰かがより良いアルゴリズムを持っていて、それをここで共有したいですか?

一般的に、私は jbarlow が説明するようにそれを行います。私は 2^x のリング バッファ長を使用します。ここで、x は「十分に大きい」、たとえば 12 です。これは、最大遅延長が 2^12=4096 サンプルであることを意味します。@ 48kHz でレンダリングする場合、これは最低基本周波数として ~12Hz です。 . 2 の累乗の理由は、モジュロがビットごとの AND で実行できるためです。これは、実際のモジュロよりもはるかに安価です。

// init
int writepointer = 0;

// loop:
writepointer = (writepointer+1) & 0xFFF;

書き込みポインタはシンプルに保たれ、たとえば 0 から始まり、出力サンプルごとに常に 1 ずつ増加します。

読み取りポインターは、周波数が変更されるたびに新たに計算された、書き込みポインターに対するデルタで始まります。

// init
float delta = samplingrate/frequency;
int readpointer = (writepointer-(int)delta)-1) & 0xFFF;
float frac = delta-(int)delta;
weight_a = frac;
weight_b = (1.0-frac);

// loop:
readpointer = (readpointer + 1) & 0xFFF;

これも 1 ずつ増加しますが、通常は 2 つの整数位置の間に多かれ少なかれあります。切り捨てられた位置を使用して、整数の readpointer に格納します。このサンプルと次のサンプルの間の重みは、weight_a と _b です。

バリエーション #1 : 小数部分を無視し、(整数) 読み取りポインターをそのまま処理します。

長所: 副作用のない完全な遅延 (遅延による暗黙のローパスがないため、周波数応答を完全に制御でき、アーティファクトがないことを意味します)

短所:基本周波数はほとんどがわずかにずれており、整数位置に量子化されています。これは、高いピッチのノートに対して非常にデチューンされたように聞こえ、微妙なピッチの変更を行うことができません。

バリエーション #2 : readpointer サンプルと次のサンプルの間の線形補間。つまり、リング バッファーから実際に 2 つの連続したサンプルを読み取り、それらを合計して、それぞれ weight_a と weight_b で重み付けします。

長所: 完璧な基本周波数、アーティファクトなし

短所: 線形補間により、望ましくないローパス フィルターが導入されます。さらに悪いことに、低域はピッチによって異なります。小数部分が 0 または 1 に近いことが判明した場合、ローパス フィルタリングはほとんど行われませんが、小数部分が 0.5 付近の場合は、ローパス フィルタリングが頻繁に行われます。これにより、楽器の一部の音が他の音よりも明るくなり、このローパスが許容するよりも明るくなることはありません. (スチールギターやハープシコードには不向き)

バリエーション #3 : ジッタリングのようなもの。私は常に整数位置から遅延を読み取りますが、私が行うエラーを追跡します。これは、小数部分を合計する変数があることを意味します。1 を超えたら、エラーから 1.0 を引き、2 番目の位置から遅延を読み取ります。

長所: 完璧な基本周波数、暗黙のローパスなし

短所:ローファイに聞こえる可聴アーチファクトが導入されます。(最近傍とのダウンサンプリングのような)。

結論: どのバリエーションも満足できるものではありません。正しいピッチ、ニュートラルな周波数応答が得られないか、アーティファクトが発生します。

オールパス フィルターの方が優れていると文献で読みましたが、遅延線は既にオールパスではありませんか? 実装の違いは何ですか?

于 2012-10-21T19:18:24.003 に答える