Snippets
Created by
Igor Brkic
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | import sys
import numpy as np
from scipy.io import wavfile
from scipy.signal import resample
if len(sys.argv)!=5:
print("usage: %s <in_file> <out_file> <pitch_percent> <robot>\n"%(sys.argv[0]));
sys.exit(-1)
srate, din = wavfile.read(sys.argv[1])
ws = 2048
overlap = 8
ss = ws/overlap
w = np.hanning(ws)
b = np.zeros(ws)
dout = np.zeros(din.size)
coeff=float(sys.argv[3])/100
fpb = srate/ws # frequency per bin
exp = 2*np.pi*ss/ws # expected phase
k = np.linspace(1, ws/2+1, ws/2+1) # ramp
lph = np.zeros(ws/2+1) # last phase
sum_phase = np.zeros(ws/2+1)
num_bl = int(din.size/ss)
for i in range(int((din.size-ws)/ss)):
b = (din[i*ss:i*ss+ws] / 2**16) * w
ff = np.fft.rfft(b)
ffs = ff.size
# analysis
# --------------------------------
re = np.real(ff)
im = np.imag(ff)
magn = 2.0 * np.sqrt(re**2+im**2)
phase = np.arctan2(im, re)
# compute phase diff
freq = phase - lph
lph = np.copy(phase)
# subtract expected phase diff
freq -= k*exp
# map to [-pi,pi]
while len(freq[freq<-np.pi]): freq[freq<-np.pi]+=2*np.pi
while len(freq[freq>np.pi]): freq[freq>np.pi]-=2*np.pi
# get deviation from bin
freq = overlap*freq/2.0/np.pi
# get partial's true freq
freq = k*fpb + freq*fpb
# proc
ii=0
synfr = np.copy(magn)
while ii<freq.size:
idx = ii*coeff
if idx <= freq.size:
magn[idx] = synfr[ii]*coeff * (np.random.random())
ii+=1
# add robot
if sys.argv[4][0]=='1':
freq = np.zeros(freq.size)
# synthesis
# --------------------------------
# subtract the bin mid freq
freq -= k*fpb
# get bin deviation
freq /= fpb
# account for overlape
freq = 2.0*np.pi*freq/overlap
# add the overlap phase advance
freq += k*exp
# accumulate delta phase
sum_phase += freq
ff = magn*np.cos(sum_phase) + magn*np.sin(sum_phase)*1j
b=np.fft.irfft(ff)
dout[i*ss:i*ss+ws] += b*w
wavfile.write(sys.argv[2], srate, dout)
|
Comments (0)
You can clone a snippet to your computer for local editing. Learn more.