| #!/usr/bin/env python |
| # Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
| # |
| # Use of this source code is governed by a BSD-style license |
| # that can be found in the LICENSE file in the root of the source |
| # tree. An additional intellectual property rights grant can be found |
| # in the file PATENTS. All contributing project authors may |
| # be found in the AUTHORS file in the root of the source tree. |
| """Perform APM module quality assessment on one or more input files using one or |
| more APM simulator configuration files and one or more test data generators. |
| |
| Usage: apm_quality_assessment.py -i audio1.wav [audio2.wav ...] |
| -c cfg1.json [cfg2.json ...] |
| -n white [echo ...] |
| -e audio_level [polqa ...] |
| -o /path/to/output |
| """ |
| |
| import argparse |
| import logging |
| import os |
| import sys |
| |
| import quality_assessment.audioproc_wrapper as audioproc_wrapper |
| import quality_assessment.echo_path_simulation as echo_path_simulation |
| import quality_assessment.eval_scores as eval_scores |
| import quality_assessment.evaluation as evaluation |
| import quality_assessment.eval_scores_factory as eval_scores_factory |
| import quality_assessment.external_vad as external_vad |
| import quality_assessment.test_data_generation as test_data_generation |
| import quality_assessment.test_data_generation_factory as \ |
| test_data_generation_factory |
| import quality_assessment.simulation as simulation |
| |
| _ECHO_PATH_SIMULATOR_NAMES = ( |
| echo_path_simulation.EchoPathSimulator.REGISTERED_CLASSES) |
| _TEST_DATA_GENERATOR_CLASSES = ( |
| test_data_generation.TestDataGenerator.REGISTERED_CLASSES) |
| _TEST_DATA_GENERATORS_NAMES = _TEST_DATA_GENERATOR_CLASSES.keys() |
| _EVAL_SCORE_WORKER_CLASSES = eval_scores.EvaluationScore.REGISTERED_CLASSES |
| _EVAL_SCORE_WORKER_NAMES = _EVAL_SCORE_WORKER_CLASSES.keys() |
| |
| _DEFAULT_CONFIG_FILE = 'apm_configs/default.json' |
| |
| _POLQA_BIN_NAME = 'PolqaOem64' |
| |
| |
| def _InstanceArgumentsParser(): |
| """Arguments parser factory. |
| """ |
| parser = argparse.ArgumentParser(description=( |
| 'Perform APM module quality assessment on one or more input files using ' |
| 'one or more APM simulator configuration files and one or more ' |
| 'test data generators.')) |
| |
| parser.add_argument('-c', |
| '--config_files', |
| nargs='+', |
| required=False, |
| help=('path to the configuration files defining the ' |
| 'arguments with which the APM simulator tool is ' |
| 'called'), |
| default=[_DEFAULT_CONFIG_FILE]) |
| |
| parser.add_argument( |
| '-i', |
| '--capture_input_files', |
| nargs='+', |
| required=True, |
| help='path to the capture input wav files (one or more)') |
| |
| parser.add_argument('-r', |
| '--render_input_files', |
| nargs='+', |
| required=False, |
| help=('path to the render input wav files; either ' |
| 'omitted or one file for each file in ' |
| '--capture_input_files (files will be paired by ' |
| 'index)'), |
| default=None) |
| |
| parser.add_argument('-p', |
| '--echo_path_simulator', |
| required=False, |
| help=('custom echo path simulator name; required if ' |
| '--render_input_files is specified'), |
| choices=_ECHO_PATH_SIMULATOR_NAMES, |
| default=echo_path_simulation.NoEchoPathSimulator.NAME) |
| |
| parser.add_argument('-t', |
| '--test_data_generators', |
| nargs='+', |
| required=False, |
| help='custom list of test data generators to use', |
| choices=_TEST_DATA_GENERATORS_NAMES, |
| default=_TEST_DATA_GENERATORS_NAMES) |
| |
| parser.add_argument('--additive_noise_tracks_path', required=False, |
| help='path to the wav files for the additive', |
| default=test_data_generation. \ |
| AdditiveNoiseTestDataGenerator. \ |
| DEFAULT_NOISE_TRACKS_PATH) |
| |
| parser.add_argument('-e', |
| '--eval_scores', |
| nargs='+', |
| required=False, |
| help='custom list of evaluation scores to use', |
| choices=_EVAL_SCORE_WORKER_NAMES, |
| default=_EVAL_SCORE_WORKER_NAMES) |
| |
| parser.add_argument('-o', |
| '--output_dir', |
| required=False, |
| help=('base path to the output directory in which the ' |
| 'output wav files and the evaluation outcomes ' |
| 'are saved'), |
| default='output') |
| |
| parser.add_argument('--polqa_path', |
| required=True, |
| help='path to the POLQA tool') |
| |
| parser.add_argument('--air_db_path', |
| required=True, |
| help='path to the Aechen IR database') |
| |
| parser.add_argument('--apm_sim_path', required=False, |
| help='path to the APM simulator tool', |
| default=audioproc_wrapper. \ |
| AudioProcWrapper. \ |
| DEFAULT_APM_SIMULATOR_BIN_PATH) |
| |
| parser.add_argument('--echo_metric_tool_bin_path', |
| required=False, |
| help=('path to the echo metric binary ' |
| '(required for the echo eval score)'), |
| default=None) |
| |
| parser.add_argument( |
| '--copy_with_identity_generator', |
| required=False, |
| help=('If true, the identity test data generator makes a ' |
| 'copy of the clean speech input file.'), |
| default=False) |
| |
| parser.add_argument('--external_vad_paths', |
| nargs='+', |
| required=False, |
| help=('Paths to external VAD programs. Each must take' |
| '\'-i <wav file> -o <output>\' inputs'), |
| default=[]) |
| |
| parser.add_argument('--external_vad_names', |
| nargs='+', |
| required=False, |
| help=('Keys to the vad paths. Must be different and ' |
| 'as many as the paths.'), |
| default=[]) |
| |
| return parser |
| |
| |
| def _ValidateArguments(args, parser): |
| if args.capture_input_files and args.render_input_files and (len( |
| args.capture_input_files) != len(args.render_input_files)): |
| parser.error( |
| '--render_input_files and --capture_input_files must be lists ' |
| 'having the same length') |
| sys.exit(1) |
| |
| if args.render_input_files and not args.echo_path_simulator: |
| parser.error( |
| 'when --render_input_files is set, --echo_path_simulator is ' |
| 'also required') |
| sys.exit(1) |
| |
| if len(args.external_vad_names) != len(args.external_vad_paths): |
| parser.error('If provided, --external_vad_paths and ' |
| '--external_vad_names must ' |
| 'have the same number of arguments.') |
| sys.exit(1) |
| |
| |
| def main(): |
| # TODO(alessiob): level = logging.INFO once debugged. |
| logging.basicConfig(level=logging.DEBUG) |
| parser = _InstanceArgumentsParser() |
| args = parser.parse_args() |
| _ValidateArguments(args, parser) |
| |
| simulator = simulation.ApmModuleSimulator( |
| test_data_generator_factory=( |
| test_data_generation_factory.TestDataGeneratorFactory( |
| aechen_ir_database_path=args.air_db_path, |
| noise_tracks_path=args.additive_noise_tracks_path, |
| copy_with_identity=args.copy_with_identity_generator)), |
| evaluation_score_factory=eval_scores_factory. |
| EvaluationScoreWorkerFactory( |
| polqa_tool_bin_path=os.path.join(args.polqa_path, _POLQA_BIN_NAME), |
| echo_metric_tool_bin_path=args.echo_metric_tool_bin_path), |
| ap_wrapper=audioproc_wrapper.AudioProcWrapper(args.apm_sim_path), |
| evaluator=evaluation.ApmModuleEvaluator(), |
| external_vads=external_vad.ExternalVad.ConstructVadDict( |
| args.external_vad_paths, args.external_vad_names)) |
| simulator.Run(config_filepaths=args.config_files, |
| capture_input_filepaths=args.capture_input_files, |
| render_input_filepaths=args.render_input_files, |
| echo_path_simulator_name=args.echo_path_simulator, |
| test_data_generator_names=args.test_data_generators, |
| eval_score_names=args.eval_scores, |
| output_dir=args.output_dir) |
| sys.exit(0) |
| |
| |
| if __name__ == '__main__': |
| main() |