Example #1
0
def test_ports_and_connections_when_activated():
    """tests the creation of connections and ports while the client is activated."""
    with _create_client() as client:
        client.inports.register("input")
        client.outports.register("output")
        # test creating and connecting ports, when the client is deactivated
        signal1 = sumpf.MergeSignals([
            sumpf.SineWave(length=2**12),
            sumpf.HannWindow(length=2**12),
            sumpf.ExponentialSweep(length=2**12)
        ]).output()
        xruns = _XRunHandler()
        sumpf_jack = sumpf.Jack(name="port_creation",
                                input_signal=signal1,
                                auto_deactivate=False)
        sumpf_jack.xruns.connect(xruns.xrun)
        sumpf_jack.activate()
        sumpf_jack.add_input_port("index1")
        sumpf_jack.add_input_port("shortname")
        sumpf_jack.add_input_port("name")
        sumpf_jack.add_input_port("index2")
        sumpf_jack.connect(0, 0)
        sumpf_jack.connect("Hann window", "shortname")
        sumpf_jack.connect("port_creation:Sweep", "port_creation:name")
        sumpf_jack.connect(0, "Testclient:input")
        sumpf_jack.connect("Testclient:output", 3)
        sumpf_jack.start()
        assert sumpf_jack.output().channels()[0:3] == pytest.approx(
            signal1.channels())
        # test that the connections remain established, when the output ports change
        signal2 = sumpf.MergeSignals([
            sumpf.HannWindow(length=2**12),
            sumpf.ExponentialSweep(length=2**12),
            sumpf.SineWave(length=2**12)
        ]).output()
        sumpf_jack.input(signal2)
        sumpf_jack.start()
        assert sumpf_jack.output().channels()[0:3] == pytest.approx(
            signal2.channels())
        # test that the connections are broken, when the input ports are changed
        sumpf_jack.remove_input_port("index1")
        sumpf_jack.remove_input_port("shortname")
        sumpf_jack.remove_input_port("name")
        sumpf_jack.remove_input_port("index2")
        sumpf_jack.add_input_port("a")
        sumpf_jack.add_input_port("b")
        sumpf_jack.add_input_port("c")
        sumpf_jack.add_input_port("d")
        sumpf_jack.start()
        assert (sumpf_jack.output().channels()[0:3] == numpy.zeros(
            shape=sumpf_jack.output()[0:3].shape())).all()
        sumpf_jack.deactivate()
Example #2
0
def test_playback_and_recording():
    """Tests connecting ports in JACK, playing back and recording a signal."""
    with _create_client(
    ):  # skip this test if the JACK server is not running or the JACK client library is not available
        excitation = sumpf.MergeSignals([
            sumpf.GaussianNoise(length=2**15).shift(-5),
            sumpf.SineWave(length=2**15),
            sumpf.HannWindow(length=2**15)
        ]).output()
        assert excitation.offset(
        ) % 2 != 0  # check that the offset and length are odd values, that
        assert excitation.length(
        ) % 2 != 0  # do not coincide with the blocks of the JACK server
        xruns = _XRunHandler()
        jack = sumpf.Jack(input_signal=excitation,
                          input_ports=["capture_1", "channel_2", "record_3"])
        jack.xruns.connect(xruns.xrun)
        jack.connect("Gaussian noise", "SuMPF:capture_1")
        jack.connect(1, "channel_2")
        jack.connect("SuMPF:Hann window", 2)
        jack.start()
        response = jack.output()
        assert response.channels() == pytest.approx(excitation.channels())
        assert response.offset() == excitation.offset()
        assert response.sampling_rate() == jack.sampling_rate()  # pylint: disable=comparison-with-callable; pylint got confused by the connectors.MacroOutput
        assert response.labels() == ("capture_1", "channel_2", "record_3")
        assert xruns.xruns == []
Example #3
0
def test_hann_window(plateau, sampling_rate, length, symmetric, overlap):
    """Tests the implementation of the Hann window."""
    window = sumpf.HannWindow(plateau, sampling_rate, length, symmetric)
    assert window.labels() == ("Hann window", )
    __check_window(window=window,
                   function=numpy.hanning,
                   plateau=plateau,
                   sampling_rate=sampling_rate,
                   length=length,
                   symmetric=symmetric,
                   overlap=overlap,
                   shape_consistency="complete")
    if length:
        plateau = int(round(length * plateau))
        assert abs(window.recommended_overlap() -
                   (length - plateau) / 2) <= 1.0
Example #4
0
def get_window(window, overlap, symmetric=True, sampling_rate=48000.0):
    """Convenience method for defining a window function

    * if window is an integer, a window function with that length will be generated.
       * if overlap is zero, the generated window will be a rectangular window.
       * otherwise, a Hann window will be generated.
    * if window is a :func:`numpy.array`, it will be wrapped in a :class:`~sumpf.Signal`.
    * if window is iterable, it will be converted to a :func:`numpy.array` and then wrapped in a :class:`~sumpf.Signal`.
    * otherwise, it will be returned as it is.

    :param window: an integer window length or a window signal
    :param overlap: the overlap in the application of the window function as an integer or a float
    :param symmetric: True, if the window's last sample shall be the same as its
                      first sample. False, if the window's last sample shall be
                      the same as its second sample. The latter is often beneficial
                      in segmentation applications, as it makes it easier to meet
                      the "constant overlap add"-constraint.
    :param sampling_rate: optional, specifies the sampling rate if a window is generated
    :returns: a :class:`~sumpf.Signal` instance
    """
    if isinstance(window, int):
        if overlap == 0:
            return sumpf.RectangularWindow(sampling_rate=sampling_rate,
                                           length=window,
                                           symmetric=symmetric)
        else:
            return sumpf.HannWindow(sampling_rate=sampling_rate,
                                    length=window,
                                    symmetric=symmetric)
    elif isinstance(window, numpy.ndarray):
        if len(window.shape) == 1:
            return sumpf.Signal(channels=numpy.array([window]),
                                sampling_rate=sampling_rate,
                                labels=("Window", ))
        elif len(window.shape) == 2:
            return sumpf.Signal(channels=window,
                                sampling_rate=sampling_rate,
                                labels=("Window", ) * len(window))
        else:
            raise ValueError(
                f"Array of shape {window.shape} cannot be wrapped in a Signal")
    elif isinstance(window, collections.abc.Iterable):
        return get_window(window=numpy.array(window),
                          overlap=overlap,
                          sampling_rate=sampling_rate)
    else:
        return window
