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