psiaudio.stim module

class BandlimitedClickFactory(fs, flb, fub, window, level, calibration=None, equalize=False, max_correction=inf, audiogram_weighting=None)

Bases: FixedWaveform

class BandlimitedFIRNoiseFactory(fs, fl, fh, level, ntaps=1001, window='hann', polarity=1, seed=None, max_correction=inf, equalize=False, calibration=None, audiogram_weighting=None)

Bases: Carrier

Factory for generating continuous shaped noise using FIR filters.

This is similar to shaped noise, but with simpler inputs if all you want is bandlimited noise (i.e., no requirement to generate the dictionary of gains).

Parameters:
  • fs (float) – Sampling rate of stimuli

  • fl (float) – Lower frequency of noise band

  • fh (float) – Upper frequency of noise band

  • level (float) – Noise level

  • ntaps (int) – Number of taps to use for FIR filter. The default generally works well.

  • window (string) – Any valid window name offered by scipy. This is passed to firwin2.

  • polarity (int) – Can be used to invert the polarity

  • seed ({None, int}) – Set the seed if you want to generate frozen, reproducible noise.

  • max_correction (float) – Maximum amount to adjust noise when equalizing based on speaker calibration. Over-correcting the noise may lead to some very large amplitudes and limit the range of possible stimulus levels. If noise is not equalized, this setting is ignored.

  • equalize (bool) – Equalize the noise based on the calibration to generate spectrally flat noise?

  • calibration (instance of psiaudio.calibration.BaseCalibration) – Used to generate the appropriate noise amplitude (and equalize the noise if requested).

max_amplitude()
next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class BandlimitedNoiseFactory(fs, seed, level, fl, fh, filter_rolloff, passband_attenuation, stopband_attenuation, equalize=False, polarity=1, calibration=None, discard_initial_samples=True)

Bases: Carrier

Factory for generating continuous bandlimited noise using IIR filters. Equalization requires a calibration that was generated using Golay.

See BandlimitedFIRNoiseFactory as an alternative.

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class BroadbandNoiseFactory(fs, level, seed=1, equalize=False, polarity=1, calibration=None)

Bases: Carrier

Factory for generating continuous broadband noise

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class Carrier

Bases: Waveform

A continuous waveform

get_duration()

Get total duration of the waveform in seconds.

is_complete()

Check if generation is complete.

n_samples_remaining()

Get the number of samples remaining.

Returns:

Number of samples remaining, or np.inf if continuous.

Return type:

float or int

class ChirpFactory(fs, start_frequency, end_frequency, duration, level, calibration, window='boxcar', equalize=False, max_correction=inf, audiogram_weighting=None)

Bases: FixedWaveform

class ClickFactory(fs, duration, level, polarity, calibration)

Bases: FixedWaveform

class ContinuousWaveform

Bases: Waveform

Waveform of infinite duration.

get_duration()

Get total duration of the waveform in seconds.

is_complete()

Check if generation is complete.

n_samples()

Get total number of samples the waveform will generate.

Returns:

Total samples, or np.inf if continuous.

Return type:

float or int

n_samples_remaining()

Get the number of samples remaining.

Returns:

Number of samples remaining, or np.inf if continuous.

Return type:

float or int

class Cos2EnvelopeFactory(fs, duration, rise_time, input_factory, start_time=0)

Bases: EnvelopeFactory

max_amplitude()
class EnvelopeFactory(envelope, fs, duration, rise_time, input_factory, start_time=0, transform=None)

Bases: GateFactory

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

class FixedWaveform(fs, waveform)

Bases: Waveform

Pre-generated waveform returned in segments.

Parameters:
  • fs (float) – Sampling rate.

  • waveform (ndarray) – The full pre-generated waveform.

get_duration()

Get total duration of the waveform in seconds.

is_complete()

Check if generation is complete.

max_amplitude()
n_samples()

Get total number of samples the waveform will generate.

Returns:

Total samples, or np.inf if continuous.

Return type:

float or int

n_samples_remaining()

Get the number of samples remaining.

Returns:

Number of samples remaining, or np.inf if continuous.

Return type:

float or int

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class GateFactory(fs, start_time, duration, input_factory)

Bases: Modulator

get_duration()

Get total duration of the waveform in seconds.

is_complete()

Check if generation is complete.

max_amplitude()
n_samples()

Get total number of samples the waveform will generate.

Returns:

Total samples, or np.inf if continuous.

Return type:

float or int

n_samples_remaining()

Get the number of samples remaining.

