• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3#
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
6# tree. An additional intellectual property rights grant can be found
7# in the file PATENTS.  All contributing project authors may
8# be found in the AUTHORS file in the root of the source tree.
9
10"""Perform APM module quality assessment on one or more input files using one or
11   more APM simulator configuration files and one or more test data generators.
12
13Usage: apm_quality_assessment.py -i audio1.wav [audio2.wav ...]
14                                 -c cfg1.json [cfg2.json ...]
15                                 -n white [echo ...]
16                                 -e audio_level [polqa ...]
17                                 -o /path/to/output
18"""
19
20import argparse
21import logging
22import os
23import sys
24
25import quality_assessment.audioproc_wrapper as audioproc_wrapper
26import quality_assessment.echo_path_simulation as echo_path_simulation
27import quality_assessment.eval_scores as eval_scores
28import quality_assessment.evaluation as evaluation
29import quality_assessment.eval_scores_factory as eval_scores_factory
30import quality_assessment.external_vad as external_vad
31import quality_assessment.test_data_generation as test_data_generation
32import quality_assessment.test_data_generation_factory as  \
33    test_data_generation_factory
34import quality_assessment.simulation as simulation
35
36_ECHO_PATH_SIMULATOR_NAMES = (
37    echo_path_simulation.EchoPathSimulator.REGISTERED_CLASSES)
38_TEST_DATA_GENERATOR_CLASSES = (
39    test_data_generation.TestDataGenerator.REGISTERED_CLASSES)
40_TEST_DATA_GENERATORS_NAMES = _TEST_DATA_GENERATOR_CLASSES.keys()
41_EVAL_SCORE_WORKER_CLASSES = eval_scores.EvaluationScore.REGISTERED_CLASSES
42_EVAL_SCORE_WORKER_NAMES = _EVAL_SCORE_WORKER_CLASSES.keys()
43
44_DEFAULT_CONFIG_FILE = 'apm_configs/default.json'
45
46_POLQA_BIN_NAME = 'PolqaOem64'
47
48
49def _InstanceArgumentsParser():
50  """Arguments parser factory.
51  """
52  parser = argparse.ArgumentParser(description=(
53      'Perform APM module quality assessment on one or more input files using '
54      'one or more APM simulator configuration files and one or more '
55      'test data generators.'))
56
57  parser.add_argument('-c', '--config_files', nargs='+', required=False,
58                      help=('path to the configuration files defining the '
59                            'arguments with which the APM simulator tool is '
60                            'called'),
61                      default=[_DEFAULT_CONFIG_FILE])
62
63  parser.add_argument('-i', '--capture_input_files', nargs='+', required=True,
64                      help='path to the capture input wav files (one or more)')
65
66  parser.add_argument('-r', '--render_input_files', nargs='+', required=False,
67                      help=('path to the render input wav files; either '
68                            'omitted or one file for each file in '
69                            '--capture_input_files (files will be paired by '
70                            'index)'), default=None)
71
72  parser.add_argument('-p', '--echo_path_simulator', required=False,
73                      help=('custom echo path simulator name; required if '
74                            '--render_input_files is specified'),
75                      choices=_ECHO_PATH_SIMULATOR_NAMES,
76                      default=echo_path_simulation.NoEchoPathSimulator.NAME)
77
78  parser.add_argument('-t', '--test_data_generators', nargs='+', required=False,
79                      help='custom list of test data generators to use',
80                      choices=_TEST_DATA_GENERATORS_NAMES,
81                      default=_TEST_DATA_GENERATORS_NAMES)
82
83  parser.add_argument('--additive_noise_tracks_path', required=False,
84                      help='path to the wav files for the additive',
85                      default=test_data_generation.  \
86                              AdditiveNoiseTestDataGenerator.  \
87                              DEFAULT_NOISE_TRACKS_PATH)
88
89  parser.add_argument('-e', '--eval_scores', nargs='+', required=False,
90                      help='custom list of evaluation scores to use',
91                      choices=_EVAL_SCORE_WORKER_NAMES,
92                      default=_EVAL_SCORE_WORKER_NAMES)
93
94  parser.add_argument('-o', '--output_dir', required=False,
95                      help=('base path to the output directory in which the '
96                            'output wav files and the evaluation outcomes '
97                            'are saved'),
98                      default='output')
99
100  parser.add_argument('--polqa_path', required=True,
101                      help='path to the POLQA tool')
102
103  parser.add_argument('--air_db_path', required=True,
104                      help='path to the Aechen IR database')
105
106  parser.add_argument('--apm_sim_path', required=False,
107                      help='path to the APM simulator tool',
108                      default=audioproc_wrapper.  \
109                              AudioProcWrapper.  \
110                              DEFAULT_APM_SIMULATOR_BIN_PATH)
111
112  parser.add_argument('--echo_metric_tool_bin_path', required=False,
113                      help=('path to the echo metric binary '
114                           '(required for the echo eval score)'),
115                      default=None)
116
117  parser.add_argument('--copy_with_identity_generator', required=False,
118                      help=('If true, the identity test data generator makes a '
119                            'copy of the clean speech input file.'),
120                      default=False)
121
122  parser.add_argument('--external_vad_paths', nargs='+', required=False,
123                      help=('Paths to external VAD programs. Each must take'
124                            '\'-i <wav file> -o <output>\' inputs'), default=[])
125
126  parser.add_argument('--external_vad_names', nargs='+', required=False,
127                      help=('Keys to the vad paths. Must be different and '
128                            'as many as the paths.'), default=[])
129
130  return parser
131
132
133def _ValidateArguments(args, parser):
134  if args.capture_input_files and args.render_input_files and (
135      len(args.capture_input_files) != len(args.render_input_files)):
136    parser.error('--render_input_files and --capture_input_files must be lists '
137                 'having the same length')
138    sys.exit(1)
139
140  if args.render_input_files and not args.echo_path_simulator:
141    parser.error('when --render_input_files is set, --echo_path_simulator is '
142                 'also required')
143    sys.exit(1)
144
145  if len(args.external_vad_names) != len(args.external_vad_paths):
146    parser.error('If provided, --external_vad_paths and '
147                 '--external_vad_names must '
148                 'have the same number of arguments.')
149    sys.exit(1)
150
151
152def main():
153  # TODO(alessiob): level = logging.INFO once debugged.
154  logging.basicConfig(level=logging.DEBUG)
155  parser = _InstanceArgumentsParser()
156  args = parser.parse_args()
157  _ValidateArguments(args, parser)
158
159  simulator = simulation.ApmModuleSimulator(
160      test_data_generator_factory=(
161          test_data_generation_factory.TestDataGeneratorFactory(
162              aechen_ir_database_path=args.air_db_path,
163              noise_tracks_path=args.additive_noise_tracks_path,
164              copy_with_identity=args.copy_with_identity_generator)),
165      evaluation_score_factory=eval_scores_factory.EvaluationScoreWorkerFactory(
166          polqa_tool_bin_path=os.path.join(args.polqa_path, _POLQA_BIN_NAME),
167          echo_metric_tool_bin_path=args.echo_metric_tool_bin_path
168      ),
169      ap_wrapper=audioproc_wrapper.AudioProcWrapper(args.apm_sim_path),
170      evaluator=evaluation.ApmModuleEvaluator(),
171      external_vads=external_vad.ExternalVad.ConstructVadDict(
172          args.external_vad_paths, args.external_vad_names))
173  simulator.Run(
174      config_filepaths=args.config_files,
175      capture_input_filepaths=args.capture_input_files,
176      render_input_filepaths=args.render_input_files,
177      echo_path_simulator_name=args.echo_path_simulator,
178      test_data_generator_names=args.test_data_generators,
179      eval_score_names=args.eval_scores,
180      output_dir=args.output_dir)
181  sys.exit(0)
182
183
184if __name__ == '__main__':
185  main()
186