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:
parent
21debb3ae8
commit
4610ec7ddd
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user