- 追加された行はこのように表示されます。
- 削除された行は
このように表示されます。
! FM変調をプログラムで
http://ism1000ch.hatenablog.com/entry/2014/06/17/205452
class Vibrato(ef.Effecter):
'''
member
depth : 変調具合[frame]
freq : 変調周波数[hz]
rate : サンプリングレート[hz]
n : 現在フレーム[frame]
'''
def __init__(self,depth=2, freq=2, rate=44100):
self.depth = int(rate * depth / 1000) # input:[ms]
self.freq = freq
self.rate = rate
self.n = 0
def process(self,data):
# 時間軸をゆがめる
frames = self.calc_frames(np.arange(data.size))
# 対応するシグナルを線形補完する
data = self.calc_signal(frames,data)
return data
# 時間軸をゆがめる. N(n)の計算
# input : 時間軸[ 0, 1, 2, 3,..]
# output : 時間軸[ 0, 0.5, 2.5, 3,..]
def calc_frames(self,frames):
vfunc = np.vectorize(self.calc_frame)
return vfunc(frames)
#return frames
def calc_frame(self,n):
# n = n ~ n + 2*depth
n = n + self.depth * (1 + np.sin(self.n * (2 * np.pi * self.freq / self.rate)))
self.n += 1
return n
# N(n)を与え,線形補完してy(n)を計算
def calc_signal(self,frames,data):
# frames: N(n)のリスト
# framesのlimit番目以降に対し処理を行う
limit = self.depth * 2
calc_data = [self.calc_interp(frame,data) for frame in frames[limit:]]
calc_data = np.hstack([data[:limit],calc_data])
return np.array(calc_data)
def calc_interp(self,frame,data):
x = int(np.floor(frame))
d = np.interp(frame,[x,x+1],data[x:x+2]) #indexオーバーする可能性アリ
return d
! Tips
http://aidiary.hatenablog.com/entry/20110514/1305377659