def _phase_map(self): self.dphi = (2 * P.pi * self.nhop * P.arange(self.nfft / 2 + 1)) / self.nfft A = P.diff(P.angle(self.STFT), 1) # Complete Phase Map U = P.c_[P.angle(self.STFT[:, 0]), A - P.atleast_2d(self.dphi).T] U = U - P.np.round(U / (2 * P.pi)) * 2 * P.pi self.dPhi = U return U
def _pvoc2(self, X_hat, Phi_hat=None, R=None): """ :: alternate (batch) implementation of phase vocoder - time-stretch inputs: X_hat - estimate of signal magnitude [Phi_hat] - estimate of signal phase [R] - resynthesis hop ratio output: updates self.X_hat with modified complex spectrum """ N, W, H = self.nfft, self.wfft, self.nhop R = 1.0 if R is None else R dphi = P.atleast_2d((2 * P.pi * H * P.arange(N / 2 + 1)) / N).T print("Phase Vocoder Resynthesis...", N, W, H, R) A = P.angle(self.STFT) if Phi_hat is None else Phi_hat U = P.diff(A, 1) - dphi U = U - P.np.round(U / (2 * P.pi)) * 2 * P.pi t = P.arange(0, n_cols, R) tf = t - P.floor(t) phs = P.c_[A[:, 0], U] phs += U[:, idx[1]] + dphi # Problem, what is idx ? Xh = (1 - tf) * Xh[:-1] + tf * Xh[1:] Xh *= P.exp(1j * phs) self.X_hat = Xh
def _pvoc(self, X_hat, Phi_hat=None, R=None): """ :: a phase vocoder - time-stretch inputs: X_hat - estimate of signal magnitude [Phi_hat] - estimate of signal phase [R] - resynthesis hop ratio output: updates self.X_hat with modified complex spectrum """ N = self.nfft W = self.wfft H = self.nhop R = 1.0 if R is None else R dphi = (2 * P.pi * H * P.arange(N / 2 + 1)) / N print("Phase Vocoder Resynthesis...", N, W, H, R) A = P.angle(self.STFT) if Phi_hat is None else Phi_hat phs = A[:, 0] self.X_hat = [] n_cols = X_hat.shape[1] t = 0 while P.floor(t) < n_cols: tf = t - P.floor(t) idx = P.arange(2) + int(P.floor(t)) idx[1] = n_cols - 1 if t >= n_cols - 1 else idx[1] Xh = X_hat[:, idx] Xh = (1 - tf) * Xh[:, 0] + tf * Xh[:, 1] self.X_hat.append(Xh * P.exp(1j * phs)) U = A[:, idx[1]] - A[:, idx[0]] - dphi U = U - P.np.round(U / (2 * P.pi)) * 2 * P.pi phs += (U + dphi) t += P.randn() * P.sqrt(PVOC_VAR * R) + R # 10% variance self.X_hat = P.np.array(self.X_hat).T
def variable_phase_vocoder(D, times_steps, hop_length=None): n_fft = 2 * (D.shape[0] - 1) if hop_length is None: hop_length = int(n_fft // 4) # time_steps = P.arange(0, D.shape[1], rate, dtype=P.double) # time_steps = P.concatenate([ # P.arange(0, D.shape[1]/2, .5, dtype=P.double), # P.arange(D.shape[1]/2, D.shape[1], 2, dtype=P.double) # ]) # Create an empty output array d_stretch = P.zeros((D.shape[0], len(time_steps)), D.dtype, order='F') # Expected phase advance in each bin phi_advance = P.linspace(0, P.pi * hop_length, D.shape[0]) # Phase accumulator; initialize to the first sample phase_acc = P.angle(D[:, 0]) # Pad 0 columns to simplify boundary logic D = P.pad(D, [(0, 0), (0, 2)], mode='constant') for (t, step) in enumerate(time_steps): columns = D[:, int(step):int(step + 2)] # Weighting for linear magnitude interpolation alpha = P.mod(step, 1.0) mag = ((1.0 - alpha) * abs(columns[:, 0]) + alpha * abs(columns[:, 1])) # Store to output array d_stretch[:, t] = mag * P.exp(1.j * phase_acc) # Compute phase advance dphase = (P.angle(columns[:, 1]) - P.angle(columns[:, 0]) - phi_advance) # Wrap to -pi:pi range dphase = dphase - 2.0 * P.pi * P.around(dphase / (2.0 * P.pi)) # Accumulate phase phase_acc += phi_advance + dphase return d_stretch
def _istftm(self, X_hat=None, Phi_hat=None, pvoc=False, usewin=True, resamp=None): """ :: Inverse short-time Fourier transform magnitude. Make a signal from a |STFT| transform. Uses phases from self.STFT if Phi_hat is None. Inputs: X_hat - N/2+1 magnitude STFT [None=abs(self.STFT)] Phi_hat - N/2+1 phase STFT [None=exp(1j*angle(self.STFT))] pvoc - whether to use phase vocoder [False] usewin - whether to use overlap-add [False] Returns: x_hat - estimated signal """ if not self._have_stft: return None X_hat = self.X if X_hat is None else P.np.abs(X_hat) if pvoc: self._pvoc(X_hat, Phi_hat, pvoc) else: Phi_hat = P.angle(self.STFT) if Phi_hat is None else Phi_hat self.X_hat = X_hat * P.exp(1j * Phi_hat) if usewin: if self.win is None: self.win = P.ones( self.wfft) if self.window == 'rect' else P.np.sqrt( P.hanning(self.wfft)) if len(self.win) != self.nfft: self.win = P.r_[self.win, P.np.zeros(self.nfft - self.wfft)] if len(self.win) != self.nfft: error.BregmanError( "features_base.Features._istftm(): assertion failed len(self.win)==self.nfft" ) else: self.win = P.ones(self.nfft) if resamp: self.win = sig.resample(self.win, int(P.np.round(self.nfft * resamp))) fp = self._check_feature_params() self.x_hat = self._overlap_add(P.real(P.irfft(self.X_hat.T)), usewin=usewin, resamp=resamp) if self.verbosity: print("Extracted iSTFTM->self.x_hat") return self.x_hat