ludlows / PESQ

PESQ (Perceptual Evaluation of Speech Quality) Wrapper for Python Users (narrow band and wide band)
https://github.com/ludlows/PESQ
MIT License
518 stars 97 forks source link

not equal to the result of P.862 #23

Closed angusxu458 closed 3 years ago

angusxu458 commented 3 years ago

i ve exam the python-pesq with the ITU-T P.862 c version of pesq, the pesq score is not the same for the same ref_wav and deg_wav.

ludlows commented 3 years ago

you should release the sample to address your problems in details. otherwise, nobody can help you solve it.

angusxu458 commented 3 years ago

thx a lot, @ludlows. here is my issue, the following code is to test the PESQ score from different pesq implement library, python-pesq and ITU P.862(02/01), and the scores are not same.

# -*- coding: utf-8 -*-

import re
import subprocess
from pesq import pesq
import soundfile as sf

def unittest_pypesq():
    ref, rate = sf.read(r"D:\Users\Documents\tools\T-REC-P.862-200102-I!!SOFT-ZST-E\P862\Software\Conform\dg105.wav")
    deg, rate = sf.read(r"D:\Users\Documents\tools\T-REC-P.862-200102-I!!SOFT-ZST-E\P862\Software\Conform\or105.wav")

    # print("PESQ of wideband: ", pesq(rate, ref, deg, 'wb'))
    print("PESQ of narrowband: ", pesq(rate, ref, deg, 'nb'))
    # print(mapped_mos2raw_mos(pesq(rate, ref, deg, 'wb')),
    #       mapped_mos2raw_mos(pesq(rate, ref, deg, 'nb')))

    return

def unittest_cpesq():
    ref_path = r"D:\Users\Documents\tools\T-REC-P.862-200102-I!!SOFT-ZST-E\P862\Software\Conform\dg105.wav"
    deg_path = r"D:\Users\Documents\tools\T-REC-P.862-200102-I!!SOFT-ZST-E\P862\Software\Conform\or105.wav"

    pesq = evaluate_pesq(ref_path, deg_path)
    print("PESQ C version: ", pesq[-1])

def evaluate_pesq(ref_path, deg_path, norm=False):
    pattern = re.compile(r"\d\.\d*")
    if not norm:
        cmd = f'D:\\Users\\Documents\\tools\\PESQ.exe {ref_path} {deg_path} +8000 '
    else:
        os.makedirs("temp", exist_ok=True)
        data1, sr1 = sf.read(ref_path)
        data1 = data1/np.sqrt(np.sum(np.square(data1)))
        data2, sr2 = sf.read(deg_path)
        data2 = data2/np.sqrt(np.sum(np.square(data2)))

        ref_basename = os.path.basename(ref_path)
        ref_new_path = os.path.join("temp", 
                                    ref_basename.replace(".wav","_norm.wav"))
        deg_basename = os.path.basename(deg_path)
        deg_new_path = os.path.join("temp", 
                                    deg_basename.replace(".wav","_norm.wav"))
        sf.write(ref_new_path, data1, sr1)
        sf.write(deg_new_path, data2, sr2)
        cmd = f'D:\\Users\\Documents\\tools\\PESQ.exe {ref_new_path} {deg_new_path} +8000 '

    p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT, shell=True)
    while p.poll() is None:
        cont = p.stdout.readline()
        if "PESQ_MOS" in cont.decode():
            match = pattern.search(cont.decode())
            return ref_path, deg_path, float(match.group())

    if norm:
        os.remove(ref_new_path)
        os.remove(deg_new_path)
    return ref_path, deg_path, -1

import math
def mapped_mos2raw_mos(mapped):
    return (math.log(4.0/(mapped - 0.999) - 1.0) - 4.6607) / (-1.4945)

if __name__ == "__main__":
    unittest_pypesq()
    unittest_cpesq()

with the result as

$ python test_pesq
PESQ of narrowband:  2.6483306884765625
PESQ C version:  2.881
angusxu458 commented 3 years ago

@ludlows when i transform the python-pesq score with the func mapped_mos2raw_mos, the scores are similar

ludlows commented 3 years ago
REFERENCE DEGRADED PESQMOS SAMPLE_FREQ
or105.wav dg105.wav 2.237 8000

but in your code

def unittest_pypesq():
    ref, rate = sf.read(r"D:\Users\Documents\tools\T-REC-P.862-200102-I!!SOFT-ZST-E\P862\Software\Conform\dg105.wav")
    deg, rate = sf.read(r"D:\Users\Documents\tools\T-REC-P.862-200102-I!!SOFT-ZST-E\P862\Software\Conform\or105.wav")

    # print("PESQ of wideband: ", pesq(rate, ref, deg, 'wb'))
    print("PESQ of narrowband: ", pesq(rate, ref, deg, 'nb'))

you just swapped the order of these two parameters.

It will lead to the problem.

angusxu458 commented 3 years ago

sorry it is my careless fault, so the out of python-pesq transformed by mapped_mos2raw_mos should be equal to the out of the P.862 PESQ.exe