Repository: pytorch/audio

Issue:
[Do not merge until test fixed] Revert "deactivate failing test (#372)"
This reverts commit 55f61d1524d2b51bdcb3be51404abc91609c9665.


Discussion:

Resolving patch:
diff --git a/torchaudio/functional.py b/torchaudio/functional.py
--- a/torchaudio/functional.py
+++ b/torchaudio/functional.py
@@ -225,7 +225,7 @@ def istft(
 def spectrogram(
     waveform, pad, window, n_fft, hop_length, win_length, power, normalized
 ):
-    # type: (Tensor, int, Tensor, int, int, int, Optional[int], bool) -> Tensor
+    # type: (Tensor, int, Tensor, int, int, int, Optional[float], bool) -> Tensor
     r"""Create a spectrogram or a batch of spectrograms from a raw audio signal.
     The spectrogram can be either magnitude-only or complex.
 
@@ -236,7 +236,7 @@ def spectrogram(
         n_fft (int): Size of FFT
         hop_length (int): Length of hop between STFT windows
         win_length (int): Window size
-        power (int): Exponent for the magnitude spectrogram,
+        power (float): Exponent for the magnitude spectrogram,
             (must be > 0) e.g., 1 for energy, 2 for power, etc.
             If None, then the complex spectrum is returned instead.
         normalized (bool): Whether to normalize by magnitude after stft
@@ -264,9 +264,9 @@ def spectrogram(
     spec_f = spec_f.reshape(shape[:-1] + spec_f.shape[-3:])
 
     if normalized:
-        spec_f /= window.pow(2).sum().sqrt()
+        spec_f /= window.pow(2.).sum().sqrt()
     if power is not None:
-        spec_f = spec_f.pow(power).sum(-1)  # get power of "complex" tensor
+        spec_f = complex_norm(spec_f, power=power)
 
     return spec_f
 
@@ -274,7 +274,7 @@ def spectrogram(
 def griffinlim(
     spectrogram, window, n_fft, hop_length, win_length, power, normalized, n_iter, momentum, length, rand_init
 ):
-    # type: (Tensor, Tensor, int, int, int, int, bool, int, float, Optional[int], bool) -> Tensor
+    # type: (Tensor, Tensor, int, int, int, float, bool, int, float, Optional[int], bool) -> Tensor
     r"""Compute waveform from a linear scale magnitude spectrogram using the Griffin-Lim transformation.
         Implementation ported from `librosa`.
 
@@ -299,7 +299,7 @@ def griffinlim(
         hop_length (int): Length of hop between STFT windows. (
             Default: ``win_length // 2``)
         win_length (int): Window size. (Default: ``n_fft``)
-        power (int): Exponent for the magnitude spectrogram,
+        power (float): Exponent for the magnitude spectrogram,
             (must be > 0) e.g., 1 for energy, 2 for power, etc. (Default: ``2``)
         normalized (bool): Whether to normalize by magnitude after stft. (Default: ``False``)
         n_iter (int): Number of iteration for phase recovery process.
diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py
--- a/torchaudio/transforms.py
+++ b/torchaudio/transforms.py
@@ -37,7 +37,7 @@ class Spectrogram(torch.nn.Module):
         pad (int): Two sided padding of signal. (Default: ``0``)
         window_fn (Callable[[...], torch.Tensor]): A function to create a window tensor
             that is applied/multiplied to each frame/window. (Default: ``torch.hann_window``)
-        power (int): Exponent for the magnitude spectrogram,
+        power (float): Exponent for the magnitude spectrogram,
             (must be > 0) e.g., 1 for energy, 2 for power, etc. (Default: ``2``)
         normalized (bool): Whether to normalize by magnitude after stft. (Default: ``False``)
         wkwargs (Dict[..., ...]): Arguments for window function. (Default: ``None``)
@@ -46,7 +46,7 @@ class Spectrogram(torch.nn.Module):
 
     def __init__(self, n_fft=400, win_length=None, hop_length=None,
                  pad=0, window_fn=torch.hann_window,
-                 power=2, normalized=False, wkwargs=None):
+                 power=2., normalized=False, wkwargs=None):
         super(Spectrogram, self).__init__()
         self.n_fft = n_fft
         # number of FFT bins. the returned STFT result will have n_fft // 2 + 1
@@ -98,7 +98,7 @@ class GriffinLim(torch.nn.Module):
             Default: ``win_length // 2``)
         window_fn (Callable[[...], torch.Tensor]): A function to create a window tensor
             that is applied/multiplied to each frame/window. (Default: ``torch.hann_window``)
-        power (int): Exponent for the magnitude spectrogram,
+        power (float): Exponent for the magnitude spectrogram,
             (must be > 0) e.g., 1 for energy, 2 for power, etc. (Default: ``2``)
         normalized (bool): Whether to normalize by magnitude after stft. (Default: ``False``)
         wkwargs (Dict[..., ...]): Arguments for window function. (Default: ``None``)
@@ -112,7 +112,7 @@ class GriffinLim(torch.nn.Module):
                      'length', 'momentum', 'rand_init']
 
     def __init__(self, n_fft=400, n_iter=32, win_length=None, hop_length=None,
-                 window_fn=torch.hann_window, power=2, normalized=False, wkwargs=None,
+                 window_fn=torch.hann_window, power=2., normalized=False, wkwargs=None,
                  momentum=0.99, length=None, rand_init=True):
         super(GriffinLim, self).__init__()
 
@@ -266,7 +266,7 @@ def __init__(self, sample_rate=16000, n_fft=400, win_length=None, hop_length=Non
         self.f_min = f_min
         self.spectrogram = Spectrogram(n_fft=self.n_fft, win_length=self.win_length,
                                        hop_length=self.hop_length,
-                                       pad=self.pad, window_fn=window_fn, power=2,
+                                       pad=self.pad, window_fn=window_fn, power=2.,
                                        normalized=False, wkwargs=wkwargs)
         self.mel_scale = MelScale(self.n_mels, self.sample_rate, self.f_min, self.f_max, self.n_fft // 2 + 1)
 


Test patch:
diff --git a/test/test_transforms.py b/test/test_transforms.py
--- a/test/test_transforms.py
+++ b/test/test_transforms.py
@@ -16,7 +16,6 @@
 if IMPORT_SCIPY:
     import scipy
 
-SKIP_LIBROSA_CONSISTENCY_TEST = True
 RUN_CUDA = torch.cuda.is_available()
 print("Run test with cuda:", RUN_CUDA)
 
@@ -210,10 +209,7 @@ def test_mfcc(self):
 
         self.assertTrue(torch_mfcc_norm_none.allclose(norm_check))
 
-    @unittest.skipIf(
-        SKIP_LIBROSA_CONSISTENCY_TEST or not IMPORT_LIBROSA or not IMPORT_SCIPY,
-        'Librosa and scipy are not available, or consisency test disabled'
-    )
+    @unittest.skipIf(not IMPORT_LIBROSA or not IMPORT_SCIPY, 'Librosa and scipy are not available')
     def test_librosa_consistency(self):
         def _test_librosa_consistency_helper(n_fft, hop_length, power, n_mels, n_mfcc, sample_rate):
             input_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav')
@@ -221,11 +217,11 @@ def _test_librosa_consistency_helper(n_fft, hop_length, power, n_mels, n_mfcc, s
             sound_librosa = sound.cpu().numpy().squeeze()  # (64000)
 
             # test core spectrogram
-            spect_transform = torchaudio.transforms.Spectrogram(n_fft=n_fft, hop_length=hop_length, power=2)
+            spect_transform = torchaudio.transforms.Spectrogram(n_fft=n_fft, hop_length=hop_length, power=power)
             out_librosa, _ = librosa.core.spectrum._spectrogram(y=sound_librosa,
                                                                 n_fft=n_fft,
                                                                 hop_length=hop_length,
-                                                                power=2)
+                                                                power=power)
 
             out_torch = spect_transform(sound).squeeze().cpu()
             self.assertTrue(torch.allclose(out_torch, torch.from_numpy(out_librosa), atol=1e-5))
@@ -308,9 +304,20 @@ def _test_librosa_consistency_helper(n_fft, hop_length, power, n_mels, n_mfcc, s
             'sample_rate': 24000
         }
 
+        kwargs4 = {
+            'n_fft': 400,
+            'hop_length': 200,
+            'power': 3.0,
+            'n_mels': 128,
+            'n_mfcc': 40,
+            'sample_rate': 16000
+        }
+
         _test_librosa_consistency_helper(**kwargs1)
         _test_librosa_consistency_helper(**kwargs2)
-        _test_librosa_consistency_helper(**kwargs3)
+        # NOTE Test passes offline, but fails on CircleCI, see #372.
+        # _test_librosa_consistency_helper(**kwargs3)
+        _test_librosa_consistency_helper(**kwargs4)
 
     def test_scriptmodule_Resample(self):
         tensor = torch.rand((2, 1000))