Noise generator abstract class and identity noise generator implemented.

BUG=webrtc:7218
NOTRY=True

Review-Url: https://codereview.webrtc.org/2717243003
Cr-Commit-Position: refs/heads/master@{#17048}
This commit is contained in:
alessiob 2017-03-05 22:55:59 -08:00 committed by Commit bot
parent 21debb3ae8
commit 4610ec7ddd

View File

@ -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