1# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 2# 3# Use of this source code is governed by a BSD-style license 4# that can be found in the LICENSE file in the root of the source 5# tree. An additional intellectual property rights grant can be found 6# in the file PATENTS. All contributing project authors may 7# be found in the AUTHORS file in the root of the source tree. 8"""Class implementing a wrapper for APM simulators. 9""" 10 11import cProfile 12import logging 13import os 14import subprocess 15 16from . import data_access 17from . import exceptions 18 19 20class AudioProcWrapper(object): 21 """Wrapper for APM simulators. 22 """ 23 24 DEFAULT_APM_SIMULATOR_BIN_PATH = os.path.abspath( 25 os.path.join(os.pardir, 'audioproc_f')) 26 OUTPUT_FILENAME = 'output.wav' 27 28 def __init__(self, simulator_bin_path): 29 """Ctor. 30 31 Args: 32 simulator_bin_path: path to the APM simulator binary. 33 """ 34 self._simulator_bin_path = simulator_bin_path 35 self._config = None 36 self._output_signal_filepath = None 37 38 # Profiler instance to measure running time. 39 self._profiler = cProfile.Profile() 40 41 @property 42 def output_filepath(self): 43 return self._output_signal_filepath 44 45 def Run(self, 46 config_filepath, 47 capture_input_filepath, 48 output_path, 49 render_input_filepath=None): 50 """Runs APM simulator. 51 52 Args: 53 config_filepath: path to the configuration file specifying the arguments 54 for the APM simulator. 55 capture_input_filepath: path to the capture audio track input file (aka 56 forward or near-end). 57 output_path: path of the audio track output file. 58 render_input_filepath: path to the render audio track input file (aka 59 reverse or far-end). 60 """ 61 # Init. 62 self._output_signal_filepath = os.path.join(output_path, 63 self.OUTPUT_FILENAME) 64 profiling_stats_filepath = os.path.join(output_path, 'profiling.stats') 65 66 # Skip if the output has already been generated. 67 if os.path.exists(self._output_signal_filepath) and os.path.exists( 68 profiling_stats_filepath): 69 return 70 71 # Load configuration. 72 self._config = data_access.AudioProcConfigFile.Load(config_filepath) 73 74 # Set remaining parameters. 75 if not os.path.exists(capture_input_filepath): 76 raise exceptions.FileNotFoundError( 77 'cannot find capture input file') 78 self._config['-i'] = capture_input_filepath 79 self._config['-o'] = self._output_signal_filepath 80 if render_input_filepath is not None: 81 if not os.path.exists(render_input_filepath): 82 raise exceptions.FileNotFoundError( 83 'cannot find render input file') 84 self._config['-ri'] = render_input_filepath 85 86 # Build arguments list. 87 args = [self._simulator_bin_path] 88 for param_name in self._config: 89 args.append(param_name) 90 if self._config[param_name] is not None: 91 args.append(str(self._config[param_name])) 92 logging.debug(' '.join(args)) 93 94 # Run. 95 self._profiler.enable() 96 subprocess.call(args) 97 self._profiler.disable() 98 99 # Save profiling stats. 100 self._profiler.dump_stats(profiling_stats_filepath) 101