blob: 063c88423d42ae288caea6389967e78155e0d233 [file] [log] [blame]
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +00001# $Id$
2
3# Quality test of media calls.
4# - UA1 calls UA2
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)
8#
9# File should be:
10# - naming: xxxxxx.CLOCK_RATE.wav, e.g: test1.8.wav
11# - clock-rate of those files can only be 8khz or 16khz
12
13import time
14import imp
15import sys
16import re
17import subprocess
Nanang Izzuddin9eac5472008-06-26 18:52:16 +000018import wave
Nanang Izzuddinffa18c92008-06-28 00:52:20 +000019import shutil
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000020import inc_const as const
21
22from inc_cfg import *
23
24# Load configuration
Nanang Izzuddina680bd62008-06-27 21:12:12 +000025cfg_file = imp.load_source("cfg_file", ARGS[1])
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000026
27# PESQ configs
Benny Prijonof84081d2009-01-04 21:28:10 +000028PESQ = "tools/pesq" # PESQ executable path
Nanang Izzuddina680bd62008-06-27 21:12:12 +000029PESQ_DEFAULT_THRESHOLD = 3.4 # Default minimum acceptable PESQ MOS value
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000030
Nanang Izzuddina680bd62008-06-27 21:12:12 +000031# PESQ params
32pesq_sample_rate_opt = "" # Sample rate option for PESQ
33input_filename = "" # Input/Reference filename
34output_filename = "" # Output/Degraded filename
35
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000036
37# Test body function
Nanang Izzuddina680bd62008-06-27 21:12:12 +000038def test_func(t):
39 global pesq_sample_rate_opt
40 global input_filename
41 global output_filename
Nanang Izzuddin6ee166d2008-06-26 12:26:52 +000042
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000043 ua1 = t.process[0]
44 ua2 = t.process[1]
45
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000046 # Get input file name
Nanang Izzuddina680bd62008-06-27 21:12:12 +000047 input_filename = re.compile(const.MEDIA_PLAY_FILE).search(ua1.inst_param.arg).group(1)
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000048
49 # Get output file name
Nanang Izzuddina680bd62008-06-27 21:12:12 +000050 output_filename = re.compile(const.MEDIA_REC_FILE).search(ua2.inst_param.arg).group(1)
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000051
Nanang Izzuddin9869cb52008-06-27 16:18:13 +000052 # Get WAV input length, in seconds
Nanang Izzuddina680bd62008-06-27 21:12:12 +000053 fin = wave.open(input_filename, "r")
Nanang Izzuddin9869cb52008-06-27 16:18:13 +000054 if fin == None:
55 raise TestError("Failed opening input WAV file")
56 inwavlen = fin.getnframes() * 1.0 / fin.getframerate()
57 inwavlen += 0.2
58 fin.close()
59 print "WAV input len = " + str(inwavlen) + "s"
60
61 # Get clock rate of the output
Nanang Izzuddina680bd62008-06-27 21:12:12 +000062 mo_clock_rate = re.compile("\.(\d+)\.wav").search(output_filename)
Nanang Izzuddinacb3e322008-06-25 18:18:32 +000063 if (mo_clock_rate==None):
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000064 raise TestError("Cannot compare input & output, incorrect output filename format")
Nanang Izzuddinacb3e322008-06-25 18:18:32 +000065 clock_rate = mo_clock_rate.group(1)
Nanang Izzuddin9869cb52008-06-27 16:18:13 +000066
67 # Get channel count of the output
68 channel_count = 1
69 if re.search("--stereo", ua2.inst_param.arg) != None:
70 channel_count = 2
71
72 # Get matched input file from output file
73 # (PESQ evaluates only files whose same clock rate & channel count)
74 if channel_count == 2:
Nanang Izzuddina680bd62008-06-27 21:12:12 +000075 if re.search("\.\d+\.\d+\.wav", input_filename) != None:
76 input_filename = re.sub("\.\d+\.\d+\.wav", "." + str(channel_count) + "."+clock_rate+".wav", input_filename)
Nanang Izzuddin9869cb52008-06-27 16:18:13 +000077 else:
Nanang Izzuddina680bd62008-06-27 21:12:12 +000078 input_filename = re.sub("\.\d+\.wav", "." + str(channel_count) + "."+clock_rate+".wav", input_filename)
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000079
Nanang Izzuddinacb3e322008-06-25 18:18:32 +000080 if (clock_rate != "8") & (clock_rate != "16"):
81 raise TestError("PESQ only works on clock rate 8kHz or 16kHz, clock rate used = "+clock_rate+ "kHz")
82
83 # Get conference clock rate of UA2 for PESQ sample rate option
Nanang Izzuddina680bd62008-06-27 21:12:12 +000084 pesq_sample_rate_opt = "+" + clock_rate + "000"
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000085
86 # UA1 making call
87 ua1.send("m")
88 ua1.send(t.inst_params[1].uri)
89 ua1.expect(const.STATE_CALLING)
Nanang Izzuddin9eac5472008-06-26 18:52:16 +000090
91 # UA2 wait until call established
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000092 ua2.expect(const.STATE_CONFIRMED)
93
Benny Prijonob9760d92008-08-26 12:15:31 +000094 ua1.sync_stdout()
95 ua2.sync_stdout()
96 time.sleep(2)
97
Nanang Izzuddin9eac5472008-06-26 18:52:16 +000098 # Disconnect mic -> rec file, to avoid echo recorded when using sound device
99 # Disconnect stream -> spk, make it silent
100 # Connect stream -> rec file, start recording
101 ua2.send("cd 0 1\ncd 4 0\ncc 4 1")
Nanang Izzuddinacb3e322008-06-25 18:18:32 +0000102
Nanang Izzuddin9eac5472008-06-26 18:52:16 +0000103 # Disconnect mic -> stream, make stream purely sending from file
104 # Disconnect stream -> spk, make it silent
105 # Connect file -> stream, start sending
106 ua1.send("cd 0 4\ncd 4 0\ncc 1 4")
Nanang Izzuddinacb3e322008-06-25 18:18:32 +0000107
Nanang Izzuddin9eac5472008-06-26 18:52:16 +0000108 time.sleep(inwavlen)
109
110 # Disconnect files from bridge
111 ua2.send("cd 4 1")
112 ua2.expect(const.MEDIA_DISCONN_PORT_SUCCESS)
113 ua1.send("cd 1 4")
114 ua1.expect(const.MEDIA_DISCONN_PORT_SUCCESS)
115
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000116
117# Post body function
Nanang Izzuddina680bd62008-06-27 21:12:12 +0000118def post_func(t):
119 global pesq_sample_rate_opt
120 global input_filename
121 global output_filename
122
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000123 endpt = t.process[0]
124
125 # Execute PESQ
Nanang Izzuddina680bd62008-06-27 21:12:12 +0000126 fullcmd = PESQ + " " + pesq_sample_rate_opt + " " + input_filename + " " + output_filename
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000127 endpt.trace("Popen " + fullcmd)
Benny Prijonof84081d2009-01-04 21:28:10 +0000128 pesq_proc = subprocess.Popen(fullcmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True)
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000129 pesq_out = pesq_proc.communicate()
130
131 # Parse ouput
Nanang Izzuddin9869cb52008-06-27 16:18:13 +0000132 mo_pesq_out = re.compile("Prediction[^=]+=\s+([\-\d\.]+)\s*").search(pesq_out[0])
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000133 if (mo_pesq_out == None):
134 raise TestError("Failed to fetch PESQ result")
135
Nanang Izzuddin9eac5472008-06-26 18:52:16 +0000136 # Get threshold
137 if (cfg_file.pesq_threshold != None) | (cfg_file.pesq_threshold > -0.5 ):
138 threshold = cfg_file.pesq_threshold
139 else:
140 threshold = PESQ_DEFAULT_THRESHOLD
141
142 # Evaluate the PESQ MOS value
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000143 pesq_res = mo_pesq_out.group(1)
Nanang Izzuddin9eac5472008-06-26 18:52:16 +0000144 if (float(pesq_res) >= threshold):
Nanang Izzuddinffa18c92008-06-28 00:52:20 +0000145 endpt.trace("Success, PESQ result = " + pesq_res + " (target=" + str(threshold) + ").")
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000146 else:
Nanang Izzuddinffa18c92008-06-28 00:52:20 +0000147 endpt.trace("Failed, PESQ result = " + pesq_res + " (target=" + str(threshold) + ").")
148 # Save the wav file
149 wavoutname = ARGS[1]
150 wavoutname = re.sub("[\\\/]", "_", wavoutname)
151 wavoutname = re.sub("\.py$", ".wav", wavoutname)
152 wavoutname = "logs/" + wavoutname
153 try:
154 shutil.copyfile(output_filename, wavoutname)
155 print "Output WAV is copied to " + wavoutname
156 except:
157 print "Couldn't copy output WAV, please check if 'logs' directory exists."
158
159 raise TestError("WAV seems to be degraded badly, PESQ = "+ pesq_res + " (target=" + str(threshold) + ").")
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000160
161
162# Here where it all comes together
163test = cfg_file.test_param
164test.test_func = test_func
165test.post_func = post_func
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000166