def synthesis_pure_python_cplx(self, coeffs): values = np.zeros((self.ntheta, self.nphi), dtype=np.complex128) for itheta, ct in enumerate(self.cos_theta): self.fft_work_array[:] = 0 self.plm.evaluate_batch(ct, result=self.plm_work_array) plm_idx = 0 # m = 0 case for l in range(self.lmax + 1): l_offset = l * (l + 1) p = self.plm_work_array[plm_idx] self.fft_work_array[0] += coeffs[l_offset] * p plm_idx += 1 for m in range(1, self.lmax + 1): sign = -1 if m & 1 else 1 for l in range(m, self.lmax + 1): l_offset = l * (l + 1) p = self.plm_work_array[plm_idx] m_idx_neg = self.nphi - m m_idx_pos = m rr = sign * coeffs[l_offset + m] * p ii = sign * coeffs[l_offset - m] * p if m & 1: ii = -ii self.fft_work_array[m_idx_neg] += ii self.fft_work_array[m_idx_pos] += rr plm_idx += 1 ifft(self.fft_work_array, norm="forward", overwrite_x=True) values[itheta, :] = self.fft_work_array[:] return values
def test_ifftn(self): x = random((30, 20, 10)) + 1j*random((30, 20, 10)) assert_array_almost_equal( fft.ifft(fft.ifft(fft.ifft(x, axis=2), axis=1), axis=0), fft.ifftn(x)) assert_array_almost_equal(fft.ifftn(x) * np.sqrt(30 * 20 * 10), fft.ifftn(x, norm="ortho"))
def prop(self, signal: QamSignal): ''' :param signal: signal object to propagation across this fiber :return: ndarray ''' center_lambda = signal.center_wavelength after_prop = np.zeros_like(signal[:]) for pol in range(0, signal.pol_number): sample = signal[pol, :] sample_fft = fft(sample) freq = fftfreq(signal[:].shape[1], 1 / signal.fs_in_fiber) omeg = 2 * np.pi * freq after_prop[pol, :] = sample_fft * np.exp( -self.alphalin * self.length / 2) after_prop[pol, :] = ifft(after_prop[pol, :]) disp = np.exp(-1j / 2 * self.beta2(center_lambda) * omeg**2 * self.length) after_prop[pol, :] = ifft(fft(after_prop[pol, :]) * disp) signal[0] = after_prop[0] signal[1] = after_prop[1] return signal
def get_Dj(lamda, beta_nd, w_ft, k): # function for computing displacements D1 (in-phase with base) and D2 (anti-phase with base) k = np.abs(k) g = beta_nd / k # relaxation function R1 = (1 / k) * ((1 + g) * np.exp(4 * k) - (2 + 4 * g * k) * np.exp(2 * k) + 1 - g) D = (1 + g) * np.exp(4 * k) + (2 * g + 4 * k + 4 * g * (k**2)) * np.exp(2 * k) - 1 + g R = R1 / D # transfer function T1 = 2 * (1 + g) * (k + 1) * np.exp( 3 * k) + 2 * (1 - g) * (k - 1) * np.exp(k) T = T1 / D G1 = T * w_ft G2 = 1 + (lamda * R)**2 # displacements D1 = ifft(G1 / G2).real D2 = ifft(lamda * R * G1 / G2).real return D1, D2
def test_ifft2(self): x = random((30, 20)) + 1j * random((30, 20)) expect = fft.ifft(fft.ifft(x, axis=1), axis=0) assert_array_almost_equal(expect, fft.ifft2(x)) assert_array_almost_equal(expect, fft.ifft2(x, norm="backward")) assert_array_almost_equal(expect * np.sqrt(30 * 20), fft.ifft2(x, norm="ortho")) assert_array_almost_equal(expect * (30 * 20), fft.ifft2(x, norm="forward"))
def test_invalid_workers(x): cpus = os.cpu_count() fft.ifft([1], workers=-cpus) with pytest.raises(ValueError, match='workers must not be zero'): fft.fft(x, workers=0) with pytest.raises(ValueError, match='workers value out of range'): fft.ifft(x, workers=-cpus - 1)
def minimum_phase(h): """Convert a linear-phase FIR filter to minimum phase. Parameters ---------- h : array Linear-phase FIR filter coefficients. Returns ------- h_minimum : array The minimum-phase version of the filter, with length ``(length(h) + 1) // 2``. """ try: from scipy.signal import minimum_phase except Exception: pass else: return minimum_phase(h) h = np.asarray(h) if np.iscomplexobj(h): raise ValueError('Complex filters not supported') if h.ndim != 1 or h.size <= 2: raise ValueError('h must be 1D and at least 2 samples long') n_half = len(h) // 2 if not np.allclose(h[-n_half:][::-1], h[:n_half]): warnings.warn( 'h does not appear to by symmetric, conversion may ' 'fail', RuntimeWarning) n_fft = 2**int(np.ceil(np.log2(2 * (len(h) - 1) / 0.01))) # zero-pad; calculate the DFT h_temp = np.abs(fft(h, n_fft)) # take 0.25*log(|H|**2) = 0.5*log(|H|) h_temp += 1e-7 * h_temp[h_temp > 0].min() # don't let log blow up np.log(h_temp, out=h_temp) h_temp *= 0.5 # IDFT h_temp = ifft(h_temp).real # multiply pointwise by the homomorphic filter # lmin[n] = 2u[n] - d[n] win = np.zeros(n_fft) win[0] = 1 stop = (len(h) + 1) // 2 win[1:stop] = 2 if len(h) % 2: win[stop] = 1 h_temp *= win h_temp = ifft(np.exp(fft(h_temp))) h_minimum = h_temp.real n_out = n_half + len(h) % 2 return h_minimum[:n_out]
def FBP(data, ig): '''Filter-Back-Projection for a nice description https://www.coursera.org/lecture/cinemaxe/filtered-back-projection-part-2-gJSJh ''' spread = ig.allocate(0) spreadarr = spread.as_array() recon = ig.allocate(0) reconarr = recon.as_array() l = spread.get_dimension_size('horizontal_x') # create |omega| filter freq = fftfreq(l) fltr = np.asarray([np.abs(el) for el in freq]) for i, angle in enumerate(data.geometry.angles): line = data.get_slice(angle=i).as_array() # apply filter in Fourier domain lf = fft(line) lf3 = lf * fltr bck = ifft(lf3) # backproject for j in range(recon.shape[1]): spreadarr[j] = bck.real # should use https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.rotate reconarr += rotate(spreadarr, angle, reshape=False) recon.fill(reconarr) return recon
def pre_filter_wdm(signal, bw, os, center_freq=0): """ Ideal LP filter for selecting part of the spectrum. Uses FFT Parameters ---------- signal : array-like Input signal bw : float Filter bandwidth, normalized units os : float Oversampling factor center_freq : float center frequency, normalized units. Default is DC centered operation Returns ------- s : array-like Output signal after filtering """ # Prepare signal N = len(signal) h = np.zeros(N, dtype=sig.real.dtype) freq_axis = scifft.fftfreq(N, 1 / os) # Create filter window idx = np.where(abs(freq_axis - center_freq) < bw / 2) h[idx] = 1 # Filter and output s = (scifft.ifft(scifft.fft(signal) * h)) return s
def OFDMtrans(): syms = generate_syms(channels) inverse = fft.ifft(syms) #ratio of the length of the number of samples in the carrier to the length of the IFFT r = int(np.rint(N / channels)) #each symbol from the ifft is tiled so that the length matches the length of the carrier inverse = inverse.reshape((channels, 1)) inverse = np.tile(inverse, (1, r)) inverse = inverse.flatten() #multiplied by this to give power of 1 mW transmit = np.cos(2 * np.pi * fc * t) * inverse plt.figure() plt.plot(t, transmit) plt.title("Optical OFDM signal in time domain") plt.xlabel("Time") plt.ylabel("Amplitude") ########################## # plt.figure() # plt.title("Transmitted") # spec = fft.fft(transmit, norm = 'ortho',) # freq = fft.fftfreq(len(transmit), d = timestep) # plt.plot(freq, abs(spec)) # plt.axis([1.917 * 10 ** 14, 1.961 * 10 ** 14, 0, 1.1 * np.max(abs(spec))]) ########################### return transmit, syms
def bandpass_filter(signal_samples, fs, fs_high, fs_low): signal_samples = np.atleast_2d(signal_samples) freq_vector = fftfreq(signal_samples.shape[1], 1 / fs) mask = np.logical_and(freq_vector < fs_high, freq_vector >= fs_low) fft_samples = fft(signal_samples, axis=1) fft_samples[:, mask] = 0 return ifft(fft_samples, axis=1)
def single_step_propagation(self, dt, wavefunction): """ Propagate the wavefunction by a single time-step :param dt: time-step :param wavefunction: 1D numpy array :return: wavefunction """ # efficiently evaluate # wavefunction *= (-1) ** k * exp(-0.5j * dt * v) self.expV(wavefunction, self.t, dt) # going to the momentum representation wavefunction = fft.fft(wavefunction, overwrite_x=True) # efficiently evaluate # wavefunction *= exp(-1j * dt * k) self.expK(wavefunction, self.t, dt) # going back to the coordinate representation wavefunction = fft.ifft(wavefunction, overwrite_x=True) # efficiently evaluate # wavefunction *= (-1) ** k * exp(-0.5j * dt * v) self.expV(wavefunction, self.t, dt) # normalize # this line is equivalent to # self.wavefunction /= np.sqrt(np.sum(np.abs(self.wavefunction) ** 2 ) * self.dx) wavefunction /= linalg.norm(wavefunction) * np.sqrt(self.dx) return wavefunction
def istft(X, chunk_size, hop, w=None): """ Naively inverts the short time fourier transform using an overlap and add method. The overlap is defined by hop Args: X: STFT windows to invert, overlap and add. chunk_size: size of analysis window. hop: hop distance between analysis windows w: windowing function to apply. Must be of length chunk_size Returns: ISTFT of X using an overlap and add method. Windowing used to smooth. Raises: ValueError if window w is not of size chunk_size """ if not w: w = hanning(chunk_size) else: if len(w) != chunk_size: raise ValueError( "window w is not of the correct length {0}.".format( chunk_size)) x = zeros(len(X) * (hop)) i_p = 0 for n, i in enumerate(range(0, len(x) - chunk_size, hop)): x[i:i + chunk_size] += w * real(ifft(X[n])) return x
def cwt(self, signal: np.ndarray, scales: np.ndarray, dt=1): """Continuous wavelet transform. Parameters ---------- signal : np.ndarray The signal to transform. scales : np.ndarray Wavelet scales. dt : float The sampling period of the signal. """ # Find the fast length for the FFT n = len(signal) fast_len = fft.next_fast_len(n) # Signal in frequency domain fs = fft.fftfreq(fast_len, d=dt) f_sig = fft.fft(signal, n=fast_len) # Compute the wavelet transform psi = np.array([self.psi_f(fs, scale) for scale in scales]) W = fft.ifft(f_sig * psi, workers=-1)[..., :n] freqs = self.central_freq(scales) return freqs, W
def Filtragem_RC(x, t, T, Tam, RC=[0.1, 0.35, 1.2]): # sinal x, vetor de tempo t # T - periodo de x # Tam - taxa de amostragem # RC - valores para RC do filtro ## filtragem X = fft(x) / len(x) # criando o vetor de frequencia w = fftfreq(len(t), d=(1 / T) * Tam) for RCk in RC: H = 1 / (1 + ((1j * w) * (RCk))) # passa-baixas Y = H * X # aplicando o filtro # retornando o sinal ao dominio do tempo yt = ifft(Y) * len(x) yr = np.real(yt) # ignorando os erros de arrendondamento do fft e ifft # plotando as figuras para visualização fig, ax = plt.subplots() ax.plot(t, x, 'c--', linewidth = 2, label = "xr(t)") ax.plot(t, yr, 'r-', linewidth = 1, label = "xr_filtrado(t)") ax.set_ylabel("Amplitude") ax.set_xlabel("tempo [s]") ax.grid(True) ax.legend() ax.set_title('xr(t) e xr_filtrado(t) para RC = ' + str(RCk)) return yr
def denoise(f, filter_level, timestep): """ Denoise a given signal in the time domain using fast fourier transform Parameters ---------- f : np.ndarray one-dimensional time-domain data filter_level : float/int level below which the values can be zeroed out in the frequency domain timestep : float/int incremental change in the independent variable Returns ------- fifft : np.ndarray denoised signal in the time domain """ length = len(f) fhat = fft(f, length) PS = fhat * np.conj(fhat) / length indices = PS > filter_level fhat = indices * fhat fifft = ifft(fhat) fifft = np.real(fifft) return fifft
def apply_DAC_filter(sig, fs, cutoff=18e9, fn=None, ch=1): """ Apply the frequency response filter of the DAC. This function uses either a 2nd order Bessel filter or a measured frequency response loaded from a file. Parameters ---------- sig : array_like signal to be filtered. Can be real or complex fs : float sampling rate of the signal cutoff : float, optional Cutoff frequency used by only by Bessel filter fn : string, optional filename of a experimentally measured response, if None use a Bessel filter approximation ch : int, optional channel number of the measured response to use Returns ------- filter_sig : array_like filtered signal """ # filtering was split into real and imaginary before but that should not be necessary if fn is None: filter_sig = filter_signal(sig, fs, cutoff, ftype="bessel", order=2) else: H_dac = load_dac_response(fn, fs, sig.shape[-1], ch=ch).astype(sig) # should check if response is real sigf = fft.fft(sig) filter_sig = fft.ifft(sigf * H_dac) return filter_sig
def applyWeights(self,img_red,ws_img): af = self.af af2 = self.af2 nc, ny, nx = ws_img.shape[1:] nc, nyr, nxr = img_red.shape if (ny > nyr): af = round(ny/nyr) af2 = round(nx/nxr) print('Assuming the data is passed without zeros at not sampled lines ......') print('Acceleration factor is af = ' + str(af) + '.....') sig_red = img_red for idx in range(1,3): sig_red = fftshift(fft(fftshift(sig_red,axes=idx),axis=idx,norm='ortho'),axes=idx) sig_new = np.zeros((nc,ny,nx),dtype=np.complex64) sig_new[:,::af,::af2] = sig_red img_red = sig_new for idx in range(1,3): img_red = ifftshift(ifft(ifftshift(img_red,axes=idx),axis=idx,norm='ortho'),axes=idx) recon = np.zeros((nc,ny,nx),dtype=np.complex64) for k in range(0,nc): recon[k,:,:] = np.sum(ws_img[k,:,:,:] * img_red,axis=0) return recon
def add_dispersion(sig, fs, D, L, wl0=1550e-9): """ Add dispersion to signal. Parameters ---------- sig : array_like input signal fs : flaot sampling frequency of the signal (in SI units) D : float Dispersion factor in s/m/m L : float Length of the dispersion in m wl0 : float,optional center wavelength of the signal Returns ------- sig_out : array_like dispersed signal """ C = 2.99792458e8 N = sig.shape[-1] omega = fft.fftfreq(N, 1/fs)*np.pi*2 beta2 = D * wl0**2 / (C*np.pi*2) H = np.exp(-0.5j * omega**2 * beta2 * L).astype(sig.dtype) sff = fft.fft(fft.ifftshift(sig, axes=-1), axis=-1) sig_out = fft.fftshift(fft.ifft(sff*H)) return sig_out
def ccf(cs_power, ps_rms, n_bins): """ Return the normalised cross-correlation function of the cross spectrum. It is normalised using the average RMS of power spectrum. Parameters ---------- cs_power : 1-d float array Power of cross spectrum. ps_rms : 1-d float array RMS of power spectrum. n_bins : int Number of buns. Returns ------- ccf_real_norm : 1-d float array Real part of normalised ccf. """ ccf = ifft(cs_power) # inverse fast fourier transformation ccf_real = ccf.real # real part of ccf ccf_real_norm = ccf_real * (2 / n_bins / ps_rms) # normalisation return ccf_real_norm
def stochasticModelSynth(stocEnv, H, N): """ Stochastic synthesis of a sound stocEnv: stochastic envelope; H: hop size; N: fft size returns y: output sound """ if not (UF.isPower2(N)): # raise error if N not a power of two raise ValueError("N is not a power of two") hN = N // 2 + 1 # positive size of fft No2 = N // 2 # half of N L = stocEnv[:, 0].size # number of frames ysize = H * (L + 3) # output sound size y = np.zeros(ysize) # initialize output array ws = 2 * hanning(N) # synthesis window pout = 0 # output sound pointer for l in range(L): mY = resample(stocEnv[l, :], hN) # interpolate to original size pY = 2 * np.pi * np.random.rand(hN) # generate phase random values Y = np.zeros(N, dtype=complex) # initialize synthesis spectrum Y[:hN] = 10**(mY / 20) * np.exp(1j * pY) # generate positive freq. Y[hN:] = 10**(mY[-2:0:-1] / 20) * np.exp( -1j * pY[-2:0:-1]) # generate negative freq. fftbuffer = np.real(ifft(Y)) # inverse FFT y[pout:pout + N] += ws * fftbuffer # overlap-add pout += H y = np.delete(y, range(No2)) # delete half of first window y = np.delete(y, range(y.size - No2, y.size)) # delete half of the last window return y
def test_filtering(self): ag = AcquisitionGeometry.create_Parallel3D()\ .set_panel([64,3],[0.1,0.1])\ .set_angles([0,90]) ad = ag.allocate('random', seed=0) reconstructor = FBP(ad) out1 = ad.copy() reconstructor._pre_filtering(out1) #by hand filter = reconstructor.get_filter_array() reconstructor._calculate_weights(ag) pad0 = (len(filter) - ag.pixel_num_h) // 2 pad1 = len(filter) - ag.pixel_num_h - pad0 out2 = ad.array.copy() out2 *= reconstructor._weights for i in range(2): proj_padded = np.zeros((ag.pixel_num_v, len(filter))) proj_padded[:, pad0:-pad1] = out2[i] filtered_proj = fft(proj_padded, axis=-1) filtered_proj *= filter filtered_proj = ifft(filtered_proj, axis=-1) out2[i] = np.real(filtered_proj)[:, pad0:-pad1] diff = (out1 - out2).abs().max() self.assertLess(diff, 1e-5)
def transform(self, X): """Apply the approximate feature map to X. Parameters ---------- X : {array-like, sparse matrix}, shape (n_samples, n_features) New data, where n_samples is the number of samples and n_features is the number of features. Returns ------- X_new : array-like, shape (n_samples, n_components) """ check_is_fitted(self, "random_weights_") X = check_array(X, True) n_samples, n_features = X.shape P = safe_sparse_dot(X, self.random_weights_[:, :n_features].T, dense_output=True) output = fft(P) for offset in range(n_features, n_features*self.degree, n_features): random_weight = self.random_weights_[:, offset:offset+n_features] P = safe_sparse_dot(X, random_weight.T, dense_output=True) output *= fft(P) return ifft(output).real
def dftSynth(mX, pX, M): """ Synthesis of a signal using the discrete Fourier transform mX: magnitude spectrum, pX: phase spectrum, M: window size returns y: output signal """ hN = mX.size # size of positive spectrum, it includes sample 0 N = (hN - 1) * 2 # FFT size if not (UF.isPower2(N) ): # raise error if N not a power of two, thus mX is wrong raise ValueError("size of mX is not (N/2)+1") hM1 = int(math.floor((M + 1) / 2)) # half analysis window size by rounding hM2 = int(math.floor(M / 2)) # half analysis window size by floor fftbuffer = np.zeros(N) # initialize buffer for FFT y = np.zeros(M) # initialize output array Y = np.zeros(N, dtype=complex) # clean output spectrum Y[:hN] = 10**(mX / 20) * np.exp(1j * pX) # generate positive frequencies Y[hN:] = 10**(mX[-2:0:-1] / 20) * np.exp( -1j * pX[-2:0:-1]) # generate negative frequencies fftbuffer = np.real(ifft(Y)) # compute inverse FFT y[:hM2] = fftbuffer[-hM2:] # undo zero-phase window y[hM2:] = fftbuffer[:hM1] return y
def signaltest(normalized_tone): myx = [ DFT(normalized_tone[:1000], n) for n in range(0, len(normalized_tone[:1000])) ] yf = fft(normalized_tone[:1000]) new_sig = ifft(yf) xf = fftfreq(1000, 1 / SAMPLE_RATE) #Freq Kotelnikova myfreq = SAMPLE_RATE / 2 myxf = np.arange(0, myfreq, 2 * myfreq / 1000) fig, axs = plt.subplots(4, 2) fig.suptitle("Task 1") # axs[0][0].set_title("Fast Fourirer Transform") axs[0][0].plot(xf[:500], np.abs(yf)[:500]) #axs[1][0].set_title("Discrete(my) Fourirer Transform") axs[1][0].plot(myxf, np.abs(myx)[:500], "tab:green") #axs[2][0].set_title("Discrete(my) and Fast FT on one graphic") axs[2][0].plot(xf[:500], np.abs(yf)[:500]) axs[2][0].plot(myxf, np.abs(myx)[:500], "tab:green") kyx = [IDFT(myx, k) for k in range(0, len(myx))] # axs[0][1].set_title("Inverse Fast Fourirer Transform") axs[0][1].plot(new_sig[:1000]) # axs[1][1].set_title("Inverse Discrete(my) Fourirer Transform") axs[1][1].plot(kyx, "tab:green") # axs[2][1].set_title("Inverse Fast and Discrete(my) FT") #axs[2][1].plot(new_sig[:1000]) axs[2][1].plot(kyx, "tab:green") # axs[3][0].set_title("Full function") axs[3][0].plot(normalized_tone) # axs[3][1].set_title("Source signal for transform") axs[3][1].plot(normalized_tone[:1000]) plt.show()
def _st_power_itc(x, start_f, compute_itc, zero_pad, decim, W): """Aux function.""" from scipy.fft import fft, ifft n_samp = x.shape[-1] n_out = (n_samp - zero_pad) n_out = n_out // decim + bool(n_out % decim) psd = np.empty((len(W), n_out)) itc = np.empty_like(psd) if compute_itc else None X = fft(x) XX = np.concatenate([X, X], axis=-1) for i_f, window in enumerate(W): f = start_f + i_f ST = ifft(XX[:, f:f + n_samp] * window) if zero_pad > 0: TFR = ST[:, :-zero_pad:decim] else: TFR = ST[:, ::decim] TFR_abs = np.abs(TFR) TFR_abs[TFR_abs == 0] = 1. if compute_itc: TFR /= TFR_abs itc[i_f] = np.abs(np.mean(TFR, axis=0)) TFR_abs *= TFR_abs psd[i_f] = np.mean(TFR_abs, axis=0) return psd, itc
def __call__(self, x, *, axis=-1): """ Calculate the chirp z-transform of a signal. Parameters ---------- x : array The signal to transform. axis : int, optional Axis over which to compute the FFT. If not given, the last axis is used. Returns ------- out : ndarray An array of the same dimensions as `x`, but with the length of the transformed axis set to `m`. """ x = np.asarray(x) if x.shape[axis] != self.n: raise ValueError(f"CZT defined for length {self.n}, not " f"{x.shape[axis]}") # Calculate transpose coordinates, to allow operation on any given axis trnsp = np.arange(x.ndim) trnsp[[axis, -1]] = [-1, axis] x = x.transpose(*trnsp) y = ifft(self._Fwk2 * fft(x * self._Awk2, self._nfft)) y = y[..., self._yidx] * self._wk2 return y.transpose(*trnsp)
def get_sequence(): '''Obtiene la secuencia desde el Front, hace la operacion y regresa el resultado ''' sequence = request.json['sec'] operation = request.json['ope'] # Validar flag = validate_sec(sequence) if (flag == '11'): # Hace la operacion if operation == 'FFT': y = fft.fft(transform_list(sequence)) elif operation == 'IFFT': y = fft.ifft(transform_list(sequence)) # Redondea y convierte en String y = np.array_str(np.around(y, 2)) elif flag == '01': y = 'La secuencia no es de tamaño n^2' elif flag == '10': y = 'La secuencia no es correcta' else: y = 'La secuencia no es de tamaño n^2 y tampoco esta escrita correctamente' # Regresa el resultado return jsonify(y)
def _rrcos_pulseshaping_freq(sig, fs, T, beta): """ Root-raised cosine filter in the spectral domain by multiplying the fft of the signal with the frequency response of the rrcos filter. Parameters ---------- sig : array_like input time distribution of the signal fs : float sampling frequency of the signal T : float width of the filter (typically this is the symbol period) beta : float filter roll-off factor needs to be in range [0, 1] Returns ------- sign_out : array_like filtered signal in time domain """ f = scifft.fftfreq(sig.shape[0]) * fs nyq_fil = rrcos_freq(f, beta, T) nyq_fil /= nyq_fil.max() sig_f = scifft.fft(sig) sig_out = scifft.ifft(sig_f * nyq_fil) return sig_out
def estimate_pitch(y, sr, fmin=10.0, fmax=1000.0): max_size = None axis = -1 # Compute autocorrelation of input segment. if max_size is None: max_size = y.shape[axis] max_size = int(min(max_size, y.shape[axis])) # Compute the power spectrum along the chosen axis # Pad out the signal to support full-length auto-correlation. powspec = np.abs(fft(y, n=2 * y.shape[axis] + 1, axis=axis))**2 # Convert back to time domain autocorr = ifft(powspec, axis=axis) # Slice down to max_size subslice = [slice(None)] * autocorr.ndim subslice[axis] = slice(max_size) autocorr = autocorr[tuple(subslice)] if not np.iscomplexobj(y): autocorr = autocorr.real # Define lower and upper limits for the autocorrelation argmax. i_min = sr / fmax i_max = sr / fmin autocorr[:int(i_min)] = 0 autocorr[int(i_max):] = 0 # Find the location of the maximum autocorrelation. i = autocorr.argmax() f0 = float(sr) / i return f0