1
# $Id: mod_pesq.py 2417 2009-01-05 15:31:25Z bennylp $
3
# Quality test of media calls.
5
# - UA1 plays a file until finished to be streamed to UA2
6
# - UA2 records from stream
7
# - Apply PESQ to played file (reference) and recorded file (degraded)
10
# - naming: xxxxxx.CLOCK_RATE.wav, e.g: test1.8.wav
11
# - clock-rate of those files can only be 8khz or 16khz
21
import inc_const as const
26
cfg_file = imp.load_source("cfg_file", ARGS[1])
29
PESQ = "tools/pesq" # PESQ executable path
30
PESQ_DEFAULT_THRESHOLD = 3.4 # Default minimum acceptable PESQ MOS value
33
pesq_sample_rate_opt = "" # Sample rate option for PESQ
34
input_filename = "" # Input/Reference filename
35
output_filename = "" # Output/Degraded filename
40
global pesq_sample_rate_opt
42
global output_filename
48
input_filename = re.compile(const.MEDIA_PLAY_FILE).search(ua1.inst_param.arg).group(1)
50
# Get output file name
51
output_filename = re.compile(const.MEDIA_REC_FILE).search(ua2.inst_param.arg).group(1)
53
# Get WAV input length, in seconds
54
fin = wave.open(input_filename, "r")
56
raise TestError("Failed opening input WAV file")
57
inwavlen = fin.getnframes() * 1.0 / fin.getframerate()
60
print "WAV input len = " + str(inwavlen) + "s"
62
# Get clock rate of the output
63
mo_clock_rate = re.compile("\.(\d+)\.wav").search(output_filename)
64
if (mo_clock_rate==None):
65
raise TestError("Cannot compare input & output, incorrect output filename format")
66
clock_rate = mo_clock_rate.group(1)
68
# Get channel count of the output
70
if re.search("--stereo", ua2.inst_param.arg) != None:
73
# Get matched input file from output file
74
# (PESQ evaluates only files whose same clock rate & channel count)
75
if channel_count == 2:
76
if re.search("\.\d+\.\d+\.wav", input_filename) != None:
77
input_filename = re.sub("\.\d+\.\d+\.wav", "." + str(channel_count) + "."+clock_rate+".wav", input_filename)
79
input_filename = re.sub("\.\d+\.wav", "." + str(channel_count) + "."+clock_rate+".wav", input_filename)
81
if (clock_rate != "8") & (clock_rate != "16"):
82
raise TestError("PESQ only works on clock rate 8kHz or 16kHz, clock rate used = "+clock_rate+ "kHz")
84
# Get conference clock rate of UA2 for PESQ sample rate option
85
pesq_sample_rate_opt = "+" + clock_rate + "000"
89
ua1.send(t.inst_params[1].uri)
90
ua1.expect(const.STATE_CALLING)
92
# UA2 wait until call established
93
ua2.expect(const.STATE_CONFIRMED)
99
# Disconnect mic -> rec file, to avoid echo recorded when using sound device
100
# Disconnect stream -> spk, make it silent
101
# Connect stream -> rec file, start recording
102
ua2.send("cd 0 1\ncd 4 0\ncc 4 1")
104
# Disconnect mic -> stream, make stream purely sending from file
105
# Disconnect stream -> spk, make it silent
106
# Connect file -> stream, start sending
107
ua1.send("cd 0 4\ncd 4 0\ncc 1 4")
111
# Disconnect files from bridge
113
ua2.expect(const.MEDIA_DISCONN_PORT_SUCCESS)
115
ua1.expect(const.MEDIA_DISCONN_PORT_SUCCESS)
120
global pesq_sample_rate_opt
121
global input_filename
122
global output_filename
127
fullcmd = os.path.normpath(PESQ) + " " + pesq_sample_rate_opt + " " + input_filename + " " + output_filename
128
endpt.trace("Popen " + fullcmd)
129
pesq_proc = subprocess.Popen(fullcmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True)
130
pesq_out = pesq_proc.communicate()
133
mo_pesq_out = re.compile("Prediction[^=]+=\s+([\-\d\.]+)\s*").search(pesq_out[0])
134
if (mo_pesq_out == None):
135
raise TestError("Failed to fetch PESQ result")
138
if (cfg_file.pesq_threshold != None) | (cfg_file.pesq_threshold > -0.5 ):
139
threshold = cfg_file.pesq_threshold
141
threshold = PESQ_DEFAULT_THRESHOLD
143
# Evaluate the PESQ MOS value
144
pesq_res = mo_pesq_out.group(1)
145
if (float(pesq_res) >= threshold):
146
endpt.trace("Success, PESQ result = " + pesq_res + " (target=" + str(threshold) + ").")
148
endpt.trace("Failed, PESQ result = " + pesq_res + " (target=" + str(threshold) + ").")
151
wavoutname = re.sub("[\\\/]", "_", wavoutname)
152
wavoutname = re.sub("\.py$", ".wav", wavoutname)
153
wavoutname = "logs/" + wavoutname
155
shutil.copyfile(output_filename, wavoutname)
156
print "Output WAV is copied to " + wavoutname
158
print "Couldn't copy output WAV, please check if 'logs' directory exists."
160
raise TestError("WAV seems to be degraded badly, PESQ = "+ pesq_res + " (target=" + str(threshold) + ").")
163
# Here where it all comes together
164
test = cfg_file.test_param
165
test.test_func = test_func
166
test.post_func = post_func