def spectral_rolloff(y=None, sr=22050, S=None, n_fft=2048, hop_length=512, freq=None, roll_percent=0.85): if not 0.0 < roll_percent < 1.0: raise ParameterError('roll_percent must lie in the range (0, 1)') S, n_fft = _spectrogram(y=y, S=S, n_fft=n_fft, hop_length=hop_length) if not np.isrealobj(S): raise ParameterError('Spectral rolloff is only defined ' 'with real-valued input') elif np.any(S < 0): raise ParameterError('Spectral rolloff is only defined ' 'with non-negative energies') # Compute the center frequencies of each bin if freq is None: freq = fft_frequencies(sr=sr, n_fft=n_fft) # Make sure that frequency can be broadcast if freq.ndim == 1: freq = freq.reshape((-1, 1)) total_energy = np.cumsum(S, axis=0) threshold = roll_percent * total_energy[-1] ind = np.where(total_energy < threshold, np.nan, 1) return np.nanmin(ind * freq, axis=0, keepdims=True)
def spectral_bandwidth(y=None, sr=22050, S=None, n_fft=2048, hop_length=512, freq=None, centroid=None, norm=True, p=2): S, n_fft = _spectrogram(y=y, S=S, n_fft=n_fft, hop_length=hop_length) if not np.isrealobj(S): raise ParameterError('Spectral bandwidth is only defined ' 'with real-valued input') elif np.any(S < 0): raise ParameterError('Spectral bandwidth is only defined ' 'with non-negative energies') if centroid is None: centroid = spectral_centroid(y=y, sr=sr, S=S, n_fft=n_fft, hop_length=hop_length, freq=freq) # Compute the center frequencies of each bin if freq is None: freq = fft_frequencies(sr=sr, n_fft=n_fft) if freq.ndim == 1: deviation = np.abs(np.subtract.outer(freq, centroid[0])) else: deviation = np.abs(freq - centroid[0]) # Column-normalize S if norm: S = util.normalize(S, norm=1, axis=0) return np.sum(S * deviation**p, axis=0, keepdims=True)**(1./p)
def melspectrogram(y, sr, filterbank, n_fft, hop_length, win_length): S, _ = spectrum._spectrogram(y=y, power=2.0, n_fft=n_fft, hop_length=hop_length, win_length=win_length) return np.dot(filterbank, S)
def spectral_centroid(y=None, sr=22050, S=None, n_fft=2048, hop_length=512, freq=None): S, n_fft = _spectrogram(y=y, S=S, n_fft=n_fft, hop_length=hop_length) if not np.isrealobj(S): raise ParameterError('Spectral centroid is only defined ' 'with real-valued input') elif np.any(S < 0): raise ParameterError('Spectral centroid is only defined ' 'with non-negative energies') # Compute the center frequencies of each bin if freq is None: freq = fft_frequencies(sr=sr, n_fft=n_fft) if freq.ndim == 1: freq = freq.reshape((-1, 1)) # Column-normalize S return np.sum(freq * util.normalize(S, norm=1, axis=0), axis=0, keepdims=True)
def test_get_psd(self): psd1, _ = _spectrogram(y=self.sig, S=None, n_fft=nfft, hop_length=stepsize) psd2 = get_psd(self.args) self.assertTrue(np.allclose(psd1, psd2))
def test_stft_from_sig(self): psd1, _ = _spectrogram(y=self.sig, S=None, n_fft=nfft, hop_length=stepsize) psd2 = np.abs( stft_from_sig(self.sig, nfft, noverlap, win_length, 'hann', True)) self.assertTrue(np.allclose(psd1, psd2))
def melspectrogram(y=None, sr=22050, S=None, n_fft=2048, hop_length=512, power=2.0, **kwargs): #Compute a mel-scaled spectrogram. S, n_fft = _spectrogram(y=y, S=S, n_fft=n_fft, hop_length=hop_length, power=power) # Build a Mel filter mel_basis = mel(sr, n_fft, **kwargs) return np.dot(mel_basis, S)
def signal_noise_split(audio): S, _ = spectrum._spectrogram(y=audio, power=1.0, n_fft=2048, hop_length=512, win_length=2048) col_median = np.median(S, axis=0, keepdims=True) row_median = np.median(S, axis=1, keepdims=True) S[S < row_median * 3] = 0.0 S[S < col_median * 3] = 0.0 S[S > 0] = 1 S = binary_erosion(S, structure=np.ones((4, 4))) S = binary_dilation(S, structure=np.ones((4, 4))) indicator = S.any(axis=0) indicator = binary_dilation(indicator, structure=np.ones(4), iterations=2) mask = np.repeat(indicator, hop_length) mask = binary_dilation(mask, structure=np.ones(win_length - hop_length), origin=-(win_length - hop_length)//2) mask = mask[:len(audio)] signal = audio[mask] noise = audio[~mask] return signal, noise
def spectral_contrast(y=None, sr=22050, S=None, n_fft=2048, hop_length=512, freq=None, fmin=200.0, n_bands=6, quantile=0.02, linear=False): S, n_fft = _spectrogram(y=y, S=S, n_fft=n_fft, hop_length=hop_length) # Compute the center frequencies of each bin if freq is None: freq = fft_frequencies(sr=sr, n_fft=n_fft) freq = np.atleast_1d(freq) if freq.ndim != 1 or len(freq) != S.shape[0]: raise ParameterError('freq.shape mismatch: expected ' '({:d},)'.format(S.shape[0])) if n_bands < 1 or not isinstance(n_bands, int): raise ParameterError('n_bands must be a positive integer') if not 0.0 < quantile < 1.0: raise ParameterError('quantile must lie in the range (0, 1)') if fmin <= 0: raise ParameterError('fmin must be a positive number') octa = np.zeros(n_bands + 2) octa[1:] = fmin * (2.0**np.arange(0, n_bands + 1)) if np.any(octa[:-1] >= 0.5 * sr): raise ParameterError('Frequency band exceeds Nyquist. ' 'Reduce either fmin or n_bands.') valley = np.zeros((n_bands + 1, S.shape[1])) peak = np.zeros_like(valley) for k, (f_low, f_high) in enumerate(zip(octa[:-1], octa[1:])): current_band = np.logical_and(freq >= f_low, freq <= f_high) idx = np.flatnonzero(current_band) if k > 0: current_band[idx[0] - 1] = True if k == n_bands: current_band[idx[-1] + 1:] = True sub_band = S[current_band] if k < n_bands: sub_band = sub_band[:-1] # Always take at least one bin from each side idx = np.rint(quantile * np.sum(current_band)) idx = int(np.maximum(idx, 1)) sortedr = np.sort(sub_band, axis=0) valley[k] = np.mean(sortedr[:idx], axis=0) peak[k] = np.mean(sortedr[-idx:], axis=0) if linear: return peak - valley else: return power_to_db(peak) - power_to_db(valley)