-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathsprModel.py
More file actions
98 lines (91 loc) · 5.95 KB
/
Copy pathsprModel.py
File metadata and controls
98 lines (91 loc) · 5.95 KB
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
# functions that implement analysis and synthesis of sounds using the Sinusoidal plus Residual Model
# (for example usage check the examples models_interface)
import numpy as np
from scipy.signal import blackmanharris, triang
from scipy.fftpack import fft, ifft
import math
import dftModel as DFT
import sineModel as SM
import utilFunctions as UF
def sprModelAnal(x, fs, w, N, H, t, minSineDur, maxnSines, freqDevOffset, freqDevSlope):
"""
Analysis of a sound using the sinusoidal plus residual model
x: input sound, fs: sampling rate, w: analysis window; N: FFT size, t: threshold in negative dB,
minSineDur: minimum duration of sinusoidal tracks
maxnSines: maximum number of parallel sinusoids
freqDevOffset: frequency deviation allowed in the sinusoids from frame to frame at frequency 0
freqDevSlope: slope of the frequency deviation, higher frequencies have bigger deviation
returns hfreq, hmag, hphase: harmonic frequencies, magnitude and phases; xr: residual signal
"""
# perform sinusoidal analysis
tfreq, tmag, tphase = SM.sineModelAnal(x, fs, w, N, H, t, maxnSines, minSineDur, freqDevOffset, freqDevSlope)
Ns = 512
xr = UF.sineSubtraction(x, Ns, H, tfreq, tmag, tphase, fs) # subtract sinusoids from original sound
return tfreq, tmag, tphase, xr
def sprModelSynth(tfreq, tmag, tphase, xr, N, H, fs):
"""
Synthesis of a sound using the sinusoidal plus residual model
tfreq, tmag, tphase: sinusoidal frequencies, amplitudes and phases; stocEnv: stochastic envelope
N: synthesis FFT size; H: hop size, fs: sampling rate
returns y: output sound, y: sinusoidal component
"""
ys = SM.sineModelSynth(tfreq, tmag, tphase, N, H, fs) # synthesize sinusoids
y = ys[:min(ys.size, xr.size)]+xr[:min(ys.size, xr.size)] # sum sinusoids and residual components
return y, ys
def sprModel(x, fs, w, N, t):
"""
Analysis/synthesis of a sound using the sinusoidal plus residual model, one frame at a time
x: input sound, fs: sampling rate, w: analysis window,
N: FFT size (minimum 512), t: threshold in negative dB,
returns y: output sound, ys: sinusoidal component, xr: residual component
"""
hN = N//2 # size of positive spectrum
hM1 = int(math.floor((w.size+1)/2)) # half analysis window size by rounding
hM2 = int(math.floor(w.size/2)) # half analysis window size by floor
Ns = 512 # FFT size for synthesis (even)
H = Ns//4 # Hop size used for analysis and synthesis
hNs = Ns//2
pin = max(hNs, hM1) # initialize sound pointer in middle of analysis window
pend = x.size - max(hNs, hM1) # last sample to start a frame
fftbuffer = np.zeros(N) # initialize buffer for FFT
ysw = np.zeros(Ns) # initialize output sound frame
xrw = np.zeros(Ns) # initialize output sound frame
ys = np.zeros(x.size) # initialize output array
xr = np.zeros(x.size) # initialize output array
w = w / sum(w) # normalize analysis window
sw = np.zeros(Ns)
ow = triang(2*H) # overlapping window
sw[hNs-H:hNs+H] = ow
bh = blackmanharris(Ns) # synthesis window
bh = bh / sum(bh) # normalize synthesis window
wr = bh # window for residual
sw[hNs-H:hNs+H] = sw[hNs-H:hNs+H] / bh[hNs-H:hNs+H]
while pin<pend:
#-----analysis-----
x1 = x[pin-hM1:pin+hM2] # select frame
mX, pX = DFT.dftAnal(x1, w, N) # compute dft
ploc = UF.peakDetection(mX, t) # find peaks
iploc, ipmag, ipphase = UF.peakInterp(mX, pX, ploc) # refine peak values iploc, ipmag, ipphase = UF.peakInterp(mX, pX, ploc) # refine peak values
ipfreq = fs*iploc/float(N) # convert peak locations to Hertz
ri = pin-hNs-1 # input sound pointer for residual analysis
xw2 = x[ri:ri+Ns]*wr # window the input sound
fftbuffer = np.zeros(Ns) # reset buffer
fftbuffer[:hNs] = xw2[hNs:] # zero-phase window in fftbuffer
fftbuffer[hNs:] = xw2[:hNs]
X2 = fft(fftbuffer) # compute FFT for residual analysis
#-----synthesis-----
Ys = UF.genSpecSines(ipfreq, ipmag, ipphase, Ns, fs) # generate spec of sinusoidal component
Xr = X2-Ys; # get the residual complex spectrum
fftbuffer = np.zeros(Ns)
fftbuffer = np.real(ifft(Ys)) # inverse FFT of sinusoidal spectrum
ysw[:hNs-1] = fftbuffer[hNs+1:] # undo zero-phase window
ysw[hNs-1:] = fftbuffer[:hNs+1]
fftbuffer = np.zeros(Ns)
fftbuffer = np.real(ifft(Xr)) # inverse FFT of residual spectrum
xrw[:hNs-1] = fftbuffer[hNs+1:] # undo zero-phase window
xrw[hNs-1:] = fftbuffer[:hNs+1]
ys[ri:ri+Ns] += sw*ysw # overlap-add for sines
xr[ri:ri+Ns] += sw*xrw # overlap-add for residual
pin += H # advance sound pointer
y = ys+xr # sum of sinusoidal and residual components
return y, ys, xr