Returns:

Number of samples remaining, or np.inf if continuous.

Return type:

float or int

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

class Modulator

Bases: Transform

Modulates an input waveform

env(samples)
transform(waveform)
class NotchFilterFactory(fs, notch_frequency, q, input_factory)

Bases: Transform

Factory for applying notch filter to a continuous input

This was written to generate stimuli similar to that used by the Intelligent Hearing Systems notch noise feature where the Q factor is set to 1.33 by default.

reset()

Reset the generator to its initial state.

transform(samples)
class RepeatFactory(fs, n, skip_n, rate, delay, input_factory)

Bases: FixedWaveform

get_duration()

Get total duration of the waveform in seconds.

max_amplitude()
reset()

Reset the generator to its initial state.

class SAMEnvelopeFactory(fs, depth, fm, delay, direction, input_factory, onset_method='ss_transition')

Bases: Modulator

env(samples)
class SAMToneFactory(fs, fc, fm, level, depth=1, phase=0, phase_lb=0, phase_ub=0, polarity=1, eq_power=True, equalize=True, calibration=None)

Bases: Carrier

max_amplitude()
next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class ShapedNoiseFactory(fs, level, gains, ntaps=1001, window='hann', polarity=1, seed=None, calibration=None)

Bases: Carrier

Factory for generating continuous shaped noise using FIR filters.

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class SilenceFactory(fill_value=0)

Bases: Carrier

Generate silence

All channels require at least one continuous output. If no token is specified for the continuous output, silence is used.

Notes

The fill_value can be set to a number other than zero for testing (e.g., to characterize the effect of a transformation).

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class SquareWaveEnvelopeFactory(fs, depth, fm, duty_cycle, calibration, input_factory, alpha=0)

Bases: Modulator

env(samples)
max_amplitude()
class SquareWaveFactory(fs, level, frequency, duty_cycle)

Bases: Carrier

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class ToneFactory(fs, frequency, level, phase=0, polarity=1, calibration=None)

Bases: Carrier

max_amplitude()
next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class Transform

Bases: Waveform

Modifies an input waveform

get_duration()

Get total duration of the waveform in seconds.

is_complete()

Check if generation is complete.

n_samples_remaining()

Get the number of samples remaining.

Returns:

Number of samples remaining, or np.inf if continuous.

Return type:

float or int

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

transform(samples)
class WavFileFactory(fs, filename, level=None, calibration=None, normalization='pe')

Bases: FixedWaveform

property waveform
class WavSequenceFactory(fs, path, level=None, calibration=None, duration=-1, normalization='pe')

Bases: ContinuousWaveform

connect(*args, **kwargs)
next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

class Waveform

Bases: object

Base class for waveform generation.

get_duration()

Get total duration of the waveform in seconds.

get_samples_remaining()

Get all remaining samples.

is_complete()

Check if generation is complete.

n_samples()

Get total number of samples the waveform will generate.

Returns:

Total samples, or np.inf if continuous.

Return type:

float or int

n_samples_remaining()

Get the number of samples remaining.

Returns:

Number of samples remaining, or np.inf if continuous.

Return type:

float or int

next(samples)

Generate the next segment of the waveform.

Parameters:

samples (int) – Number of samples to generate.

Returns:

Generated samples.

Return type:

ndarray

reset()

Reset the generator to its initial state.

apply_cos2envelope(waveform, fs, rise_time, duration=None, start_time=0)
apply_max_correction(sf, max_correction)

Apply a maximum correction limit to the requested calibration scale factor.

Parameters:
  • sf (array_like) – Scale factors to correct.

  • max_correction (float) – Maximum allowed correction in dB relative to the mean correction.

Returns:

Clipped scaling factors.

Return type:

array_like

apply_sam_envelope(waveform, fs, depth, fm, delay, equalize)
apply_weighting(freq, sf, weighting_type)

Apply acoustic weighting to scaling factors.

Parameters:
  • freq (array_like) – Frequencies corresponding to scaling factors.

  • sf (array_like) – Scaling factors.

  • weighting_type (str) – Type of weighting, e.g., ‘A’, ‘C’, etc.

Returns:

Weighted scaling factors.

Return type:

array_like

bandlimited_click(fs, flb, fub, window=0.1, level=1, level_unit='rms', calibration=None, equalize=False, max_correction=inf, audiogram_weighting=None)

Generate bandlimited click.

