Exemplo n.º 1
0
def test_fft_orthogonality_noise_even_fftw(noise, fft_lib_pyfftw):
    signal_spec = fft.rfft(
        noise.time, noise.n_samples, noise.sampling_rate, noise.fft_norm)
    transformed_signal_time = fft.irfft(
        signal_spec, noise.n_samples, noise.sampling_rate, noise.fft_norm)
    npt.assert_allclose(
        transformed_signal_time, noise.time,
        rtol=1e-10, atol=10*np.finfo(float).eps)
Exemplo n.º 2
0
def test_fft_orthogonality_sine_odd_fftw(sine_odd, fft_lib_pyfftw):
    signal_spec = fft.rfft(
        sine_odd.time, sine_odd.n_samples, sine_odd.sampling_rate,
        sine_odd.fft_norm)
    transformed_signal_time = fft.irfft(
        signal_spec, sine_odd.n_samples, sine_odd.sampling_rate,
        sine_odd.fft_norm)
    npt.assert_allclose(
        transformed_signal_time, sine_odd.time,
        rtol=1e-10, atol=10*np.finfo(float).eps)
Exemplo n.º 3
0
    def domain(self, new_domain):
        """Set the domain of the signal."""
        if new_domain not in self._VALID_DOMAINS:
            raise ValueError("Incorrect domain, needs to be time/freq.")

        if not (self._domain == new_domain):
            # Only process if we change domain
            if new_domain == 'time':
                # If the new domain should be time, we had a saved spectrum
                # and need to do an inverse Fourier Transform
                self.time = fft.irfft(self._data, self.n_samples,
                                      self._sampling_rate, self._fft_norm)
            elif new_domain == 'freq':
                # If the new domain should be freq, we had sampled time data
                # and need to do a Fourier Transform
                self.freq = fft.rfft(self._data, self.n_samples,
                                     self._sampling_rate, self._fft_norm)
Exemplo n.º 4
0
def noise(n_samples, spectrum="white", rms=1, sampling_rate=44100, seed=None):
    """
    Generate single or multi channel normally distributed white or pink noise.

    The pink noise is generated by applying a sqrt(1/f) filter to the spectrum.

    Parameters
    ----------
    n_samples : int
        The length of the signal in samples
    spectrum : str, optional
        'white' to generate noise with constant energy across frequency.
        'pink' to generate noise with constant energy across filters with
        constant relative bandwith.
    rms : double, array like, optional
        The route mean square (RMS) value of the noise signal. A multi channel
        noise signal is generated if an array of RMS values is passed.
        The default is 1.
    sampling_rate : int, optional
        The sampling rate in Hz. The default is 44100.
    seed : int, None
        The seed for the random generator. Pass a seed to obtain identical
        results for multiple calls of white noise. The default is None, which
        will yield different results with every call.

    Returns
    -------
    signal : Signal
        The noise as a Signal object. The Signal is in the time domain and
        has the 'rms' FFT normalization (see pyfar.fft.normalization).
    """

    # generate the noise
    rms = np.atleast_1d(rms)
    n_samples = int(n_samples)
    cshape = np.atleast_1d(rms).shape
    rng = np.random.default_rng(seed)
    noise = rng.standard_normal(np.prod(cshape + (n_samples, )))
    noise = noise.reshape(cshape + (n_samples, ))

    if spectrum == "pink":
        # apply 1/f filter in the frequency domain
        noise = fft.rfft(noise, n_samples, sampling_rate, 'none')
        noise /= np.sqrt(np.arange(1, noise.shape[-1] + 1))
        noise = fft.irfft(noise, n_samples, sampling_rate, 'none')
    elif spectrum != "white":
        raise ValueError(
            f"spectrum is '{spectrum}' but must be 'white' or 'pink'")

    # level the noise
    rms_current = np.atleast_1d(np.sqrt(np.mean(noise**2, axis=-1)))
    for idx in np.ndindex(rms.shape):
        noise[idx] = noise[idx] / rms_current[idx] * rms[idx]

    # save to Signal
    nl = "\n"  # required as variable because f-strings cannot contain "\"
    comment = f"{spectrum} noise signal (rms = {str(rms).replace(nl, ',')})"

    signal = Signal(noise, sampling_rate, fft_norm="rms", comment=comment)

    return signal