トップ 一覧 検索 ヘルプ 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