def test_getter_signal_type(): """Test if attribute signal type is accessed correctly.""" signal = Signal([1, 2, 3], 44100, fft_norm='none') npt.assert_string_equal(signal.signal_type, 'energy') signal = Signal([1, 2, 3], 44100, fft_norm='rms') npt.assert_string_equal(signal.signal_type, 'power')
def test_get_arithmetic_data_with_signal(): # all possible combinations of `domain`, `signal_type`, and `fft_norm` meta = [['time', None], ['freq', None], ['time', 'unitary'], ['freq', 'unitary'], ['time', 'amplitude'], ['freq', 'amplitude'], ['time', 'rms'], ['freq', 'rms'], ['time', 'power'], ['freq', 'power'], ['time', 'psd'], ['freq', 'psd']] # reference signal - _get_arithmetic_data should return the data without # any normalization regardless of the input data s_ref = Signal([1, 0, 0], 44100) for m_in in meta: # create input signal with current domain, type, and norm s_in = Signal([1, 0, 0], 44100, fft_norm=m_in[1]) s_in.domain = m_in[0] for domain in ['time', 'freq']: print(f"Testing from {m_in[0]} ({m_in[1]}) to {domain}.") # get output data data_out = signal._get_arithmetic_data(s_in, n_samples=3, domain=domain) if domain == 'time': npt.assert_allclose(s_ref.time, data_out, atol=1e-15) elif domain == 'freq': npt.assert_allclose(s_ref.freq, data_out, atol=1e-15)
def test_division(): # only test one case - everything else is tested below x = Signal([1, 0, 0], 44100) y = Signal([2, 2, 2], 44100) z = signal.divide((x, y), 'time') # check result npt.assert_allclose(z.time, np.atleast_2d([0.5, 0, 0]), atol=1e-15)
def test_power(): # only test one case - everything else is tested below x = Signal([2, 1, 0], 44100) y = Signal([2, 2, 2], 44100) z = signal.power((x, y), 'time') # check result npt.assert_allclose(z.time, np.atleast_2d([4, 1, 0]), atol=1e-15)
def test_magic_setitem_wrong_norm(sine, sine_rms): """Test the magic function __setitem__.""" signal = Signal(sine.time, sine.sampling_rate, fft_norm=sine.fft_norm) set_signal = Signal(sine_rms.time, sine_rms.sampling_rate, fft_norm=sine_rms.fft_norm) with pytest.raises(ValueError, match='FFT norms do not match'): signal[0] = set_signal
def test___eq___notEqual(sine_signal, sine): actual = Signal(0.5 * sine.time, sine.sampling_rate, domain='time') assert not sine_signal == actual actual = Signal(sine.time, 2 * sine.sampling_rate, domain='time') assert not sine_signal == actual actual = sine_signal.copy() actual.comment = f'{actual.comment} A completely different thing' assert not sine_signal == actual
def test_multiplication(): # only test one case - everything else is tested below x = Signal([1, 0, 0], 44100) y = Signal([0, 1, 0], 44100) z = signal.multiply((x, y), 'time') # check result npt.assert_allclose(z.time, np.atleast_2d([0, 0, 0]), atol=1e-15)
def test_getter_signal_type(sine, sine_rms): """Test if attribute signal type is accessed correctly.""" signal = Signal(sine.time, sine.sampling_rate, fft_norm=sine.fft_norm) npt.assert_string_equal(signal.signal_type, 'energy') signal = Signal(sine_rms.time, sine_rms.sampling_rate, fft_norm=sine_rms.fft_norm) npt.assert_string_equal(signal.signal_type, 'power')
def test___eq___notEqual(): time = np.arange(2 * 3 * 4).reshape((2, 3, 4)) signal = Signal(time, 44100, domain='time') actual = Signal(0.5 * time, 44100, domain='time') assert not signal == actual actual = Signal(time, 2 * 44100, domain='time') assert not signal == actual comment = f'{signal.comment} A completely different thing' actual = Signal(time, 44100, domain='time', comment=comment) assert not signal == actual
def test_setter_fft_norm(): spec_power_unitary = np.atleast_2d([1, 2, 1]) spec_power_amplitude = np.atleast_2d([1 / 4, 2 / 4, 1 / 4]) signal = Signal(spec_power_unitary, 44100, n_samples=4, domain='freq', fft_norm='unitary') # changing the fft_norm also changes the spectrum signal.fft_norm = 'amplitude' assert signal.fft_norm == 'amplitude' npt.assert_allclose(signal.freq, spec_power_amplitude, atol=1e-15) # changing the fft norm in the time domain does not change the time data signal.domain = 'time' time_power_amplitude = signal._data.copy() signal.fft_norm = 'unitary' npt.assert_allclose(signal.time, time_power_amplitude) npt.assert_allclose(signal.freq, spec_power_unitary) # setting an invalid fft_norm with pytest.raises(ValueError): signal.fft_norm = 'bullshit'
def test_signal_init_default_parameter(sine): # using all defaults signal = Signal(sine.time, sine.sampling_rate) assert signal.domain == 'time' assert signal.fft_norm == 'none' assert signal.comment == 'none' assert signal.fft_norm == 'none'
def test_signal_init_default_parameter(): # using all defaults signal = Signal([1, 2, 3], 44100) assert signal.domain == 'time' assert signal.fft_norm == 'none' assert signal.comment == 'none' assert signal.fft_norm == 'none'
def read_wav(filename): """ Import a WAV file as signal object. This method is based on scipy.io.wavfile.read(). Parameters ---------- filename : string or open file handle Input wav file. Returns ------- signal : signal instance An audio signal object from the pyfar Signal class containing the audio data from the WAV file. Notes ----- * This function is based on scipy.io.wavfile.write(). * This function cannot read wav files with 24-bit data. """ sampling_rate, data = wavfile.read(filename) signal = Signal(data.T, sampling_rate, domain='time') return signal
def test_sti_warn_data_type_unknown(): sig = Signal(np.zeros((1, 31072)), 44100) sig.time[0] = 1 with pytest.raises(ValueError, match="Data_type is 'generic' but must " "be 'electrical' or 'acoustical'."): sti.sti(sig, data_type="generic")
def test_signal_init_val(sine): """Test to init Signal with complete parameters.""" signal = Signal(sine.time, sine.sampling_rate, domain='time', fft_norm=sine.fft_norm) assert isinstance(signal, Signal)
def test_iter_write(): data = np.ones((3, 1024)) * np.atleast_2d(np.arange(3)).T sig = Signal(data, 1) sig.domain = 'time' for idx, s in enumerate(sig): sig[idx] = s
def signal_stub(time, freq, sampling_rate, fft_norm): """Function to generate stub of pyfar Signal class based on MagicMock. The properties of the signal are set without any further check. Parameters ---------- time : ndarray Time data freq : ndarray Frequency data sampling_rate : float Sampling rate fft_norm : 'unitary', 'amplitude', 'rms', 'power', 'psd' See documentation of pyfar.fft.normalization. Returns ------- signal stub of pyfar Signal class """ # Use MagicMock and side_effect to mock __getitem__ # See "Mocking a dictionary with MagicMock", # https://het.as.utexas.edu/HET/Software/mock/examples.html def getitem(slice): time = np.atleast_2d(signal.time[slice]) freq = np.atleast_2d(signal.freq[slice]) item = signal_stub(time, freq, signal.sampling_rate, signal.fft_norm) return item def find_nearest_time(times): samples = np.zeros(len(times), dtype=int) for idx, time in enumerate(times): samples[idx] = np.argmin(np.abs(signal.times - time)) return samples def find_nearest_frequency(freqs): bin = np.zeros(len(freqs), dtype=int) for idx, freq in enumerate(freqs): bin[idx] = np.argmin(np.abs(signal.frequencies - freq)) return bin signal = mock.MagicMock( spec_set=Signal(time, sampling_rate, domain='time')) signal.time = np.atleast_2d(time) signal.freq = np.atleast_2d(freq) signal.sampling_rate = sampling_rate signal.fft_norm = fft_norm signal.n_samples = signal.time.shape[-1] signal.n_bins = signal.freq.shape[-1] signal.cshape = signal.time.shape[:-1] signal.times = np.atleast_1d( np.arange(0, signal.n_samples) / sampling_rate) signal.frequencies = np.atleast_1d( np.fft.rfftfreq(signal.n_samples, 1 / sampling_rate)) signal.__getitem__.side_effect = getitem signal.find_nearest_time = find_nearest_time signal.find_nearest_frequency = find_nearest_frequency return signal
def test_sti_value_error_gender(): sig = Signal(np.zeros((1, 31072)), 44100) sig.time[0] = 1 with pytest.raises(ValueError, match="Gender is 'generic' but must be " "'male' or 'female'."): sti.sti(sig, gender="generic")
def test_sti_value_error_level(): sig = Signal(np.zeros((1, 31072)), 44100) sig.time[0] = 1 lvl = np.array([30, 30, 30, 30, 30, 30]) with pytest.raises(ValueError, match="Level consists of wrong number of " "components."): sti.sti(sig, level=lvl)
def test_iter_domain_change(): data = np.ones((3, 1024)) * np.atleast_2d(np.arange(3)).T sig = Signal(data, 1) sig.domain = 'time' with pytest.raises(RuntimeError, match='domain changes'): for s in sig: s.freq
def test_reshape(): # test reshape with tuple signal_in = Signal(np.random.rand(6, 256), 44100) signal_out = signal_in.reshape((3, 2)) npt.assert_allclose(signal_in._data.reshape(3, 2, -1), signal_out._data) assert id(signal_in) != id(signal_out) signal_out = signal_in.reshape((3, -1)) npt.assert_allclose(signal_in._data.reshape(3, 2, -1), signal_out._data) assert id(signal_in) != id(signal_out) # test reshape with int signal_in = Signal(np.random.rand(3, 2, 256), 44100) signal_out = signal_in.reshape(6) npt.assert_allclose(signal_in._data.reshape(6, -1), signal_out._data) assert id(signal_in) != id(signal_out)
def test_flatten(): # test 2D signal (flatten should not change anything) x = np.random.rand(2, 256) signal_in = Signal(x, 44100) signal_out = signal_in.flatten() npt.assert_allclose(signal_in._data, signal_out._data) assert id(signal_in) != id(signal_out) # test 3D signal x = np.random.rand(3, 2, 256) signal_in = Signal(x, 44100) signal_out = signal_in.flatten() npt.assert_allclose(signal_in._data.reshape((6, -1)), signal_out._data) assert id(signal_in) != id(signal_out)
def test_sti_value_error_snr(): sig = Signal(np.zeros((1, 31072)), 44100) sig.time[0] = 1 sn = np.array([30, 30, 30, 30, 30, 30]) with pytest.raises(ValueError, match="SNR consists of wrong number of " "components."): sti.sti(sig, snr=sn)
def test_sti_warn_data_type_not_given(): sig = Signal(np.zeros((1, 31072)), 44100) sig.time[0] = 1 with pytest.warns(UserWarning, match="Data type is considered as " "acoustical. Consideration of masking effects not valid " "for electrically obtained signals."): sti.sti(sig)
def test_sti_female(): expected = np.array([0.6116]) sig = Signal(np.zeros((1, 131072)), 44100) sig.time[0, 0] = 1 sig.time[0, 1000] = 1 sig.time[0, 10000] = 1 array = sti.sti(sig, gender="female") np.testing.assert_allclose(array, expected, rtol=1e-3, atol=0)
def test_domain_setter_time_when_freq(sine): signal = Signal(sine.freq, sine.sampling_rate, domain='freq', fft_norm=sine.fft_norm) domain = 'time' signal.domain = domain assert signal.domain == domain npt.assert_allclose(signal._data, sine.time, atol=1e-10, rtol=1e-10)
def test_sti_warn_snr_low(): sig = Signal(np.zeros((1, 31072)), 44100) sig.time[0] = 1 lvl = np.array([70, 70, 70, 70, 70, 70, 70]) sn = np.array([10, 30, 30, 30, 30, 30, 30]) with pytest.warns(UserWarning, match="SNR should be at least 20 dB for " "every octave band."): sti.sti(sig, level=lvl, snr=sn)
def test_sti_lvl_snr_1D(): expected = np.array([0.8933]) sig = Signal(np.zeros((1, 131072)), 44100) sig.time[0, 0] = 1 sig.time[0, 1000] = 1 lvl = np.array([70, 70, 70, 70, 70, 70, 70]) sn = np.array([30, 30, 30, 30, 30, 30, 30]) array = sti.sti(sig, level=lvl, snr=sn) np.testing.assert_allclose(array, expected, rtol=1e-3, atol=0)
def test_sti_amb_false(): expected = np.array([0.8864]) sig = Signal(np.zeros((1, 131072)), 44100) sig.time[0, 0] = 1 sig.time[0, 1000] = 1 lvl = np.array([70, 70, 70, 70, 70, 70, 70]) sn = np.array([20, 20, 20, 20, 20, 20, 20]) array = sti.sti(sig, level=lvl, snr=sn, amb=False) np.testing.assert_allclose(array, expected, rtol=1e-3, atol=0)
def test_sti_2D(): expected = np.ones((2, 2)) sig = Signal(np.zeros((2, 2, 131072)), 44100) sig.time[0, 0, 0] = 1 sig.time[1, 0, 0] = 1 sig.time[0, 1, 0] = 1 sig.time[1, 1, 0] = 1 array = sti.sti(sig) np.testing.assert_allclose(array, expected, rtol=1e-2, atol=0)