blob: ef76def3fea044bf2a71d71accef68100ce7d0a3 [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 Izzuddinb6133fb2008-06-20 21:45:50 +000019import inc_const as const
20
21from inc_cfg import *
22
23# Load configuration
24cfg_file = imp.load_source("cfg_file", sys.argv[2])
25
26# PESQ configs
27# PESQ_THRESHOLD specifies the minimum acceptable PESQ MOS value, so test can be declared successful
28PESQ = "tools/pesq.exe"
Nanang Izzuddin9eac5472008-06-26 18:52:16 +000029PESQ_DEFAULT_THRESHOLD = 3.4
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000030
31# UserData
32class mod_pesq_user_data:
33 # Sample rate option for PESQ
34 pesq_sample_rate_opt = ""
35 # Input/Reference filename
36 input_filename = ""
37 # Output/Degraded filename
38 output_filename = ""
39
40# Test body function
41def test_func(t, user_data):
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 Izzuddinacb3e322008-06-25 18:18:32 +000047 user_data.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 Izzuddinacb3e322008-06-25 18:18:32 +000050 user_data.output_filename = re.compile(const.MEDIA_REC_FILE).search(ua2.inst_param.arg).group(1)
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000051
52 # Find appropriate clock rate for the input file
Nanang Izzuddinacb3e322008-06-25 18:18:32 +000053 mo_clock_rate = re.compile("\.(\d+)\.wav").search(user_data.output_filename)
54 if (mo_clock_rate==None):
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000055 raise TestError("Cannot compare input & output, incorrect output filename format")
Nanang Izzuddinacb3e322008-06-25 18:18:32 +000056 clock_rate = mo_clock_rate.group(1)
57 user_data.input_filename = re.sub("\.\d+\.wav", "."+clock_rate+".wav", user_data.input_filename)
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000058
Nanang Izzuddinacb3e322008-06-25 18:18:32 +000059 if (clock_rate != "8") & (clock_rate != "16"):
60 raise TestError("PESQ only works on clock rate 8kHz or 16kHz, clock rate used = "+clock_rate+ "kHz")
61
62 # Get conference clock rate of UA2 for PESQ sample rate option
63 user_data.pesq_sample_rate_opt = "+" + clock_rate + "000"
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000064
Nanang Izzuddin9eac5472008-06-26 18:52:16 +000065 # Get WAV input length, in seconds
66 fin = wave.open(user_data.input_filename, "r")
67 if fin == None:
68 raise TestError("Failed opening input WAV file")
69 inwavlen = fin.getnframes() // fin.getframerate()
70 if (fin.getnframes() % fin.getframerate()) > 0:
71 inwavlen = inwavlen + 1
72 fin.close()
73
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000074 # UA1 making call
75 ua1.send("m")
76 ua1.send(t.inst_params[1].uri)
77 ua1.expect(const.STATE_CALLING)
Nanang Izzuddin9eac5472008-06-26 18:52:16 +000078
79 # UA2 wait until call established
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +000080 ua2.expect(const.STATE_CONFIRMED)
81
Nanang Izzuddin9eac5472008-06-26 18:52:16 +000082 # Disconnect mic -> rec file, to avoid echo recorded when using sound device
83 # Disconnect stream -> spk, make it silent
84 # Connect stream -> rec file, start recording
85 ua2.send("cd 0 1\ncd 4 0\ncc 4 1")
Nanang Izzuddinacb3e322008-06-25 18:18:32 +000086
Nanang Izzuddin9eac5472008-06-26 18:52:16 +000087 # Disconnect mic -> stream, make stream purely sending from file
88 # Disconnect stream -> spk, make it silent
89 # Connect file -> stream, start sending
90 ua1.send("cd 0 4\ncd 4 0\ncc 1 4")
Nanang Izzuddinacb3e322008-06-25 18:18:32 +000091
Nanang Izzuddin9eac5472008-06-26 18:52:16 +000092 time.sleep(inwavlen)
93
94 # Disconnect files from bridge
95 ua2.send("cd 4 1")
96 ua2.expect(const.MEDIA_DISCONN_PORT_SUCCESS)
97 ua1.send("cd 1 4")
98 ua1.expect(const.MEDIA_DISCONN_PORT_SUCCESS)
99
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000100
101# Post body function
102def post_func(t, user_data):
103 endpt = t.process[0]
104
105 # Execute PESQ
106 fullcmd = PESQ + " " + user_data.pesq_sample_rate_opt + " " + user_data.input_filename + " " + user_data.output_filename
107 endpt.trace("Popen " + fullcmd)
108 pesq_proc = subprocess.Popen(fullcmd, stdout=subprocess.PIPE, universal_newlines=True)
109 pesq_out = pesq_proc.communicate()
110
111 # Parse ouput
Nanang Izzuddin6ee166d2008-06-26 12:26:52 +0000112 mo_pesq_out = re.compile("Prediction[^=]+=\s+([\d\.]+)\s*").search(pesq_out[0])
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000113 if (mo_pesq_out == None):
114 raise TestError("Failed to fetch PESQ result")
115
Nanang Izzuddin9eac5472008-06-26 18:52:16 +0000116 # Get threshold
117 if (cfg_file.pesq_threshold != None) | (cfg_file.pesq_threshold > -0.5 ):
118 threshold = cfg_file.pesq_threshold
119 else:
120 threshold = PESQ_DEFAULT_THRESHOLD
121
122 # Evaluate the PESQ MOS value
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000123 pesq_res = mo_pesq_out.group(1)
Nanang Izzuddin9eac5472008-06-26 18:52:16 +0000124 if (float(pesq_res) >= threshold):
Nanang Izzuddin6ee166d2008-06-26 12:26:52 +0000125 endpt.trace("Success, PESQ result = " + pesq_res)
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000126 else:
Nanang Izzuddin6ee166d2008-06-26 12:26:52 +0000127 endpt.trace("Failed, PESQ result = " + pesq_res)
Nanang Izzuddinb6133fb2008-06-20 21:45:50 +0000128 raise TestError("WAV seems to be degraded badly")
129
130
131# Here where it all comes together
132test = cfg_file.test_param
133test.test_func = test_func
134test.post_func = post_func
135test.user_data = mod_pesq_user_data()
136