Parameters:
  • fs (float) – Sampling rate of waveform

  • flb (float) – Lower frequency of click passband

  • fub (float) – Upper frequency of click passband

  • window (float) – Duration of window to embed click in. The click waveform will be symmetric around the center of the window.

  • level (float) – Overall level of click. See notes regarding level calculation.

  • level_unit ({'peak', 'average'}) – If ‘peak’, click level is peak power using a peak to average power ratio. The min/max of the returned waveform will always be identical regardless of the window.

bandlimited_fir_noise(fs, level, fl, fh, duration, ntaps=10001, window='hann', polarity=1, seed=1, calibration=None, equalize=True)

Generate shaped noise using scipy.signal.firwin2.

Parameters:
  • fs (float) – Sampling rate

  • level (float) – Level in units of calibration. If no calibration is provided, noise will be scaled such that rms(noise) == level.

  • fl (float) – Lower bound of noise band (Hz).

  • fh (float) – Upper bound of noise band (Hz).

  • ntaps (int) – Number of taps to use for filter calculation. See scipy.signal.firwin2 for hints on choosing a reasonable value.

  • window ({string, (string, float), float, None}) – Window function to use. See window parameter of scipy.signal.firwin2 for additional details on acceptable values.

  • polarity ({-1, 1}) – Polarity of noise. Useful if you need to present two trials in inverted polarity to cancel out electrical artifacts.

  • seed (int) – Seed to use for random number generator.

  • calibration ({BaseCalibration, None}) – Instance of a psiaudio.calibration.BaseCalibration or subclass thereof. Used to determine scaling factor for noise amplitude.

bandlimited_noise(fs, level, fl, fh, duration=None, filter_rolloff=1, passband_attenuation=1, stopband_attenuation=80, equalize=False, polarity=1, seed=1, samples='auto', calibration=None)
broadband_noise(fs, level, duration, seed=1, equalize=False, polarity=1, calibration=None)
chirp(fs, start_frequency, end_frequency, duration, level, calibration=None, window='boxcar', equalize=False, max_correction=inf, audiogram_weighting=None)

Notes

Windowing algorithm was implemented as described in Neumann et al., 1994 to enable implementation of the Hann windowed chirp in the middel ear acoustic reflex assay described by Valero et al., 2016.

cos2envelope(fs, duration, rise_time, offset=0, start_time=0, samples='auto')
cos2ramp(m)
envelope(window, fs, duration, rise_time=None, offset=0, start_time=0, samples='auto', transform=None)

Generates envelope. Can handle generating fragments (i.e., incomplete sections of the waveform).

Parameters:
  • window ({'cosine-squared', etc.}) – Name of window

  • fs (float) – Sampling rate

  • duration (float) – Duration of envelope (from rise onset to rise offset)

  • rise_time ({None, float}) – Rise time of envelope. If None, then there is no plateau/steady-state portion of the envelope. See notes for special-case handling.

  • offset (int) – Offset to begin generating waveform at (in samples relative to start)

  • start_time (float) – Start time of envelope

  • samples (int) – Number of samples to generate for envelope.

  • transform (callable) – Callable that can transform the resulting envelope into the desired units.

Notes

For gaussian envelopes, the standard deviation is set to 1/8 of the total width (onset to offset) of the envelope.

fast_cache(f)
gap(fs, fc, octaves, gap, durations, rise_time, level, calibration)

Generate an acoustic gap stimulus consisting of two markers separated by silence.

The stimulus applies an amplitude envelope with Gaussian onset and offset ramps to a carrier signal. If octaves is greater than 0, the carrier is bandlimited noise centered at fc. If octaves is 0, the carrier is a pure tone at fc.

Parameters:
  • fs (int or float) – The sampling frequency of the signal in Hz.

  • fc (int or float) – The center frequency of the bandlimited noise, or the exact frequency of the pure tone if octaves is 0, in Hz.

  • octaves (float) – The bandwidth of the noise carrier in octaves. If set to 0, the function generates a pure tone instead of noise.

  • gap (float) – The duration of the silent gap separating the two markers, in seconds.

  • durations (list/array of float) – The durations of the acoustic markers separating the gap, in seconds. Must be at least two (for a single gap).

  • rise_time (float) – The rise and fall time for the Gaussian envelope windows, in seconds.

  • level (float) – The target sound pressure level (SPL) of the carrier signal in dB.

  • calibration (float or object) – The calibration factor or object required by the carrier generation functions to correctly scale the output amplitude based on the level.

Returns:

A 1D numpy array containing the generated audio waveform of the gap stimulus.

Return type:

