! 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