def zpFFTsizeExpt(x, fs): """ Inputs: x (numpy array) = input signal (2*M samples long) fs (float) = sampling frequency in Hz Output: The function should return a tuple (mX1_80, mX2_80, mX3_80) mX1_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-1 mX2_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-2 mX3_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-3 The first few lines of the code to generate xseg and the windows have been written for you, please use it and do not modify it. """ ## Your code here M = len(x)/2 xseg = x[:M] w1 = get_window('hamming',M) w2 = get_window('hamming',2*M) mX1 = dftAnal(xseg, w1, M)[0] mX2 = dftAnal(x, w2, 2*M)[0] mX3 = dftAnal(xseg, w1, 2*M)[0] mX1_80 = mX1[:80] mX2_80 = mX2[:80] mX3_80 = mX3[:80] plt.plot(mX1_80, label="mX1(half/half)", color="red") plt.plot(mX2_80, label="mX1(full/full)", color="blue") plt.plot(mX3_80, label="mX1(half/full)", color="green") plt.show() return mX1_80, mX2_80, mX3_80
def test_boxcar(self): w = signal.get_window('boxcar', 12) assert_array_equal(w, np.ones_like(w)) # window is a tuple of len 1 w = signal.get_window(('boxcar',), 16) assert_array_equal(w, np.ones_like(w))
def zpFFTsizeExpt(x, fs): """ Inputs: x (numpy array) = input signal (2*M samples long) fs (float) = sampling frequency in Hz Output: The function should return a tuple (mX1_80, mX2_80, mX3_80) mX1_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-1 mX2_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-2 mX3_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-3 The first few lines of the code to generate xseg and the windows have been written for you, please use it and do not modify it. """ M = len(x)/2 xseg = x[:M] w1 = get_window('hamming',M) w2 = get_window('hamming',2*M) ## Your code here # NOTE: The shape of the window is affected by the size parameter M. So if you want a 256 size window #you need to specifically create it and cant use w[:256] # Case-1: Input signal xseg (256 samples), window w1 (256 samples), and FFT size of 256 N = 256 mX1_80, pX1 = dftAnal(xseg, w1, N) #Input signal x (512 samples), window w2 (512 samples), and FFT size of 512 N = 512 mX2_80, pX2 = dftAnal(x[:N], w2[:N], N) #Input signal xseg (256 samples), window w1 (256 samples), and FFT size of 512 (Implicitly does a zero-padding of xseg by 256 samples) N = 256 mX3_80, pX3 = dftAnal(x[:N], w1, 512) return(mX1_80[:80],mX2_80[:80],mX3_80[:80])
def window(sw, window = 'barthann'): """ Creates 2d window of size sw -------------------------------------------------------------------------- Usage: Call: w = window(sw, window = 'barthann') Input: sw size of window window string specifying window type Output: Window of size sw -------------------------------------------------------------------------- Copyright (C) 2010 Michael Hirsch """ w1 = signal.get_window(window,sw[0]) w1 = (w1 + w1[::-1])/2 w1 -= w1.min() w2 = signal.get_window(window,sw[1]) w2 = (w2 + w2[::-1])/2 w2 -= w2.min() www = np.outer(w1,w2) www = www/www.max() www = np.maximum(www, 1e-16) return www
def zpFFTsizeExpt(x, fs): """ Inputs: x (numpy array) = input signal (2*M = 512 samples long) fs (float) = sampling frequency in Hz Output: The function should return a tuple (mX1_80, mX2_80, mX3_80) mX1_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-1 mX2_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-2 mX3_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-3 The first few lines of the code to generate xseg and the windows have been written for you, please use it and do not modify it. """ M = len(x)/2 xseg = x[:M] w1 = get_window('hamming',M) w2 = get_window('hamming',2*M) mX1, P = dftAnal(xseg, w1, 256) mX2, P = dftAnal(x, w2, 512) mX3, P = dftAnal(xseg, w1, 512) return (mX1[:80], mX2[:80], mX3[:80])
def zpFFTsizeExpt(x, fs): """ Inputs: x (numpy array) = input signal (2*M samples long) fs (float) = sampling frequency in Hz Output: The function should return a tuple (mX1_80, mX2_80, mX3_80) mX1_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-1 mX2_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-2 mX3_80 (numpy array): The first 80 samples of the magnitude spectrum output of dftAnal for Case-3 The first few lines of the code to generate xseg and the windows have been written for you, please use it and do not modify it. """ M = len(x)/2 xseg = x[:M] w1 = get_window('hamming',M) w2 = get_window('hamming',2*M) ## Your code here (xM1, pX1) = dftAnal(xseg, w1, M) (xM2, pX2) = dftAnal(x, w2, len(x)) (xM3, pX3) = dftAnal(xseg, w1, len(x)) plt.plot(np.arange(0,80,2), xM1[:40], color="red") plt.plot(xM2[:80], color="blue") plt.plot(xM3[:80], color="green") plt.show() return (xM1[:80], xM2[:80], xM3[:80])
def B_ell(flat_map, component, bin_size, window=None): """ Return the binned beam function of the given flat map component, using ell bins of bin_size. If a window name is given, multiply the map component by the window function before taking the 2-D DFT. The returned beam function is the absolute value of the DFT, so it has the same units as the map component. The returned bins array contains the left edges of the bins corresponding to the returned data: for all i in range(bins.size), bins[i] <= data[i] < bins[i+1] """ ell_x, ell_y= np.meshgrid(fftshift(fftfreq(flat_map.x.size, flat_map.dx()/(2*np.pi))), fftshift(fftfreq(flat_map.y.size, flat_map.dy()/(2*np.pi)))) ell_x = ell_x.T ell_y = ell_y.T ell_r = np.sqrt(ell_x**2 + ell_y**2) ell_bins = np.arange(0, np.max(ell_r), bin_size) beam = flat_map[component] if window is not None: beam *= get_window(window, flat_map.y.size) beam *= get_window(window, flat_map.x.size)[:, np.newaxis] dft = fftshift(fft2(beam)) # Shift the indices down by 1 so that they correspond to the data # indices. These indices should always be valid indices for the # DFT data because r_ell has a lower bound at 0 and max(r_ell) # will have index ell_bins.size. bin_indices = np.digitize(ell_r.flatten(), ell_bins) - 1 binned = np.zeros(ell_bins.size) # dtype? for i in range(binned.size): binned[i] = np.sqrt(np.mean(abs(dft.flatten()[i==bin_indices])**2)) return ell_bins, binned, dft
def test_window_external(self): x = np.zeros(16) x[0] = 1 f, p = periodogram(x, 10, 'hann') win = signal.get_window('hann', 16) fe, pe = periodogram(x, 10, win) assert_array_almost_equal_nulp(p, pe) assert_array_almost_equal_nulp(f, fe) win_err = signal.get_window('hann', 32) assert_raises(ValueError, periodogram, x, 10, win_err) # win longer than signal
def window(self, index1=None, index2=None, is_positional=False, win_fcn='boxcar', fftbins=False): """ Applies a window to the signal within a given time range. Parameters ---------- index1 : float or int, optional The start index/position of the window. Default value is minimum of index. index2 : float or int, optional The end index/position of the window. Default value is maximum of index. is_positional : bool, optional Indicates whether the inputs `index1` and `index2` are positional or value based. Default is :const:`False`, i.e. value based. win_fcn : string/float/tuple, optional The type of window to create. See the function :func:`scipy.signal.get_window()` for a complete list of available windows, and how to pass extra parameters for a specific window function. fftbins : bool, optional If True, then applies a symmetric window with respect to index of value 0. Returns ------- Signal: The windowed Signal signal. Note ---- If the window requires no parameters, then `win_fcn` can be a string. If the window requires parameters, then `win_fcn` must be a tuple with the first argument the string name of the window, and the next arguments the needed parameters. If `win_fcn` is a floating point number, it is interpreted as the beta parameter of the kaiser window. """ wind = Signal(0, index=self.index) if is_positional: if isinstance(index1, float) or isinstance(index2, float): raise ValueError('Indices are floats, are you sure you want positional indices?') index1 = wind.index.values[index1] index2 = wind.index.values[index2] wind[index1:index2] = get_window(win_fcn, len(wind[index1:index2])) if fftbins: if wind[-index2:-index1].size == 0: raise IndexError('The signal does not have values at the negative of the indices ' 'supplied. Disable fftbins for one-sided windowing.') wind[-index2:-index1] = get_window(win_fcn, len(wind[-index2:-index1])) return self*wind
def sineModelMultiResTest1(inputFile, M1, M2, M3): print "\n\n\n############### RUN MULTIRESOLUTION TEST ###############\n" #M1 = 4095 #M2 = 2047 #M3 = 1023 print "M1: " print M1 print "M2: " print M2 print "M3: " print M3 N1 = int(pow(2, np.ceil(np.log2(M1)))) # FFT Size, power of 2 larger than M N2 = int(pow(2, np.ceil(np.log2(M2)))) # FFT Size, power of 2 larger than M N3 = int(pow(2, np.ceil(np.log2(M3)))) # FFT Size, power of 2 larger than M print "N1: " print N1 print "N2: " print N2 print "N3: " print N3 t = -80.0 # threshold fs, x = UF.wavread(inputFile) # read input sound #print "Ploting \"x\"" #plt.plot(x) window = 'blackman' # Window type w1 = get_window(window, M1) # compute analysis window w2 = get_window(window, M2) # compute analysis window w3 = get_window(window, M3) # compute analysis window #B1 = 1000 # the band from 0 to 999 Hz #B2 = 5000 # the band from 1000 to 4999 Hz #B3 = 22050 # the band from 5000 to 22049 Hz B1 = 100 B2 = 1000 B3 = 22050 if (B3 > (44100 / 2)): B3 = 22050 return sineModelMultiRes(x, fs, w1, w2, w3, N1, N2, N3, t, B1=1000, B2=5000, B3=22050)
def suppressFreqDFTmodel(x, fs, N): """ Inputs: x (numpy array) = input signal of length M (odd) fs (float) = sampling frequency (Hz) N (positive integer) = FFT size Outputs: The function should return a tuple (y, yfilt) y (numpy array) = Output of the dftSynth() without filtering (M samples long) yfilt (numpy array) = Output of the dftSynth() with filtering (M samples long) The first few lines of the code have been written for you, do not modify it. """ M = len(x) w = get_window('hamming', M) #smotthing window outputScaleFactor = sum(w) ## Your code here mX, pX = dftAnal(x,w,N) axis = (fs) * np.arange(M)/float(M) belowAxis = sum(axis < 70) mXX = mX.copy() mXX[:belowAxis+1] = -120 #Synthesis y = dftSynth(mX, pX, w.size)*sum(w) yfilt = dftSynth(mXX, pX, w.size)*sum(w) return (y,yfilt)
def _normalize_window(window, nfft, library, dtype): """Normalise a window specification for a PSD calculation Parameters ---------- window : `str`, `numpy.ndarray`, `None` the input window specification nfft : `int` the length of the Fourier transform, in samples library : `str` the name of the library that provides the PSD routine dtype : `type` the required type of the window array, only used if `library='lal'` is given Returns ------- window : `numpy.ndarray`, `lal.REAL8Window` a numpy-, or `LAL`-format window array """ if library == '_lal' and isinstance(window, numpy.ndarray): from ._lal import window_from_array return window_from_array(window) if library == '_lal': from ._lal import generate_window return generate_window(nfft, window=window, dtype=dtype) if isinstance(window, string_types): window = canonical_name(window) if isinstance(window, string_types + (tuple,)): return get_window(window, nfft) return None
def testContribSignalSTFT(self): ws = 512 hs = 128 dims = (ws * 20,) shape = BATCH_DIMS + dims data = np.arange(np.prod(shape)) / np.prod(dims) np.random.seed(123) np.random.shuffle(data) data = np.reshape(data.astype(np.float32), shape) window = sps.get_window("hann", ws) expected = sps.stft( data, nperseg=ws, noverlap=ws - hs, boundary=None, window=window)[2] expected = np.swapaxes(expected, -1, -2) expected *= window.sum() # scipy divides by window sum with self.test_session() as sess: with self.test_scope(): ph = array_ops.placeholder( dtypes.as_dtype(data.dtype), shape=data.shape) out = signal.stft(ph, ws, hs) grad = gradients_impl.gradients(out, ph, grad_ys=array_ops.ones_like(out)) # For gradients, we simply verify that they compile & execute. value, _ = sess.run([out, grad], {ph: data}) self.assertAllClose(expected, value, rtol=RTOL, atol=ATOL)
def test_array_as_window(self): # github issue 3603 osfactor = 128 sig = np.arange(128) win = signal.get_window(('kaiser', 8.0), osfactor // 2) assert_raises(ValueError, signal.resample, (sig, len(sig) * osfactor), {'window': win})
def computeSNR(inputFile, window, M, N, H): """ Input: inputFile (string): wav file name including the path window (string): analysis window type (choice of rectangular, triangular, hanning, hamming, blackman, blackmanharris) M (integer): analysis window length (odd positive integer) N (integer): fft size (power of two, > M) H (integer): hop size for the stft computation Output: The function should return a python tuple of both the SNR values (SNR1, SNR2) SNR1 and SNR2 are floats. """ ## your code here def energy(X, k1, k2): X2 = np.power(X, 2) return np.sum(X2[k1:k2]) fs, x = UF.wavread(inputFile) w = get_window(window, M) xsyn = stft.stft(x, fs, w, N, H) noise = np.subtract(xsyn, x) Esignal1 = energy(x, 0, len(x)) Enoise1 = energy(noise, 0, len(noise)) SNR1 = 10*np.log10(Esignal1/Enoise1) Esignal2 = energy(x, M+1, len(x)-M-1) Enoise2 = energy(noise, M+1, len(noise)-M-1) SNR2 = 10*np.log10(Esignal2/Enoise2) return SNR1, SNR2
def _calc_harmonic_spec(self, fs, K, harmonics): nyquist_bin = K>>1 # initialize spectrum of detected harmonics Y_t_D = np.zeros(nyquist_bin) # calculate the partial spectrum for each harmonic # Klapuri PhD Thesis, page 62 and (Klapuri, 2006) Section 2.5 # Even with these sources, the algorithm for estimating the # spectrum of the fundamental and partials is rather unclear. frame_len_samps = int(fs * self._frame_len_sec) win = get_window(self._window_func, frame_len_samps) window_spec = np.abs(np.fft.fft(win, K)) partial_spectrum = np.hstack((window_spec[self._partial_width::-1], window_spec[1:self._partial_width+1])) # normalize the spectrum partial_spectrum /= np.max(partial_spectrum) for h in harmonics: h_lb = max(0, h['bin']-self._partial_width) h_ub = min(nyquist_bin-1, h['bin']+self._partial_width) # translate the spectrum of the window function to the position of the harmonic Y_t_D[h_lb:h_ub+1] = h['amp']*partial_spectrum[h_lb-h['bin']+self._partial_width:h_ub-h['bin']+self._partial_width+1] return Y_t_D
def computeSNR(inputFile, window, M, N, H): """ Input: inputFile (string): wav file name including the path window (string): analysis window type (choice of rectangular, triangular, hanning, hamming, blackman, blackmanharris) M (integer): analysis window length (odd positive integer) N (integer): fft size (power of two, > M) H (integer): hop size for the stft computation Output: The function should return a python tuple of both the SNR values (SNR1, SNR2) SNR1 and SNR2 are floats. """ ## your code here fs, x = UF.wavread(inputFile) w = get_window(window, M) y = stft.stft(x, fs, w, N, H) noise = np.array(x - y) E_x = np.sum( abs(x)**2 ) E_noise = np.sum( abs(noise)**2 ) E_xAfterM = np.sum( abs( x[M : x.size-M] )**2 ) E_nAfterM = np.sum( abs( noise[M : x.size-M] )**2 ) SNR1 = 10 * np.log10(E_x / E_noise) SNR2 = 10 * np.log10(E_xAfterM/E_nAfterM) return (SNR1, SNR2)
def extractMainLobe(window, M): """ Input: window (string): Window type to be used (Either rectangular ('boxcar'), 'hamming' or ' blackmanharris') M (integer): length of the window to be used Output: The function should return a numpy array containing the main lobe of the magnitude spectrum of the window in decibels (dB). """ ### Your code here w = get_window(window, M) hM1 = int(math.floor((M+1)/2)) hM2 = int(math.floor(M/2)) N = 8*M fftBuffer = np.zeros(N) fftBuffer[:hM1] = w[hM2:] fftBuffer[N-hM2:] = w[:hM2] X = fft(w, N) Xabs = abs(X) Xabs[Xabs<eps] = eps mX = 20.*np.log10(Xabs) hW = min( [i for i in range(len(mX)-1) if mX[i]<mX[i+1] and mX[i]<mX[i-1]]) result = np.zeros(2*hW + 1) result[:hW] = mX[-hW:] result[hW:] = mX[:hW+1] # plt.plot(result) # plt.show() return result
def computeEngEnv(inputFile, window, M, N, H): """ Inputs: inputFile (string): input sound file (monophonic with sampling rate of 44100) window (string): analysis window type (choice of rectangular, triangular, hanning, hamming, blackman, blackmanharris) M (integer): analysis window size (odd positive integer) N (integer): FFT size (power of 2, such that N > M) H (integer): hop size for the stft computation Output: The function should return a numpy array engEnv with shape Kx2, K = Number of frames containing energy envelop of the signal in decibles (dB) scale engEnv[:,0]: Energy envelope in band 0 < f < 3000 Hz (in dB) engEnv[:,1]: Energy envelope in band 3000 < f < 10000 Hz (in dB) """ (fs,x) = UF.wavread(inputFile) w = get_window(window, M) (xmX, xpX) = stft.stftAnal(x, fs, w, N, H) kLow1 = 0 kLow2 = 0 while (True): kLow2 += 1 if( (kLow2 < N*(fLow2)/float(fs)) & (kLow2 > N*(fLow2)/float(fs) - 1.0 ) ): break kHigh1 = 0 while (True): kHigh1 += 1 if( (kHigh1 < N*(fHigh1)/float(fs)) & (kHigh1 > N*(fHigh1)/float(fs) - 1.0 ) ): break kHigh2 = 0 while (True): kHigh2 += 1 if( (kHigh2 < N*(fHigh2)/float(fs)) & (kHigh2 > N*(fHigh2)/float(fs) - 1.0 ) ): break nHops = int(xmX.shape[0]) out = np.zeros((nHops,2)) i = 0 while i < nHops: subxmX = xmX[i,:] subLowxmX = subxmX[kLow1+1:kLow2+1] subLowxmX = 10**(subLowxmX/20) eSignalLow = sum(subLowxmX**2) out[i,0] = 10.0*np.log10(eSignalLow) subHighxmX = subxmX[kHigh1+1:kHigh2+1] subHighxmX = 10**(subHighxmX/20) eSignalHigh = sum(subHighxmX**2) out[i,1] = 10.0*np.log10(eSignalHigh) i += 1 return out
def suppressFreqDFTmodel(x, fs, N): """ Inputs: x (numpy array) = input signal of length M (odd) fs (float) = sampling frequency (Hz) N (positive integer) = FFT size Outputs: The function should return a tuple (y, yfilt) y (numpy array) = Output of the dftSynth() without filtering (M samples long) yfilt (numpy array) = Output of the dftSynth() with filtering (M samples long) The first few lines of the code have been written for you, do not modify it. """ M = len(x) w = get_window('hamming', M) outputScaleFactor = sum(w) mx,px = dftAnal(x,w,N) mx2 = mx.copy() mx2[:np.floor(70*N/fs)+1] = -120 yone = dftSynth(mx,px,M)*sum(w) ytwo = dftSynth(mx2,px,M)*sum(w) return yone,ytwo
def tenFeatureSTFT(x): """ Give stft analysis of data ------------------------ Variables : ------------------------ x = the imput data, a np.array of amplitude data ranging from -1 to 1 ------------------------ Returns X = a ten dimention FFT analysis """ #print("This is the incomming data x:", x) if N is None:#number of samples in each window N = 2**11#2048 if hop is None: #this is the distance between FFT windows hop = N//1.5#default is 1.5 we want it large b/c we are limited to 10 data points if win is None: win = 'hann'#should try a blockier window window = get_window(win, N) xLen = len(x) #print("the shape of x : ",x) X = np.empty((10, N), dtype=np.complex)#create an array to dump data into #print("number of data points :", xLen) for i in range(9): chunk = window*x[i:i+N] myFFT = fft(chunk) X[i//hop,:] = myFFT X = X[:,:N//2 +1] X = X.transpose() return X
def _compute_mt_params(n_times, sfreq, bandwidth, low_bias, adaptive, interp_from=None, verbose=None): """Triage windowing and multitaper parameters.""" # Compute standardized half-bandwidth from scipy.signal import get_window if isinstance(bandwidth, str): logger.info(' Using standard spectrum estimation with "%s" window' % (bandwidth,)) window_fun = get_window(bandwidth, n_times)[np.newaxis] return window_fun, np.ones(1), False if bandwidth is not None: half_nbw = float(bandwidth) * n_times / (2. * sfreq) else: half_nbw = 4. if half_nbw < 0.5: raise ValueError( 'bandwidth value %s yields a normalized bandwidth of %s < 0.5, ' 'use a value of at least %s' % (bandwidth, half_nbw, sfreq / n_times)) # Compute DPSS windows n_tapers_max = int(2 * half_nbw) window_fun, eigvals = dpss_windows(n_times, half_nbw, n_tapers_max, low_bias=low_bias, interp_from=interp_from) logger.info(' Using multitaper spectrum estimation with %d DPSS ' 'windows' % len(eigvals)) if adaptive and len(eigvals) < 3: warn('Not adaptively combining the spectral estimators due to a ' 'low number of tapers (%s < 3).' % (len(eigvals),)) adaptive = False return window_fun, eigvals, adaptive
def spectrum(data, sampling, NFFT=256, overlap=0.5,\ window='hanning', detrender=mlab.detrend_linear,\ sides='onesided', scale='PSD'): numpoints = len(data) numoverlap = int(sampling * (1.0 - overlap)) if isinstance(window,str): window=window.lower() win = signal.get_window(window, NFFT) # calculate PSD with given parameters spec,freq = mlab.psd(data, NFFT=NFFT, Fs=sampling, noverlap=numoverlap,\ window=win, sides=sides, detrend=detrender) # rescale data to meet user's request scale = scale.lower() if scale == 'asd': spec = numpy.sqrt(spec) * numpy.sqrt(2 / (sampling*sum(win**2))) elif scale == 'psd': spec *= 2/(sampling*sum(win**2)) elif scale == 'as': spec = nump.sqrt(spec) * numpy.sqrt(2) / sum(win) elif scale == 'ps': spec = spec * 2 / (sum(win)**2) return freq, spec.flatten()
def _get_lims_cola(n_samp, n_times, sfreq, picks): from scipy.signal import get_window if n_samp > n_times: raise ValueError('Effective duration (%s) must be at most the ' 'duration of the raw instance (%s)' % (n_samp / sfreq, n_times / sfreq)) # Eventually this could be configurable window = 'hann' step = n_samp // 2 win = get_window(window, n_samp) n_overlap = n_samp - step if not check_cola(win, n_samp, n_overlap, tol=1e-2): raise RuntimeError('COLA not met') starts = np.arange(0, n_times - n_samp + 1, step) stops = starts + n_samp delta = n_times - stops[-1] stops[-1] = n_times pl = 's' if len(starts) != 1 else '' logger.info(' Processing %s data chunk%s of (at least) %0.1f sec with ' '%s windowing' % (len(starts), pl, n_samp / sfreq, window)) if delta > 0: logger.info(' The final %0.3f sec will be lumped into the final ' 'window' % (delta / sfreq,)) windows = list(np.tile(win[np.newaxis], (len(starts), 1))) # First and last windows are special, fix them windows[0][:n_overlap] = 1. windows[-1] = np.concatenate([windows[-1], np.ones(delta)]) windows[-1][n_overlap:] = 1. return starts, stops, windows
def extractMainLobe(window, M): """ Input: window (string): Window type to be used (Either rectangular (‘boxcar’), ‘hamming’ or ‘blackmanharris’) M (integer): length of the window to be used Output: The function should return a numpy array containing the main lobe of the magnitude spectrum of the window in decibels (dB). """ M = np.asarray(M, int) w = get_window(window, M) # get the window N = 8 * M W_N = fftshift(fft(w, N)) W_N = np.abs(W_N) W_N[W_N < eps] = eps idx_l = int(N / 2) lim_l = lim_u = False while lim_l is False: if W_N[idx_l-1] > W_N[idx_l] and W_N[idx_l+1] > W_N[idx_l]: lim_l = True print(idx_l) else: idx_l += -1 idx_u = int(N / 2)+1 while lim_u is False: if W_N[idx_u-1] > W_N[idx_u] and W_N[idx_u+1] > W_N[idx_u]: lim_u = True print(idx_u) else: idx_u += 1 W_N_dB = 10 * np.log10(W_N) # return(W_N_dB, idx_l, idx_u) return(W_N_dB[idx_l:idx_u + 1])
def stft(data,Fs=100): """ Input: 3 Axis Data Output: Power Representation of """ # Remove the DC Component of the function data = noDC(data) wlen = Fs * 10 segs = len(data) // wlen # integer divsion to return number of segments of data windsegs = [] numz = nextpow2(wlen) - wlen j = 0 win = [] for i in data: if j < wlen: # append the value from j=0 to j = (number of samples - 1) win.append(i) else: j = 0 for i in range(0, numz): # Zero padding the window win.append(0) windsegs.append(win) # Add that window to the segmented dataset win = [i] # Reset the window variable j += 1 b, a = signal.butter(4, [.01, .5], 'bandpass') dft=[] winlen = int(len(windsegs[0])) for seg in windsegs: seg = signal.lfilter(b, a, seg) wind = signal.get_window(('kaiser', 4.0), winlen) # Beta Parameter of Kaiser: 4. Num Samples in window: 9. snip = seg * wind nfft = nextpow2(wlen) A = np.fft.fft(snip, nfft) dft.append(A) return dft
def suppressFreqDFTmodel(x, fs, N): """ Inputs: x (numpy array) = input signal of length M (odd) fs (float) = sampling frequency (Hz) N (positive integer) = FFT size Outputs: The function should return a tuple (y, yfilt) y (numpy array) = Output of the dftSynth() without filtering (M samples long) yfilt (numpy array) = Output of the dftSynth() with filtering (M samples long) The first few lines of the code have been written for you, do not modify it. """ M = len(x) w = get_window("hamming", M) outputScaleFactor = sum(w) # get Magnitude and Phase Spectrum mX, pX = dftAnal(x, w, N) # generate output signal without filtering y = dftSynth(mX, pX, M) * outputScaleFactor # get bin number that is nearest to 70 Hz bin_number = int(70.0 / (fs / float(N))) + 1 # do the 'filtering' for i in range(bin_number + 1): mX[i] = -120 # generate the time signal after filtering yfilt = dftSynth(mX, pX, M) * outputScaleFactor return (y, yfilt)
def FIR(lowcutoff,highcutoff,fs): transwidthratio = 0.25 fnyq = fs/2 if highcutoff < lowcutoff : temp = highcutoff highcutoff = lowcutoff lowcutoff = temp print "cutoff frequecy is swapped. lowcutoff cannot be higher than highcutoff" if fnyq-highcutoff < lowcutoff: print "ERROR : (highcutoff - half of sampling frequency (Nyquist)) cannot be higher than lowcutoff" return 0 maxTWBArray = [lowcutoff, fnyq-highcutoff] maxDf = min(maxTWBArray) df = min([max([maxTWBArray[0] * transwidthratio, 2.0]),maxDf]) filtorder = 3.3 / (df / fs) # Hamming window filtorder = np.ceil(filtorder / 2) * 2 + 1 # Filter order must be even. +1 for centerpoint window #print filtorder #print np.array([range(int(filtorder))]) win = get_window('hamming',filtorder) cutoffarray = np.array([lowcutoff,highcutoff]) + [-df/2,df/2] # bandpass winsinc = firws(filtorder, cutoffarray / fnyq, win) return winsinc
def computeSNR(inputFile, window, M, N, H): """ Input: inputFile (string): wav file name including the path window (string): analysis window type (choice of rectangular, triangular, hanning, hamming, blackman, blackmanharris) M (integer): analysis window length (odd positive integer) N (integer): fft size (power of two, > M) H (integer): hop size for the stft computation Output: The function should return a python tuple of both the SNR values (SNR1, SNR2) SNR1 and SNR2 are floats. """ #read from the file FS, x = UF.wavread(inputFile) w = get_window(window, M) #do a stft computation y = stft.stft(x, FS, w, N, H) #compute SNR over complete signal diff = y - x energy_signal = (y**2).sum() energy_noise = (diff**2).sum() SNR1 = 10 * np.log10(energy_signal/energy_noise) #compute SNR over sliced signal energy_signal_sliced = (y[M:-M]**2).sum() energy_noise_sliced = (diff[M:-M]**2).sum() SNR2 = 10 * np.log10(energy_signal_sliced/energy_noise_sliced) return (SNR1, SNR2)
def test_window_external(self): x = np.zeros(16) x[0] = 1 x[8] = 1 f, p = csd(x, x, 10, 'hann', 8) win = signal.get_window('hann', 8) fe, pe = csd(x, x, 10, win, nperseg=None) assert_array_almost_equal_nulp(p, pe) assert_array_almost_equal_nulp(f, fe) assert_array_equal(fe.shape, (5,)) # because win length used as nperseg assert_array_equal(pe.shape, (5,)) assert_raises(ValueError, csd, x, x, 10, win, nperseg=256) # because nperseg != win.shape[-1] win_err = signal.get_window('hann', 32) assert_raises(ValueError, csd, x, x, 10, win_err, nperseg=None) # because win longer than signal
def segmentStableNotesRegions(inputFile='../../sounds/sax-phrase-short.wav', stdThsld=10, minNoteDur=0.1, winStable=3, window='hamming', M=1024, N=2048, H=256, f0et=5.0, t=-100, minf0=310, maxf0=650): """ Function to segment the stable note regions in an audio signal Input: inputFile (string): wav file including the path stdThsld (float): threshold for detecting stable regions in the f0 contour (in cents) minNoteDur (float): minimum allowed segment length (note duration) winStable (integer): number of samples used for computing standard deviation window (string): analysis window M (integer): window size used for computing f0 contour N (integer): FFT size used for computing f0 contour H (integer): Hop size used for computing f0 contour f0et (float): error threshold used for the f0 computation t (float): magnitude threshold in dB used in spectral peak picking minf0 (float): minimum fundamental frequency in Hz maxf0 (float): maximum fundamental frequency in Hz Output: segments (np.ndarray): Numpy array containing starting and ending frame indexes of every segment. """ fs, x = UF.wavread(inputFile) #reading inputFile w = get_window(window, M) #obtaining analysis window f0 = HM.f0Detection(x, fs, w, N, H, t, minf0, maxf0, f0et) #estimating F0 ### your code here # 1. convert f0 values from Hz to Cents (as described in pdf document) def hertzToCents(f): cents = 1200 * np.log2(f / 55.0) return cents f0inCents = hertzToCents(f0) indxs = np.where(f0inCents == -np.inf)[0] f0inCents[indxs] = -9999 # avoids -infs #2. create an array containing standard deviation of last winStable samples stdevs = np.array([]) for i in range(f0inCents.size): stdevs = np.append(stdevs, np.std(f0inCents[i - 2:i + 1])) #3. apply threshold on standard deviation values to find indexes of the stable points in melody lessThanThsldIndexs = np.where(stdevs < stdThsld)[0] #4. create segments of continuous stable points such that consecutive stable points belong to same segment stables = [] currentSegment = np.zeros(2) for i in lessThanThsldIndexs: if currentSegment[0] == 0: currentSegment[0] = i currentSegment[1] = i continue if i == (currentSegment[1] + 1): currentSegment[1] = i continue stables.append(currentSegment) # I use python array here currentSegment = np.zeros(2) #5. apply segment filtering, i.e. remove segments with are < minNoteDur in length filteredSegments = [] for s in stables: if ((s[1] - s[0]) * H / float(fs) > minNoteDur): filteredSegments.append(s) segments = np.array(filteredSegments) plotSpectogramF0Segments(x, fs, w, N, H, f0, segments) # Plot spectrogram and F0 if needed # return segments return segments
def smooth(): lengthSmoothed = length for i in range(0, 2): lengthSmoothed = signal.savgol_filter(x=lengthSmoothed, window_length=115, polyorder=2, deriv=0, mode='nearest') plt.plot(length) plt.plot(lengthSmoothed, color='r') plt.show() b = signal.get_window('triang', 1000, False) print(len(b)) lengthDeriv = signal.savgol_filter(length, 285, 4, 1) lengthDeriv = signal.savgol_filter(lengthDeriv, 255, 1, mode='nearest') flagus = 0 pnts = [] for i in range(len(lengthDeriv)): if lengthDeriv[i] < 0 and flagus == 0: flagus = 1 tmpList = [] tmpList.append(i) if lengthDeriv[i] > 0 and flagus == 1: flagus = 0 if lengthSmoothed[tmpList[0]] - lengthSmoothed[i] >= 0.02: tmpList.append(i) pnts.append(tmpList) for pnt in pnts: plt.plot(pnt[0], lengthDeriv[pnt[0]], 'ro') plt.plot(pnt[1], lengthDeriv[pnt[1]], 'ro', color = 'g') plt.plot(lengthDeriv) plt.show() for pnt in pnts: plt.plot(pnt[0], length[pnt[0]], 'ro') plt.plot(pnt[1], length[pnt[1]], 'ro', color = 'g') plt.plot(length) plt.show() ''' ### 03 -- B ### # Baseline correction # ''' def baseline_als(y, lam, p, niter=10): L = len(y) D = sparse.csc_matrix(np.diff(np.eye(L), 2)) w = np.ones(L) for i in xrange(niter): W = sparse.spdiags(w, 0, L, L) Z = W + lam * D.dot(D.transpose()) z = spsolve(Z, w*y) w = p * (y > z) + (1-p) * (y < z) return z lengthDecimated = lengthSmoothed for i in range(0, 11): lengthDecimated = signal.decimate(lengthDecimated, 2, zero_phase=True) baseline4correction = baseline_als(lengthDecimated, 10000, 0.01) print("base") #baseline4correction = signal.resample(baseline4correction, len(length)) #baseline4correction = signal.resample_poly(baseline4correction, len(lengthSmoothed), len(baseline4correction)) #baseline4correction = signal.savgol_filter(length, 121, 1) print("resamp") #length4peaks = lengthSmoothed - baseline4correction length4peaks = lengthDecimated - baseline4correction #print np.mean(length4peaks) #print np.median(length4peaks) #print np.max(length4peaks) #print np.min(length4peaks) plt.plot(lengthDecimated) plt.plot(baseline4correction, color='r') plt.plot(length4peaks, color='g') plt.show() minimal_length = np.mean(length4peaks)-np.median(length4peaks) minimal_length2 = (np.max(length4peaks)-np.min(length4peaks))/2 #print minimal_length, minimal_length2 points = pnts for i in range(len(points)): points[i][0] = points[i][0] + int((points[i][1] - points[i][0]) * 0.05) #points[i][1] = points[i][1] + int((points[i][1] - points[i][0]) * 0.01) for point in points: plt.plot(point[0], length[point[0]], 'ro') plt.plot(point[1], length[point[1]], 'ro', color = 'g') plt.plot(length) plt.show() finalTable = fit(points=points, current=current, length=length, voltage=voltage, conc_KCL=conc_KCL, gain=gain) return finalTable
#st.decimate(10) #st.decimate(10) st.rotate(method="->ZNE", inventory=inventory) for tr in st: if tr.stats.channel == 'LHN': tr.stats.channel = "LH1" if tr.stats.channel == "LHE": tr.stats.channel = "LH2" # decimate to 1 sample per 20 s st.decimate(5) st.decimate(2) st.decimate(2) for tr in st: win = signal.get_window(('kaiser', 2. * np.pi), tr.stats.npts) tr.data *= win for tr in st: tr.data = np.pad(tr.data, (int((length * 60 * 60 * 24 / 20. - tr.stats.npts) / 2.), int((length * 60 * 60 * 24 / 20. - tr.stats.npts) / 2.)), 'edge') NFFT = 2**(math.ceil(math.log(st[0].stats.npts, 2))) if pcorr: trP = st.select(channel='LDO')[0] if debug: if pcorr: print(trP)
def __init__(self, window_type='hann', table_length=4096): self.window = signal.get_window(window_type, table_length) self.table_length = table_length
def main(inputFile='../../sounds/sax-phrase-short.wav', window='blackman', M=601, N=1024, t=-100, minSineDur=0.1, nH=100, minf0=350, maxf0=700, f0et=5, harmDevSlope=0.01): """ Perform analysis/synthesis using the harmonic plus residual model inputFile: input sound file (monophonic with sampling rate of 44100) window: analysis window type (rectangular, hanning, hamming, blackman, blackmanharris) M: analysis window size; N: fft size (power of two, bigger or equal than M) t: magnitude threshold of spectral peaks; minSineDur: minimum duration of sinusoidal tracks nH: maximum number of harmonics; minf0: minimum fundamental frequency in sound maxf0: maximum fundamental frequency in sound; f0et: maximum error accepted in f0 detection algorithm harmDevSlope: allowed deviation of harmonic tracks, higher harmonics have higher allowed deviation """ # size of fft used in synthesis Ns = 512 # hop size (has to be 1/4 of Ns) H = 128 # read input sound (fs, x) = UF.wavread(inputFile) # compute analysis window w = get_window(window, M) # find harmonics and residual hfreq, hmag, hphase, xr = HPR.hprModelAnal(x, fs, w, N, H, t, minSineDur, nH, minf0, maxf0, f0et, harmDevSlope) # compute spectrogram of residual mXr, pXr = STFT.stftAnal(xr, fs, w, N, H) # synthesize hpr model y, yh = HPR.hprModelSynth(hfreq, hmag, hphase, xr, Ns, H, fs) # output sound file (monophonic with sampling rate of 44100) outputFileSines = 'output_sounds/' + os.path.basename(inputFile)[:-4] + '_hprModel_sines.wav' outputFileResidual = 'output_sounds/' + os.path.basename(inputFile)[:-4] + '_hprModel_residual.wav' outputFile = 'output_sounds/' + os.path.basename(inputFile)[:-4] + '_hprModel.wav' # write sounds files for harmonics, residual, and the sum UF.wavwrite(yh, fs, outputFileSines) UF.wavwrite(xr, fs, outputFileResidual) UF.wavwrite(y, fs, outputFile) # create figure to plot plt.figure(figsize=(12, 9)) # frequency range to plot maxplotfreq = 5000.0 # plot the input sound plt.subplot(3,1,1) plt.plot(np.arange(x.size)/float(fs), x) plt.axis([0, x.size/float(fs), min(x), max(x)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('input sound: x') # plot the magnitude spectrogram of residual plt.subplot(3,1,2) maxplotbin = int(N*maxplotfreq/fs) numFrames = int(mXr[:,0].size) frmTime = H*np.arange(numFrames)/float(fs) binFreq = np.arange(maxplotbin+1)*float(fs)/N plt.pcolormesh(frmTime, binFreq, np.transpose(mXr[:,:maxplotbin+1])) plt.autoscale(tight=True) # plot harmonic frequencies on residual spectrogram if (hfreq.shape[1] > 0): harms = hfreq*np.less(hfreq,maxplotfreq) harms[harms==0] = np.nan numFrames = int(harms[:,0].size) frmTime = H*np.arange(numFrames)/float(fs) plt.plot(frmTime, harms, color='k', ms=3, alpha=1) plt.xlabel('time(s)') plt.ylabel('frequency(Hz)') plt.autoscale(tight=True) plt.title('harmonics + residual spectrogram') # plot the output sound plt.subplot(3,1,3) plt.plot(np.arange(y.size)/float(fs), y) plt.axis([0, y.size/float(fs), min(y), max(y)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('output sound: y') plt.tight_layout() plt.show()
def cmov_window(data, span, window_type): """ Applies a centered moving window of type ``window_type`` and size ``span`` on the data. Parameters ---------- %(data)s %(span)s window_type : {string/tuple/float} Window type (see Notes) Returns ------- A (subclass of) MaskedArray. Noting ``k=span//2``, the ``k`` first and ``k`` last data are always masked. If ``data`` has a missing value at position ``i``, then the result has missing values in the interval ``[i-k:i+k+1]``. Notes ----- The recognized window types are: * ``boxcar`` * ``triang`` * ``blackman`` * ``hamming`` * ``bartlett`` * ``parzen`` * ``bohman`` * ``blackmanharris`` * ``nuttall`` * ``barthann`` * ``kaiser`` (needs beta) * ``gaussian`` (needs std) * ``general_gaussian`` (needs power, width) * ``slepian`` (needs width). If the window requires special parameters, the ``window_type`` argument should be a tuple with the first argument the string name of the window, and the next arguments the needed parameters. If ``window_type`` is a floating point number, it is interpreted as the beta parameter of the ``kaiser`` window. Warnings -------- Only ``boxcar`` has been thoroughly tested so far... """ % _doc_parameters from scipy.signal import convolve, get_window data = marray(data, copy=True, subok=True) if data._mask is nomask: data._mask = np.zeros(data.shape, bool_) window = get_window(window_type, span, fftbins=False) (n, k) = (len(data), span // 2) # if data.ndim == 1: data._data.flat = convolve(data._data, window)[k:n + k] / float(span) data._mask[:] = ((convolve(getmaskarray(data), window) > 0)[k:n + k]) elif data.ndim == 2: for i in range(data.shape[-1]): _data = data._data[:, i] _data.flat = convolve(_data, window)[k:n + k] / float(span) data._mask[:, i] = (convolve(data._mask[:, i], window) > 0)[k:n + k] else: raise ValueError, "Data should be at most 2D" data._mask[:k] = data._mask[-k:] = True return data
def test_gr_preprocessing(self): yaml_file = '../../python/tests/qa_darkflow/yolo_model.yml' pkl_file = '~/Dropbox/Programming/deep_learning/test_data/qa_darkflow/data_wifi_0_0_0_0_0.pkl' # FIXME freader = pkl_sig_format.WaveformPklReader( os.path.expanduser(pkl_file)) x = freader.read_section() stage_data = freader.data() spec_metadata = sda.get_stage_derived_parameter( stage_data, 'subsection_spectrogram_img_metadata') # convert x to spectrogram Sxx = spec_metadata[0].image_data(x) Sxx_img = np.zeros((104, 104), np.float32) Sxx_img[0:Sxx.shape[0], 0:Sxx.shape[1]] = Sxx Sxx_bytes = np.uint8(Sxx_img * 255) section_bounds = spec_metadata[0].section_bounds xsection = x[ section_bounds[0]::] # let the block head finish the section xtuple = tuple([complex(i) for i in xsection]) # create blocks vector_source = blocks.vector_source_c(xtuple, True) head = blocks.head(gr.sizeof_gr_complex, 64 * 104 * 10) toparallel = blocks.stream_to_vector(gr.sizeof_gr_complex, 64) # fftblock = fft.fft_vcc(64,True,fft.window.rectangular(64),True) fftblock = fft.fft_vcc(64, True, signal.get_window(('tukey', 0.25), 64), True) mag2 = blocks.complex_to_mag_squared(64) # avg = blocks.moving_average_ff(104,1.0/104,104) classifier = darkflow_ckpt_classifier_c(yaml_file, 64, True, 10) dst1 = blocks.vector_sink_c() dst2 = blocks.vector_sink_c(64) dst3 = blocks.vector_sink_f(64) # make flowgraph self.tb.connect(vector_source, head) self.tb.connect(head, toparallel) self.tb.connect(toparallel, fftblock) self.tb.connect(fftblock, mag2) self.tb.connect(mag2, classifier) self.tb.connect(head, dst1) self.tb.connect(fftblock, dst2) self.tb.connect(mag2, dst3) self.tb.run() xout = np.array(dst1.data(), np.complex64) xfft = np.array(dst2.data(), np.complex64) xmag2 = np.array(dst3.data(), np.float32) im = classifier.imgcv[:, :, 0] # check output data correctness self.assertEqual(xout.size, 104 * 64 * 10) self.assertComplexTuplesAlmostEqual(xsection[0:len(xout)], xout) # check all the steps for spectrogram creation are correct sxx_xout = spectrogram.compute_spectrogram(xout, 64) # sxx_xout = spectrogram.make_spectrogram_image(xout,{'fftsize':64,'cancel_DC_offset':True}) sxx_xout_avg = spectrogram.time_average_Sxx(sxx_xout, 10, 10) sxx_xout_avg = spectrogram.normalize_spectrogram(sxx_xout_avg) sxx_xout_avg = spectrogram.cancel_spectrogram_DCoffset(sxx_xout_avg) sxx_xout_bytes = np.zeros((104, 104), np.uint8) sxx_xout_bytes[:, 0:64] = np.uint8(sxx_xout_avg * 255) self.assertAlmostEqual(np.mean(np.abs(sxx_xout_bytes - Sxx_bytes)**2), 0) self.assertAlmostEqual(np.mean(np.abs(sxx_xout_bytes - im)**2), 0) sxx_xfft = np.abs(xfft.reshape((104 * 10, 64)))**2 sxx_xfft_avg = spectrogram.time_average_Sxx(sxx_xfft, 10, 10) sxx_xfft_avg = spectrogram.normalize_spectrogram(sxx_xfft_avg) sxx_xfft_avg = spectrogram.cancel_spectrogram_DCoffset(sxx_xfft_avg) sxx_xfft_bytes = np.zeros((104, 104), np.uint8) sxx_xfft_bytes[:, 0:64] = np.uint8(sxx_xfft_avg * 255) self.assertAlmostEqual(np.mean(np.abs(sxx_xfft_bytes - Sxx_bytes)**2), 0) self.assertAlmostEqual(np.mean(np.abs(sxx_xfft_bytes - im)**2), 0) # xoutwin = xout[0:64]*signal.get_window(('tukey',0.25),64) # xfft_debug = np.fft.fftshift(np.fft.fft(xoutwin)) print 'detected boxes:', classifier.last_result self.assertEqual(len(classifier.last_result), 4) for b in classifier.last_result: self.assertEqual(b['label'], 'wifi')
import numpy as np import matplotlib.pyplot as plt import sys from scipy.signal import get_window sys.path.append('../../software/models/') import dftModel as DFT fs = 44100 f = 5000.0 M = 101 x = np.cos(2 * np.pi * f * np.arange(M) / float(fs)) N = 512 w = get_window('blackmanharris', M) mX, pX = DFT.dftAnal(x, w, N) #dftAnal: analyze the x using window with N FFT size plt.plot(np.arange(0, fs / 2 + 1, fs / float(N)), mX - max(mX)) plt.show()
from koe.colourmap import cm_blue, cm_green, cm_red from koe.management.commands import utils from koe.management.commands.utils import get_syllable_end_time, wav_2_mono, import_pcm from koe.models import AudioFile, Segment, AudioTrack, Database, DatabaseAssignment, DatabasePermission from koe.utils import spect_fft_path, spect_mask_path, audio_path, wav_path from root.models import User from root.utils import ensure_parent_folder_exists COLOURS = [[69, 204, 255], [73, 232, 62], [255, 212, 50], [232, 75, 48], [170, 194, 102]] FF_COLOUR = [0, 0, 0] AXIS_COLOUR = [127, 127, 127] window_size = 256 noverlap = 256 * 0.75 window = signal.get_window('hann', 256) low_bound = 800 scale = window.sum() roi_max_width = 1200 roi_pad_width = 10 global_min_spect_pixel = -9.421019554138184 global_max_spect_pixel = 2.8522987365722656 global_spect_pixel_range = global_max_spect_pixel - global_min_spect_pixel interval64 = global_spect_pixel_range / 63 name_regex = re.compile('(\d\d)(\d\d)(\d\d)_(.*) (\d+)(.*)wav') note_attr = settings.ATTRS.audio_file.note def import_song_info(conn, user):
def rolling_window(arg, window=None, win_type=None, min_periods=None, freq=None, center=False, mean=True, axis=0, how=None, **kwargs): """ Applies a moving window of type ``window_type`` and size ``window`` on the data. Parameters ---------- arg : Series, DataFrame window : int or ndarray Weighting window specification. If the window is an integer, then it is treated as the window length and win_type is required win_type : str, default None Window type (see Notes) min_periods : int, default None Minimum number of observations in window required to have a value (otherwise result is NA). freq : string or DateOffset object, optional (default None) Frequency to conform the data to before computing the statistic. Specified as a frequency string or DateOffset object. center : boolean, default False Whether the label should correspond with center of window mean : boolean, default True If True computes weighted mean, else weighted sum axis : {0, 1}, default 0 how : string, default 'mean' Method for down- or re-sampling Returns ------- y : type of input argument Notes ----- The recognized window types are: * ``boxcar`` * ``triang`` * ``blackman`` * ``hamming`` * ``bartlett`` * ``parzen`` * ``bohman`` * ``blackmanharris`` * ``nuttall`` * ``barthann`` * ``kaiser`` (needs beta) * ``gaussian`` (needs std) * ``general_gaussian`` (needs power, width) * ``slepian`` (needs width). By default, the result is set to the right edge of the window. This can be changed to the center of the window by setting ``center=True``. The `freq` keyword is used to conform time series data to a specified frequency by resampling the data. This is done with the default parameters of :meth:`~pandas.Series.resample` (i.e. using the `mean`). """ if isinstance(window, (list, tuple, np.ndarray)): if win_type is not None: raise ValueError(('Do not specify window type if using custom ' 'weights')) window = pdcom._asarray_tuplesafe(window).astype(float) elif pdcom.is_integer(window): # window size if win_type is None: raise ValueError('Must specify window type') try: import scipy.signal as sig except ImportError: raise ImportError('Please install scipy to generate window weight') win_type = _validate_win_type(win_type, kwargs) # may pop from kwargs window = sig.get_window(win_type, window).astype(float) else: raise ValueError('Invalid window %s' % str(window)) minp = _use_window(min_periods, len(window)) arg = _conv_timerule(arg, freq, how) return_hook, values = _process_data_structure(arg) if values.size == 0: result = values.copy() else: offset = int((len(window) - 1) / 2.) if center else 0 additional_nans = np.array([np.NaN] * offset) f = lambda x: algos.roll_window(np.concatenate((x, additional_nans)) if center else x, window, minp, avg=mean) result = np.apply_along_axis(f, axis, values) if center: result = _center_window(result, len(window), axis) return return_hook(result)
def rolling_window(arg, window=None, win_type=None, min_periods=None, freq=None, center=False, mean=True, time_rule=None, axis=0, **kwargs): """ Applies a moving window of type ``window_type`` and size ``window`` on the data. Parameters ---------- arg : Series, DataFrame window : int or ndarray Weighting window specification. If the window is an integer, then it is treated as the window length and win_type is required win_type : str, default None Window type (see Notes) min_periods : int Minimum number of observations in window required to have a value. freq : None or string alias / date offset object, default=None Frequency to conform to before computing statistic center : boolean, default False Whether the label should correspond with center of window mean : boolean, default True If True computes weighted mean, else weighted sum Returns ------- y : type of input argument Notes ----- The recognized window types are: * ``boxcar`` * ``triang`` * ``blackman`` * ``hamming`` * ``bartlett`` * ``parzen`` * ``bohman`` * ``blackmanharris`` * ``nuttall`` * ``barthann`` * ``kaiser`` (needs beta) * ``gaussian`` (needs std) * ``general_gaussian`` (needs power, width) * ``slepian`` (needs width). """ if isinstance(window, (list, tuple, np.ndarray)): if win_type is not None: raise ValueError(('Do not specify window type if using custom ' 'weights')) window = com._asarray_tuplesafe(window).astype(float) elif com.is_integer(window): #window size if win_type is None: raise ValueError('Must specify window type') try: import scipy.signal as sig except ImportError: raise ImportError('Please install scipy to generate window weight') win_type = _validate_win_type(win_type, kwargs) # may pop from kwargs window = sig.get_window(win_type, window).astype(float) else: raise ValueError('Invalid window %s' % str(window)) minp = _use_window(min_periods, len(window)) arg = _conv_timerule(arg, freq, time_rule) return_hook, values = _process_data_structure(arg) f = lambda x: algos.roll_window(x, window, minp, avg=mean) result = np.apply_along_axis(f, axis, values) rs = return_hook(result) if center: rs = _center_window(rs, len(window), axis) return rs
def extractHarmSpec(inputFile='../../sounds/bendir.wav', window='hamming', M=2001, N=2048, t=-80, minSineDur=0.02, maxnSines=150, freqDevOffset=10, freqDevSlope=0.001): """ Perform analysis/synthesis using the sinusoidal model inputFile: input sound file (monophonic with sampling rate of 44100) window: analysis window type (rectangular, hanning, hamming, blackman, blackmanharris) M: analysis window size; N: fft size (power of two, bigger or equal than M) t: magnitude threshold of spectral peaks; 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 """ # size of fft used in synthesis Ns = 512 # hop size (has to be 1/4 of Ns) H = 128 # read input sound fs, x = UF.wavread(inputFile) # compute analysis window w = get_window(window, M) # analyze the sound with the sinusoidal model tfreq, tmag, tphase = SM.sineModelAnal(x, fs, w, N, H, t, maxnSines, minSineDur, freqDevOffset, freqDevSlope) # synthesize the output sound from the sinusoidal representation y = SM.sineModelSynth(tfreq, tmag, tphase, Ns, H, fs) # output sound file name outputFile = 'output_sounds/' + os.path.basename(inputFile)[:-4] + '_sineModel.wav' # write the synthesized sound obtained from the sinusoidal synthesis UF.wavwrite(y, fs, outputFile) # create figure to show plots plt.figure(figsize=(12, 9)) # frequency range to plot maxplotfreq = 5000.0 # plot the input sound plt.subplot(3,1,1) plt.plot(np.arange(x.size)/float(fs), x) plt.axis([0, x.size/float(fs), min(x), max(x)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('input sound: x') # plot the sinusoidal frequencies plt.subplot(3,1,2) if (tfreq.shape[1] > 0): numFrames = tfreq.shape[0] frmTime = H*np.arange(numFrames)/float(fs) tfreq[tfreq<=0] = np.nan plt.plot(frmTime, tfreq) plt.axis([0, x.size/float(fs), 0, maxplotfreq]) plt.title('frequencies of sinusoidal tracks') # plot the output sound plt.subplot(3,1,3) plt.plot(np.arange(y.size)/float(fs), y) plt.axis([0, y.size/float(fs), min(y), max(y)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('output sound: y') plt.tight_layout() plt.show()
voltages = data[1] #%% plt.figure() for ii in range(4): plt.subplot(4, 1, ii + 1) plt.plot(voltages[:, ii, :, 0].squeeze(), 'k', alpha=0.1) #%% select_state = 2 NFFT = 512 plt.figure() F, T, SG = sig.spectrogram(voltages[:, select_state, 2, 0].squeeze().T, nperseg=NFFT, noverlap=0.5 * NFFT, window=sig.get_window('blackmanharris', NFFT), fs=16) plt.pcolormesh(T, F, 10 * np.log10(SG), rasterized=True) #%% # NetworkX stuff def nx_conn(white_matter): G = nx.from_numpy_matrix(white_matter.weights) plt.figure() nx.draw_random(G) plt.xlim((-0.2, 0.2))
def _fft(x, s_freq, detrend='linear', taper=None, output='spectraldensity', sides='one', scaling='power', halfbandwidth=4, NW=None, n_fft=None): """ Core function taking care of computing the power spectrum / power spectral density or the complex representation. Parameters ---------- x : 1d or 2d numpy array input data (fft will be computed on the last dimension) s_freq : int sampling frequency detrend : str None (no detrending), 'constant' (remove mean), 'linear' (remove linear trend) output : str 'spectraldensity' (= 'psd' in scipy) or 'complex' (for complex output) sides : str 'one' or 'two', where 'two' implies negative frequencies scaling : str 'power' (= 'density' in scipy, units: uV ** 2 / Hz), 'energy' (= 'spectrum' in scipy, units: uV ** 2), 'fieldtrip', 'chronux' taper : str Taper to use, commonly used tapers are 'boxcar', 'hann', 'dpss' (see below) halfbandwidth : int (only if taper='dpss') Half bandwidth (in Hz), frequency smoothing will be from +halfbandwidth to -halfbandwidth NW : int (only if taper='dpss') Normalized half bandwidth (NW = halfbandwidth * dur). Number of DPSS tapers is 2 * NW - 1. If specified, NW takes precedence over halfbandwidth n_fft: int Length of FFT, in samples. If less than input axis, input is cropped. If longer than input axis, input is padded with zeros. If None, FFT length set to axis length. Returns ------- freqs : 1d ndarray vector with frequencies at which the PSD / ESD / complex fourier was computed result: ndarray PSD / ESD / complex fourier. It has the same number of dim as the input. Frequency transform is computed on the last dimension. If output='complex', there is one additional dimension with the taper(s). Notes ----- The nomenclature of the frequency-domain analysis is not very consistent across packages / toolboxes. The convention used here is based on `wikipedia`_ So, you can have the spectral density (called sometimes power spectrum) or a complex output. Conceptually quite different but they can both be computed using the fft algorithm, so we do both here. Regarding the spectral density, you can have the power spectral density (PSD) or the energy spectral density (ESD). PSD should be used for stationary signals (gamma activity), while ESD should be used for signals that have a clear beginning and end (spindles). ESD gives the energy over the whole duration of the input window, while PSD is normalized by the window length. Parseval's theorem says that the energy of the signal in the time-domain must be equal to the energy in the frequency domain. All the tapers are correct to comply with this theorem (see tests/test_trans_frequency.py for all the examples). Note that packages such as 'FieldTrip' and 'Chronux' do not usually respect this convention (and use some ad-hoc convention). You can use the scaling of these packages to compare the results from those matlab toolboxes, but note that the results probably don't satisty Parseval's theorem. Note that scipy.signal is not consistent with these names, but the formulas are the same. Also, scipy (v1.1 at least) does not handle dpss. Finally, the complex output has an additional dimension (taper), for each taper (even for the boxcar or hann taper). This is useful for multitaper analysis (DPSS), where it doesn't make sense to average complex results. .. _wikipedia: https://en.wikipedia.org/wiki/Spectral_density TODO ---- Scipy v1.1 can generate dpss tapers. Once scipy v1.1 is available, use that instead of the extern folder. """ if output == 'complex' and sides == 'one': print('complex always returns both sides') sides = 'two' axis = x.ndim - 1 n_smp = x.shape[axis] if n_fft is None: n_fft = n_smp if sides == 'one': freqs = np_fft.rfftfreq(n_fft, 1 / s_freq) elif sides == 'two': freqs = fftpack.fftfreq(n_fft, 1 / s_freq) if taper is None: taper = 'boxcar' if taper == 'dpss': if NW is None: NW = halfbandwidth * n_smp / s_freq tapers, eig = dpss_windows(n_smp, NW, 2 * NW - 1) if scaling == 'chronux': tapers *= sqrt(s_freq) else: if taper == 'hann': tapers = windows.hann(n_smp, sym=False)[None, :] else: # TODO: it'd be nice to use sym=False if possible, but the difference is very small tapers = get_window(taper, n_smp)[None, :] if scaling == 'energy': rms = sqrt(mean(tapers**2)) tapers /= rms * sqrt(n_smp) elif scaling != 'chronux': # idk how chronux treats other windows apart from dpss tapers /= norm(tapers) if detrend is not None: x = detrend_func(x, axis=axis, type=detrend) tapered = tapers * x[..., None, :] if sides == 'one': result = np_fft.rfft(tapered, n=n_fft) elif sides == 'two': result = fftpack.fft(tapered, n=n_fft) if scaling == 'chronux': result /= s_freq elif scaling == 'fieldtrip': result *= sqrt(2 / n_smp) if output == 'spectraldensity': result = (result.conj() * result) elif output == 'csd': result = (result[None, 0, ...].conj() * result[None, 1, ...]) if (sides == 'one' and output in ('spectraldensity', 'csd') and scaling != 'chronux'): if n_fft % 2: result[..., 1:] *= 2 else: # Last point is unpaired Nyquist freq point, don't double result[..., 1:-1] *= 2 if scaling == 'power': scale = 1.0 / s_freq elif scaling == 'energy': scale = 1.0 / n_smp else: scale = 1 if output == 'complex' and scaling in ('power', 'energy'): scale = sqrt(scale) result *= scale if scaling == 'fieldtrip' and output in ('spectraldensity', 'csd'): # fieldtrip uses only one side result /= 2 if output in ('spectraldensity', 'csd'): if output == 'spectraldensity': result = result.real result = mean(result, axis=axis) elif output == 'complex': # dpss should be last dimension in complex, no mean result = swapaxes(result, axis, -1) return freqs, result
raise ValueError("Requires NFFT to be greater than noverlap") except ValueError, err_msg: raise ValueError(err_msg) return if x.shape[0] < NFFT: res_x = pd.DataFrame(0 * np.arange(0, NFFT)) pd_x = x.combine_first(res_x) x = pd_x.fillna(0) if y.shape[0] < NFFT: res_y = pd.DataFrame(0 * np.arange(0, NFFT)) pd_y = y.combine_first(res_y) y = pd_y.fillna(0) window = signal.get_window('hanning', NFFT) step = NFFT - noverlap num_wind = np.arange(0, x.shape[0] + 1 - NFFT, step) NFreqs = NFFT // 2 + 1 Pxy_re = np.zeros((NFreqs, len(num_wind))) Pxy_im = np.zeros((NFreqs, len(num_wind))) Pxy = np.vectorize(complex)(Pxy_re, Pxy_im) count = 0 pos = 0 while ((pos + NFFT) < x.shape[0]): end = pos + NFFT - 1 if detrend == 0:
def window(n, /, wintype='boxcar'): """ Retrieve the `~scipy.signal.get_window` weighting function window. Parameters ---------- n : int The window length. wintype : str or (str, float, ...) tuple The window name or ``(name, param1, ...)`` tuple containing the name and the required parameter(s). normalize : bool, optional Whether to divide the resulting coefficients by their sum. Returns ------- win : array-like The window coefficients. """ if wintype == 'welch': raise ValueError('Welch window needs 2-tuple of (name, beta).') elif wintype == 'kaiser': raise ValueError('Kaiser window needs 2-tuple of (name, beta).') elif wintype == 'gaussian': raise ValueError('Gaussian window needs 2-tuple of (name, stdev).') else: w = signal.get_window(wintype, n) # if normalize: # w /= np.sum(w) return w
import numpy as np from scipy.signal import get_window from scipy.fftpack import fft import math import matplotlib.pyplot as plt # window size, change if you need a different size window. # window size means the number of samples in the window M = 63 #change here to 'hamming or blackman or blackmanharris or hanning to get those windows' window = get_window('hanning', M) hM1 = int(math.floor((M+1)/2)) # 63+1 / 2 = 32 hM2 = int(math.floor(M/2)) # 63 / 2 = 31 N = 512 #number of samples to take fft should be power of 2 hN = N/2 #256 fftbuffer = np.zeros(N) #make a array of size N with zeros filled fftbuffer[:hM1] = window[hM2:] #put second part of window samples as first part of fft buffer fftbuffer[N-hM2:] = window[:hM2] #put first part of window samples at last in fft buffer X = fft(fftbuffer) #calculate the fft of signal which is in fft buffer absX = abs(X) # calculating the amplitude of bins. # if values are lower than that of minimum float value that python float can represent, make them # to minum value of python float absX[absX<np.finfo(float).eps] = np.finfo(float).eps mX = 20*np.log10(absX) # calculate the amplitude as decibels pX = np.angle(X)
def extractHarmSpec(inputFile='../../sounds/piano.wav', window='blackman', M=511, N=1024, time=.2): """ inputFile: input sound file (monophonic with sampling rate of 44100) window: analysis window type (choice of rectangular, hanning, hamming, blackman, blackmanharris) M: analysis window size (odd integer value) N: fft size (power of two, bigger or equal than than M) time: time to start analysis (in seconds) """ # read input sound (monophonic with sampling rate of 44100) fs, x = UF.wavread(inputFile) # compute analysis window w = get_window(window, M) # get a fragment of the input sound of size M sample = int(time * fs) if (sample + M >= x.size or sample < 0): # raise error if time outside of sound raise ValueError("Time outside sound boundaries") x1 = x[sample:sample + M] # compute the dft of the sound fragment mX, pX = DFT.dftAnal(x1, w, N) # compute the inverse dft of the spectrum y = DFT.dftSynth(mX, pX, w.size) * sum(w) # create figure plt.figure(figsize=(12, 9)) # plot the sound fragment plt.subplot(4, 1, 1) plt.plot(time + np.arange(M) / float(fs), x1) plt.axis([time, time + M / float(fs), min(x1), max(x1)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('input sound: x') # plot the magnitude spectrum plt.subplot(4, 1, 2) plt.plot(float(fs) * np.arange(mX.size) / float(N), mX, 'r') plt.axis([0, fs / 2.0, min(mX), max(mX)]) plt.title('magnitude spectrum: mX') plt.ylabel('amplitude (dB)') plt.xlabel('frequency (Hz)') # plot the phase spectrum plt.subplot(4, 1, 3) plt.plot(float(fs) * np.arange(pX.size) / float(N), pX, 'c') plt.axis([0, fs / 2.0, min(pX), max(pX)]) plt.title('phase spectrum: pX') plt.ylabel('phase (radians)') plt.xlabel('frequency (Hz)') # plot the sound resulting from the inverse dft plt.subplot(4, 1, 4) plt.plot(time + np.arange(M) / float(fs), y) plt.axis([time, time + M / float(fs), min(y), max(y)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('output sound: y') plt.tight_layout() plt.show()
eps = np.finfo(float).eps inputFile = '../../sounds/sax-phrase-short.wav' N = 1024 M = 512 H = 64 window = 'hamming' # calculate the signal energy if (M % 2): M = M - 1 (fs, x) = UF.wavread(inputFile) Esignal = sum(np.power(x, 2)) # do the stft convert w = get_window(window, M, True) y = STFT.stft(x, w, N, H) y2 = y[M:-M] # calculate the output signal engery noise = abs(x - y) Enoise = sum(np.power(noise, 2)) x2 = x[M:-M] noise2 = abs(x2 - y2) Enoise2 = sum(np.power(noise2, 2)) # calculate the SNR SNR1 = 10 * np.log10(Esignal / Enoise) SNR2 = 10 * np.log10(Esignal / Enoise2)
def time_domain_window(time_domain_strain, window_type=None): if window_type != None: window = get_window(window_type, time_domain_strain.size) time_domain_strain = time_domain_strain * window return time_domain_strain
def main(inputFile = '../../sounds/piano.wav', window = 'hamming', M = 1024, N = 1024, H = 512): """ analysis/synthesis using the STFT inputFile: input sound file (monophonic with sampling rate of 44100) window: analysis window type (choice of rectangular, hanning, hamming, blackman, blackmanharris) M: analysis window size N: fft size (power of two, bigger or equal than M) H: hop size (at least 1/2 of analysis window size to have good overlap-add) """ # read input sound (monophonic with sampling rate of 44100) fs, x = UF.wavread(inputFile) # compute analysis window w = get_window(window, M, fftbins=True) # compute the magnitude and phase spectrogram mX, pX = STFT.stftAnal(x, w, N, H) # perform the inverse stft y = STFT.stftSynth(mX, pX, M, H) # output sound file (monophonic with sampling rate of 44100) outputFile = 'output_sounds/' + os.path.basename(inputFile)[:-4] + '_stft.wav' # write the sound resulting from the inverse stft UF.wavwrite(y, fs, outputFile) # create figure to plot plt.figure(figsize=(9, 6)) # frequency range to plot maxplotfreq = 5000.0 # plot the input sound plt.subplot(4,1,1) plt.plot(np.arange(x.size)/float(fs), x) plt.axis([0, x.size/float(fs), min(x), max(x)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('input sound: x') # plot magnitude spectrogram plt.subplot(4,1,2) numFrames = int(mX[:,0].size) frmTime = H*np.arange(numFrames)/float(fs) binFreq = fs*np.arange(N*maxplotfreq/fs)/N plt.pcolormesh(frmTime, binFreq, np.transpose(mX[:,:int(N*maxplotfreq/fs+1)])) plt.xlabel('time (sec)') plt.ylabel('frequency (Hz)') plt.title('magnitude spectrogram') plt.autoscale(tight=True) # plot the phase spectrogram plt.subplot(4,1,3) numFrames = int(pX[:,0].size) frmTime = H*np.arange(numFrames)/float(fs) binFreq = fs*np.arange(N*maxplotfreq/fs)/N plt.pcolormesh(frmTime, binFreq, np.transpose(np.diff(pX[:,:int(N*maxplotfreq/fs+1)],axis=1))) plt.xlabel('time (sec)') plt.ylabel('frequency (Hz)') plt.title('phase spectrogram (derivative)') plt.autoscale(tight=True) # plot the output sound plt.subplot(4,1,4) plt.plot(np.arange(y.size)/float(fs), y) plt.axis([0, y.size/float(fs), min(y), max(y)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('output sound: y') plt.tight_layout() plt.ion() plt.show()
window2 = 'blackman' M2 = 901 N2 = 1024 t2 = -100 minSineDur2 = 0.05 minf02 = 250 maxf02 = 500 f0et2 = 10 harmDevSlope2 = 0.01 Ns = 512 H = 128 (fs1, x1) = UF.wavread(inputFile1) (fs2, x2) = UF.wavread(inputFile2) w1 = get_window(window1, M1) w2 = get_window(window2, M2) hfreq1, hmag1, hphase1, stocEnv1 = HPS.hpsModelAnal(x1, fs1, w1, N1, H, t1, nH, minf01, maxf01, f0et1, harmDevSlope1, minSineDur1, Ns, stocf) hfreq2, hmag2, hphase2, stocEnv2 = HPS.hpsModelAnal(x2, fs2, w2, N2, H, t2, nH, minf02, maxf02, f0et2, harmDevSlope2, minSineDur2, Ns, stocf) hfreqIntp = np.array([0, .5, 1, .5]) hmagIntp = np.array([0, .5, 1, .5]) stocIntp = np.array([0, .5, 1, .5]) yhfreq, yhmag, ystocEnv = HPST.hpsMorph(hfreq1, hmag1, stocEnv1, hfreq2, hmag2, stocEnv2, hfreqIntp, hmagIntp,
def compare_cwt_example(x, t, fs=128, sLog=False): t1 = t t0 = 0 #print('Gauss') f0 = np.linspace(0.1, 40, 100) Q = np.linspace(0.1, 5, 100) #[:,None] XW1, S1 = ScalogramCWT(x, t, wType='Gauss', fs=fs, PlotW=False, PlotPSD=False, fftMeth=True, f0=f0, Q=Q) #print('Morlet') sig = np.linspace(0.1, 10, 100) f = np.linspace(-10, 10, 2 * len(x) - 1) XW2, S2 = ScalogramCWT(x, t, wType='Morlet', fs=fs, PlotW=False, PlotPSD=False, fftMeth=True, sig=sig, f=f) #print('Gabor') f0 = np.linspace(1, 40, 100) a = 0.5 XW3, S3 = ScalogramCWT(x, t, wType='Gabor', fs=fs, PlotW=False, PlotPSD=False, fftMeth=True, f0=f0, a=a) #print('Poisson') n = np.arange(100) XW4, S4 = ScalogramCWT(x, t, wType='Poisson', fs=fs, PlotW=False, PlotPSD=False, fftMeth=True, n=n, method=3) #print('cMaxican') f0 = np.linspace(0, 40, 80) #[:,None] a = 0.005 XW5, S5 = ScalogramCWT(x, t, wType='cMaxican', fs=fs, PlotW=False, PlotPSD=False, fftMeth=True, f0=f0, a=a) #print('cShannon') f0 = np.linspace(0, 40, 40) #[:,None] fw = 5 XW6, S6 = ScalogramCWT(x, t, wType='cShannon', fs=128, PlotW=False, PlotPSD=False, fftMeth=True, f0=f0, fw=fw) N = 32 win = signal.get_window('hann', N) fx, tx, Sxx = signal.spectrogram(x, fs=fs, nfft=2 * N, nperseg=N, noverlap=N // 2, window=win) plt.figure(figsize=(15, 15)) plt.subplot(811) #print(x.shape,t.shape) plt.plot(t, x) plt.xlim([t[0], t[-1]]) plt.grid() plt.subplot(812) plt.imshow(abs(XW1), aspect='auto', origin='lower', cmap=plt.cm.jet, extent=[t[0], t[-1], S1[0], S1[-1]], interpolation='sinc') plt.ylabel('Gauss') plt.subplot(813) plt.imshow(abs(XW2), aspect='auto', origin='lower', cmap=plt.cm.jet, extent=[t[0], t[-1], S2[0], S2[-1]], interpolation='sinc') plt.ylabel('Morlet') plt.subplot(814) plt.imshow(abs(XW3), aspect='auto', origin='lower', cmap=plt.cm.jet, extent=[t[0], t[-1], S3[0], S3[-1]], interpolation='sinc') plt.ylabel('Gabor') plt.subplot(815) plt.imshow(abs(XW4), aspect='auto', origin='lower', cmap=plt.cm.jet, extent=[t[0], t[-1], S4[0], S4[-1]], interpolation='sinc') plt.ylabel('Poisson') plt.subplot(816) plt.imshow(abs(XW5), aspect='auto', origin='lower', cmap=plt.cm.jet, extent=[t[0], t[-1], S5[0], S5[-1]], interpolation='sinc') plt.ylabel('cMaxican') plt.subplot(817) plt.imshow((abs(XW6)), aspect='auto', origin='lower', cmap=plt.cm.jet, extent=[t[0], t[-1], S6[0], S6[-1]], interpolation='sinc') plt.ylabel('cShannon') plt.subplot(818) if sLog: plt.imshow(np.log10(Sxx), aspect='auto', origin='lower', cmap=plt.cm.jet, extent=[t[0], t[-1], fx[0], fx[-1]], interpolation='sinc') else: plt.imshow(Sxx, aspect='auto', origin='lower', cmap=plt.cm.jet, extent=[t[0], t[-1], fx[0], fx[-1]], interpolation='sinc') plt.ylabel('Spectrogram') plt.subplots_adjust(hspace=0.05) plt.show()
#Simple cleaning/enhancement y_offset = np.mean(x) x = x - y_offset #plot time-series and spectrogram vowel_period_length = 0.075 NFFT = int(0.01 * fs) noverlap = int(0.005 * fs) nperseg = int((NFFT + noverlap) / 2) print(NFFT, noverlap, nperseg) f, t, Sxx = signal.spectrogram(x, fs=fs, nperseg=nperseg, noverlap=noverlap, nfft=NFFT, window=signal.get_window( 'hanning', nperseg), detrend=False) #Upsample and guassian smooth? fig, (ax1, ax2) = plt.subplots(2) ax1.set(xlabel='Time [sec]') ax1.plot(time_series, x) ax2.pcolormesh(t, f, Sxx, cmap=cm.gray_r, shading='gouraud', norm=LogNorm()) ax2.set(xlabel='Time [sec]', ylabel='Frequency [Hz]')
def lomb_scargle(ys, ts, freq=None, freq_method='lomb_scargle', freq_kwargs=None, n50=3, window='hann', detrend=None, sg_kwargs=None, gaussianize=False, standardize=False, average='mean'): """ Return the computed periodogram using lomb-scargle algorithm Uses the lombscargle implementation from scipy.signal: https://scipy.github.io/devdocs/generated/scipy.signal.lombscargle.html#scipy.signal.lombscargle Parameters ---------- ys : array a time series ts : array time axis of the time series freq : str or array vector of frequency. If string, uses the following method: freq_method : str Method to generate the frequency vector if not set directly. The following options are avialable: - log - lomb_scargle (default) - welch - scale - nfft See utils.wavelet.make_freq_vector for details freq_kwargs : dict Arguments for the method chosen in freq_method. See specific functions in utils.wavelet for details By default, uses dt=median(ts), ofac=4 and hifac=1 for Lomb-Scargle n50: int The number of 50% overlapping segment to apply window : str or tuple Desired window to use. Possible values: - boxcar - triang - blackman - hamming - hann (default) - bartlett - flattop - parzen - bohman - blackmanharris - nuttail - barthann - kaiser (needs beta) - gaussian (needs standard deviation) - general_gaussian (needs power, width) - slepian (needs width) - dpss (needs normalized half-bandwidth) - chebwin (needs attenuation) - exponential (needs decay scale) - tukey (needs taper fraction) If the window requires no parameters, then window can be a string. If the window requires parameters, then window must be a tuple with the first argument the string name of the window, and the next arguments the needed parameters. If window is a floating point number, it is interpreted as the beta parameter of the kaiser window. detrend : str If None, no detrending is applied. Available detrending methods: - None - no detrending will be applied (default); - linear - a linear least-squares fit to `ys` is subtracted; - constant - the mean of `ys` is subtracted - savitzy-golay - ys is filtered using the Savitzky-Golay filters and the resulting filtered series is subtracted from y. - emd - Empirical mode decomposition sg_kwargs : dict The parameters for the Savitzky-Golay filters. see pyleoclim.utils.filter.savitzy_golay for details. gaussianize : bool If True, gaussianizes the timeseries standardize : bool If True, standardizes the timeseriesprep_args : dict average : {'mean','median'} Method to use when averaging periodograms. Defaults to ‘mean’. Returns ------- res_dict : dict the result dictionary, including - freq (array): the frequency vector - psd (array): the spectral density vector See Also -------- pyleoclim.utils.spectral.periodogram : Estimate power spectral density using a periodogram pyleoclim.utils.spectral.mtm : Retuns spectral density using a multi-taper method pyleoclim.utils.spectral.welch : Returns power spectral density using the Welch method pyleoclim.utils.spectral.wwz_psd : Return the psd of a timeseries using wwz method. pyleoclim.utils.filter.savitzy_golay : Filtering using Savitzy-Golay pyleoclim.utils.tsutils.detrend : Detrending method References ---------- Lomb, N. R. (1976). Least-squares frequency analysis of unequally spaced data. Astrophysics and Space Science 39, 447-462. Scargle, J. D. (1982). Studies in astronomical time series analysis. II. Statistical aspects of spectral analyis of unvenly spaced data. The Astrophysical Journal, 263(2), 835-853. Scargle, J. D. (1982). Studies in astronomical time series analysis. II. Statistical aspects of spectral analyis of unvenly spaced data. The Astrophysical Journal, 263(2), 835-853. Examples -------- .. plot:: :context: close-figs >>> from pyleoclim import utils >>> import matplotlib.pyplot as plt >>> import numpy as np >>> # Create a signal >>> time = np.arange(2001) >>> f = 1/50 >>> signal = np.cos(2*np.pi*f*time) >>> # Spectral Analysis >>> res = utils.lomb_scargle(signal, time) >>> # plot >>> fig = plt.loglog( ... res['freq'], ... res['psd']) >>> plt.xlabel('Frequency') >>> plt.ylabel('PSD') >>> plt.show() """ ts = np.array(ts) ys = np.array(ys) if len(ts) != len(ys): raise ValueError('Time and value axis should be the same length') if n50 <= 0: raise ValueError( 'Number of overlapping segments should be greater than 1') # remove NaNs ys, ts = clean_ts(ys, ts) # preprocessing ys = preprocess(ys, ts, detrend=detrend, sg_kwargs=sg_kwargs, gaussianize=gaussianize, standardize=standardize) # divide into segments nseg = int(np.floor(2 * len(ts) / (n50 + 1))) index = np.array(np.arange(0, len(ts), nseg / 2), dtype=int) index[-1] = len(ts) #make it ends at the time series ts_seg = [] ys_seg = [] if n50 > 1: for idx, i in enumerate(np.arange(0, len(index) - 2, 1)): ts_seg.append(ts[index[idx]:index[idx + 2]]) ys_seg.append(ys[index[idx]:index[idx + 2]]) else: ts_seg.append(ts) ys_seg.append(ys) # calculate the frequency vector if needed if freq is None: freq_kwargs = {} if freq_kwargs is None else freq_kwargs.copy() if 'dt' not in freq_kwargs.keys(): dt = np.median(np.diff(ts)) freq_kwargs.update({'dt': dt}) freq = make_freq_vector(ts_seg[0], method=freq_method, **freq_kwargs) freq_angular = 2 * np.pi * freq # fix the zero frequency point #if freq[0] == 0: #freq_copy = freq[1:] #freq_angular = 2 * np.pi * freq_copy psd_seg = [] for idx, item in enumerate(ys_seg): psd_seg.append( signal.lombscargle( ts_seg[idx], item * signal.get_window(window, len(ts_seg[idx])), freq_angular)) # average them up if average == 'mean': psd = np.mean(psd_seg, axis=0) elif average == 'median': psd = np.median(psd_seg, axis=0) else: raise ValueError('Average should either be set to mean or median') #if freq[0] == 0: #psd = np.insert(psd, 0, np.nan) # output result res_dict = { 'freq': np.asarray(freq), 'psd': np.asarray(psd), } return res_dict
def welch_percentile(x, bias_func, fs=1.0, window='hann', nperseg=None, overlap=None, nfft=None, detrend='constant', return_onesided=True, scaling='density', axis=-1, percentile=0.5, numRV='edof', percentage_outliers=0.0): """ This function implements the Welch Percentile (WP) estimator. It extends the scipy.signal.welch() function by supporting arbitrary percentiles (instead of just median) and also uses a more accurate bias correction term. The mathematical background along with extensive simulations can be found in Schwock & Abadi "Statistical properties of a modified Welch method that uses sample percentiles" (2021) x : array signal in time domain bias_func : approximation used for the bias correction. All functions are implemented below. As a default bias_digamma_approx should be used as it works well for arbitrary percentiles and number of segments. Other functions can give faster performance, however at the cost of lower accuracy. overlap : float percentage of overlap between adjacent segments percentile : float between 0 to 1 percentile (as fraction between 0 to 1) used for the estimation. If percentile is None, mean averaging over periodograms is used. numRV : str number of independent random variables assumed for the percentile estimation. Since adjacent segments are allowed to overlap, periodogram estimates are not necessarily independent. If 'edof' (default) is used this is accounted for by computing the equivalent number of independent periodgoram which improves the bias correction. If independence between periodograms can be guaranteed 'n', the number of segments, can also be used. percentage_outliers : float between 0 to 1 approximate percentage of outliers in the data. This parameter is useful if the percentage of outlier is large (>5%) and known and an unbiased estimate is desired. All other parameters are the same as for the scipy.signal.welch() function https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.welch.html retuns : (freqs, Pxy, Nb) freqs : array frequency bins Pxy : array power spectral density estimate Nb : int number of segments. This parameter can usually be ignored but may be useful for debugging and analysis purpose. """ freqs, _, Pxy = signal.spectral._spectral_helper(x, x, fs, window, nperseg, int(nperseg * overlap), nfft, detrend, return_onesided, scaling, axis, mode='psd') Nb = Pxy.shape[-1] if len(Pxy.shape) >= 2 and Pxy.size > 0: if Pxy.shape[-1] > 1: if percentile == None: Pxy = Pxy.mean(axis=axis) elif isinstance(percentile, int) or isinstance(percentile, float): if percentile >= 0 and percentile <= 1: if numRV == 'n': Pxy = np.quantile( Pxy, percentile, axis=axis) / bias_func( Pxy.shape[-1], percentile, percentage_outliers) elif numRV == 'edof': win = signal.get_window(window, nperseg) / np.sqrt( np.sum(signal.get_window(window, nperseg)**2)) edof = compute_nu(len(x), nperseg, win, overlap) Pxy = np.quantile( Pxy, percentile, axis=axis) / bias_func( edof / 2, percentile, percentage_outliers) else: raise ValueError( 'percentile must be between 0 and 1, got %s' % (percentile, )) else: raise ValueError( 'percentile must be integer, float, or None type, got type %s' % (type(percentile), )) else: Pxy = np.reshape(Pxy, Pxy.shape[:-1]) return freqs, Pxy, Nb
def get_step_spectograms(): global CURRENT_INDEX global SPECTOGRAMS, LABELS # CLear the RAM. SPECTOGRAMS = [] n = len(FILE_NAMES) # Keep openning the connection to make sure it is not lost. # Keep openning the connection to make sure it is not lost. client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(MACHINE_NAME, username=USERNAME, password=PASSWORD) sftp = client.open_sftp() # Read .wav files from STEPS folders form teh DIRECTORY_NAME. for i in range(CURRENT_INDEX, CURRENT_INDEX + STEPS): # Make sure that you dont go beyong the number of folders found in the # DIRECOTRY_NAME. if (i >= n): break # The command is listing all the .wav files on the folder FILE_NAMES[i] cmd = ('ls ' + DIRECTORY_NAME + '/' + FILE_NAMES[i] + '/' + FILE_NAMES[i][:4] + '_audio_formatted_and_segmented_downloads/') stdin, stdout, stderr = client.exec_command(cmd) wav_files_in_directory = ( stdout.read().decode('utf-8')).split("\n")[:-1] count = 0 check = 10 for wav_filename in wav_files_in_directory: # print count if (count == check): print("Finished reading", count, ".wav files from", FILE_NAMES[i][:4]) check += 10 #count = 0 # Read the audiofile wave_file = sftp.open( '/home/sshaar/' + FILE_NAMES[i] + '/' + FILE_NAMES[i][:4] + '_audio_formatted_and_segmented_downloads/' + wav_filename, 'r') rate, data = wavfile.read(wave_file) # Specification for the spectorgram. You may change this function if wanted. # I think we need to modify this more. ## if ("xaa" in FILE_NAMES[i]): ## fs = 1600 ## else: fs = 16000 #fs = 1600 f, t, Sxx = signal.spectrogram(data, fs=fs, window=signal.get_window( "boxcar", int(fs * 0.025)), nperseg=int(fs * .025), noverlap=int(fs * .01), nfft=2048) Sxx = np.resize(Sxx, (1025, 600)) #Sxx = Sxx.reshape((1,) + Sxx.shape) print("SPECTO SHAPE", Sxx.shape) # Add the spectogram of the audiofile to the list. SPECTOGRAMS.append(Sxx) # I am not sure anout this! #print (SPECTOGRAMS) print("file", wav_filename) t = wav_filename.split(".wav") t = t[0] t = t.split("@")[1] if (t not in UNIQUETAGS): UNIQUETAGS.append(t) #print (t) LABELS.append(t) #print ("TAG", t) #print ("SPECTO SHAPE", Sxx.shape) #print( "ALL SHAPE", SPECTOGRAMS.shape) wave_file.close() count += 1 print(count) print(len(SPECTOGRAMS)) if (count == 50): break print('Finished reading all .wav files in ' + FILE_NAMES[i][:4]) client.close() CURRENT_INDEX += STEPS
def main(inputFile='../../sounds/bendir.wav', window='hamming', M=2001, N=2048, t=-80, minSineDur=0.02, maxnSines=150, freqDevOffset=10, freqDevSlope=0.001, stocf=0.2): """ inputFile: input sound file (monophonic with sampling rate of 44100) window: analysis window type (rectangular, hanning, hamming, blackman, blackmanharris) M: analysis window size; N: fft size (power of two, bigger or equal than M) t: magnitude threshold of spectral peaks; 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 stocf: decimation factor used for the stochastic approximation """ # size of fft used in synthesis Ns = 512 # hop size (has to be 1/4 of Ns) H = 128 # read input sound (fs, x) = UF.wavread(inputFile) # compute analysis window w = get_window(window, M) # perform sinusoidal+sotchastic analysis tfreq, tmag, tphase, stocEnv = SPS.spsModelAnal(x, fs, w, N, H, t, minSineDur, maxnSines, freqDevOffset, freqDevSlope, stocf) # synthesize sinusoidal+stochastic model y, ys, yst = SPS.spsModelSynth(tfreq, tmag, tphase, stocEnv, Ns, H, fs) # output sound file (monophonic with sampling rate of 44100) outputFileSines = 'output_sounds/' + os.path.basename( inputFile)[:-4] + '_spsModel_sines.wav' outputFileStochastic = 'output_sounds/' + os.path.basename( inputFile)[:-4] + '_spsModel_stochastic.wav' outputFile = 'output_sounds/' + os.path.basename( inputFile)[:-4] + '_spsModel.wav' # write sounds files for sinusoidal, residual, and the sum UF.wavwrite(ys, fs, outputFileSines) UF.wavwrite(yst, fs, outputFileStochastic) UF.wavwrite(y, fs, outputFile) # create figure to plot plt.figure(figsize=(9, 6)) # frequency range to plot maxplotfreq = 10000.0 # plot the input sound plt.subplot(3, 1, 1) plt.plot(np.arange(x.size) / float(fs), x) plt.axis([0, x.size / float(fs), min(x), max(x)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('input sound: x') plt.subplot(3, 1, 2) numFrames = int(stocEnv[:, 0].size) sizeEnv = int(stocEnv[0, :].size) frmTime = H * np.arange(numFrames) / float(fs) binFreq = (.5 * fs) * np.arange(sizeEnv * maxplotfreq / (.5 * fs)) / sizeEnv plt.pcolormesh( frmTime, binFreq, np.transpose(stocEnv[:, :int(sizeEnv * maxplotfreq / (.5 * fs) + 1)])) plt.autoscale(tight=True) # plot sinusoidal frequencies on top of stochastic component if (tfreq.shape[1] > 0): sines = tfreq * np.less(tfreq, maxplotfreq) sines[sines == 0] = np.nan numFrames = int(sines[:, 0].size) frmTime = H * np.arange(numFrames) / float(fs) plt.plot(frmTime, sines, color='k', ms=3, alpha=1) plt.xlabel('time(s)') plt.ylabel('Frequency(Hz)') plt.autoscale(tight=True) plt.title('sinusoidal + stochastic spectrogram') # plot the output sound plt.subplot(3, 1, 3) plt.plot(np.arange(y.size) / float(fs), y) plt.axis([0, y.size / float(fs), min(y), max(y)]) plt.ylabel('amplitude') plt.xlabel('time (sec)') plt.title('output sound: y') plt.tight_layout() plt.ion() plt.show()
def minFreqEstErr(inputFile, f): """ Inputs: inputFile (string) = wav file including the path f (float) = frequency of the sinusoid present in the input audio signal (Hz) Output: fEst (float) = Estimated frequency of the sinusoid (Hz) M (int) = Window size N (int) = FFT size """ # analysis parameters: window = 'blackman' t = -40 ### Your code here (fs, x) = UF.wavread( os.path.join(os.path.dirname(os.path.realpath(__file__)), inputFile)) #minSineDur = 0 #maxnSines = 150 #freqDevOffset = 10 #freqDevSlope = 0.001 fMin = 100.0 fMax = 2000.0 fMaxError = 0.05 fCurrentError = 1.0 middle = int(0.5 * fs) k = 1 while fCurrentError >= fMaxError and k * fMin + 1 < fMax: M = int(fMin * k + 1) # 100 * k + 1 N = int(2**math.ceil(math.log( M, 2))) # the smallest power of 2 larger than M. w = get_window(window, M) hM1 = int(math.floor( (M + 1) / 2)) # (w.size = M) half analysis window size by rounding hM2 = int(math.floor(M / 2)) # half analysis window size by floor pin = middle # initialize sound pointer in middle of analysis window #w = w / sum(w) # normalize analysis window #tfreq = np.array([]) # while input sound pointer is within sound x1 = x[pin - hM1:pin + hM2] # select frame mX, pX = DFT.dftAnal(x1, w, N) # compute dft ploc = UF.peakDetection(mX, t) # detect locations of peaks iploc, ipmag, ipphase = UF.peakInterp( mX, pX, ploc) # refine peak values by interpolation ipfreq = fs * iploc / float(N) # convert peak locations to Hertz #print ipfreq if len(ipfreq) > 0: fEst = ipfreq[0] fCurrentError = abs(f - fEst) k += 1 # tfreq, tmag, tphase = SM.sineModelAnal(x1, fs, w, N, H, t, maxnSines, minSineDur, freqDevOffset, freqDevSlope) return fEst, M, N
inputFile = '../../sounds/cello-phrase.wav' stdThsld = 10 minNoteDur = 0.1 winStable = 3 window = 'hamming' M = 1025 N = 2048 H = 256 f0et = 5.0 t = -100 minf0 = 310 maxf0 = 650 fs, x = UF.wavread(inputFile) #reading inputFile w = get_window(window, M) #obtaining analysis window f0 = HM.f0Detection(x, fs, w, N, H, t, minf0, maxf0, f0et) #estimating F0 ### your code here # 1. convert f0 values from Hz to Cents (as described in pdf document) f0[np.where(f0 < eps)] = eps f0Cent = 1200 * np.log2(f0 / 55.0) #2. create an array containing standard deviation of last winStable samples devf0 = np.zeros(f0Cent.size) for i in range(winStable, f0Cent.size): devf0[i] = np.std(f0Cent[i - winStable:i]) stablePts = np.where(devf0 < stdThsld)[0]