トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

PRG-FmModulation

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