def make_harmonic_stack(f0=100, n_harm=40, dur=0.25001, sr=20000, low_lim=50, hi_lim=20000, n=None): """Synthesize a tone created with a stack of harmonics. Args: f0 (int, optional): Fundamental frequency. n_harm (int, optional): Number of harmonics to include. dur (float, optional): Duration, in milliseconds. Note, the default value was chosen to create a signal length that is compatible with the predefined downsampling method. sr (int, optional): Sampling rate. low_lim (int, optional): Lower limit for filterbank. hi_lim (int, optional): Upper limit for filerbank. n (None, optional): Number of filters in filterbank. Returns: tuple: **signal** (array): Synthesized tone. **signal_params** (dict): A dictionary containing all of the parameters used to synthesize the tone. """ # i don't know where this came from, but choose a number of filters if n is None: n = int(np.floor(erb.freq2erb(hi_lim) - erb.freq2erb(low_lim)) - 1) # synthesize tone from harmonic stack t = np.arange(0, dur + 1 / sr, 1 / sr) signal = np.zeros_like(t) for i in range(1, n_harm + 1): signal += np.sin(2 * np.pi * f0 * i * t) # zero-phase # store all the params in a dictionary signal_params = { 'f0': f0, 'n_harm': n_harm, 'dur': dur, 'sr': sr, 'low_lim': low_lim, 'hi_lim': hi_lim, 'n': n } return signal, signal_params
def human_cochleagram(signal, sr, n=None, low_lim=50, hi_lim=20000, sample_factor=2, padding_size=None, downsample=None, nonlinearity=None, fft_mode='auto', ret_mode='envs', strict=True, **kwargs): """Convenience function to generate the subband envelopes (i.e., the cochleagram) of the provided signal using sensible default parameters for a human cochleagram. This first creates a an ERB filterbank with the provided input arguments for the provided signal. This filterbank is then used to perform the subband decomposition to create the subband envelopes. The resulting envelopes can be optionally downsampled and then modified with a nonlinearity. Args: signal (array): The sound signal (waveform) in the time domain. Should be flattened, i.e., the shape is (n_samples,). sr (int): Sampling rate associated with the signal waveform. n (int): Number of filters (subbands) to be generated with standard sampling (i.e., using a sampling factor of 1). Note, the actual number of filters in the generated filterbank depends on the sampling factor, and will also include lowpass and highpass filters that allow for perfect reconstruction of the input signal (the exact number of lowpass and highpass filters is determined by the sampling factor). low_lim (int): Lower limit of frequency range. Filters will not be defined below this limit. hi_lim (int): Upper limit of frequency range. Filters will not be defined above this limit. sample_factor (int): Positive integer that determines how densely ERB function will be sampled to create bandpass filters. 1 represents standard sampling; adjacent bandpass filters will overlap by 50%. 2 represents 2x overcomplete sampling; adjacent bandpass filters will overlap by 75%. 4 represents 4x overcomplete sampling; adjacent bandpass filters will overlap by 87.5%. padding_size (int, optional): If None (default), the signal will not be padded before filtering. Otherwise, the filters will be created assuming the waveform signal will be padded to length padding_size+signal_length. downsample (None, int, callable, optional): The `downsample` argument can be an integer representing the upsampling factor in polyphase resampling (with `sr` as the downsampling factor), a callable (to perform custom downsampling), or None to return the unmodified cochleagram; see `apply_envelope_downsample` for more information. If `ret_mode` is 'envs', this will be applied to the cochleagram before the nonlinearity, otherwise no downsampling will be performed. Providing a callable for custom downsampling is suggested. nonlinearity ({None, 'db', 'power', callable}, optional): The `nonlinearity` argument can be an predefined type, a callable (to apply a custom nonlinearity), or None to return the unmodified cochleagram; see `apply_envelope_nonlinearity` for more information. If `ret_mode` is 'envs', this will be applied to the cochleagram after downsampling, otherwise no nonlinearity will be applied. Providing a callable for applying a custom nonlinearity is suggested. fft_mode ({'auto', 'fftw', 'np'}, optional): Determine what implementation to use for FFT-like operations. 'auto' will attempt to use pyfftw, but will fallback to numpy, if necessary. ret_mode ({'envs', 'subband', 'analytic', 'all'}): Determines what will be returned. 'envs' (default) returns the subband envelopes; 'subband' returns just the subbands, 'analytic' returns the analytic signal provided by the Hilber transform, 'all' returns all local variables created in this function. strict (bool, optional): If True (default), will throw an errors if this function is used in a way that is unsupported by the MATLAB implemenation. Returns: array: **out**: The output, depending on the value of `ret_mode`. If the `ret_mode` is 'envs' and a downsampling and/or nonlinearity operation was requested, the output will reflect these operations. """ if n is None: n = int(np.floor(erb.freq2erb(hi_lim) - erb.freq2erb(low_lim)) - 1) #print("here. calling coch") out = cochleagram(signal, sr, n, low_lim, hi_lim, sample_factor, padding_size, downsample, nonlinearity, fft_mode, ret_mode, strict, **kwargs) return out