Esempio n. 1
0
def verify_res_divisor_rounding(
    target_int: int,
    res_divisor: float,
    speed_hack: bool,
):
    """Ensure that pathological-case float rounding errors
    don't cause inconsistent dimensions and assertion errors."""
    target_dim = target_int + 0.5
    undivided_dim = round(target_dim * res_divisor)

    cfg = RendererConfig(undivided_dim, undivided_dim, res_divisor=res_divisor)
    cfg.before_preview()

    with ExitStack() as stack:
        if speed_hack:
            stack.enter_context(
                patch.object(AbstractMatplotlibRenderer, "_save_background")
            )
            datas = []
        else:
            datas = [RENDER_Y_ZEROS]

        try:
            renderer = Renderer(cfg, LayoutConfig(), datas, None, None)
            if not speed_hack:
                renderer.update_main_lines(datas)
                renderer.get_frame()
        except Exception:
            perr(cfg.divided_width)
            raise
Esempio n. 2
0
def template_config(**kwargs) -> Config:
    """Default template values do NOT indicate optional attributes."""
    cfg = Config(
        master_audio="",
        fps=_FPS,
        amplification=1,
        trigger_ms=40,
        render_ms=40,
        trigger_subsampling=1,
        render_subsampling=2,
        trigger=CorrelationTriggerConfig(
            mean_responsiveness=0.0,
            edge_strength=1.0,
            reset_below=0.3,
            responsiveness=0.5,
            pitch_tracking=SpectrumConfig(),
            # post_trigger=ZeroCrossingTriggerConfig(),
        ),
        channels=[],
        layout=LayoutConfig(orientation="v", ncols=1),
        render=RendererConfig(
            1280,
            720,
            res_divisor=4 / 3,
            grid_color="#55aaff",
            v_midline=True,
            h_midline=True,
        ),
    )
    return attr.evolve(cfg, **kwargs)
Esempio n. 3
0
def default_config(**kwargs) -> Config:
    """ Default template values do NOT indicate optional attributes. """
    cfg = Config(
        render_subfps=1,
        master_audio="",
        fps=_FPS,
        amplification=1,
        trigger_ms=40,
        render_ms=40,
        trigger_subsampling=1,
        render_subsampling=2,
        trigger=CorrelationTriggerConfig(
            edge_strength=2,
            responsiveness=0.5,
            buffer_falloff=0.5,
            use_edge_trigger=False,
            # Removed due to speed hit.
            # post=LocalPostTriggerConfig(strength=0.1),
        ),
        channels=[],
        layout=LayoutConfig(orientation="v", ncols=1),
        render=RendererConfig(
            1280,
            720,
            res_divisor=4 / 3,
            midline_color="#404040",
            v_midline=True,
            h_midline=True,
        ),
    )
    return attr.evolve(cfg, **kwargs)
