~noskcaj/ubuntu/saucy/sflphone/merge-1.2.3-2

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/tests/pjsua/mod_pesq.py

  • Committer: Jackson Doak
  • Date: 2013-07-10 21:04:46 UTC
  • mfrom: (20.1.3 sid)
  • Revision ID: noskcaj@ubuntu.com-20130710210446-y8f587vza807icr9
Properly merged from upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# $Id: mod_pesq.py 2417 2009-01-05 15:31:25Z bennylp $
 
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
 
 
13
import time
 
14
import imp
 
15
import os
 
16
import sys
 
17
import re
 
18
import subprocess
 
19
import wave
 
20
import shutil
 
21
import inc_const as const
 
22
 
 
23
from inc_cfg import *
 
24
 
 
25
# Load configuration
 
26
cfg_file = imp.load_source("cfg_file", ARGS[1])
 
27
 
 
28
# PESQ configs
 
29
PESQ = "tools/pesq"                     # PESQ executable path
 
30
PESQ_DEFAULT_THRESHOLD = 3.4            # Default minimum acceptable PESQ MOS value
 
31
 
 
32
# PESQ params
 
33
pesq_sample_rate_opt = ""               # Sample rate option for PESQ
 
34
input_filename  = ""                    # Input/Reference filename
 
35
output_filename = ""                    # Output/Degraded filename
 
36
 
 
37
 
 
38
# Test body function
 
39
def test_func(t):
 
40
        global pesq_sample_rate_opt
 
41
        global input_filename
 
42
        global output_filename
 
43
 
 
44
        ua1 = t.process[0]
 
45
        ua2 = t.process[1]
 
46
 
 
47
        # Get input file name
 
48
        input_filename = re.compile(const.MEDIA_PLAY_FILE).search(ua1.inst_param.arg).group(1)
 
49
 
 
50
        # Get output file name
 
51
        output_filename = re.compile(const.MEDIA_REC_FILE).search(ua2.inst_param.arg).group(1)
 
52
 
 
53
        # Get WAV input length, in seconds
 
54
        fin = wave.open(input_filename, "r")
 
55
        if fin == None:
 
56
                raise TestError("Failed opening input WAV file")
 
57
        inwavlen = fin.getnframes() * 1.0 / fin.getframerate()
 
58
        inwavlen += 0.2
 
59
        fin.close()
 
60
        print "WAV input len = " + str(inwavlen) + "s"
 
61
 
 
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)
 
67
 
 
68
        # Get channel count of the output
 
69
        channel_count = 1
 
70
        if re.search("--stereo", ua2.inst_param.arg) != None:
 
71
                channel_count = 2
 
72
 
 
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)
 
78
            else:
 
79
                    input_filename = re.sub("\.\d+\.wav", "." + str(channel_count) + "."+clock_rate+".wav", input_filename)
 
80
 
 
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")
 
83
 
 
84
        # Get conference clock rate of UA2 for PESQ sample rate option
 
85
        pesq_sample_rate_opt = "+" + clock_rate + "000"
 
86
 
 
87
        # UA1 making call
 
88
        ua1.send("m")
 
89
        ua1.send(t.inst_params[1].uri)
 
90
        ua1.expect(const.STATE_CALLING)
 
91
 
 
92
        # UA2 wait until call established
 
93
        ua2.expect(const.STATE_CONFIRMED)
 
94
 
 
95
        ua1.sync_stdout()
 
96
        ua2.sync_stdout()
 
97
        time.sleep(2)
 
98
 
 
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")
 
103
 
 
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")
 
108
 
 
109
        time.sleep(inwavlen)
 
110
 
 
111
        # Disconnect files from bridge
 
112
        ua2.send("cd 4 1")
 
113
        ua2.expect(const.MEDIA_DISCONN_PORT_SUCCESS)
 
114
        ua1.send("cd 1 4")
 
115
        ua1.expect(const.MEDIA_DISCONN_PORT_SUCCESS)
 
116
 
 
117
 
 
118
# Post body function
 
119
def post_func(t):
 
120
        global pesq_sample_rate_opt
 
121
        global input_filename
 
122
        global output_filename
 
123
 
 
124
        endpt = t.process[0]
 
125
 
 
126
        # Execute PESQ
 
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()
 
131
 
 
132
        # Parse ouput
 
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")
 
136
 
 
137
        # Get threshold
 
138
        if (cfg_file.pesq_threshold != None) | (cfg_file.pesq_threshold > -0.5 ):
 
139
                threshold = cfg_file.pesq_threshold
 
140
        else:
 
141
                threshold = PESQ_DEFAULT_THRESHOLD
 
142
 
 
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) + ").")
 
147
        else:
 
148
                endpt.trace("Failed, PESQ result = " + pesq_res + " (target=" + str(threshold) + ").")
 
149
                # Save the wav file
 
150
                wavoutname = ARGS[1]
 
151
                wavoutname = re.sub("[\\\/]", "_", wavoutname)
 
152
                wavoutname = re.sub("\.py$", ".wav", wavoutname)
 
153
                wavoutname = "logs/" + wavoutname
 
154
                try:
 
155
                        shutil.copyfile(output_filename, wavoutname)
 
156
                        print "Output WAV is copied to " + wavoutname
 
157
                except:
 
158
                        print "Couldn't copy output WAV, please check if 'logs' directory exists."
 
159
 
 
160
                raise TestError("WAV seems to be degraded badly, PESQ = "+ pesq_res + " (target=" + str(threshold) + ").")
 
161
 
 
162
 
 
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