ndarray

load_wav(fs, filename, level=None, calibration=None, normalization=None)

Load wav file, scale, and resample

Parameters:
  • fs (float) – Desired sampling rate for wav file. If wav file sampling rate is different, it will be resampled to the correct sampling rate using a FFT-based resampling algorithm.

  • filename ({str, Path}) – Path to wav file

  • level ({None, float}) – Level to present wav files at. If normalization is ‘pe’, level will be in units of peSPL (assuming calibration is in units of SPL). If normalization is in ‘rms’, level will be dB SPL RMS.

  • calibration ({None, Calibration}) – Used to scale waveform to appropriate peSPL. If not provided, waveform is not scaled.

  • normalization ({None, 'pe', 'rms'}) – Method for rescaling waveform. If None, no rescaling is done. If ‘pe’, rescales to peak-equivalent so the max value of the waveform matches the target level. If ‘rms’, rescales so that the RMS value of the waveform matches the target level.

notch_noise(fs, notch_frequency, q, level, duration, seed=1, equalize=False, polarity=1, calibration=None)
ramped_tone(fs, frequency, level, duration, rise_time=None, window='cosine-squared', phase=0, calibration=None)
repeat(waveform, fs, n, skip_n, rate, delay)
sam_envelope(offset, samples, fs, depth, fm, delay, equalize)
sam_eq_phase(depth, direction='positive')
sam_eq_power(depth)
sam_tone(fs, fc, fm, level, depth=1, phase=0, phase_lb=0, phase_ub=0, polarity=1, calibration=None, samples='auto', offset=0, duration=None, eq_power=True, equalize=True)

Generates a SAM tone

Unlike the alternate approach of combining a SAM envelope with a tone carrier, this is specially designed to handle speakers with nonlinear outputs as a function of frequency by adjusting the levels of the harmonics accordingly.

