Error Handling ============== :func:`audio_samples_qoe.visqol` and :class:`audio_samples_qoe.Scoreq` raise the same argument-validation exceptions, plus a metric-specific pipeline exception (:class:`~audio_samples_qoe.VisqolError` or :class:`~audio_samples_qoe.ScoreqError`). TypeError: wrong argument type ------------------------------ Raised when a signal argument is neither an :class:`audio_samples.AudioSamples` nor a path. .. code-block:: python import numpy as np from audio_samples_qoe import visqol arr = np.zeros(48_000 * 5) visqol(arr, arr) # TypeError: reference must be an audio_samples.AudioSamples, str, or # os.PathLike, got ndarray; wrap raw sample arrays with # audio_samples.AudioSamples.new_mono(arr, sample_rate) or new_multi **Fix**: wrap the array with ``AudioSamples.new_mono(arr, sample_rate)``. ValueError: invalid mode ------------------------ Raised when ``mode`` is not ``"audio"`` or ``"speech"``. .. code-block:: python visqol(ref, deg, mode="music") # ValueError: mode must be 'audio' or 'speech', got 'music' OSError: file not found or decode error --------------------------------------- Raised when a file path cannot be opened or the format is not supported. .. code-block:: python visqol("does_not_exist.wav", "degraded.wav") # OSError: No such file or directory (os error 2): does_not_exist.wav VisqolError: pipeline failure ----------------------------- Raised when the metric pipeline itself fails. The most common cause is a signal too short to extract a single analysis patch. .. code-block:: python import numpy as np from audio_samples import AudioSamples from audio_samples_qoe import visqol, VisqolError short = AudioSamples.new_mono(np.zeros(1000), 48_000) # ~20 ms, far too short try: visqol(short, short) except VisqolError as e: print(f"Pipeline failed: {e}") **Minimum signal length** (approximate): - Audio mode: ~0.6 s at 48 kHz - Speech mode: ~0.5 s at 16 kHz ScoreqError: pipeline failure or wrong mode -------------------------------------------- Raised when the SCOREQ model fails to load, or when :meth:`~audio_samples_qoe.Scoreq.predict` is called on a ``"ref"``-mode model (or :meth:`~audio_samples_qoe.Scoreq.predict_ref` on an ``"nr"``-mode model). .. code-block:: python from audio_samples_qoe import Scoreq, ScoreqError model = Scoreq(domain="natural", mode="nr") try: model.predict_ref(test, reference) except ScoreqError as e: print(f"Wrong mode: {e}") Defensive Pattern ----------------- .. code-block:: python from audio_samples_qoe import visqol, VisqolError def safe_score(ref_path: str, deg_path: str) -> float | None: try: return visqol(ref_path, deg_path) except (OSError, VisqolError) as e: print(f"Skipping {deg_path}: {e}") return None