def test_crossfade(var, benchmark): w1, p1, e1 = var dict: UserDict = UserDict() dict["wave"], dict["partition"] = w1, p1 mt1 = MultiTrack(dict) w2 = Wave(value=np.arange(0, 50), fs=1) p2 = Partition( np.array([0, 15, 20, 50], dtype=np.int64), np.array(["start", "middle", "end"]), 1, ) dict = UserDict() dict["wave"], dict["partition"] = w2, p2 mt2 = MultiTrack(dict) mt3 = benchmark(mt1.crossfade, mt2, 5) assert mt3.duration == mt1.duration + mt2.duration - 5 assert mt3["wave"] == Wave( value=np.r_[np.arange(45), np.array([37, 31, 24, 18, 11]), np.arange(5, 50)], fs=1, ) assert mt3["partition"] == Partition( np.array([0, 15, 20, 48, 60, 65, 95], dtype=np.int64), np.array(["start", "middle", "end", "start", "middle", "end"]), 1, )
def var(): p1 = Partition(np.array([0, 5, 6, 10], dtype=np.int64), np.array(["start", "middle", "end"]), 1) p2 = Partition(np.array([0, 5, 10], dtype=np.int64), np.array(["start2", "end2"]), 1) assert isinstance(p1, Track) assert isinstance(p2, Track) return p1, p2
def test_crossfade(benchmark): prt1 = Partition(np.array([0, 8, 10], dtype=np.int64), np.array(["1", "2"]), 1) prt2 = Partition(np.array([0, 2, 10], dtype=np.int64), np.array(["3", "4"]), 1) length = 4 prt = benchmark(prt1.crossfade, prt2, length) assert prt1.duration + prt2.duration - length == prt.duration assert np.allclose(prt.time, np.array([0, 8, 16])) assert (prt.value == np.array(["1", "4"])).all()
def test_select(var): p1, p2 = var p = p1.select(5, 6) assert p == Partition(np.array([0, 1], dtype=np.int64), np.array(["middle"]), 1) p = p1.select(5, 7) assert p == Partition(np.array([0, 1, 2], dtype=np.int64), np.array(["middle", "end"]), 1) p = p1.select(4, 6) assert p == Partition(np.array([0, 1, 2], dtype=np.int64), np.array(["start", "middle"]), 1) p = p1.select(4, 7) assert p == Partition(np.array([0, 1, 2, 3], dtype=np.int64), np.array(["start", "middle", "end"]), 1)
def var(): w = Wave(value=np.arange(0, 50), fs=1) p = Partition( np.array([0, 15, 20, 50], dtype=np.int64), np.array(["start", "middle", "end"]), 1, ) e = Event(np.array([0, 10, 30]).astype(np.int64), 1, 50) return w, p, e
def test_select(var, benchmark): dict: UserDict = UserDict() dict["wave"], dict["partition"], dict["event"] = var mt = MultiTrack(dict) new_mt = benchmark(mt.select, 10, 24) assert new_mt["wave"] == Wave(value=np.arange(10, 24), fs=1) assert new_mt["partition"] == Partition( np.array([0, 5, 10, 14], dtype=np.int64), np.array(["start", "middle", "end"]), 1, )
def process( self, progressTracker: Optional[DefaultProgressTracker] = None ) -> Tuple[Partition, TimeValue]: if progressTracker is not None: self.progressTracker = progressTracker wav = self.data.wave assert isinstance(wav, Wave) wav = wav.convert_dtype(np.float64) self.progressTracker.update(10) assert isinstance(wav, Wave) M, time, frequency = dsp.spectrogram(wav, self.parameters["frame_size"], self.parameters["frame_rate"]) self.progressTracker.update(20) # Emax = np.atleast_2d(np.max(M, axis=1)).T Emax = 20 * np.log10(np.mean((10**(M / 10)), axis=1)**0.5) P = np.empty((len(Emax), 2)) P[:, 0] = 1 / (1 + np.exp(Emax - self.parameters["threshold"])) P[:, 1] = 1 - P[:, 0] # complement self.progressTracker.update(30) seq, _ = viterbi.search_smooth(P, self.parameters["smooth"]) self.progressTracker.update(90) tmv = TimeValue( time, seq, wav.fs, wav.duration, wav.path.with_name(wav.path.stem + "-act").with_suffix( TimeValue.default_suffix), ) par = Partition.from_TimeValue(tmv) par.value = np.char.mod("%d", par.value) emax = TimeValue( time, Emax, wav.fs, wav.duration, wav.path.with_name(wav.path.stem + "-emax").with_suffix( TimeValue.default_suffix), ) emax.min = Emax.min() emax.max = Emax.max() emax.unit = "dB" emax.label = "maximum frequency magnitude" return par, emax
def process( self, progressTracker: Optional[DefaultProgressTracker] = None ) -> Tuple[TimeValue, TimeValue, Partition]: if progressTracker is not None: self.progressTracker = progressTracker wav = self.data.wave assert isinstance(wav, Wave) wav = wav.convert_dtype(np.float64) self.progressTracker.update(10) assert isinstance(wav, Wave) R, time, frequency = dsp.correlogram(wav, self.parameters["frame_size"], self.parameters["frame_rate"]) self.progressTracker.update(30) assert isinstance(wav, Wave) t0_min = int(round(wav.fs / self.parameters["f0_max"])) t0_max = int(round(wav.fs / self.parameters["f0_min"])) index = np.arange(t0_min, t0_max + 1, dtype=np.int16) E = R[:, 0] # energy R = R[:, index] # only look at valid candidates # normalize R -= R.min() R /= R.max() # find best sequence seq, _ = viterbi.search_smooth(R, self.parameters["smooth"]) self.progressTracker.update(80) f0 = wav.fs / (t0_min + seq) # degree of periodicity dop = R[np.arange(R.shape[0]), seq] # voicing v = ((dop > self.parameters["dop threshold"]) & (E > self.parameters["energy threshold"]) # (seq > 0) & (seq < len(index) - 1) ).astype(np.int16) v = signal.medfilt(v, 5) # TODO: replace by a 2-state HMM f0[v == 0] = np.nan # prepare tracks f0 = TimeValue( time, f0, wav.fs, wav.duration, wav.path.with_name(wav.path.stem + "-f0").with_suffix( TimeValue.default_suffix), ) f0.min = self.parameters["f0_min"] f0.max = self.parameters["f0_max"] f0.unit = "Hz" f0.label = "F0" dop = TimeValue( time, dop, wav.fs, wav.duration, wav.path.with_name(wav.path.stem + "-dop").with_suffix( TimeValue.default_suffix), ) dop.min = 0 dop.max = 1 dop.label = "degree of periodicity" vox = TimeValue( time, v, wav.fs, wav.duration, wav.path.with_name(wav.path.stem + "-vox").with_suffix( TimeValue.default_suffix), ) vox = Partition.from_TimeValue(vox) vox.label = "voicing" assert isinstance(f0, TimeValue) assert isinstance(dop, TimeValue) assert isinstance(vox, Partition) return f0, dop, vox
def test_merge_same(benchmark): p = Partition(np.array([0, 3, 6, 10], dtype=np.int64), np.array(["1", "1", "2"]), 1) p = benchmark(p.merge_same) assert p.value[1] == "2"
def test_insert(): p = Partition(np.array([0, 5, 6, 10], dtype=np.int64), np.array(["start", "middle", "end"]), 1) p.insert(7, "still the middle") assert (p.time == np.array([0, 5, 6, 7, 10])).all()