Parameters:
  • phase (float) – Starting phase of carrier frequency.

  • phase_lb (float) – Starting phase of lower sideband frequency (fc-fm). This is primarily for testing and debugging purposes (modifying the starting phase of phase_lb and phase_ub will affect the modulation depth).

  • phase_ub (float) – Starting phase of upper sideband frequency (fc+fm).

  • eq_power (bool) – If True, compensate for modualtion depth so the overall RMS is the same when varying modulation depth. This is useful when doing AM detection studies as it minimizes loudness cues.

  • equalize (bool) – If True and the calibration is provided, ensure that the sidebands (fc-fm, fc+fm) are adjusted to reflect the actual output of the speaker at those frequencies. If not provided, the calibration at the carrier frequency is used for both the carrier and modulation sidebands.

  • TODO (#)

sfm(fs, fc, fm, depth, duration, level, calibration=None, equalize=False, max_correction=inf)

Generates linear or exponential spectro-temporal modulations using an inverse FFT approach.

Parameters:
  • fs (float) – Sampling rate.

  • fc (float) – Carrier frequency.

  • fm (float) – Modulation frequency (in same units as fc).

  • depth (float) – Depth of modulation (in same units as fm and fc).

  • duration (float) – Duration of waveform in seconds.

  • level (float) – RMS level of stimulus. If no calibration is provided, this is assumed to be in units of Volts.

  • calibration ({None, Calibration}) – Instance of a psiaudio.calibration class that can be used to calculate the amplitude of the waveform to obtain the desired level.

  • equalize (bool) – If True, the calibration is used to compensate for changes in speaker output as a function of frequency.

  • max_correction (float) – If equalize is True, limit the amount, in dB, of the equalization.

sfm_tone(fs, fc, fm, level, fd, delay=0, polarity=1, calibration=None, samples='auto', offset=0, duration=None, equalize=True)

Generates a SFM (sinusoidally frequency modulated) tone

Parameters:
  • fs (float) – Sampling frequency (Hz).

  • fc (float) – Center frequency (Hz).

  • fm (float) – Modulation frequency (Hz).

  • level (float) – The units of level depend on the calibration provided (e.g., typically dB SPL). If no calibration is provided, this defines the RMS power of the tone.

  • fd (float) – Maximum deviation from center frequency.

  • delay (float) – Delay, in seconds, before modulation begins.

  • equalize (bool) – If True and the calibration is provided, ensure that the sidebands (fc-fm, fc+fm) are adjusted to reflect the actual output of the speaker at those frequencies. If not provided, the calibration at the carrier frequency is used for both the carrier and modulation sidebands.

  • TODO (#)

shaped_noise(fs, level, gains, duration, ntaps=10001, window='hann', polarity=1, seed=1, calibration=None)

Generate shaped noise using scipy.signal.firwin2.

Parameters:
  • fs (float) – Sampling rate

  • level (float) – Level in units of calibration. If no calibration is provided, noise will be scaled such that rms(noise) == level.

  • gains (dict) – Dictionary mapping frequency breakpoints (Hz) to gain (dB).

  • ntaps (int) – Number of taps to use for filter calculation. See scipy.signal.firwin2 for hints on choosing a reasonable value.

  • window ({string, (string, float), float, None}) – Window function to use. See window parameter of scipy.signal.firwin2 for additional details on acceptable values.

  • polarity ({-1, 1}) – Polarity of noise. Useful if you need to present two trials in inverted polarity to cancel out electrical artifacts.

  • seed (int) – Seed to use for random number generator.

  • calibration ({BaseCalibration, None}) – Instance of a psiaudio.calibration.BaseCalibration or subclass thereof. Used to determine scaling factor for noise amplitude.

silence(fs, duration)

Utility function for generating silence

While this is a very simple function, it’s provided to ensure consistency in calculating the number of samples given sampling rate and duration when using this in the context of other functions that actually generate a waveform.

square_wave(fs, offset, samples, depth, fm, duty_cycle, alpha=0)

Create a square wave envelope that is optionally modified as a Tukey (tapered cosine) to minimize offsets.

Parameters:
  • {fs}

  • {offset}

  • {samples}

  • depth (float) – Modulation depth of window in range (0, 1)

  • fm (float) – Modulation frequency

  • duty_cycle (float) – Duty cycle of square wave (i.e., fraction of “on” portion)

  • alpha (float) – Shape parameter of the Tukey window. See scipy.signal.windows.tukey for more details.

stm(fs, frequency, level=1, phase='random', amplitude='white', depth=1, cps=4, cpo=2, duration=1, mod_type='linear', n_sidebands=10, calibration=None, return_type='time', masker=None)

Generates linear or exponential spectro-temporal modulations using an inverse FFT approach.

Parameters:
  • fs (float) – Sampling rate

  • frequency ({scalar, 1D array, dict}) – Carrier frequencies in modulation. If a scalar, this will be an amplitude-modulated tone. If an array, then the nature of the stimulus will depend on the phase. If random, then this will be spectrotemporally modulated noise. If a dictionary, then it should have fc (center frequency) and octaves as keys, indicating the center frequency and bandwidth of the noise. The upper and lower edges of the noise band will be configured so that they are equidistant from fc on an octave scale.

  • amplitude ({None, 'white', 'pink'}) – Amplitude of carrier frequencies TODO

  • phase ({float, 1D array, 'random'}) – Phase of carrier frequencies TODO

  • depth (float) – If mod_type is exponential, depth is in dB, otherwise fractional on the scale 0 to 1.

  • cps (float (Hz)) – Cycles per second of modulation.

  • cpo (float (Hz)) – Cycles per octave of modulation.

  • duration (float (sec)) – Duration of stimulus.

  • mod_type ({'linear', 'lin', 'exponential', 'exp'}) – How depth of the modulation is generated.

  • n_sidebands (int) – Number of sidebands for approximating the classic approach to spectrotemporal modulation.

  • return_type ({'time', 'csd'}) – If ‘time’, returns the time-domain waveform. If ‘csd’

  • masker ({None, dict}) – Add unmodulated masker to the stimulus. Keys must include fc (center frequency), octaves, relative_level, and type. If None, no masker is added. The masker type can either be “flanking” (i.e., masker noise is only added to either side of the STM), or “full” (i.e., masker noise is added across the full frequency range specified by fc and octaves). relative_level is specified relative to the spectrum level of the STM.

Note

For exponential modulation, implements the algorithm described in J. Acoust. Soc. Am. 149, 1434-1443 (2021) https://doi.org/10.1121/10.0003604 (Stavropoulos et al.).

stm_classic(fs, frequency, level=1, phase='random', amplitude='white', depth=1, cps=4, cpo=2, duration=1, mod_type='linear', calibration=None)

Generates linear or exponential spectro-temporal modulations using the classic approach of generating a waveform for each frequency and then summing.

This approach is slow, and is meant only for reference to compare with the faster stm approach.

tone(fs, frequency, level, phase=0, polarity=1, calibration=None, samples='auto', offset=0, duration=None)
wavs_from_path(fs, path, *args, **kwargs)