PESQ Score Calculator
pesq is a Python wrapper for the Perceptual Evaluation of Speech Quality (PESQ) metric, implementing the ITU-T P.862 standard. It supports both narrow-band ('nb') and wide-band ('wb') calculations, providing an objective measure of speech quality. The current version is 0.0.4, with releases occurring infrequently but introducing new features like multiprocessing support.
Common errors
-
ERROR: Failed building wheel for pesq
cause Missing C compiler (e.g., GCC, MSVC) or development headers required for Cython extensions during installation.fixInstall a C compiler for your operating system. For Debian/Ubuntu: `sudo apt-get install build-essential`. For macOS: `xcode-select --install`. For Windows: Install Visual Studio Build Tools with C++ desktop development workload. -
ValueError: Input signals must be 16-bit PCM and have same sampling rate
cause The reference or degraded audio signals do not meet the strict requirements of the PESQ algorithm (e.g., incorrect bit depth, mismatched sampling rates, or unequal signal lengths).fixEnsure both `ref` and `deg` signals are 16-bit PCM (e.g., float32 scaled to int16 range, or loaded from 16-bit WAVs), have identical sampling rates, and are of the same length before passing them to `pesq`. -
OSError: pesq: Cannot open input file 'non_existent_file.wav'
cause The file path provided for the reference or degraded audio file does not exist or is not accessible by the script.fixVerify that the file paths are correct and that the audio files exist at the specified locations. Use absolute paths or ensure your script's working directory is correct. -
TypeError: argument of type 'int' is not iterable
cause `pesq_batch` expects iterables of signals (e.g., lists of NumPy arrays or file paths), not single arguments.fixIf using `pesq_batch`, wrap your single reference/degraded signals in a list. For multiple pairs, ensure both the `ref` and `deg` arguments are lists of corresponding signals/paths.
Warnings
- gotcha Due to its reliance on Cython for performance, installing `pesq` often requires a C compiler (e.g., GCC on Linux, Apple Clang on macOS, MSVC on Windows). Users may encounter `Failed building wheel` errors during `pip install` without one.
- gotcha The underlying PESQ algorithm is highly sensitive to input audio characteristics. Signals provided to `pesq` must effectively represent 16-bit PCM, have the same sampling rate, and typically be of equal length to avoid `ValueError` or incorrect scores.
- gotcha Incorrectly specifying the PESQ mode ('nb' for narrow-band or 'wb' for wide-band) can lead to unexpected scores or errors. The chosen mode must match the characteristics and intended evaluation context of your audio.
- deprecated Prior to v0.0.3, error handling behaviors were less robust. While not a breaking API change, errors might have been less descriptive or harder to catch.
Install
-
pip install pesq
Imports
- pesq
from pesq import pesq
- pesq_batch
from pesq import pesq_batch
Quickstart
import numpy as np
from pesq import pesq
# Define sampling rate and generate dummy audio signals (16 kHz, 3 seconds)
fs = 16000
duration = 3 # seconds
t = np.linspace(0, duration, int(fs * duration), endpoint=False)
# Reference signal (e.g., clean speech)
ref_signal = (0.5 * np.sin(2 * np.pi * 440 * t)).astype(np.float32)
# Degraded signal (e.g., speech with noise or distortion)
deg_signal = (0.5 * np.sin(2 * np.pi * 440 * t + 0.1) + 0.1 * np.random.randn(len(t))).astype(np.float32)
# Ensure signals are 16-bit PCM (by scaling to int16 range) if not already
# The library expects float32, but underlying PESQ is 16-bit.
# For this example, float32 is fine as it will be handled internally.
# Calculate Wide-Band PESQ score
score_wb = pesq(fs, ref_signal, deg_signal, 'wb')
print(f"PESQ Wide-Band (wb) score: {score_wb:.2f}")
# Calculate Narrow-Band PESQ score (requires adjusting signals if necessary)
# score_nb = pesq(fs, ref_signal, deg_signal, 'nb')
# print(f"PESQ Narrow-Band (nb) score: {score_nb:.2f}")
# The `pesq` function also accepts file paths directly:
# import soundfile as sf
# import os
# sf.write('ref.wav', ref_signal, fs, subtype='PCM_16')
# sf.write('deg.wav', deg_signal, fs, subtype='PCM_16')
# score_files = pesq(fs, 'ref.wav', 'deg.wav', 'wb')
# print(f"PESQ from files: {score_files:.2f}")
# os.remove('ref.wav'); os.remove('deg.wav')