Index: webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/input_mixer.py |
diff --git a/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/input_mixer.py b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/input_mixer.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8f9e5422a70cfd63262283de1cd7bcb584b7a93d |
--- /dev/null |
+++ b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/input_mixer.py |
@@ -0,0 +1,93 @@ |
+# 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. |
+ |
+"""Input mixer module. |
+""" |
+ |
+import logging |
+import os |
+ |
+from . import exceptions |
+from . import signal_processing |
+ |
+ |
+class ApmInputMixer(object): |
+ """Class to mix a set of audio segments down to the APM input.""" |
+ |
+ _HARD_CLIPPING_LOG_MSG = 'hard clipping detected in the mixed signal' |
+ |
+ def __init__(self): |
+ pass |
+ |
+ @classmethod |
+ def HardClippingLogMessage(cls): |
+ """Returns the log message used when hard clipping is detected in the mix. |
+ |
+ This method is mainly intended to be used by the unit tests. |
+ """ |
+ return cls._HARD_CLIPPING_LOG_MSG |
+ |
+ @classmethod |
+ def Mix(cls, output_path, capture_input_filepath, echo_filepath): |
+ """Mixes capture and echo. |
+ |
+ Creates the overall capture input for APM by mixing the "echo-free" capture |
+ signal with the echo signal (e.g., echo simulated via the |
+ echo_path_simulation module). |
+ |
+ The echo signal cannot be shorter than the capture signal and the generated |
+ mix will have the same duration of the capture signal. The latter property |
+ is enforced in order to let the input of APM and the reference signal |
+ created by TestDataGenerator have the same length (required for the |
+ evaluation step). |
+ |
+ Hard-clipping may occur in the mix; a warning is raised when this happens. |
+ |
+ If |echo_filepath| is None, nothing is done and |capture_input_filepath| is |
+ returned. |
+ |
+ Args: |
+ speech: AudioSegment instance. |
+ echo_path: AudioSegment instance or None. |
+ |
+ Returns: |
+ Path to the mix audio track file. |
+ """ |
+ if echo_filepath is None: |
+ return capture_input_filepath |
+ |
+ # Build the mix output file name as a function of the echo file name. |
+ # This ensures that if the internal parameters of the echo path simulator |
+ # change, no erroneous cache hit occurs. |
+ echo_file_name, _ = os.path.splitext(os.path.split(echo_filepath)[1]) |
+ mix_filepath = os.path.join(output_path, 'mix_capture_{}.wav'.format( |
+ echo_file_name)) |
+ |
+ # Create the mix if not done yet. |
+ mix = None |
+ if not os.path.exists(mix_filepath): |
+ echo_free_capture = signal_processing.SignalProcessingUtils.LoadWav( |
+ capture_input_filepath) |
+ echo = signal_processing.SignalProcessingUtils.LoadWav(echo_filepath) |
+ |
+ if signal_processing.SignalProcessingUtils.CountSamples(echo) < ( |
+ signal_processing.SignalProcessingUtils.CountSamples( |
+ echo_free_capture)): |
+ raise exceptions.InputMixerException( |
+ 'echo cannot be shorter than capture') |
+ |
+ mix = echo_free_capture.overlay(echo) |
+ signal_processing.SignalProcessingUtils.SaveWav(mix_filepath, mix) |
+ |
+ # Check if hard clipping occurs. |
+ if mix is None: |
+ mix = signal_processing.SignalProcessingUtils.LoadWav(mix_filepath) |
+ if signal_processing.SignalProcessingUtils.DetectHardClipping(mix): |
+ logging.warning(cls._HARD_CLIPPING_LOG_MSG) |
+ |
+ return mix_filepath |