ガレスタさんのDIY日記

電子回路、Web、組み込み、自作エフェクターを語るblog

STM32F7:トレモロ(リングモジュレータ)の実装

ここ最近実装エフェクト数が増えてきたのでまとめておきます。
今回はトレモロです。
音量を周期的に揺らすエフェクトですね。


トレモロの仕組み

何かに追従して可変できる抵抗

f:id:gsmcustomeffects:20171007052538p:plain
Strymon様より引用


図に示すように周期的に音量を上下させるようにLDRなどを用いて構成します。

f:id:gsmcustomeffects:20171007053052p:plain
Codaエフェクト様より引用

このような実現方法もあります。

その他。帰還抵抗をLDRに変えたり。FETのような電圧で抵抗が変化するものを使ったりいろいろ実現方法があります。

LFO

もう一個工夫する点があります。
変調波であるLFOの作り方ですね。

これもアナログではいろいろな発振回路が用いられています。
f:id:gsmcustomeffects:20171007053757p:plain

デジタルでは?

というわけでアナログの場合

原音→可変抵抗素子で音量を上下に→出力

みたいな流れでエフェクトを実現していました。


デジタルの場合間接的な可変をするみたいな考えを捨てて脳死できます。
通常のトレモロ効果を得るならかんたんで
もらってきた原音に対してsin関数を書ければ終ります。
式で表すとこんな感じ

\displaystyle
out = input \times sin(wt)

オシロでみるとこんな感じ

演算が浮動小数点なので-1~+1の間でsin関数を用意してあげて乗算しているだけです。

これだけでは面白くないのでLFO波形を変えてみます。

二個の正弦波を足す

式で書くとこんな感じです。

\displaystyle
out = input \times (\frac{sin(wt)+sin(2wt)}{2})

処理後の波形はこんな感じです。


さらなる工夫

実際にはやってないですがアイデアとしてあげておきます。

  • ノコギリ波形
  • 三角波
  • 非周期的信号を使う

少しレベルアップすると

  • 入力をスプリットしてべつべつのフィルタを通過後別々の変調を行い加算

こういうこともできますね。

デジタルでやる利点

まずLFOの種類を増やすと回路規模が多くなります。
デジタルの場合LFOをいっぱい作れるし保存もできます。非周期的信号もメモリに持っておけば簡単に流すことができます。
こういった点で有利になりますね。

その他連続してトレモロをかけることもできますし並列にエフェクトをかけることができるのもいいですね。

C言語での実装例

ARM CortexM7で処理した時の例です。
サンプリング周波数は48kHz
作成LFO周波数 1Hz
固定少数(blackfinなど)の場合は数値の処理をきちんとしてください

#include "tremolo.h"
float tremolo_index = 0.0;
void effects_tremolo(float rx_float_buffer[],float tx_float_buffer[],ControlParamTypeDef param){
	//s = Asin(2*pi*f0*t)
	//t = n/fs
	//s = Asin(2*pi*(n/fs));
	//正規化するならAは1かな
	float	freq = 1.0;
	float	fs	 = 48000.0;
	tx_float_buffer[0] = rx_float_buffer[0] * (arm_sin_f32(2.0 * PI * freq * (tremolo_index++/fs)))
}

離散信号処理で正弦波を使うときの解説はこの方のが一番わかりやすいので読むのおすすめです。

aidiary.hatenablog.com