def test_puretone_run_sequence(): """ Check that puretone's synthesize_sequence() correctly accepts a list of dicts and returns a correspond ing number of stimuli """ synth = sy.PureTone() # Generate 1000 and 2000 Hz pure tones using synthesize_parameter_sequence results = synth.synthesize_sequence([{ 'freq': 1000, 'level': 50, 'phase': 0, 'dur': 1, 'fs': int(48e3), 'dur_ramp': 0.1 }, { 'freq': 2000, 'level': 50, 'phase': 0, 'dur': 1, 'fs': int(48e3), 'dur_ramp': 0.1 }]) # Generate references manually reference1 = sg.cosine_ramp( sg.scale_dbspl(sg.pure_tone(1000, 0, 1, int(48e3)), 50), 0.1, int(48e3)) reference2 = sg.cosine_ramp( sg.scale_dbspl(sg.pure_tone(2000, 0, 1, int(48e3)), 50), 0.1, int(48e3)) assert np.all(results[0] == reference1) and np.all( results[1] == reference2)
def synthesize(self, freq=1000, level=50, phase=0, dur=1, dur_ramp=0.1, fs=int(500e3), **kwargs): """ Synthesizes a single instance of a scaled copy of a pure tone with a raised-cosine ramp. Stimulus duration is defined as the duration between the half-amplitude points of the ramps. Arguments: freq (float): frequency of pure tone in Hz level (float): level of pure tone in dB SPL phase (float): phase offset in degrees, must be between 0 and 360 dur (float): duration in seconds dur_ramp (float): duration of raised-cosine ramp in seconds fs (int): sampling rate in Hz Returns: output (array): pure tone """ pt = sg.pure_tone(freq, phase, dur + dur_ramp, fs) pt = sg.scale_dbspl(pt, level) pt = sg.cosine_ramp(pt, dur_ramp, fs) return pt
def test_scale_dbspl_pure_tone(): """ Check that we can specify a dB SPL value for a pure tone and have the tone calibrate to that value """ baseline_signal = sg.pure_tone(1000, 0, 1, int(48e3)) scaled_signal = sg.scale_dbspl(baseline_signal, 43) np.testing.assert_approx_equal(sg.dbspl_pascal(scaled_signal), 43, significant=3)
def synthesize(self, freq=1000, level=50, phase=0, dur=1, dur_ramp=0.1, fs=int(48e3), **kwargs): """ Synthesizes a single instance of a scaled copy of a pure tone with a raised-cosine ramp. Args: freq (float): frequency of pure tone in Hz level (float): level of pure tone in dB SPL phase (float): phase offset in degrees, must be between 0 and 360 dur (float): duration in seconds dur_ramp (float): duration of raised-cosine ramp in seconds fs (int): sampling rate in Hz Returns: output (array): pure tone """ # Synthesize stimulus pt = sg.pure_tone(freq, phase, dur, fs) pt = sg.scale_dbspl(pt, level) pt = sg.cosine_ramp(pt, dur_ramp, fs) # Raise warnings about arguments check_args(kwargs) return pt
def test_puretone_incremented_sequence(): """ Check that puretone's synthesize_sequence() and increment_sequence() successfully combine to produce two pure tones, one with a slightly higher frequency""" synth = sy.PureTone() # Generate 1000 and 2000 Hz pure tones using synthesize_parameter_sequence results = synth.synthesize_sequence( increment_parameters(parameters={'freq': 1000}, increments={'freq': 0.001})) # Generate references manually reference1 = sg.cosine_ramp( sg.scale_dbspl(sg.pure_tone(1000, 0, 1, int(48e3)), 50), 0.1, int(48e3)) reference2 = sg.cosine_ramp( sg.scale_dbspl(sg.pure_tone(1000.001, 0, 1, int(48e3)), 50), 0.1, int(48e3)) assert np.all(results[0] == reference1) and np.all( results[1] == reference2)
def test_puretone_synthesize(): """ Check that PureTone object can successfully synthesize and replicates standard pure tone synthesis""" synth = sy.PureTone() output = synth.synthesize(1000, 50, 0, 1, 0.1, int(48e3)) reference = sg.cosine_ramp( sg.scale_dbspl(sg.pure_tone(1000, 0, 1, int(48e3)), 50), 0.1, int(48e3)) assert np.all(output == reference)
def test_pure_tone_single_frequency(): """ Check to make sure that manually synthesizing a pure tone produces the same results as pure_tone() """ fs = int(48e3) f = 1000 t = np.linspace(0, 1, fs) target = np.sin(2 * np.pi * t * f) output = sg.pure_tone(f, 0, 1, fs) assert np.max(np.abs(output - target)) < 1e-10
def test_pure_tone_multiple_components(): """ Check to make sure that manually synthesizing a pure tone produces the same results as pure_tone() when we pass multiple components """ fs = int(48e3) f = 1000 t = np.linspace(0, 1, fs) target = np.sin(2 * np.pi * t * f) output = sg.pure_tone(np.array([100, 200, f]), np.array([0, 0, 0]), 1, fs) assert np.max(np.abs(output[:, 2] - target)) < 1e-10
def test_dbspl_error_one_channel_empty(): """ Check that an array with one empty channel still raises an error """ try: stim = np.stack( [sg.pure_tone(1, 0, 1, int(48e3)), np.zeros(int(48e3))], axis=1) sg.dbspl_pascal(stim) raise Exception('This should have failed!') except ValueError: return
def test_amplify_power_and_amplitude_decrease(): """ Check that amplifying a signal by -10 dB produces the corresponding changes in power and amplitude""" baseline_signal = sg.pure_tone(1000, 0, 1, int(48e3)) amplified_signal = sg.amplify(baseline_signal, -6) # Test that amplitude ratio is about 2 np.testing.assert_approx_equal(np.max(amplified_signal) / np.max(baseline_signal), 0.501, significant=3) # Test that power ratio is about 4 np.testing.assert_approx_equal(np.max(amplified_signal)**2 / np.max(baseline_signal**2), 0.251, significant=3)
def test_dbspl_pure_tone_rms1(): """ Check that pure tone with RMS 1 calibrates to 90.9 dB SPL""" x = sg.pure_tone(1000, 0, 1, int(48e3)) x = x / sg.rms(x) np.testing.assert_approx_equal(sg.dbspl_pascal(x), 100, significant=1)
def test_dbspl_pure_tone_peak1(): """ Check that pure tone with peak 1 calibrates to 90.9 dB SPL""" np.testing.assert_approx_equal(sg.dbspl_pascal( sg.pure_tone(1000, 0, 1, int(48e3))), 90.9, significant=1)
def test_amplify_by_zero_db(): """ Check that rms does not change when amplifying a signal by 0 dB""" baseline_signal = sg.pure_tone(1000, 0, 1, int(48e3)) amplified_signal = sg.amplify(baseline_signal, 0) assert sg.rms(baseline_signal) == sg.rms(amplified_signal)
def test_rms_pure_tone(): """ Check that pure tone with peak 1 calibrates to 0.707 rms""" np.testing.assert_approx_equal(sg.rms(sg.pure_tone(1000, 0, 1, int(48e3))), 0.707, significant=3)