Example #5
0
def test_bandwidth():
    """Tests the bandwidth of the window functions, for which it is known from literature."""
    bandwidths = {
        sumpf.RectangularWindow(): 0.8845,
        sumpf.BartlettWindow(): 1.2736,
        sumpf.HannWindow(): 1.4382,
        sumpf.HammingWindow(): 1.3008,
        sumpf.KaiserWindow(2.0 * math.pi): 1.4270,
        sumpf.KaiserWindow(2.5 * math.pi): 1.5700,
        sumpf.KaiserWindow(3.0 * math.pi): 1.7025,
        sumpf.KaiserWindow(3.5 * math.pi): 1.8262,
        sumpf.KaiserWindow(4.0 * math.pi): 1.9417,
        sumpf.KaiserWindow(4.5 * math.pi): 2.0512,
        sumpf.KaiserWindow(5.0 * math.pi): 2.1553,
        sumpf.KaiserWindow(5.5 * math.pi): 2.2546,
        sumpf.KaiserWindow(6.0 * math.pi): 2.3499,
        sumpf.KaiserWindow(6.5 * math.pi): 2.4414,
        sumpf.KaiserWindow(7.0 * math.pi): 2.5297
    }
    if scipy:
        bandwidths.update({
            sumpf.BlackmanHarrisWindow():
            1.8962,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL3):
            1.8496,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL3A):
            1.6828,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL3B):
            1.6162,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL4):
            2.1884,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL4A):
            2.0123,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL4B):
            1.9122,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL4C):
            1.8687,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT3F):
            3.1502,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT4F):
            3.7618,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT5F):
            4.2910,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT3M):
            2.9183,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT4M):
            3.3451,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT5M):
            3.8340,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.FTNI):
            2.9355,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.FTHP):
            3.3846,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.FTSRS):
            3.7274,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT70):
            3.3720,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT90D):
            3.8320,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT95):
            3.7590,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT116D):
            4.1579,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT144D):
            4.4697,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT169D):
            4.7588,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT196D):
            5.0308,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT223D):
            5.3000,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT248D):
            5.5567
        })
    for window in bandwidths:
        resolution = window.fourier_transform().resolution()
        bandwidth = bandwidths[window] * resolution
        assert window.bandwidth() == pytest.approx(bandwidth, rel=0.01)
        assert window.bandwidth(oversampling=32) == pytest.approx(bandwidth,
                                                                  rel=0.0025)
Example #6
0
def test_scalloping_loss():
    """Tests the scalloping loss of the window functions, for which it is known from literature."""
    scalloping_losses = {
        sumpf.RectangularWindow(): 3.9224,
        sumpf.BartlettWindow(): 1.8242,
        sumpf.HannWindow(): 1.4236,
        sumpf.HammingWindow(): 1.7514,
        sumpf.KaiserWindow(2.0 * math.pi): 1.4527,
        sumpf.KaiserWindow(2.5 * math.pi): 1.2010,
        sumpf.KaiserWindow(3.0 * math.pi): 1.0226,
        sumpf.KaiserWindow(3.5 * math.pi): 0.8900,
        sumpf.KaiserWindow(4.0 * math.pi): 0.7877,
        sumpf.KaiserWindow(4.5 * math.pi): 0.7064,
        sumpf.KaiserWindow(5.0 * math.pi): 0.6403,
        sumpf.KaiserWindow(5.5 * math.pi): 0.5854,
        sumpf.KaiserWindow(6.0 * math.pi): 0.5392,
        sumpf.KaiserWindow(6.5 * math.pi): 0.4998,
        sumpf.KaiserWindow(7.0 * math.pi): 0.4657
    }
    if scipy:
        scalloping_losses.update({
            sumpf.BlackmanHarrisWindow():
            0.8256,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL3):
            0.8630,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL3A):
            1.0453,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL3B):
            1.1352,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL4):
            0.6184,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL4A):
            0.7321,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL4B):
            0.8118,
            sumpf.NuttallWindow(sumpf.NuttallWindow.functions.NUTTALL4C):
            0.8506,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT3F):
            0.0082,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT4F):
            0.0041,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT5F):
            0.0025,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT3M):
            0.0115,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT4M):
            0.0067,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.SFT5M):
            0.0039,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.FTSRS):
            0.0156,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT70):
            0.0065,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT90D):
            0.0039,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT95):
            0.0044,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT116D):
            0.0028,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT144D):
            0.0021,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT169D):
            0.0017,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT196D):
            0.0013,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT223D):
            0.0011,
            sumpf.FlatTopWindow(sumpf.FlatTopWindow.functions.HFT248D):
            0.0009
        })
    for window in scalloping_losses:
        linear = 10**(-scalloping_losses[window] / 20.0)
        assert window.scalloping_loss() == pytest.approx(linear, rel=1e-4)