Source code for pitch_garden.metrics.voicing

"""Metrics on the voicing decision."""

import numpy as np

from ._utils import F0Like, prepare, safe_divide


[docs] def vde(reference: F0Like, estimate: F0Like, mask: np.ndarray | None = None) -> float: """Calculate VDE (Voicing Decision Error). Parameters ---------- reference : Pitch | np.ndarray The reference F0 in Hz (unvoiced: 0). estimate : Pitch | np.ndarray The estimated F0 in Hz (unvoiced: 0). mask : np.ndarray | None, optional The boolean array that is True for the frames to be evaluated. Returns ------- out : float The ratio of frames whose voicing decision is wrong. """ ref, est = prepare(reference, estimate, mask) return safe_divide(np.sum((0 < ref) != (0 < est)), len(ref))
[docs] def voicing_scores( reference: F0Like, estimate: F0Like, mask: np.ndarray | None = None ) -> dict[str, float]: """Calculate the precision, recall, and F1 of the voicing decision. The voiced frames are regarded as positive. Parameters ---------- reference : Pitch | np.ndarray The reference F0 in Hz (unvoiced: 0). estimate : Pitch | np.ndarray The estimated F0 in Hz (unvoiced: 0). mask : np.ndarray | None, optional The boolean array that is True for the frames to be evaluated. Returns ------- out : dict[str, float] The 'precision', 'recall', and 'f1'. """ ref, est = prepare(reference, estimate, mask) ref_voiced, est_voiced = 0 < ref, 0 < est tp = np.sum(ref_voiced & est_voiced) precision = safe_divide(tp, np.sum(est_voiced)) recall = safe_divide(tp, np.sum(ref_voiced)) f1 = safe_divide(2 * precision * recall, precision + recall) return {"precision": precision, "recall": recall, "f1": f1}