Repository: speechbrain/speechbrain

Issue:
Data augmentation at 8kHz
I intend to train a speaker recognition model with 8kHz data, but it looks like the data augmentation implementation is somewhat restricted to work with the original RIRS noise sampling rate, which is 16kHz. More specifically, the EnvCorrupt class does not allow specifying the sampling rate.
I considered using the "rir_scale_factor" param to resample the reverb impulse response, but I suppose the resulting response might be affected by aliasing. With regard to noise addition, I didn't find a way to work with a different sampling rate.
At last, I observed that the TimeDomainSpecAugment class does not expose some parameters such as drop_freq_low, drop_freq_high, drop_width, which need to be set in accordance with the target sampling rate. 
Please let me know if I am missing something.


Discussion:
Good point. I think we should try to integrate here our resampler to resample the noise to the target sampling rate. What do you think @pplantinga?
That's a valid point. We should address it in the new version (@pplantinga @aheba)
have there been any developments regarding this issue?

Resolving patch:
diff --git a/speechbrain/lobes/augment.py b/speechbrain/lobes/augment.py
--- a/speechbrain/lobes/augment.py
+++ b/speechbrain/lobes/augment.py
@@ -338,6 +338,12 @@ class EnvCorrupt(torch.nn.Module):
         If ``0 < rir_scale_factor < 1``, the impulse response is compressed
         (less reverb), while if ``rir_scale_factor > 1`` it is dilated
         (more reverb).
+    reverb_sample_rate : int
+        Sample rate of input audio signals (rirs) used for reverberation.
+    noise_sample_rate: int
+        Sample rate of input audio signals used for adding noise.
+    clean_sample_rate: int
+        Sample rate of original (clean) audio signals.
 
     Example
     -------
@@ -362,11 +368,15 @@ def __init__(
         noise_snr_low=0,
         noise_snr_high=0,
         rir_scale_factor=1.0,
+        reverb_sample_rate=16000,
+        noise_sample_rate=16000,
+        clean_sample_rate=16000,
     ):
         super().__init__()
 
         # Download and prepare openrir
         if openrir_folder and (not reverb_csv or not noise_csv):
+
             open_reverb_csv = os.path.join(openrir_folder, "reverb.csv")
             open_noise_csv = os.path.join(openrir_folder, "noise.csv")
             _prepare_openrir(
@@ -376,16 +386,22 @@ def __init__(
                 openrir_max_noise_len,
             )
 
-            # Override if they aren't specified
-            reverb_csv = reverb_csv or open_reverb_csv
-            noise_csv = noise_csv or open_noise_csv
+            # Specify filepath and sample rate if not specified already
+            if not reverb_csv:
+                reverb_csv = open_reverb_csv
+                reverb_sample_rate = 16000
+
+            if not noise_csv:
+                noise_csv = open_noise_csv
+                noise_sample_rate = 16000
 
         # Initialize corrupters
         if reverb_csv is not None and reverb_prob > 0.0:
             self.add_reverb = AddReverb(
                 reverb_prob=reverb_prob,
                 csv_file=reverb_csv,
-                rir_scale_factor=rir_scale_factor,
+                reverb_sample_rate=reverb_sample_rate,
+                clean_sample_rate=clean_sample_rate,
             )
 
         if babble_speaker_count > 0 and babble_prob > 0.0:
@@ -403,6 +419,8 @@ def __init__(
                 num_workers=noise_num_workers,
                 snr_low=noise_snr_low,
                 snr_high=noise_snr_high,
+                noise_sample_rate=noise_sample_rate,
+                clean_sample_rate=clean_sample_rate,
             )
 
     def forward(self, waveforms, lengths):
diff --git a/speechbrain/processing/speech_augmentation.py b/speechbrain/processing/speech_augmentation.py
--- a/speechbrain/processing/speech_augmentation.py
+++ b/speechbrain/processing/speech_augmentation.py
@@ -64,6 +64,12 @@ class AddNoise(torch.nn.Module):
         A set of string replacements to carry out in the
         csv file. Each time a key is found in the text, it will be replaced
         with the corresponding value.
+    noise_sample_rate : int
+        The sample rate of the noise audio signals, so noise can be resampled
+        to the clean sample rate if necessary.
+    clean_sample_rate : int
+        The sample rate of the clean audio signals, so noise can be resampled
+        to the clean sample rate if necessary.
 
     Example
     -------
@@ -88,6 +94,8 @@ def __init__(
         start_index=None,
         normalize=False,
         replacements={},
+        noise_sample_rate=16000,
+        clean_sample_rate=16000,
     ):
         super().__init__()
 
@@ -103,6 +111,9 @@ def __init__(
         self.normalize = normalize
         self.replacements = replacements
 
+        if noise_sample_rate != clean_sample_rate:
+            self.resampler = Resample(noise_sample_rate, clean_sample_rate)
+
     def forward(self, waveforms, lengths):
         """
         Arguments
@@ -194,6 +205,10 @@ def _load_noise(self, lengths, max_length):
         noise_batch = noise_batch.to(lengths.device)
         noise_len = noise_len.to(lengths.device)
 
+        # Resample noise if necessary
+        if hasattr(self, "resampler"):
+            noise_batch = self.resampler(noise_batch)
+
         # Convert relative length to an index
         noise_len = (noise_len * noise_batch.shape[1]).long()
 
@@ -299,6 +314,12 @@ class AddReverb(torch.nn.Module):
         A set of string replacements to carry out in the
         csv file. Each time a key is found in the text, it will be replaced
         with the corresponding value.
+    reverb_sample_rate : int
+        The sample rate of the corruption signals (rirs), so that they
+        can be resampled to clean sample rate if necessary.
+    clean_sample_rate : int
+        The sample rate of the clean signals, so that the corruption
+        signals can be resampled to the clean sample rate before convolution.
 
     Example
     -------
@@ -317,6 +338,8 @@ def __init__(
         reverb_prob=1.0,
         rir_scale_factor=1.0,
         replacements={},
+        reverb_sample_rate=16000,
+        clean_sample_rate=16000,
     ):
         super().__init__()
         self.csv_file = csv_file
@@ -336,6 +359,9 @@ def __init__(
         )
         self.rir_data = iter(self.data_loader)
 
+        if reverb_sample_rate != clean_sample_rate:
+            self.resampler = Resample(reverb_sample_rate, clean_sample_rate)
+
     def forward(self, waveforms, lengths):
         """
         Arguments
@@ -366,6 +392,10 @@ def forward(self, waveforms, lengths):
         # Load and prepare RIR
         rir_waveform = self._load_rir(waveforms)
 
+        # Resample to correct rate
+        if hasattr(self, "resampler"):
+            rir_waveform = self.resampler(rir_waveform)
+
         # Compress or dilate RIR
         if self.rir_scale_factor != 1:
             rir_waveform = F.interpolate(


Test patch: