Beispiel #1
0
def test_normalization_exceptions():
    # Call without numpy array
    with raises(ValueError):
        fft.normalization(1, 1, 44100, 'rms')
    # Invalid normalization
    with raises(ValueError):
        fft.normalization(np.array([1]), 1, 44100, 'goofy')
Beispiel #2
0
def test_normalization_with_window():
    """
    Test if the window cancels out if applying the normalization and
    inverse normalization.
    """

    # test with window as list and numpy array
    windows = [[1, 1, 1, 1], np.array([1, 1, 1, 1])]

    fft_norms = ['unitary', 'amplitude', 'rms', 'power', 'psd']
    for window in windows:
        for fft_norm in fft_norms:
            print(f"testing: {window}, {fft_norm}")
            spec = fft.normalization(np.array([.5, 1, .5]),
                                     4,
                                     44100,
                                     fft_norm,
                                     window=window)
            spec = fft.normalization(spec,
                                     4,
                                     44100,
                                     fft_norm,
                                     inverse=True,
                                     window=window)
            npt.assert_allclose(spec, np.array([.5, 1, .5]), atol=1e-15)
Beispiel #3
0
def test_normalization_with_window_value_error():
    """
    Test if normalization throws a ValueError if the window has the
    wrong length.
    """

    with raises(ValueError):
        # n_samples=5, and len(window)=5
        fft.normalization(np.array([.5, 1, .5]),
                          4,
                          44100,
                          'amplitude',
                          window=[1, 1, 1, 1, 1])
Beispiel #4
0
def _arithmetic(data: tuple, domain: str, operation: Callable):
    """Apply arithmetic operations."""

    # check input and obtain meta data of new signal
    sampling_rate, n_samples, fft_norm, times, frequencies, audio_type = \
        _assert_match_for_arithmetic(data, domain)

    # apply arithmetic operation
    result = _get_arithmetic_data(data[0], n_samples, domain)

    for d in range(1, len(data)):
        result = operation(
            result, _get_arithmetic_data(data[d], n_samples, domain))

    # check if to return an audio object
    if audio_type == Signal:
        # apply desired fft normalization
        if domain == 'freq':
            result = fft.normalization(result, n_samples, sampling_rate,
                                       fft_norm)

        result = Signal(
            result, sampling_rate, n_samples, domain, fft_norm=fft_norm)
    elif audio_type == TimeData:
        result = TimeData(result, times)
    elif audio_type == FrequencyData:
        result = FrequencyData(result, frequencies, fft_norm)

    return result
Beispiel #5
0
def test_normalization_none(impulse_stub):
    spec_out = fft.normalization(impulse_stub.freq.copy(),
                                 impulse_stub.n_samples,
                                 impulse_stub.sampling_rate,
                                 impulse_stub.fft_norm,
                                 inverse=False)
    npt.assert_allclose(spec_out,
                        impulse_stub.freq,
                        atol=10 * np.finfo(float).eps)

    spec_out = fft.normalization(impulse_stub.freq.copy(),
                                 impulse_stub.n_samples,
                                 impulse_stub.sampling_rate,
                                 impulse_stub.fft_norm,
                                 inverse=True)
    npt.assert_allclose(spec_out,
                        impulse_stub.freq,
                        atol=10 * np.finfo(float).eps)
Beispiel #6
0
def test_normalization_single_sided_multi_channel_even_samples():
    # single sided test spectrum
    v = 1 / 3 + 1 / 3j
    vsq = v * np.abs(v)
    tile = (4, 2, 1)
    spec_single = np.tile(np.array([v, v, v]), tile)
    # valid number of samples of time signal corresponding to spec_single
    N = 4  # time signal with even number of samples
    Nsq = N**2  # factor for power and psd normalization
    fs = 40  # arbitrary sampling frequency for psd normalization

    # expected results for even number of samples
    sqrt2 = np.sqrt(2)
    truth = {
        'unitary': np.array([v, v * 2, v]),
        'amplitude': np.array([v / N, v / N * 2, v / N]),
        'rms': np.array([v / N, v / N / sqrt2 * 2, v / N]),
        'power': np.array([vsq / Nsq, vsq / Nsq * 2, vsq / Nsq]),
        'psd': np.array([vsq / N / fs, vsq / N / fs * 2, vsq / N / fs])
    }

    for normalization in truth:
        print(f"Assesing normalization: '{normalization}'")
        spec_out = fft.normalization(spec_single.copy(),
                                     N,
                                     fs,
                                     normalization,
                                     inverse=False)
        npt.assert_allclose(spec_out,
                            np.tile(truth[normalization], tile),
                            atol=1e-15)

        print(f"Assesing normalization: '{normalization}' (inverse)")
        spec_out_inv = fft.normalization(spec_out,
                                         N,
                                         fs,
                                         normalization,
                                         inverse=True)
        npt.assert_allclose(spec_out_inv, spec_single, atol=1e-15)
