def sineSubtraction(x, N, H, sfreq, smag, sphase, fs): """ Subtract sinusoids from a sound x: input sound, N: fft-size, H: hop-size sfreq, smag, sphase: sinusoidal frequencies, magnitudes and phases returns xr: residual sound """ hN = N/2 # half of fft size x = np.append(np.zeros(hN),x) # add zeros at beginning to center first window at sample 0 x = np.append(x,np.zeros(hN)) # add zeros at the end to analyze last sample bh = blackmanharris(N) # blackman harris window w = bh/ sum(bh) # normalize window sw = np.zeros(N) # initialize synthesis window sw[hN-H:hN+H] = triang(2*H) / w[hN-H:hN+H] # synthesis window L = sfreq.shape[0] # number of frames, this works if no sines xr = np.zeros(x.size) # initialize output array pin = 0 for l in range(L): xw = x[pin:pin+N]*w # window the input sound X = fft(fftshift(xw)) # compute FFT Yh = UF_C.genSpecSines(N*sfreq[l,:]/fs, smag[l,:], sphase[l,:], N) # generate spec sines Xr = X-Yh # subtract sines from original spectrum xrw = np.real(fftshift(ifft(Xr))) # inverse FFT xr[pin:pin+N] += xrw*sw # overlap-add pin += H # advance sound pointer xr = np.delete(xr, range(hN)) # delete half of first window which was added in stftAnal xr = np.delete(xr, range(xr.size-hN, xr.size)) # delete half of last window which was added in stftAnal return xr
def stochasticResidualAnal(x, N, H, sfreq, smag, sphase, fs, stocf): """ Subtract sinusoids from a sound and approximate the residual with an envelope x: input sound, N: fft size, H: hop-size sfreq, smag, sphase: sinusoidal frequencies, magnitudes and phases fs: sampling rate; stocf: stochastic factor, used in the approximation returns stocEnv: stochastic approximation of residual """ hN = N // 2 # half of fft size x = np.append( np.zeros(hN), x) # add zeros at beginning to center first window at sample 0 x = np.append(x, np.zeros(hN)) # add zeros at the end to analyze last sample bh = blackmanharris(N) # synthesis window w = bh / sum(bh) # normalize synthesis window L = sfreq.shape[0] # number of frames, this works if no sines pin = 0 for l in range(L): xw = x[pin:pin + N] * w # window the input sound X = fft(fftshift(xw)) # compute FFT Yh = UF_C.genSpecSines(N * sfreq[l, :] / fs, smag[l, :], sphase[l, :], N) # generate spec sines Xr = X - Yh # subtract sines from original spectrum mXr = 20 * np.log10(abs(Xr[:hN])) # magnitude spectrum of residual mXrenv = resample(np.maximum(-200, mXr), mXr.size * stocf) # decimate the mag spectrum if l == 0: # if first frame stocEnv = np.array([mXrenv]) else: # rest of frames stocEnv = np.vstack((stocEnv, np.array([mXrenv]))) pin += H # advance sound pointer return stocEnv
def stochasticResidualAnal(x, N, H, sfreq, smag, sphase, fs, stocf): """ Subtract sinusoids from a sound and approximate the residual with an envelope x: input sound, N: fft size, H: hop-size sfreq, smag, sphase: sinusoidal frequencies, magnitudes and phases fs: sampling rate; stocf: stochastic factor, used in the approximation returns stocEnv: stochastic approximation of residual """ hN = N/2 # half of fft size x = np.append(np.zeros(hN),x) # add zeros at beginning to center first window at sample 0 x = np.append(x,np.zeros(hN)) # add zeros at the end to analyze last sample bh = blackmanharris(N) # synthesis window w = bh/ sum(bh) # normalize synthesis window L = sfreq.shape[0] # number of frames, this works if no sines pin = 0 for l in range(L): xw = x[pin:pin+N] * w # window the input sound X = fft(fftshift(xw)) # compute FFT Yh = UF_C.genSpecSines(N*sfreq[l,:]/fs, smag[l,:], sphase[l,:], N) # generate spec sines Xr = X-Yh # subtract sines from original spectrum mXr = 20*np.log10(abs(Xr[:hN])) # magnitude spectrum of residual mXrenv = resample(np.maximum(-200, mXr), mXr.size*stocf) # decimate the mag spectrum if l == 0: # if first frame stocEnv = np.array([mXrenv]) else: # rest of frames stocEnv = np.vstack((stocEnv, np.array([mXrenv]))) pin += H # advance sound pointer return stocEnv
def stochasticResidual(x, N, H, sfreq, smag, sphase, fs, stocf): # subtract sinusoids from a sound # x: input sound, N: fft-size, H: hop-size # sfreq, smag, sphase: sinusoidal frequencies, magnitudes and phases # returns mYst: stochastic approximation of residual hN = N/2 x = np.append(np.zeros(hN),x) # add zeros at beginning to center first window at sample 0 x = np.append(x,np.zeros(hN)) # add zeros at the end to analyze last sample bh = blackmanharris(N) # synthesis window w = bh/ sum(bh) # normalize synthesis window L = sfreq[:,0].size # number of frames pin = 0 for l in range(L): xw = x[pin:pin+N]*w # window the input sound X = fft(fftshift(xw)) # compute FFT Yh = UF_C.genSpecSines(N*sfreq[l,:]/fs, smag[l,:], sphase[l,:], N) # generate spec sines Xr = X-Yh # subtract sines from original spectrum mXr = 20*np.log10(abs(Xr[:hN])) # magnitude spectrum of residual mXrenv = resample(np.maximum(-200, mXr), mXr.size*stocf) # decimate the mag spectrum if l == 0: mYst = np.array([mXrenv]) else: mYst = np.vstack((mYst, np.array([mXrenv]))) pin += H # advance sound pointer return mYst
def genSpecSines(ipfreq, ipmag, ipphase, N, fs): # Generate a spectrum from a series of sine values # ipfreq, ipmag, ipphase: sine peaks frequencies, magnitudes and phases # N: size of the complex spectrum to generate # fs: sampling frequency # returns Y: generated complex spectrum of sines Y = UF_C.genSpecSines(N*ipfreq/float(fs), ipmag, ipphase, N) return Y
def genSpecSines(ipfreq, ipmag, ipphase, N, fs): """ Generate a spectrum from a series of sine values, calling a C function ipfreq, ipmag, ipphase: sine peaks frequencies, magnitudes and phases N: size of the complex spectrum to generate; fs: sampling frequency returns Y: generated complex spectrum of sines """ Y = UF_C.genSpecSines(N * ipfreq / float(fs), ipmag, ipphase, N) return Y
def genSpecSines(ipfreq, ipmag, ipphase, N, fs): """ Generate a spectrum from a series of sine values, calling a C function ipfreq, ipmag, ipphase: sine peaks frequencies, magnitudes and phases N: size of the complex spectrum to generate; fs: sampling frequency returns Y: generated complex spectrum of sines """ Y = UF_C.genSpecSines(N*ipfreq/float(fs), ipmag, ipphase, N) return Y
b = np.arange(round(loc)-4, round(loc)+5) for m in range(0, 9): if b[m] < 0: # peak lobe crosses DC bin Y[-b[m]] += lmag[m]*np.exp(-1j*ipphase[i]) elif b[m] > hN: # peak lobe croses Nyquist bin Y[b[m]] += lmag[m]*np.exp(-1j*ipphase[i]) elif b[m] == 0 or b[m] == hN: # peak lobe in the limits of the spectrum Y[b[m]] += lmag[m]*np.exp(1j*ipphase[i]) + lmag[m]*np.exp(-1j*ipphase[i]) else: # peak lobe in positive freq. range Y[b[m]] += lmag[m]*np.exp(1j*ipphase[i]) Y[hN+1:] = Y[hN-1:0:-1].conjugate() # fill the negative part of the spectrum return Y # Determine which implementation of genSpecSines to use. if UF_C: genSpecSines = lambda ipfreq, ipmag, ipphase, N, fs: UF_C.genSpecSines(N*ipfreq/float(fs), ipmag, ipphase, N) else: genSpecSines = genSpecSines_p def sinewaveSynth(freqs, amp, H, fs): """ Synthesis of one sinusoid with time-varying frequency freqs, amps: array of frequencies and amplitudes of sinusoids H: hop size, fs: sampling rate returns y: output array sound """ t = np.arange(H)/float(fs) # time array lastphase = 0 # initialize synthesis phase lastfreq = freqs[0] # initialize synthesis frequency y = np.array([]) # initialize output array