Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 1 | # $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 | |
| 13 | import time |
| 14 | import imp |
| 15 | import sys |
| 16 | import re |
| 17 | import subprocess |
| 18 | import inc_const as const |
| 19 | |
| 20 | from inc_cfg import * |
| 21 | |
| 22 | # Load configuration |
| 23 | cfg_file = imp.load_source("cfg_file", sys.argv[2]) |
| 24 | |
| 25 | # PESQ configs |
| 26 | # PESQ_THRESHOLD specifies the minimum acceptable PESQ MOS value, so test can be declared successful |
| 27 | PESQ = "tools/pesq.exe" |
| 28 | PESQ_THRESHOLD = 1.0 |
| 29 | |
| 30 | # UserData |
| 31 | class mod_pesq_user_data: |
| 32 | # Sample rate option for PESQ |
| 33 | pesq_sample_rate_opt = "" |
| 34 | # Input/Reference filename |
| 35 | input_filename = "" |
| 36 | # Output/Degraded filename |
| 37 | output_filename = "" |
| 38 | |
| 39 | # Test body function |
| 40 | def test_func(t, user_data): |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 41 | ua1 = t.process[0] |
| 42 | ua2 = t.process[1] |
| 43 | |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 44 | # Get input file name |
Nanang Izzuddin | acb3e32 | 2008-06-25 18:18:32 +0000 | [diff] [blame] | 45 | user_data.input_filename = re.compile(const.MEDIA_PLAY_FILE).search(ua1.inst_param.arg).group(1) |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 46 | |
| 47 | # Get output file name |
Nanang Izzuddin | acb3e32 | 2008-06-25 18:18:32 +0000 | [diff] [blame] | 48 | user_data.output_filename = re.compile(const.MEDIA_REC_FILE).search(ua2.inst_param.arg).group(1) |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 49 | |
| 50 | # Find appropriate clock rate for the input file |
Nanang Izzuddin | acb3e32 | 2008-06-25 18:18:32 +0000 | [diff] [blame] | 51 | mo_clock_rate = re.compile("\.(\d+)\.wav").search(user_data.output_filename) |
| 52 | if (mo_clock_rate==None): |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 53 | raise TestError("Cannot compare input & output, incorrect output filename format") |
Nanang Izzuddin | acb3e32 | 2008-06-25 18:18:32 +0000 | [diff] [blame] | 54 | clock_rate = mo_clock_rate.group(1) |
| 55 | user_data.input_filename = re.sub("\.\d+\.wav", "."+clock_rate+".wav", user_data.input_filename) |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 56 | |
Nanang Izzuddin | acb3e32 | 2008-06-25 18:18:32 +0000 | [diff] [blame] | 57 | if (clock_rate != "8") & (clock_rate != "16"): |
| 58 | raise TestError("PESQ only works on clock rate 8kHz or 16kHz, clock rate used = "+clock_rate+ "kHz") |
| 59 | |
| 60 | # Get conference clock rate of UA2 for PESQ sample rate option |
| 61 | user_data.pesq_sample_rate_opt = "+" + clock_rate + "000" |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 62 | |
| 63 | # UA1 making call |
| 64 | ua1.send("m") |
| 65 | ua1.send(t.inst_params[1].uri) |
| 66 | ua1.expect(const.STATE_CALLING) |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 67 | ua2.expect(const.STATE_CONFIRMED) |
| 68 | |
Nanang Izzuddin | acb3e32 | 2008-06-25 18:18:32 +0000 | [diff] [blame] | 69 | # Disconnect mic -> rec file to avoid echo recorded when using sound device |
| 70 | ua2.send("cd 0 1") |
| 71 | |
| 72 | # Auto answer, auto play, auto hangup |
| 73 | # Just wait for call disconnected |
| 74 | # Assumed WAV input is no more than 30 secs |
| 75 | while 1: |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 76 | line = ua2.proc.stdout.readline() |
| 77 | if line == "": |
| 78 | raise TestError(ua2.name + ": Premature EOF") |
Nanang Izzuddin | acb3e32 | 2008-06-25 18:18:32 +0000 | [diff] [blame] | 79 | |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 80 | # Search for disconnected text |
| 81 | if re.search(const.STATE_DISCONNECTED, line) != None: |
| 82 | break |
| 83 | |
| 84 | |
| 85 | # Post body function |
| 86 | def post_func(t, user_data): |
| 87 | endpt = t.process[0] |
| 88 | |
| 89 | # Execute PESQ |
| 90 | fullcmd = PESQ + " " + user_data.pesq_sample_rate_opt + " " + user_data.input_filename + " " + user_data.output_filename |
| 91 | endpt.trace("Popen " + fullcmd) |
| 92 | pesq_proc = subprocess.Popen(fullcmd, stdout=subprocess.PIPE, universal_newlines=True) |
| 93 | pesq_out = pesq_proc.communicate() |
| 94 | |
| 95 | # Parse ouput |
| 96 | mo_pesq_out = re.compile("Prediction\s+:\s+PESQ_MOS\s+=\s+(.+)\s*").search(pesq_out[0]) |
| 97 | if (mo_pesq_out == None): |
| 98 | raise TestError("Failed to fetch PESQ result") |
| 99 | |
| 100 | # Evaluate the similarity value |
| 101 | pesq_res = mo_pesq_out.group(1) |
Nanang Izzuddin | acb3e32 | 2008-06-25 18:18:32 +0000 | [diff] [blame] | 102 | if (float(pesq_res) >= PESQ_THRESHOLD): |
Nanang Izzuddin | b6133fb | 2008-06-20 21:45:50 +0000 | [diff] [blame] | 103 | endpt.trace("Success, PESQ result=" + pesq_res) |
| 104 | else: |
| 105 | endpt.trace("Failed, PESQ result=" + pesq_res) |
| 106 | raise TestError("WAV seems to be degraded badly") |
| 107 | |
| 108 | |
| 109 | # Here where it all comes together |
| 110 | test = cfg_file.test_param |
| 111 | test.test_func = test_func |
| 112 | test.post_func = post_func |
| 113 | test.user_data = mod_pesq_user_data() |
| 114 | |