Beispiel #7
0
    def fft_norm(self, value):
        """
        The normalization for the Discrete Fourier Transform (DFT).

        See :py:func:`~pyfar.dsp.fft.normalization` for more information.
        """
        # check input
        if value not in self._VALID_FFT_NORMS:
            raise ValueError(("Invalid FFT normalization. Has to be "
                              f"{', '.join(self._VALID_FFT_NORMS)}, but found "
                              f"'{value}'"))

        # apply new normalization if Signal is in frequency domain
        if self._fft_norm != value and self._domain == 'freq':
            # de-normalize
            self._data = fft.normalization(
                self._data, self._n_samples, self._sampling_rate,
                self._fft_norm, inverse=True)
            # normalize
            self._data = fft.normalization(
                self._data, self._n_samples, self._sampling_rate,
                value, inverse=False)

        self._fft_norm = value
Beispiel #8
0
def test_normalization_both_sided_single_channel():
    # single sided test spectrum
    v = 1 / 3 + 1 / 3j
    vsq = v * np.abs(v)
    spec_single = np.array([v, v, v])
    # valid number of samples of time signal corresponding to spec_single
    N = 3  # time signal with even number of samples
    Nsq = N**2  # factor for power and psd normalization
    fs = 30  # arbitrary sampling frequency for psd normalization

    # expected results for even number of samples
    truth = {
        'unitary': np.array([v, v, v]),
        'amplitude': np.array([v / N, v / N, v / N]),
        'power': np.array([vsq / Nsq, vsq / Nsq, vsq / Nsq]),
        'psd': np.array([vsq / N / fs, vsq / N / fs, vsq / N / fs])
    }

    for normalization in truth:
        print(f"Assesing normalization: '{normalization}'")
        spec_out = fft.normalization(spec_single.copy(),
                                     N,
                                     fs,
                                     normalization,
                                     inverse=False,
                                     single_sided=False)
        npt.assert_allclose(spec_out, truth[normalization], atol=1e-15)

        print(f"Assesing normalization: '{normalization}' (inverse)")
        spec_out_inv = fft.normalization(spec_out,
                                         N,
                                         fs,
                                         normalization,
                                         inverse=True,
                                         single_sided=False)
        npt.assert_allclose(spec_out_inv, spec_single, atol=1e-15)
Beispiel #9
0
def _get_arithmetic_data(data, n_samples, domain):
    """
    Return data in desired domain without any fft normalization.

    Parameters
    ----------
    data : Signal, array like, number
        Input data
    n_samples :
        Number of samples of data if data is a Signal (required for fft
        normalization).
    domain : 'time', 'freq'
        Domain in which the data is returned

    Returns
    -------
    data_out : numpy array
        Data in desired domain without any fft normalization if data is a
        Signal. `np.asarray(data)` otherwise.
    """
    if isinstance(data, (Signal, TimeData, FrequencyData)):

        # get signal in correct domain
        if domain == "time":
            data_out = data.time.copy()
        elif domain == "freq":
            data_out = data.freq.copy()

            if isinstance(data, Signal):
                if data.fft_norm != 'none':
                    # remove current fft normalization
                    data_out = fft.normalization(
                        data_out, n_samples, data.sampling_rate,
                        data.fft_norm, inverse=True)

        else:
            raise ValueError(
                f"domain must be 'time' or 'freq' but found {domain}")

    else:
        data_out = np.asarray(data)

    return data_out