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

Unified Diff: webrtc/audio/test/low_bandwidth_audio_test.py

Issue 2804083003: Add POLQA to low bandwidth audio test (Closed)
Patch Set: Rebase 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 side-by-side diff with in-line comments
Download patch
Index: webrtc/audio/test/low_bandwidth_audio_test.py
diff --git a/webrtc/audio/test/low_bandwidth_audio_test.py b/webrtc/audio/test/low_bandwidth_audio_test.py
index 8f4068199be7342e521eeb2e27f5bbe1b4083610..379a2d3ebea014dd2b500d1ad301f1e38196f0cc 100755
--- a/webrtc/audio/test/low_bandwidth_audio_test.py
+++ b/webrtc/audio/test/low_bandwidth_audio_test.py
@@ -15,6 +15,7 @@ output files will be performed.
"""
import argparse
+import collections
import logging
import os
import re
@@ -59,13 +60,14 @@ def _DownloadTools():
tools_dir = os.path.join(SRC_DIR, 'tools-webrtc')
toolchain_dir = os.path.join(tools_dir, 'audio_quality')
- # Download pesq.
+ # Download PESQ and POLQA.
download_script = os.path.join(tools_dir, 'download_tools.py')
command = [sys.executable, download_script, toolchain_dir]
subprocess.check_call(_LogCommand(command))
pesq_path = os.path.join(toolchain_dir, _GetPlatform(), 'pesq')
- return pesq_path
+ polqa_path = os.path.join(toolchain_dir, _GetPlatform(), 'PolqaOem64')
+ return pesq_path, polqa_path
def ExtractTestRuns(lines, echo=False):
@@ -108,13 +110,74 @@ def _GetFile(file_path, out_dir, move=False,
return out_file_path
+def _RunPesq(executable_path, reference_file, degraded_file,
+ sampling_frequency_hz=16000):
+ directory = os.path.dirname(reference_file)
+ assert os.path.dirname(degraded_file) == directory
+
+ # Analyze audio.
+ command = [executable_path, '+%d' % sampling_frequency_hz,
+ os.path.basename(reference_file),
+ os.path.basename(degraded_file)]
+ # Need to provide paths in the current directory due to a bug in PESQ:
+ # On Mac, for some 'path/to/file.wav', if 'file.wav' is longer than
+ # 'path/to', PESQ crashes.
+ out = subprocess.check_output(_LogCommand(command),
+ cwd=directory, stderr=subprocess.STDOUT)
+
+ # Find the scores in stdout of PESQ.
+ match = re.search(
+ r'Prediction \(Raw MOS, MOS-LQO\):\s+=\s+([\d.]+)\s+([\d.]+)', out)
+ if match:
+ raw_mos, _ = match.groups()
+
+ return {'pesq_mos': (raw_mos, 'score')}
+ else:
+ logging.error('PESQ: %s', out.splitlines()[-1])
+ return {}
+
+
+def _RunPolqa(executable_path, reference_file, degraded_file):
+ # Analyze audio.
+ command = [executable_path, '-q', '-LC', 'NB',
+ '-Ref', reference_file, '-Test', degraded_file]
+ try:
+ process = subprocess.Popen(_LogCommand(command),
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ except OSError as e:
+ if e.errno == os.errno.ENOENT:
+ logging.warning('POLQA executable missing, skipping test.')
+ return {}
+ else:
+ raise
+ out, err = process.communicate()
+
+ # Find the scores in stdout of POLQA.
+ match = re.search(r'\bMOS-LQO:\s+([\d.]+)', out)
+
+ if process.returncode != 0 or not match:
+ if process.returncode == 2:
+ logging.warning('%s (2)', err.strip())
+ logging.warning('POLQA license error, skipping test.')
+ else:
+ logging.error('%s (%d)', err.strip(), process.returncode)
+ return {}
+
+ mos_lqo, = match.groups()
+ return {'polqa_mos_lqo': (mos_lqo, 'score')}
+
+
+Analyzer = collections.namedtuple('Analyzer', ['func', 'executable',
+ 'sampling_frequency_hz'])
+
+
def main():
# pylint: disable=W0101
logging.basicConfig(level=logging.INFO)
args = _ParseArgs()
- pesq_path = _DownloadTools()
+ pesq_path, polqa_path = _DownloadTools()
out_dir = os.path.join(args.build_dir, '..')
if args.android:
@@ -123,51 +186,44 @@ def main():
else:
test_command = [os.path.join(args.build_dir, 'low_bandwidth_audio_test')]
- # Start the test executable that produces audio files.
- test_process = subprocess.Popen(_LogCommand(test_command),
- stdout=subprocess.PIPE)
-
- try:
- lines = iter(test_process.stdout.readline, '')
- for result in ExtractTestRuns(lines, echo=True):
- (android_device, test_name, reference_file, degraded_file) = result
-
- adb_prefix = (args.adb_path,)
- if android_device:
- adb_prefix += ('-s', android_device)
-
- reference_file = _GetFile(reference_file, out_dir,
- android=args.android, adb_prefix=adb_prefix)
- degraded_file = _GetFile(degraded_file, out_dir, move=True,
- android=args.android, adb_prefix=adb_prefix)
-
- # Analyze audio.
- pesq_command = [pesq_path, '+16000',
- os.path.basename(reference_file),
- os.path.basename(degraded_file)]
- # Need to provide paths in the current directory due to a bug in PESQ:
- # On Mac, for some 'path/to/file.wav', if 'file.wav' is longer than
- # 'path/to', PESQ crashes.
- pesq_output = subprocess.check_output(_LogCommand(pesq_command),
- cwd=out_dir)
-
- # Find the scores in stdout of pesq.
- match = re.search(
- r'Prediction \(Raw MOS, MOS-LQO\):\s+=\s+([\d.]+)\s+([\d.]+)',
- pesq_output)
- if match:
- raw_mos, _ = match.groups()
-
- # Output a result for the perf dashboard.
- print 'RESULT pesq_mos: %s= %s score' % (test_name, raw_mos)
- else:
- logging.error('PESQ: %s', pesq_output.splitlines()[-1])
-
- if args.remove:
- os.remove(reference_file)
- os.remove(degraded_file)
- finally:
- test_process.terminate()
+ analyzers = [Analyzer(_RunPesq, pesq_path, 16000)]
+ # Check if POLQA can run at all, or skip the 48 kHz tests entirely.
+ example_path = os.path.join(SRC_DIR, 'resources',
+ 'voice_engine', 'audio_tiny48.wav')
+ if _RunPolqa(polqa_path, example_path, example_path):
+ analyzers.append(Analyzer(_RunPolqa, polqa_path, 48000))
+
+ for analyzer in analyzers:
+ # Start the test executable that produces audio files.
+ test_process = subprocess.Popen(
+ _LogCommand(test_command + ['--sampling_frequency=%d' %
+ analyzer.sampling_frequency_hz]),
+ stdout=subprocess.PIPE)
+ try:
+ lines = iter(test_process.stdout.readline, '')
+ for result in ExtractTestRuns(lines, echo=True):
+ (android_device, test_name, reference_file, degraded_file) = result
+
+ adb_prefix = (args.adb_path,)
+ if android_device:
+ adb_prefix += ('-s', android_device)
+
+ reference_file = _GetFile(reference_file, out_dir,
+ android=args.android, adb_prefix=adb_prefix)
+ degraded_file = _GetFile(degraded_file, out_dir, move=True,
+ android=args.android, adb_prefix=adb_prefix)
+
+ analyzer_results = analyzer.func(analyzer.executable,
+ reference_file, degraded_file)
+ for metric, (value, units) in analyzer_results.items():
+ # Output a result for the perf dashboard.
+ print 'RESULT %s: %s= %s %s' % (metric, test_name, value, units)
+
+ if args.remove:
+ os.remove(reference_file)
+ os.remove(degraded_file)
+ finally:
+ test_process.terminate()
return test_process.wait()

Powered by Google App Engine
This is Rietveld 408576698