がれすたさんのDIY日記

電子回路、Python、組み込みシステム開発、自作エフェクターを語るblog

Python:ビブラートとコーラス:2

前回の記事ではPythonでビブラートエフェクトとコーラスエフェクトを実装した。
今回はFM変調とBessel関数に関して面白い記述*1があったのでほとんどパクりだけど(情報は多いほうがいいに決まってるw)それについてみていく

FM変調

FM変調は以下の式で示されるのだった。

  • y(n) = Asin(2 \pi f_{c} \frac{n}{f_{s}} + Isin(2\pi f_{m}\frac{n}{f_{s}}))
  • A:原音信号振幅
  • fc:原音信号周波数
  • fs:サンプリング
  • fm:変調周波数
  • I:変調深度(エフェクターによくあるdepthつまみ)

このままでもいいのだが書くのがめんどいので2 \pi fの部分を\omegaに置き換えさせてもらう
置き換えるとこうなると思う。

\begin{align*}
y(t) = a_c \sin(\omega_c t + a_m \sin(\omega_m t))
\end{align*}

ここで
\begin{align*}
t &= n / fs\\
\omega_c&= carrier freq\\
\omega_m&=modulation freq
\end{align*}

キャリアは原音信号のこと

この式を加法定理を使って展開しておく。

\begin{align*}
\sin (\alpha+\beta)=\sin\alpha\cos\beta+\cos\alpha\sin\beta
\end{align*}


\begin{align*}
y(t) = a_c (\sin(\omega_c t)\cos(a_m \sin(\omega_m t)) + \cos(\omega_c t)\sin(a_m \sin(\omega_m t)) )
\end{align*}

第一種ベッセル関数

第一種ベッセル関数はベッセル微分方程式の解のひとつである。
第二種とか、特殊とかあるので詳しくは参考文献を見てくれたほうがいいと思う。
形としてはこんなグラフです。

f:id:gsmcustomeffects:20180819070610p:plain

ベッセル関数とFM基本式

参考文献よりベッセル関数から以下の関係式が得られます。

\begin{align*}
\cos(x \sin(y)) &= \sum_{n=-\infty}^{n=\infty} J_n (x) \cos (ny) \\
\sin(x \sin(y)) &= \sum_{n=-\infty}^{n=\infty} J_n (x) \sin (ny)
\end{align*}


それを用いて上の加法定理の式をそれで置き換えると
\begin{align*}
y(t)=&
a_c
\sum_{n=-\infty}^{n=\infty} J_n (a_m) (\sin(\omega_c t)\cos(n \omega_m t) + \cos(\omega_c t)\sin(n \omega_m t)) \\
=&
a_c
\sum_{n=-\infty}^{n=\infty} J_n (a_m) \sin ( (\omega_c + n \omega_m)t )
\end{align*}

となる。

もう一度まとめてみると

\begin{align*}
a_c \sin(\omega_c t + a_m \sin(\omega_m t)) = a_c
\sum_{n=-\infty}^{n=\infty} J_n (a_m) \sin ( (\omega_c + n \omega_m)t )
\end{align*}

ここからFM変調はベッセル関数と基音+倍音の積で表すことが可能だとわかる。

変調指数の大きさと倍音の関係

次に変調指数についてみていく


第一種ベッセル関数の\(J_{n}(\alpha)\)は一般的に変調指数と呼ばれる。
上で導いたようにFMの変調深度もそれにあたる。

というわけでこいつを大きくしていけばエフェクトとしては深くかかっていく理論。
その時ベッセル関数での挙動はどうなっているのか出してみた。
x軸を第一ベッセル関数の次数にしてy軸をJn(固定)にして表示すればよい

Jn(0.5)の場合

f:id:gsmcustomeffects:20180819071931p:plain

Jn(5)

f:id:gsmcustomeffects:20180819072006p:plain

Jn(10)

f:id:gsmcustomeffects:20180819072016p:plain

変調指数が低いと原音がきちんと聞こえるエフェクトとなるがJn(0.5)の時を見ると元スペクトルが大きく、側波帯が低くなっています。
第一種ベッセル関数は徐々に振幅が下がっていく特性を持つので側波帯のスペクトルは速やかに減衰する。すなわちエフェクトの効果通り原音の色が強い音色となる。


この記事で使ったPythonコード

scipy.specialモジュールを使います

from scipy.special import jv, yv
import numpy as np
import matplotlib.pyplot as plt

z = np.arange(-20,20,0.01)#x軸の範囲

for i in  range(0,5):#次数の決定(別に何個でもいい)
    bessel = (jv(i,z))
    plt.plot(z,bessel,label="J"+str(i))

plt.legend()
plt.show()

nを横軸にしたグラフのコード

from scipy.special import jv, yv
import numpy as np
import matplotlib.pyplot as plt
z = np.arange(0,50,0.01)
x = []
bessel = []
jn = 0.5
jn_index = int(jn*100)
for i in  range(0,30):
    bessel.append(jv(i,z[jn_index]))
    x.append(i)

plt.xlabel("bessel order")
plt.ylabel("Jn(" +str(jn) + ")")
plt.scatter(x, bessel)
plt.show()

参考文献

*1:Analyzing an FM signal [John d .cook氏]