Index: webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/noise_generation.py |
diff --git a/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/noise_generation.py b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/noise_generation.py |
index 5c8126bb2819a860cb8cc6e2736ea286dda5be74..8faa4e265242947176baef42b6be0303a2f5bee0 100644 |
--- a/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/noise_generation.py |
+++ b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/noise_generation.py |
@@ -6,21 +6,119 @@ |
# in the file PATENTS. All contributing project authors may |
# be found in the AUTHORS file in the root of the source tree. |
+import os |
+ |
+from . import data_access |
+ |
class NoiseGenerator(object): |
+ """Abstract class responsible for the generation of noisy signals. |
+ |
+ Given a clean signal, it generates two streams named noisy signal and |
+ reference. The former is the clean signal deteriorated by the noise source, |
+ the latter goes trhough the same deterioration process, but more "gently". |
+ Noisy signal and reference are produced so that the reference is the signal |
+ expected at the output of the APM module when the latter is fed with the nosiy |
+ signal. |
+ |
+ This is useful since it is not realistic to expect that APM will remove all |
+ the background noise or all the echo. Hence, the process that generates the |
+ reference signal is responsible for setting realistic expectations. |
+ |
+ Finally, note that a noise source can generate multiple input-reference pairs. |
+ """ |
NAME = None |
REGISTERED_CLASSES = {} |
def __init__(self): |
- pass |
+ # Input |
+ self._noisy_signal_filepaths = None |
+ self._output_paths = None |
+ self._reference_signal_filepaths = None |
+ self.clear() |
@classmethod |
def register_class(cls, class_to_register): |
- """ |
- Decorator to automatically register the classes that extend NoiseGenerator. |
+ """ Decorator to automatically register the classes that extend |
+ NoiseGenerator. |
""" |
cls.REGISTERED_CLASSES[class_to_register.NAME] = class_to_register |
+ @property |
+ def config_names(self): |
+ return self._noisy_signal_filepaths.keys() |
+ |
+ @property |
+ def noisy_signal_filepaths(self): |
+ return self._noisy_signal_filepaths |
+ |
+ @property |
+ def output_paths(self): |
+ return self._output_paths |
+ |
+ @property |
+ def reference_signal_filepaths(self): |
+ return self._reference_signal_filepaths |
+ |
+ def generate( |
+ self, input_signal_filepath, input_noise_cache_path, base_output_path): |
+ self.clear() |
+ return self._generate( |
+ input_signal_filepath, input_noise_cache_path, base_output_path) |
+ |
+ def clear(self): |
+ self._noisy_signal_filepaths = {} |
+ self._output_paths = {} |
+ self._reference_signal_filepaths = {} |
+ |
+ def _generate( |
+ self, input_signal_filepath, input_noise_cache_path, base_output_path): |
+ raise NotImplementedError() |
+ |
+ def _add_noise_snr_pairs(self, base_output_path, noisy_mix_filepaths, |
+ snr_value_pairs): |
+ """ Add noisy-reference signal pairs. |
+ |
+ Args: |
+ base_output_path: noisy tracks base output path. |
+ noisy_mix_filepaths: nested dictionary of noisy signal paths organized |
+ by noisy track name and SNR level. |
+ snr_value_pairs: list of SNR pairs. |
+ """ |
+ for noise_track_name in noisy_mix_filepaths: |
+ for snr_noisy, snr_refence in snr_value_pairs: |
+ config_name = '{0}_{1:d}_{2:d}_SNR'.format( |
+ noise_track_name, snr_noisy, snr_refence) |
+ output_path = self._make_dir(base_output_path, config_name) |
+ self._add_noise_reference_files_pair( |
+ config_name=config_name, |
+ noisy_signal_filepath=noisy_mix_filepaths[ |
+ noise_track_name][snr_noisy], |
+ reference_signal_filepath=noisy_mix_filepaths[ |
+ noise_track_name][snr_refence], |
+ output_path=output_path) |
+ |
+ def _add_noise_reference_files_pair(self, config_name, noisy_signal_filepath, |
+ reference_signal_filepath, output_path): |
+ assert config_name not in self._noisy_signal_filepaths |
+ self._noisy_signal_filepaths[config_name] = os.path.abspath( |
+ noisy_signal_filepath) |
+ self._output_paths[config_name] = os.path.abspath(output_path) |
+ self._reference_signal_filepaths[config_name] = os.path.abspath( |
+ reference_signal_filepath) |
+ |
+ # Save noisy and reference file paths. |
+ data_access.Metadata.save_audio_in_ref_paths( |
+ output_path=output_path, |
+ audio_in_filepath=self._noisy_signal_filepaths[config_name], |
+ audio_ref_filepath=self._reference_signal_filepaths[config_name]) |
+ |
+ @classmethod |
+ def _make_dir(cls, base_output_path, noise_generator_config_name): |
+ output_path = os.path.join(base_output_path, noise_generator_config_name) |
+ data_access.make_directory(output_path) |
+ return output_path |
+ |
# Identity generator. |
@NoiseGenerator.register_class |
@@ -35,8 +133,19 @@ class IdentityGenerator(NoiseGenerator): |
def __init__(self): |
NoiseGenerator.__init__(self) |
+ def _generate( |
+ self, input_signal_filepath, input_noise_cache_path, base_output_path): |
+ CONFIG_NAME = 'default' |
+ output_path = self._make_dir(base_output_path, CONFIG_NAME) |
+ self._add_noise_reference_files_pair( |
+ config_name=CONFIG_NAME, |
+ noisy_signal_filepath=input_signal_filepath, |
+ reference_signal_filepath=input_signal_filepath, |
+ output_path=output_path) |
-@NoiseGenerator.register_class |
+ |
+# TODO(alessiob): remove comment when class implemented. |
+# @NoiseGenerator.register_class |
class WhiteNoiseGenerator(NoiseGenerator): |
""" |
Additive white noise generator. |
@@ -47,8 +156,14 @@ class WhiteNoiseGenerator(NoiseGenerator): |
def __init__(self): |
NoiseGenerator.__init__(self) |
+ def _generate( |
+ self, input_signal_filepath, input_noise_cache_path, base_output_path): |
+ # TODO(alessiob): implement. |
+ pass |
-@NoiseGenerator.register_class |
+ |
+# TODO(alessiob): remove comment when class implemented. |
+# @NoiseGenerator.register_class |
class NarrowBandNoiseGenerator(NoiseGenerator): |
""" |
Additive narrow-band noise generator. |
@@ -59,8 +174,14 @@ class NarrowBandNoiseGenerator(NoiseGenerator): |
def __init__(self): |
NoiseGenerator.__init__(self) |
+ def _generate( |
+ self, input_signal_filepath, input_noise_cache_path, base_output_path): |
+ # TODO(alessiob): implement. |
+ pass |
-@NoiseGenerator.register_class |
+ |
+# TODO(alessiob): remove comment when class implemented. |
+# @NoiseGenerator.register_class |
class EnvironmentalNoiseGenerator(NoiseGenerator): |
""" |
Additive environmental noise generator. |
@@ -71,8 +192,14 @@ class EnvironmentalNoiseGenerator(NoiseGenerator): |
def __init__(self): |
NoiseGenerator.__init__(self) |
+ def _generate( |
+ self, input_signal_filepath, input_noise_cache_path, base_output_path): |
+ # TODO(alessiob): implement. |
+ pass |
-@NoiseGenerator.register_class |
+ |
+# TODO(alessiob): remove comment when class implemented. |
+# @NoiseGenerator.register_class |
class EchoNoiseGenerator(NoiseGenerator): |
""" |
Echo noise generator. |
@@ -82,3 +209,8 @@ class EchoNoiseGenerator(NoiseGenerator): |
def __init__(self): |
NoiseGenerator.__init__(self) |
+ |
+ def _generate( |
+ self, input_signal_filepath, input_noise_cache_path, base_output_path): |
+ # TODO(alessiob): implement. |
+ pass |