summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/echo_path_simulation.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/echo_path_simulation.py')
-rw-r--r--third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/echo_path_simulation.py136
1 files changed, 136 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/echo_path_simulation.py b/third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/echo_path_simulation.py
new file mode 100644
index 0000000000..65903ea32d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/echo_path_simulation.py
@@ -0,0 +1,136 @@
+# 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.
+"""Echo path simulation module.
+"""
+
+import hashlib
+import os
+
+from . import signal_processing
+
+
+class EchoPathSimulator(object):
+ """Abstract class for the echo path simulators.
+
+ In general, an echo path simulator is a function of the render signal and
+ simulates the propagation of the latter into the microphone (e.g., due to
+ mechanical or electrical paths).
+ """
+
+ NAME = None
+ REGISTERED_CLASSES = {}
+
+ def __init__(self):
+ pass
+
+ def Simulate(self, output_path):
+ """Creates the echo signal and stores it in an audio file (abstract method).
+
+ Args:
+ output_path: Path in which any output can be saved.
+
+ Returns:
+ Path to the generated audio track file or None if no echo is present.
+ """
+ raise NotImplementedError()
+
+ @classmethod
+ def RegisterClass(cls, class_to_register):
+ """Registers an EchoPathSimulator implementation.
+
+ Decorator to automatically register the classes that extend
+ EchoPathSimulator.
+ Example usage:
+
+ @EchoPathSimulator.RegisterClass
+ class NoEchoPathSimulator(EchoPathSimulator):
+ pass
+ """
+ cls.REGISTERED_CLASSES[class_to_register.NAME] = class_to_register
+ return class_to_register
+
+
+@EchoPathSimulator.RegisterClass
+class NoEchoPathSimulator(EchoPathSimulator):
+ """Simulates absence of echo."""
+
+ NAME = 'noecho'
+
+ def __init__(self):
+ EchoPathSimulator.__init__(self)
+
+ def Simulate(self, output_path):
+ return None
+
+
+@EchoPathSimulator.RegisterClass
+class LinearEchoPathSimulator(EchoPathSimulator):
+ """Simulates linear echo path.
+
+ This class applies a given impulse response to the render input and then it
+ sums the signal to the capture input signal.
+ """
+
+ NAME = 'linear'
+
+ def __init__(self, render_input_filepath, impulse_response):
+ """
+ Args:
+ render_input_filepath: Render audio track file.
+ impulse_response: list or numpy vector of float values.
+ """
+ EchoPathSimulator.__init__(self)
+ self._render_input_filepath = render_input_filepath
+ self._impulse_response = impulse_response
+
+ def Simulate(self, output_path):
+ """Simulates linear echo path."""
+ # Form the file name with a hash of the impulse response.
+ impulse_response_hash = hashlib.sha256(
+ str(self._impulse_response).encode('utf-8', 'ignore')).hexdigest()
+ echo_filepath = os.path.join(
+ output_path, 'linear_echo_{}.wav'.format(impulse_response_hash))
+
+ # If the simulated echo audio track file does not exists, create it.
+ if not os.path.exists(echo_filepath):
+ render = signal_processing.SignalProcessingUtils.LoadWav(
+ self._render_input_filepath)
+ echo = signal_processing.SignalProcessingUtils.ApplyImpulseResponse(
+ render, self._impulse_response)
+ signal_processing.SignalProcessingUtils.SaveWav(
+ echo_filepath, echo)
+
+ return echo_filepath
+
+
+@EchoPathSimulator.RegisterClass
+class RecordedEchoPathSimulator(EchoPathSimulator):
+ """Uses recorded echo.
+
+ This class uses the clean capture input file name to build the file name of
+ the corresponding recording containing echo (a predefined suffix is used).
+ Such a file is expected to be already existing.
+ """
+
+ NAME = 'recorded'
+
+ _FILE_NAME_SUFFIX = '_echo'
+
+ def __init__(self, render_input_filepath):
+ EchoPathSimulator.__init__(self)
+ self._render_input_filepath = render_input_filepath
+
+ def Simulate(self, output_path):
+ """Uses recorded echo path."""
+ path, file_name_ext = os.path.split(self._render_input_filepath)
+ file_name, file_ext = os.path.splitext(file_name_ext)
+ echo_filepath = os.path.join(
+ path, '{}{}{}'.format(file_name, self._FILE_NAME_SUFFIX, file_ext))
+ assert os.path.exists(echo_filepath), (
+ 'cannot find the echo audio track file {}'.format(echo_filepath))
+ return echo_filepath