Exemplo n.º 1
0
    def __init__(self, cfg: ChannelConfig, corr_cfg: "Config"):
        self.cfg = cfg

        # Create a Wave object.
        wave = Wave(
            abspath(cfg.wav_path),
            amplification=coalesce(cfg.amplification, corr_cfg.amplification),
        )

        # Flatten wave stereo for trigger and render.
        tflat = coalesce(cfg.trigger_stereo, corr_cfg.trigger_stereo)
        rflat = coalesce(cfg.render_stereo, corr_cfg.render_stereo)

        self.trigger_wave = wave.with_flatten(tflat, return_channels=False)
        self.render_wave = wave.with_flatten(rflat, return_channels=True)

        # `subsampling` increases `stride` and decreases `nsamp`.
        # `width` increases `stride` without changing `nsamp`.
        tsub = corr_cfg.trigger_subsampling
        tw = cfg.trigger_width

        rsub = corr_cfg.render_subsampling
        rw = cfg.render_width

        # nsamp = orig / subsampling
        # stride = subsampling * width
        def calculate_nsamp(width_ms, sub):
            width_s = width_ms / 1000
            return round(width_s * wave.smp_s / sub)

        trigger_samp = calculate_nsamp(corr_cfg.trigger_ms, tsub)
        self.render_samp = calculate_nsamp(corr_cfg.render_ms, rsub)

        self.trigger_stride = tsub * tw
        self.render_stride = rsub * rw

        # Create a Trigger object.
        if isinstance(cfg.trigger, ITriggerConfig):
            tcfg = cfg.trigger
        elif isinstance(
                cfg.trigger,
            (CommentedMap, dict)):  # CommentedMap may/not be subclass of dict.
            tcfg = attr.evolve(corr_cfg.trigger, **cfg.trigger)
        elif cfg.trigger is None:
            tcfg = corr_cfg.trigger
        else:
            raise CorrError(
                f"invalid per-channel trigger {cfg.trigger}, type={type(cfg.trigger)}, "
                f"must be (*)TriggerConfig, dict, or None")

        self.trigger = tcfg(
            wave=self.trigger_wave,
            tsamp=trigger_samp,
            stride=self.trigger_stride,
            fps=corr_cfg.fps,
        )
Exemplo n.º 2
0
def test_stereo_flatten_modes(
    flatten: Flatten,
    return_channels: bool,
    path: str,
    nchan: int,
    peaks: Sequence[float],
):
    """Ensures all Flatten modes are handled properly
    for stereo and mono signals."""

    # return_channels=False <-> triggering.
    # flatten=stereo -> rendering.
    # These conditions do not currently coexist.
    # if not return_channels and flatten == Flatten.Stereo:
    #     return

    assert nchan == len(peaks)
    wave = Wave(path)

    if flatten not in Flatten.modes:
        with pytest.raises(CorrError):
            wave.with_flatten(flatten, return_channels)
        return
    else:
        wave = wave.with_flatten(flatten, return_channels)

    nsamp = wave.nsamp
    data = wave[:]

    # wave.data == 2-D array of shape (nsamp, nchan)
    if flatten == Flatten.Stereo:
        assert data.shape == (nsamp, nchan)
        for chan_data, peak in zip(data.T, peaks):
            assert_full_scale(chan_data, peak)
    else:
        if return_channels:
            assert data.shape == (nsamp, 1)
        else:
            assert data.shape == (nsamp, )

        # If DiffAvg and in-phase, L-R=0.
        if flatten == Flatten.DiffAvg:
            if len(peaks) >= 2 and peaks[0] == peaks[1]:
                np.testing.assert_equal(data, 0)
            else:
                pass
        # If SumAvg, check average.
        else:
            assert flatten == Flatten.SumAvg
            assert_full_scale(data, np.mean(peaks))
Exemplo n.º 3
0
    def __init__(self, cfg: ChannelConfig, corr_cfg: "Config", channel_idx: int = 0):
        """channel_idx counts from 0."""
        self.cfg = cfg

        self.label = cfg.label
        if not self.label:
            if corr_cfg.default_label is DefaultLabel.FileName:
                self.label = Path(cfg.wav_path).stem
            elif corr_cfg.default_label is DefaultLabel.Number:
                self.label = str(channel_idx + 1)

        # Create a Wave object.
        wave = Wave(
            abspath(cfg.wav_path),
            amplification=coalesce(cfg.amplification, corr_cfg.amplification),
        )

        # Flatten wave stereo for trigger and render.
        tflat = coalesce(cfg.trigger_stereo, corr_cfg.trigger_stereo)
        rflat = coalesce(cfg.render_stereo, corr_cfg.render_stereo)

        self.trigger_wave = wave.with_flatten(tflat, return_channels=False)
        self.render_wave = wave.with_flatten(rflat, return_channels=True)

        # `subsampling` increases `stride` and decreases `nsamp`.
        # `width` increases `stride` without changing `nsamp`.
        tsub = corr_cfg.trigger_subsampling
        tw = cfg.trigger_width

        rsub = corr_cfg.render_subsampling
        rw = cfg.render_width

        # nsamp = orig / subsampling
        # stride = subsampling * width
        def calculate_nsamp(width_ms, sub):
            width_s = width_ms / 1000
            return round(width_s * wave.smp_s / sub)

        trigger_samp = calculate_nsamp(corr_cfg.trigger_ms, tsub)
        self._render_samp = calculate_nsamp(corr_cfg.render_ms, rsub)

        self._trigger_stride = tsub * tw
        self.render_stride = rsub * rw

        # Create a Trigger object.
        if isinstance(cfg.trigger, MainTriggerConfig):
            tcfg = cfg.trigger

        elif isinstance(
            cfg.trigger, (CommentedMap, dict)
        ):  # CommentedMap may/not be subclass of dict.
            tcfg = evolve_compat(corr_cfg.trigger, **cfg.trigger)

        elif cfg.trigger is None:
            tcfg = corr_cfg.trigger

        else:
            raise CorrError(
                f"invalid per-channel trigger {cfg.trigger}, type={type(cfg.trigger)}, "
                f"must be (*)TriggerConfig, dict, or None"
            )

        self.trigger = tcfg(
            wave=self.trigger_wave,
            tsamp=trigger_samp,
            stride=self._trigger_stride,
            fps=corr_cfg.fps,
            wave_idx=channel_idx,
        )