Esempio n. 4
0
def test_label_render(label_position: LabelPosition, data, hide_lines):
    """Test that text labels are drawn:
    - in the correct quadrant
    - with the correct color (defaults to init_line_color)
    - even if no lines are drawn at all
    """
    font_str = "#FF00FF"
    font_u8 = color_to_bytes(font_str)

    # If hide_lines: set line color to purple, draw text using the line color.
    # Otherwise: draw lines white, draw text purple,
    cfg_kwargs = {}
    if hide_lines:
        cfg_kwargs.update(init_line_color=font_str)

    cfg = RendererConfig(
        WIDTH,
        HEIGHT,
        antialiasing=False,
        label_font=Font(size=16, bold=True),
        label_position=label_position,
        label_color_override=font_str,
        **cfg_kwargs,
    )

    lcfg = LayoutConfig()

    nplots = 1
    labels = ["#"] * nplots
    datas = [data] * nplots

    r = Renderer(cfg, lcfg, datas, None, None)
    r.add_labels(labels)
    if not hide_lines:
        r.update_main_lines(datas)

    frame_buffer: np.ndarray = np.frombuffer(r.get_frame(), dtype=np.uint8).reshape(
        (r.h, r.w, BYTES_PER_PIXEL)
    )
    # Allow mutation
    frame_buffer = frame_buffer.copy()

    yslice = label_position.y.match(
        top=slice(None, r.h // 2), bottom=slice(r.h // 2, None)
    )
    xslice = label_position.x.match(
        left=slice(None, r.w // 2), right=slice(r.w // 2, None)
    )
    quadrant = frame_buffer[yslice, xslice]

    assert np.prod(quadrant == font_u8, axis=-1).any(), "Missing text"

    quadrant[:] = 0
    assert not np.prod(
        frame_buffer == font_u8, axis=-1
    ).any(), "Text appeared in wrong area of screen"
Esempio n. 5
0
def test_renderer_layout():
    # 2 columns
    cfg = RendererConfig(WIDTH, HEIGHT)
    lcfg = LayoutConfig(ncols=2)
    nplots = 15

    r = MatplotlibRenderer(cfg, lcfg, nplots, None)
    r.render_frame([RENDER_Y_ZEROS] * nplots)
    layout = r.layout

    # 2 columns, 8 rows
    assert layout.wave_ncol == 2
    assert layout.wave_nrow == 8
Esempio n. 6
0
def test_renderer_layout():
    # 2 columns
    cfg = RendererConfig(WIDTH, HEIGHT)
    lcfg = LayoutConfig(ncols=2)
    nplots = 15

    datas = [RENDER_Y_ZEROS] * nplots
    r = Renderer(cfg, lcfg, datas, None, None)
    r.update_main_lines(RenderInput.wrap_datas(datas), [0] * nplots)
    layout = r.layout

    # 2 columns, 8 rows
    assert layout.wave_ncol == 2
    assert layout.wave_nrow == 8
Esempio n. 7
0
def test_stereo_render_integration(mocker: "pytest_mock.MockFixture"):
    """Ensure corrscope plays/renders in stereo, without crashing."""

    # Stub out FFplay output.
    mocker.patch.object(FFplayOutputConfig, "cls")

    # Render in stereo.
    cfg = template_config(
        channels=[ChannelConfig("tests/stereo in-phase.wav")],
        render_stereo=Flatten.Stereo,
        end_time=0.5,  # Reduce test duration
        render=RendererConfig(WIDTH, HEIGHT),
    )

    # Make sure it doesn't crash.
    corr = CorrScope(cfg, Arguments(".", [FFplayOutputConfig()]))
    corr.play()
Esempio n. 8
0
def get_renderer_config(appear: Appearance) -> RendererConfig:
    cfg = RendererConfig(
        WIDTH,
        HEIGHT,
        # BG
        bg_color=appear.bg.color,
        # FG
        init_line_color=appear.fg.color,
        line_width=appear.fg.line_width,
        viewport_width=appear.debug.viewport_width,
        # Grid
        grid_color=appear.grid.color,
        grid_line_width=appear.grid.line_width,
        stereo_grid_opacity=OPACITY,
        antialiasing=False,
    )
    return cfg
Esempio n. 9
0
def test_line_colors(bg_str, fg_str, grid_str, data):
    """ Test channel-specific line color overrides """
    cfg = RendererConfig(
        WIDTH,
        HEIGHT,
        bg_color=bg_str,
        init_line_color="#888888",
        grid_color=grid_str,
        stereo_grid_opacity=OPACITY,
        line_width=2.0,
        antialiasing=False,
    )
    lcfg = LayoutConfig()

    chan = ChannelConfig(wav_path="", line_color=fg_str)
    channels = [chan] * NPLOTS
    r = MatplotlibRenderer(cfg, lcfg, NPLOTS, channels)
    verify(r, bg_str, fg_str, grid_str, data)
Esempio n. 10
0
def test_default_colors(bg_str, fg_str, grid_str, data):
    """ Test the default background/foreground colors. """
    cfg = RendererConfig(
        WIDTH,
        HEIGHT,
        bg_color=bg_str,
        init_line_color=fg_str,
        grid_color=grid_str,
        stereo_grid_opacity=OPACITY,
        line_width=2.0,
        antialiasing=False,
    )
    lcfg = LayoutConfig()

    r = MatplotlibRenderer(cfg, lcfg, NPLOTS, None)
    verify(r, bg_str, fg_str, grid_str, data)

    # Ensure default ChannelConfig(line_color=None) does not override line color
    chan = ChannelConfig(wav_path="")
    channels = [chan] * NPLOTS
    r = MatplotlibRenderer(cfg, lcfg, NPLOTS, channels)
    verify(r, bg_str, fg_str, grid_str, data)
Esempio n. 11
0
        popen.stdin.write.side_effect = exc
        popen.wait.return_value = 0
        return popen

    Popen = mocker.patch.object(subprocess, "Popen", autospec=True)
    Popen.side_effect = popen_factory
    return Popen


class DummyException(Exception):
    pass


NULL_FFMPEG_OUTPUT = FFmpegOutputConfig(None, "-f null")

render_cfg = RendererConfig(WIDTH, HEIGHT)
CFG = default_config(render=render_cfg)


def sine440_config():
    cfg = default_config(
        channels=[ChannelConfig("tests/sine440.wav")],
        master_audio="tests/sine440.wav",
        end_time=0.5,  # Reduce test duration
        render=render_cfg,
    )
    return cfg


## Begin tests
# Calls MatplotlibRenderer, FFmpegOutput, FFmpeg.