.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "gallery/notch-noise-abr.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_gallery_notch-noise-abr.py: ==================== Tones in notch noise ==================== This demonstrates how to generate notch-noise tone pips that can be used for an ABR stimulus. .. GENERATED FROM PYTHON SOURCE LINES 9-19 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from psiaudio import calibration, stim, util cal = calibration.FlatCalibration.from_spl(94) fs = 100e3 .. GENERATED FROM PYTHON SOURCE LINES 20-22 In human ABRs, duration typically varies with frequency but the number of cycles are fixed. .. GENERATED FROM PYTHON SOURCE LINES 22-28 .. code-block:: Python n_cycles = 8 frequency = 4e3 duration = 8 / 4e3 noise_duration = 20e-3 noise_level = 94-20 .. GENERATED FROM PYTHON SOURCE LINES 29-31 Since the calibration scales stimuli to match the requested RMS level, we need to subtract by 3 dB if we want peak-equivalent SPL. .. GENERATED FROM PYTHON SOURCE LINES 31-41 .. code-block:: Python tone = stim.ramped_tone( fs=fs, duration=duration, rise_time=None, frequency=frequency, level=94 - 3, calibration=cal, ) .. GENERATED FROM PYTHON SOURCE LINES 42-45 Notch noise calculations. By dividing or multiplying by the same number, we generate a notch where both sides are equidistant from the target frequency on a log scale. .. GENERATED FROM PYTHON SOURCE LINES 45-48 .. code-block:: Python fl = frequency / 1.5 fh = frequency * 1.5 .. GENERATED FROM PYTHON SOURCE LINES 49-50 The gain dictionary must start at 0 Hz and end at Nyquist (i.e., fs/2). .. GENERATED FROM PYTHON SOURCE LINES 50-77 .. code-block:: Python gains = { # No attenuation for frequencies below the notch. The transition from no # attenuation to full attenuation is specified by fl / 1.1 to fl. 0: 0, fl / 1.1: 0, # Attenuate frequencies in the notch by 80 dB. fl: -80, fh: -80, # No attenuation for frequencies above the notch. fh * 1.1: 0, fs / 2: 0 } noise = stim.shaped_noise( fs=fs, gains=gains, duration=noise_duration, level=noise_level, calibration=cal, ) noise_level = cal.get_spl(None, util.rms(noise)) tone_level = cal.get_spl(frequency, tone.max()) .. GENERATED FROM PYTHON SOURCE LINES 78-80 Alternatively, we can use a simple notch like that used by Intelligent Hearing Systems. .. GENERATED FROM PYTHON SOURCE LINES 80-107 .. code-block:: Python # Here, we want to set the noise level such that the spectrum level is 20 dB # below the peak-equivalent of the tone burst. This is a somewhat complex # calculation since it requires us to figure out how the noise is divided into # bins given the noise duration and sampling rate. The number of FFT bins is # defined as fs / N where N is the number of samples. Since N is equal to # duration * fs, this simplifies to 1 / duration. Next, we are assuming the # noise will be fully broadband, so this means the noise will span the full # range of possible frequencies (0 to Nyquist). By dividing the frequency range # by the bin width, we get the number of bands the noise is distributed across. bin_width = 1 / noise_duration f_max = fs / 2 n_bins = f_max / bin_width band_level = util.spectrum_to_band_level(94-20, n_bins) ihs_noise = stim.notch_noise( fs=fs, notch_frequency=frequency, q=1.33, level=band_level, duration=noise_duration, calibration=cal, ) ihs_noise_level = cal.get_spl(None, util.rms(ihs_noise)) .. GENERATED FROM PYTHON SOURCE LINES 108-109 Calculate an offset such that the tone is centeredi n the time plot. .. GENERATED FROM PYTHON SOURCE LINES 109-140 .. code-block:: Python tone_offset = 10e-3 - duration / 2 t_tone = (np.arange(len(tone)) / fs + tone_offset) * 1e3 t_noise = np.arange(len(noise)) / fs * 1e3 psd_tone = util.patodb(util.psd_df(tone, fs)) psd_noise = util.patodb(util.psd_df(noise, fs)) psd_ihs_noise = util.patodb(util.psd_df(ihs_noise, fs)) figure, axes = plt.subplots(1, 2, figsize=(8, 4)) axes[0].plot(t_tone, tone) axes[0].plot(t_noise, noise) axes[0].set_xlabel('Time (msec)') axes[0].set_ylabel('Amplitude (Pascals)') axes[1].semilogx(psd_tone, label=f'Tone ({tone_level:.1f} dB peSPL)') axes[1].semilogx(psd_noise, label=f'Notch noise ({noise_level:.1f} dB SPL)') axes[1].semilogx(psd_ihs_noise, label=f'IHS notch noise ({ihs_noise_level:.1f} dB SPL)') ticks = util.octave_space(250, 16e3, 1) axes[1].axis(xmin=ticks[0], xmax=ticks[-1], ymin=0, ymax=100) axes[1].set_xticks(ticks) axes[1].set_xticklabels(f'{t*1e-3:.2f}' for t in ticks) axes[1].set_xticks([], minor=True) axes[1].set_xlabel('Frequency (kHz)') axes[1].set_ylabel('Amplitude (dB SPL)') axes[1].legend() figure.tight_layout() plt.show() .. image-sg:: /gallery/images/sphx_glr_notch-noise-abr_001.png :alt: notch noise abr :srcset: /gallery/images/sphx_glr_notch-noise-abr_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 8.179 seconds) .. _sphx_glr_download_gallery_notch-noise-abr.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: notch-noise-abr.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: notch-noise-abr.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: notch-noise-abr.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_