Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: webrtc/audio/test/low_bandwidth_audio_test.py

Issue 2804083003: Add POLQA to low bandwidth audio test (Closed)
Patch Set: Add POLQA to low bandwidth audio test Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 2 # Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 # 3 #
4 # Use of this source code is governed by a BSD-style license 4 # Use of this source code is governed by a BSD-style license
5 # that can be found in the LICENSE file in the root of the source 5 # that can be found in the LICENSE file in the root of the source
6 # tree. An additional intellectual property rights grant can be found 6 # tree. An additional intellectual property rights grant can be found
7 # in the file PATENTS. All contributing project authors may 7 # in the file PATENTS. All contributing project authors may
8 # be found in the AUTHORS file in the root of the source tree. 8 # be found in the AUTHORS file in the root of the source tree.
9 9
10 """ 10 """
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 def _DownloadTools(): 58 def _DownloadTools():
59 tools_dir = os.path.join(SRC_DIR, 'tools-webrtc') 59 tools_dir = os.path.join(SRC_DIR, 'tools-webrtc')
60 toolchain_dir = os.path.join(tools_dir, 'audio_quality') 60 toolchain_dir = os.path.join(tools_dir, 'audio_quality')
61 61
62 # Download pesq. 62 # Download pesq.
63 download_script = os.path.join(tools_dir, 'download_tools.py') 63 download_script = os.path.join(tools_dir, 'download_tools.py')
64 command = [sys.executable, download_script, toolchain_dir] 64 command = [sys.executable, download_script, toolchain_dir]
65 subprocess.check_call(_LogCommand(command)) 65 subprocess.check_call(_LogCommand(command))
66 66
67 pesq_path = os.path.join(toolchain_dir, _GetPlatform(), 'pesq') 67 pesq_path = os.path.join(toolchain_dir, _GetPlatform(), 'pesq')
68 return pesq_path 68 polqa_path = os.path.join(toolchain_dir, _GetPlatform(), 'PolqaOem64')
69 return pesq_path, polqa_path
69 70
70 71
71 def ExtractTestRuns(lines, echo=False): 72 def ExtractTestRuns(lines, echo=False):
72 """Extracts information about tests from the output of a test runner. 73 """Extracts information about tests from the output of a test runner.
73 74
74 Produces tuples (android_device, test_name, reference_file, degraded_file). 75 Produces tuples (android_device, test_name, reference_file, degraded_file).
75 """ 76 """
76 for line in lines: 77 for line in lines:
77 if echo: 78 if echo:
78 sys.stdout.write(line) 79 sys.stdout.write(line)
(...skipping 22 matching lines...) Expand all
101 subprocess.check_call(_LogCommand(adb_command)) 102 subprocess.check_call(_LogCommand(adb_command))
102 elif os.path.abspath(file_path) != os.path.abspath(out_file_path): 103 elif os.path.abspath(file_path) != os.path.abspath(out_file_path):
103 if move: 104 if move:
104 shutil.move(file_path, out_file_path) 105 shutil.move(file_path, out_file_path)
105 else: 106 else:
106 shutil.copy(file_path, out_file_path) 107 shutil.copy(file_path, out_file_path)
107 108
108 return out_file_path 109 return out_file_path
109 110
110 111
112 def _RunPesq(executable_path, reference_file, degraded_file, bitrate=16000):
kjellander_webrtc 2017/04/07 18:26:12 bitrate -> sampling_frequency_in_hz
oprypin_webrtc 2017/04/10 12:20:41 Thanks. I really should be more careful about this
113 directory = os.path.dirname(reference_file)
114 assert os.path.dirname(degraded_file) == directory
115
116 # Analyze audio.
117 command = [executable_path, '+%d' % bitrate,
118 os.path.basename(reference_file),
119 os.path.basename(degraded_file)]
120 # Need to provide paths in the current directory due to a bug in PESQ:
121 # On Mac, for some 'path/to/file.wav', if 'file.wav' is longer than
122 # 'path/to', PESQ crashes.
123 out = subprocess.check_output(_LogCommand(command),
124 cwd=directory, stderr=subprocess.STDOUT)
125
126 # Find the scores in stdout of pesq.
127 match = re.search(
128 r'Prediction \(Raw MOS, MOS-LQO\):\s+=\s+([\d.]+)\s+([\d.]+)', out)
129 if match:
130 raw_mos, _ = match.groups()
131
132 return {'pesq_mos': (raw_mos, 'score')}
133 else:
134 logging.error('PESQ: %s', out.splitlines()[-1])
135 return {}
136
137
138 def _RunPolqa(executable_path, reference_file, degraded_file):
139 # Analyze audio.
140 command = [executable_path, '-q', '-LC', 'NB',
141 '-Ref', reference_file, '-Test', degraded_file]
142 try:
143 process = subprocess.Popen(_LogCommand(command),
144 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
145 except OSError as e:
146 if e.errno == os.errno.ENOENT:
147 logging.warning('POLQA executable missing, skipping test.')
148 return {}
149 else:
150 raise
151 out, err = process.communicate()
152
153 # Find the scores in stdout of polqa.
kjellander_webrtc 2017/04/07 18:26:12 polqa -> POLQA
oprypin_webrtc 2017/04/10 12:20:40 Done.
154 match = re.search(r'\bMOS-LQO:\s+([\d.]+)', out)
155
156 if process.returncode != 0 or not match:
157 if process.returncode == 2:
158 logging.warning('%s (2)', err.strip())
159 logging.warning('POLQA license error, skipping test.')
160 else:
161 logging.error('%s (%d)', err.strip(), process.returncode)
162 return {}
163
164 mos_lqo, = match.groups()
165 return {'polqa_mos_lqo': (mos_lqo, 'score')}
166
167
111 def main(): 168 def main():
112 # pylint: disable=W0101 169 # pylint: disable=W0101
113 logging.basicConfig(level=logging.INFO) 170 logging.basicConfig(level=logging.INFO)
114 171
115 args = _ParseArgs() 172 args = _ParseArgs()
116 173
117 pesq_path = _DownloadTools() 174 pesq_path, polqa_path = _DownloadTools()
118 175
119 out_dir = os.path.join(args.build_dir, '..') 176 out_dir = os.path.join(args.build_dir, '..')
120 if args.android: 177 if args.android:
121 test_command = [os.path.join(args.build_dir, 'bin', 178 test_command = [os.path.join(args.build_dir, 'bin',
122 'run_low_bandwidth_audio_test'), '-v'] 179 'run_low_bandwidth_audio_test'), '-v']
123 else: 180 else:
124 test_command = [os.path.join(args.build_dir, 'low_bandwidth_audio_test')] 181 test_command = [os.path.join(args.build_dir, 'low_bandwidth_audio_test')]
125 182
126 # Start the test executable that produces audio files. 183 analyzers = [(_RunPesq, pesq_path, 16000)]
kjellander_webrtc 2017/04/07 18:26:12 How about using this instead for improved readabil
oprypin_webrtc 2017/04/10 12:20:41 Done.
127 test_process = subprocess.Popen(_LogCommand(test_command), 184 # Check if POLQA can run at all, or skip the 48000 tests entirely.
128 stdout=subprocess.PIPE) 185 example_path = os.path.join(SRC_DIR, 'resources',
186 'voice_engine', 'audio_tiny48.wav')
187 if _RunPolqa(polqa_path, example_path, example_path):
188 analyzers.insert(0, (_RunPolqa, polqa_path, 48000))
kjellander_webrtc 2017/04/07 18:26:12 any reason you don't just use .append instead?
oprypin_webrtc 2017/04/10 12:20:41 This was meant to run POLQA first, but it doesn't
129 189
130 try: 190 for analyzer_func, analyzer_executable, bitrate in analyzers:
131 lines = iter(test_process.stdout.readline, '') 191 # Start the test executable that produces audio files.
132 for result in ExtractTestRuns(lines, echo=True): 192 test_process = subprocess.Popen(_LogCommand(test_command +
133 (android_device, test_name, reference_file, degraded_file) = result 193 ['--bitrate=%d' % bitrate]),
194 stdout=subprocess.PIPE)
195 try:
196 lines = iter(test_process.stdout.readline, '')
197 for result in ExtractTestRuns(lines, echo=True):
198 (android_device, test_name, reference_file, degraded_file) = result
134 199
135 adb_prefix = (args.adb_path,) 200 adb_prefix = (args.adb_path,)
136 if android_device: 201 if android_device:
137 adb_prefix += ('-s', android_device) 202 adb_prefix += ('-s', android_device)
138 203
139 reference_file = _GetFile(reference_file, out_dir, 204 reference_file = _GetFile(reference_file, out_dir,
140 android=args.android, adb_prefix=adb_prefix) 205 android=args.android, adb_prefix=adb_prefix)
141 degraded_file = _GetFile(degraded_file, out_dir, move=True, 206 degraded_file = _GetFile(degraded_file, out_dir, move=True,
142 android=args.android, adb_prefix=adb_prefix) 207 android=args.android, adb_prefix=adb_prefix)
143 208
144 # Analyze audio. 209 analyzer_results = analyzer_func(analyzer_executable,
145 pesq_command = [pesq_path, '+16000', 210 reference_file, degraded_file)
146 os.path.basename(reference_file), 211 for metric, (value, units) in analyzer_results.items():
147 os.path.basename(degraded_file)] 212 # Output a result for the perf dashboard.
148 # Need to provide paths in the current directory due to a bug in PESQ: 213 print 'RESULT %s: %s= %s %s' % (metric, test_name, value, units)
149 # On Mac, for some 'path/to/file.wav', if 'file.wav' is longer than
150 # 'path/to', PESQ crashes.
151 pesq_output = subprocess.check_output(_LogCommand(pesq_command),
152 cwd=out_dir)
153 214
154 # Find the scores in stdout of pesq. 215 if args.remove:
155 match = re.search( 216 os.remove(reference_file)
156 r'Prediction \(Raw MOS, MOS-LQO\):\s+=\s+([\d.]+)\s+([\d.]+)', 217 os.remove(degraded_file)
157 pesq_output) 218 finally:
158 if match: 219 test_process.terminate()
159 raw_mos, _ = match.groups()
160
161 # Output a result for the perf dashboard.
162 print 'RESULT pesq_mos: %s= %s score' % (test_name, raw_mos)
163 else:
164 logging.error('PESQ: %s', pesq_output.splitlines()[-1])
165
166 if args.remove:
167 os.remove(reference_file)
168 os.remove(degraded_file)
169 finally:
170 test_process.terminate()
171 220
172 return test_process.wait() 221 return test_process.wait()
173 222
174 223
175 if __name__ == '__main__': 224 if __name__ == '__main__':
176 sys.exit(main()) 225 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698