From 36def9c023e8666fe9df46005494667f40cdab1b Mon Sep 17 00:00:00 2001 From: jcaw Date: Sun, 20 Dec 2020 17:09:33 +0000 Subject: [PATCH 01/35] Make `amplitude_to_DB` clamp items separately When passed a batch, `amplitude_to_DB` was clamping based on the entire batch's maximum value. This was wrong. Apply the clamp based on each item's maximum when a batch is detected. This change requires `amplitude_to_DB` to be restricted to spectrogram inputs only, since items need to have a predictable number of dimensions (in this case, 3) to automatically detect batches. Additional tests are also added to check both batched and unbatched inputs, and ensure items are being clamped correctly. --- .../functional/functional_cpu_test.py | 119 +++++++++++++----- torchaudio/functional/functional.py | 15 ++- 2 files changed, 100 insertions(+), 34 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 4fbe4d871e..aa0560a797 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -70,47 +70,104 @@ def test_pitch(self, frequency): self.assertFalse(s) -class TestDB_to_amplitude(common_utils.TorchaudioTestCase): - def test_DB_to_amplitude(self): - # Make some noise - x = torch.rand(1000) +class Testamplitude_to_DB(common_utils.TorchaudioTestCase): + AMPLITUDE_MULT = 20. + POWER_MULT = 10. + AMIN = 1e-10 + REF = 1.0 + # FIXME: So the DB multiplier is 0? + DB_MULT = math.log10(max(AMIN, REF)) + + def _make_spectrogram(self, items, channels, wave_samples, scale=1.): + # Make some noise, -1 to 1 (then scale it) + wave = (torch.rand(items, channels, wave_samples) * 2. - 1.) * scale spectrogram = torchaudio.transforms.Spectrogram() - spec = spectrogram(x) - - amin = 1e-10 - ref = 1.0 - db_multiplier = math.log10(max(amin, ref)) - - # Waveform amplitude -> DB -> amplitude - multiplier = 20. - power = 0.5 - - db = F.amplitude_to_DB(torch.abs(x), multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) - - torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) + return spectrogram(wave) + def _ensure_reversible(self, spec): + """Check `amplitude_to_db` returns the original when reversed.""" # Spectrogram amplitude -> DB -> amplitude - db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) + db = F.amplitude_to_DB(spec, self.AMPLITUDE_MULT, self.AMIN, self.DB_MULT, top_db=None) + x2 = F.DB_to_amplitude(db, self.REF, 0.5) torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) - # Waveform power -> DB -> power - multiplier = 10. - power = 1. - - db = F.amplitude_to_DB(x, multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) - - torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) - # Spectrogram power -> DB -> power - db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) + db = F.amplitude_to_DB(spec, self.POWER_MULT, self.AMIN, self.DB_MULT, top_db=None) + x2 = F.DB_to_amplitude(db, self.REF, 1.) torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) + def test_amplitude_to_DB(self): + spec = self._make_spectrogram(2, 2, 1000, scale=0.5) + # Ensure it works on both batches and items + self._ensure_reversible(spec) + self._ensure_reversible(spec[0]) + + def test_top_db(self): + top_db = 40. + + spec = self._make_spectrogram(1, 2, 1000, scale=0.5) + # Make the max value (and thus DB cutoff) predictable. + spec[0,0,0] = 200 + + decibels = F.amplitude_to_DB(spec[0], self.AMPLITUDE_MULT, self.AMIN, + self.DB_MULT, top_db=top_db) + # The actual db floor will be just below 6.0206 - use 6.0205 to deal + # with rounding error. + above_top = decibels >= 6.0205 + assert above_top.all(), decibels + + # And check it works with batch dimension + decibels_batch = F.amplitude_to_DB(spec, self.AMPLITUDE_MULT, self.AMIN, + self.DB_MULT, top_db=top_db) + above_top_batch = decibels_batch >= 6.0205 + assert above_top_batch.all(), decibels_batch + + def test_batched(self): + top_db = 40. + + # Make a batch of noise + spec = self._make_spectrogram(2, 2, 1000) + # Make the second item blow out the first + spec[0] *= 0.5 + # Predictability + spec[1, 0, 0, 0] = 200 + + # Ensure the clamp applies per-item, not at the batch level. + batchwise_dbs = F.amplitude_to_DB(spec, self.AMPLITUDE_MULT, self.AMIN, + self.DB_MULT, top_db=top_db) + itemwise_dbs = torch.stack([ + F.amplitude_to_DB(item, self.AMPLITUDE_MULT, self.AMIN, + self.DB_MULT, top_db=top_db) + for item in spec + ]) + + torch.testing.assert_allclose(batchwise_dbs, itemwise_dbs, atol=5e-5, rtol=1e-5) + + def test_per_spectrogram(self): + channels = 2 + top_db = 40. + + spec = self._make_spectrogram(1, channels, 1000) + # Make the second channel blow out the first + spec[:, 0] *= 0.5 + # Predictability + spec[0, 1, 0, 0] = 200 + + # Ensure the clamp applies per-item, not per-channel. + specwise_dbs = F.amplitude_to_DB(spec, self.AMPLITUDE_MULT, self.AMIN, + self.DB_MULT, top_db=top_db) + channelwise_dbs = torch.stack([ + F.amplitude_to_DB(spec[:, i], self.AMPLITUDE_MULT, self.AMIN, + self.DB_MULT, top_db=top_db) + for i in range(channels) + ]) + + # Just check channelwise gives a different answer. + difference = (specwise_dbs - channelwise_dbs).abs() + assert (difference >= 1e-5).any() + @pytest.mark.parametrize('complex_tensor', [ torch.randn(1, 2, 1025, 400, 2), diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 3fedf93d09..90a28399db 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -227,14 +227,17 @@ def amplitude_to_DB( db_multiplier: float, top_db: Optional[float] = None ) -> Tensor: - r"""Turn a tensor from the power/amplitude scale to the decibel scale. + r"""Turn a spectrogram from the power/amplitude scale to the decibel scale. This output depends on the maximum value in the input tensor, and so may return different values for an audio clip split into snippets vs. a full clip. Args: - x (Tensor): Input tensor before being converted to decibel scale + + x (Tensor): Input spectrogram(s) before being converted to decibel scale. Input should take + the form `(..., freq, time)`. Batched inputs must include a channel dimension and should + take the form `(item, channel, freq, time)`. multiplier (float): Use 10. for power and 20. for amplitude amin (float): Number to clamp ``x`` db_multiplier (float): Log10(max(reference value and amin)) @@ -248,7 +251,13 @@ def amplitude_to_DB( x_db -= multiplier * db_multiplier if top_db is not None: - x_db = x_db.clamp(min=x_db.max().item() - top_db) + dims = x_db.dim() + if dims > 3: + db_floors = torch.amax(x_db, dim=tuple(range(1, dims))) - top_db + broadcast_shape = (...,) + (None,)*(dims-1) + x_db = torch.max(x_db, db_floors[broadcast_shape]) + else: + x_db = x_db.clamp(min=x_db.max().item() - top_db) return x_db From 10b3301edf2ee59f6dd8af4039ea186137e249d5 Mon Sep 17 00:00:00 2001 From: jcaw Date: Sun, 20 Dec 2020 18:09:03 +0000 Subject: [PATCH 02/35] Don't pack batches in MFCC transform The `MFCC` transform doesn't need to pack batches, since the mel spectrogram conversion operates fine on batched input (it packs batches itself). The fixed form of `amplitude_to_DB` also now requires an unpacked batch to clamp correctly. Since it's unnecessary, remove packing from the MFFC transform completely. --- torchaudio/transforms.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index 3306491b21..64cc226d45 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -494,24 +494,16 @@ def forward(self, waveform: Tensor) -> Tensor: Returns: Tensor: specgram_mel_db of size (..., ``n_mfcc``, time). """ - - # pack batch - shape = waveform.size() - waveform = waveform.reshape(-1, shape[-1]) - mel_specgram = self.MelSpectrogram(waveform) if self.log_mels: log_offset = 1e-6 mel_specgram = torch.log(mel_specgram + log_offset) else: mel_specgram = self.amplitude_to_DB(mel_specgram) - # (channel, n_mels, time).tranpose(...) dot (n_mels, n_mfcc) - # -> (channel, time, n_mfcc).tranpose(...) - mfcc = torch.matmul(mel_specgram.transpose(1, 2), self.dct_mat).transpose(1, 2) - - # unpack batch - mfcc = mfcc.reshape(shape[:-1] + mfcc.shape[-2:]) + # (..., channel, n_mels, time).tranpose(...) dot (n_mels, n_mfcc) + # -> (..., channel, time, n_mfcc).tranpose(...) + mfcc = torch.matmul(mel_specgram.transpose(-2, -1), self.dct_mat).transpose(-2, -1) return mfcc From d3ad3cf7104e3c467b8c3e4a3d990e53fb01607a Mon Sep 17 00:00:00 2001 From: jcaw Date: Mon, 21 Dec 2020 12:35:28 +0000 Subject: [PATCH 03/35] Remove range->tuple conversion for torchscript This should allow `amplitude_to_DB` to compile to torchscript. --- torchaudio/functional/functional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 90a28399db..94c187c7b5 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -253,7 +253,7 @@ def amplitude_to_DB( if top_db is not None: dims = x_db.dim() if dims > 3: - db_floors = torch.amax(x_db, dim=tuple(range(1, dims))) - top_db + db_floors = x_db.reshape(x_db.size(0), -1).amax(dim=1) - top_db broadcast_shape = (...,) + (None,)*(dims-1) x_db = torch.max(x_db, db_floors[broadcast_shape]) else: From 6e43af7c73bb6ef83616095fa43aa3e0bd9ec78d Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 20:05:24 +0000 Subject: [PATCH 04/35] Split basic amplitude_to_DB test Test the batch & channel dimensions separately --- test/torchaudio_unittest/functional/functional_cpu_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index aa0560a797..59b7152265 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -98,10 +98,12 @@ def _ensure_reversible(self, spec): torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) - def test_amplitude_to_DB(self): + def test_amplitude_to_DB_batch(self): spec = self._make_spectrogram(2, 2, 1000, scale=0.5) - # Ensure it works on both batches and items self._ensure_reversible(spec) + + def test_amplitude_to_DB_channels(self): + spec = self._make_spectrogram(1, 2, 1000, scale=0.5) self._ensure_reversible(spec[0]) def test_top_db(self): From f668caff17b7b70a5645ffb06e13345b79bd00b9 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 20:31:00 +0000 Subject: [PATCH 05/35] Test `amplitude_to_DB` without channel dim --- .../functional/functional_cpu_test.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 59b7152265..dcb9c5770a 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -106,6 +106,10 @@ def test_amplitude_to_DB_channels(self): spec = self._make_spectrogram(1, 2, 1000, scale=0.5) self._ensure_reversible(spec[0]) + def test_amplitude_to_DB_item(self): + spec = self._make_spectrogram(1, 2, 1000, scale=0.5) + self._ensure_reversible(spec[0][0]) + def test_top_db(self): top_db = 40. @@ -126,6 +130,12 @@ def test_top_db(self): above_top_batch = decibels_batch >= 6.0205 assert above_top_batch.all(), decibels_batch + # And check it works with shape (freq, time) only + decibels_batch = F.amplitude_to_DB(spec[0][0], self.AMPLITUDE_MULT, self.AMIN, + self.DB_MULT, top_db=top_db) + above_top_batch = decibels_batch >= 6.0205 + assert above_top_batch.all(), decibels_batch + def test_batched(self): top_db = 40. From eba14b009a726d788d350beb5d5571ad7ead2e37 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 20:34:29 +0000 Subject: [PATCH 06/35] Always clamp amplitude as a batch --- torchaudio/functional/functional.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 94c187c7b5..52967106f6 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -237,7 +237,7 @@ def amplitude_to_DB( x (Tensor): Input spectrogram(s) before being converted to decibel scale. Input should take the form `(..., freq, time)`. Batched inputs must include a channel dimension and should - take the form `(item, channel, freq, time)`. + take the form `(batch, channel, freq, time)`. multiplier (float): Use 10. for power and 20. for amplitude amin (float): Number to clamp ``x`` db_multiplier (float): Log10(max(reference value and amin)) @@ -251,13 +251,15 @@ def amplitude_to_DB( x_db -= multiplier * db_multiplier if top_db is not None: - dims = x_db.dim() - if dims > 3: - db_floors = x_db.reshape(x_db.size(0), -1).amax(dim=1) - top_db - broadcast_shape = (...,) + (None,)*(dims-1) - x_db = torch.max(x_db, db_floors[broadcast_shape]) - else: - x_db = x_db.clamp(min=x_db.max().item() - top_db) + # Expand batch + shape = x_db.size() + packed_channels = shape[-3] if x_db.dim() > 2 else 1 + x_db = x_db.reshape(-1, packed_channels, shape[-2], shape[-1]) + + x_db = torch.max(x_db, (x_db.amax(dim=(-3, -2, -1)) - top_db).view(-1, 1, 1, 1)) + + # Repack batch + x_db = x_db.reshape(shape) return x_db From 18d57bdc3b5f9091990531e08a8b1cff976fe69c Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 21:15:45 +0000 Subject: [PATCH 07/35] Remove `_make_spectrogram` helper method It's not necessary, just generate random tensors. --- .../functional/functional_cpu_test.py | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index dcb9c5770a..d9f244a3cb 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -78,12 +78,6 @@ class Testamplitude_to_DB(common_utils.TorchaudioTestCase): # FIXME: So the DB multiplier is 0? DB_MULT = math.log10(max(AMIN, REF)) - def _make_spectrogram(self, items, channels, wave_samples, scale=1.): - # Make some noise, -1 to 1 (then scale it) - wave = (torch.rand(items, channels, wave_samples) * 2. - 1.) * scale - spectrogram = torchaudio.transforms.Spectrogram() - return spectrogram(wave) - def _ensure_reversible(self, spec): """Check `amplitude_to_db` returns the original when reversed.""" # Spectrogram amplitude -> DB -> amplitude @@ -99,21 +93,21 @@ def _ensure_reversible(self, spec): torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) def test_amplitude_to_DB_batch(self): - spec = self._make_spectrogram(2, 2, 1000, scale=0.5) + spec = torch.rand([2, 2, 100, 100]) * 200 self._ensure_reversible(spec) def test_amplitude_to_DB_channels(self): - spec = self._make_spectrogram(1, 2, 1000, scale=0.5) - self._ensure_reversible(spec[0]) + spec = torch.rand([2, 100, 100]) * 200 + self._ensure_reversible(spec) def test_amplitude_to_DB_item(self): - spec = self._make_spectrogram(1, 2, 1000, scale=0.5) - self._ensure_reversible(spec[0][0]) + spec = torch.rand([100, 100]) * 200 + self._ensure_reversible(spec) def test_top_db(self): top_db = 40. - spec = self._make_spectrogram(1, 2, 1000, scale=0.5) + spec = torch.rand([1, 2, 100, 100]) * 200 # Make the max value (and thus DB cutoff) predictable. spec[0,0,0] = 200 @@ -140,7 +134,7 @@ def test_batched(self): top_db = 40. # Make a batch of noise - spec = self._make_spectrogram(2, 2, 1000) + spec = torch.rand([2, 2, 100, 100]) * 200 # Make the second item blow out the first spec[0] *= 0.5 # Predictability @@ -161,7 +155,7 @@ def test_per_spectrogram(self): channels = 2 top_db = 40. - spec = self._make_spectrogram(1, channels, 1000) + spec = torch.rand([1, channels, 100, 100]) * 200 # Make the second channel blow out the first spec[:, 0] *= 0.5 # Predictability From 381ee07fdd713d8b242ddef56680c27b1348a3f6 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 21:42:45 +0000 Subject: [PATCH 08/35] Redefine test constants inside each test Ensure they're independent. --- .../functional/functional_cpu_test.py | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index d9f244a3cb..62fa4e922c 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -71,24 +71,23 @@ def test_pitch(self, frequency): class Testamplitude_to_DB(common_utils.TorchaudioTestCase): - AMPLITUDE_MULT = 20. - POWER_MULT = 10. - AMIN = 1e-10 - REF = 1.0 - # FIXME: So the DB multiplier is 0? - DB_MULT = math.log10(max(AMIN, REF)) - def _ensure_reversible(self, spec): """Check `amplitude_to_db` returns the original when reversed.""" + AMPLITUDE_MULT = 20. + POWER_MULT = 10. + AMIN = 1e-10 + REF = 1.0 + DB_MULT = math.log10(max(AMIN, REF)) + # Spectrogram amplitude -> DB -> amplitude - db = F.amplitude_to_DB(spec, self.AMPLITUDE_MULT, self.AMIN, self.DB_MULT, top_db=None) - x2 = F.DB_to_amplitude(db, self.REF, 0.5) + db = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, DB_MULT, top_db=None) + x2 = F.DB_to_amplitude(db, REF, 0.5) torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) # Spectrogram power -> DB -> power - db = F.amplitude_to_DB(spec, self.POWER_MULT, self.AMIN, self.DB_MULT, top_db=None) - x2 = F.DB_to_amplitude(db, self.REF, 1.) + db = F.amplitude_to_DB(spec, POWER_MULT, AMIN, DB_MULT, top_db=None) + x2 = F.DB_to_amplitude(db, REF, 1.) torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) @@ -131,6 +130,11 @@ def test_top_db(self): assert above_top_batch.all(), decibels_batch def test_batched(self): + AMPLITUDE_MULT = 20. + POWER_MULT = 10. + AMIN = 1e-10 + REF = 1.0 + DB_MULT = math.log10(max(AMIN, REF)) top_db = 40. # Make a batch of noise @@ -141,17 +145,22 @@ def test_batched(self): spec[1, 0, 0, 0] = 200 # Ensure the clamp applies per-item, not at the batch level. - batchwise_dbs = F.amplitude_to_DB(spec, self.AMPLITUDE_MULT, self.AMIN, - self.DB_MULT, top_db=top_db) + batchwise_dbs = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, + DB_MULT, top_db=top_db) itemwise_dbs = torch.stack([ - F.amplitude_to_DB(item, self.AMPLITUDE_MULT, self.AMIN, - self.DB_MULT, top_db=top_db) + F.amplitude_to_DB(item, AMPLITUDE_MULT, AMIN, + DB_MULT, top_db=top_db) for item in spec ]) torch.testing.assert_allclose(batchwise_dbs, itemwise_dbs, atol=5e-5, rtol=1e-5) def test_per_spectrogram(self): + AMPLITUDE_MULT = 20. + POWER_MULT = 10. + AMIN = 1e-10 + REF = 1.0 + DB_MULT = math.log10(max(AMIN, REF)) channels = 2 top_db = 40. @@ -162,12 +171,12 @@ def test_per_spectrogram(self): spec[0, 1, 0, 0] = 200 # Ensure the clamp applies per-item, not per-channel. - specwise_dbs = F.amplitude_to_DB(spec, self.AMPLITUDE_MULT, self.AMIN, - self.DB_MULT, top_db=top_db) + specwise_dbs = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, + DB_MULT, top_db=top_db) channelwise_dbs = torch.stack([ - F.amplitude_to_DB(spec[:, i], self.AMPLITUDE_MULT, self.AMIN, - self.DB_MULT, top_db=top_db) for i in range(channels) + F.amplitude_to_DB(spec[:, i], AMPLITUDE_MULT, AMIN, + DB_MULT, top_db=top_db) ]) # Just check channelwise gives a different answer. From 156f183b3de7844c8f6116a4128ea306a0f704ee Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 21:45:22 +0000 Subject: [PATCH 09/35] Use leftmost dim for test name --- test/torchaudio_unittest/functional/functional_cpu_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 62fa4e922c..e6eea2d26c 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -99,7 +99,7 @@ def test_amplitude_to_DB_channels(self): spec = torch.rand([2, 100, 100]) * 200 self._ensure_reversible(spec) - def test_amplitude_to_DB_item(self): + def test_amplitude_to_DB_freq(self): spec = torch.rand([100, 100]) * 200 self._ensure_reversible(spec) From 5275442cc4b60843a2aa5a7fb86fbfad5ce56f10 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 21:45:44 +0000 Subject: [PATCH 10/35] Split `test_top_db` into separate tests One for each target shape. (The subtests now pass again) --- .../functional/functional_cpu_test.py | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index e6eea2d26c..82fe9439e3 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -103,31 +103,39 @@ def test_amplitude_to_DB_freq(self): spec = torch.rand([100, 100]) * 200 self._ensure_reversible(spec) - def test_top_db(self): - top_db = 40. - - spec = torch.rand([1, 2, 100, 100]) * 200 - # Make the max value (and thus DB cutoff) predictable. - spec[0,0,0] = 200 + def _check_top_db(self, spec): + AMPLITUDE_MULT = 20. + POWER_MULT = 10. + AMIN = 1e-10 + REF = 1.0 + DB_MULT = math.log10(max(AMIN, REF)) + TOP_DB = 40. - decibels = F.amplitude_to_DB(spec[0], self.AMPLITUDE_MULT, self.AMIN, - self.DB_MULT, top_db=top_db) - # The actual db floor will be just below 6.0206 - use 6.0205 to deal - # with rounding error. + decibels = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, + DB_MULT, top_db=TOP_DB) above_top = decibels >= 6.0205 assert above_top.all(), decibels - # And check it works with batch dimension - decibels_batch = F.amplitude_to_DB(spec, self.AMPLITUDE_MULT, self.AMIN, - self.DB_MULT, top_db=top_db) - above_top_batch = decibels_batch >= 6.0205 - assert above_top_batch.all(), decibels_batch - - # And check it works with shape (freq, time) only - decibels_batch = F.amplitude_to_DB(spec[0][0], self.AMPLITUDE_MULT, self.AMIN, - self.DB_MULT, top_db=top_db) - above_top_batch = decibels_batch >= 6.0205 - assert above_top_batch.all(), decibels_batch + def test_top_db_batch(self): + spec = torch.rand([1, 2, 100, 100]) * 200 + # Predictability + spec[0, 0, 1] = 0 + spec[0, 0, 0] = 200 + self._check_top_db(spec) + + def test_top_db_channel(self): + spec = torch.rand([1, 2, 100, 100]) * 200 + # Predictability + spec[0, 0, 1] = 0 + spec[0, 0, 0] = 200 + self._check_top_db(spec[0]) + + def test_top_db_freq(self): + spec = torch.rand([1, 2, 100, 100]) * 200 + # Predictability + spec[0, 0, 1] = 0 + spec[0, 0, 0] = 200 + self._check_top_db(spec[0][0]) def test_batched(self): AMPLITUDE_MULT = 20. From 670fe977e2631c53ed30366774aa0fea6bbe197d Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 21:47:18 +0000 Subject: [PATCH 11/35] Capitalise test constants --- .../functional/functional_cpu_test.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 82fe9439e3..b8a98b7767 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -143,7 +143,7 @@ def test_batched(self): AMIN = 1e-10 REF = 1.0 DB_MULT = math.log10(max(AMIN, REF)) - top_db = 40. + TOP_DB = 40. # Make a batch of noise spec = torch.rand([2, 2, 100, 100]) * 200 @@ -154,10 +154,10 @@ def test_batched(self): # Ensure the clamp applies per-item, not at the batch level. batchwise_dbs = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=top_db) + DB_MULT, top_db=TOP_DB) itemwise_dbs = torch.stack([ F.amplitude_to_DB(item, AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=top_db) + DB_MULT, top_db=TOP_DB) for item in spec ]) @@ -170,7 +170,7 @@ def test_per_spectrogram(self): REF = 1.0 DB_MULT = math.log10(max(AMIN, REF)) channels = 2 - top_db = 40. + TOP_DB = 40. spec = torch.rand([1, channels, 100, 100]) * 200 # Make the second channel blow out the first @@ -180,11 +180,11 @@ def test_per_spectrogram(self): # Ensure the clamp applies per-item, not per-channel. specwise_dbs = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=top_db) + DB_MULT, top_db=TOP_DB) channelwise_dbs = torch.stack([ for i in range(channels) F.amplitude_to_DB(spec[:, i], AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=top_db) + DB_MULT, top_db=TOP_DB) ]) # Just check channelwise gives a different answer. From fd33b46a2cb353ad10970ce67dcba1c983781251 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 21:47:35 +0000 Subject: [PATCH 12/35] Inline channels variable --- test/torchaudio_unittest/functional/functional_cpu_test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index b8a98b7767..300d71d87c 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -169,10 +169,9 @@ def test_per_spectrogram(self): AMIN = 1e-10 REF = 1.0 DB_MULT = math.log10(max(AMIN, REF)) - channels = 2 TOP_DB = 40. - spec = torch.rand([1, channels, 100, 100]) * 200 + spec = torch.rand([1, 2, 100, 100]) * 200 # Make the second channel blow out the first spec[:, 0] *= 0.5 # Predictability @@ -182,9 +181,9 @@ def test_per_spectrogram(self): specwise_dbs = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, DB_MULT, top_db=TOP_DB) channelwise_dbs = torch.stack([ - for i in range(channels) F.amplitude_to_DB(spec[:, i], AMPLITUDE_MULT, AMIN, DB_MULT, top_db=TOP_DB) + for i in range(spec.size(-3)) ]) # Just check channelwise gives a different answer. From 44c2259f01603e54501fcd1ccca54b2d3ee7d9fc Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 21:47:57 +0000 Subject: [PATCH 13/35] Also specify minimum value for tests Don't rely on torch.rand to produce good values. --- test/torchaudio_unittest/functional/functional_cpu_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 300d71d87c..f54af057f9 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -150,6 +150,7 @@ def test_batched(self): # Make the second item blow out the first spec[0] *= 0.5 # Predictability + spec[0, 0, 0, 0] = 0 spec[1, 0, 0, 0] = 200 # Ensure the clamp applies per-item, not at the batch level. @@ -175,6 +176,7 @@ def test_per_spectrogram(self): # Make the second channel blow out the first spec[:, 0] *= 0.5 # Predictability + spec[0, 0, 0, 0] = 0 spec[0, 1, 0, 0] = 200 # Ensure the clamp applies per-item, not per-channel. From c9c3a93b3e2ff9fd40d73e9afdf432c16ea47d87 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 21:48:42 +0000 Subject: [PATCH 14/35] Reword comment --- test/torchaudio_unittest/functional/functional_cpu_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index f54af057f9..0051178fb9 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -153,7 +153,7 @@ def test_batched(self): spec[0, 0, 0, 0] = 0 spec[1, 0, 0, 0] = 200 - # Ensure the clamp applies per-item, not at the batch level. + # Ensure separate clamps are applied per-item in a batch. batchwise_dbs = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, DB_MULT, top_db=TOP_DB) itemwise_dbs = torch.stack([ From 3bff1fe349770b520d5dbdce4652bcf33d67ec64 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 6 Jan 2021 21:54:56 +0000 Subject: [PATCH 15/35] Replace `assert_allclose` with `self.assertEqual` --- test/torchaudio_unittest/functional/functional_cpu_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 0051178fb9..21853343ac 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -89,7 +89,7 @@ def _ensure_reversible(self, spec): db = F.amplitude_to_DB(spec, POWER_MULT, AMIN, DB_MULT, top_db=None) x2 = F.DB_to_amplitude(db, REF, 1.) - torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) + self.assertEqual(x2, spec) def test_amplitude_to_DB_batch(self): spec = torch.rand([2, 2, 100, 100]) * 200 @@ -162,7 +162,7 @@ def test_batched(self): for item in spec ]) - torch.testing.assert_allclose(batchwise_dbs, itemwise_dbs, atol=5e-5, rtol=1e-5) + self.assertEqual(batchwise_dbs, itemwise_dbs) def test_per_spectrogram(self): AMPLITUDE_MULT = 20. From d5070f951975288336f0e6249c7fa83fbf785781 Mon Sep 17 00:00:00 2001 From: jcaw Date: Thu, 7 Jan 2021 00:34:29 +0000 Subject: [PATCH 16/35] Remove unused power constants --- test/torchaudio_unittest/functional/functional_cpu_test.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 21853343ac..6b00edc0b1 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -105,7 +105,6 @@ def test_amplitude_to_DB_freq(self): def _check_top_db(self, spec): AMPLITUDE_MULT = 20. - POWER_MULT = 10. AMIN = 1e-10 REF = 1.0 DB_MULT = math.log10(max(AMIN, REF)) @@ -139,7 +138,6 @@ def test_top_db_freq(self): def test_batched(self): AMPLITUDE_MULT = 20. - POWER_MULT = 10. AMIN = 1e-10 REF = 1.0 DB_MULT = math.log10(max(AMIN, REF)) @@ -166,7 +164,6 @@ def test_batched(self): def test_per_spectrogram(self): AMPLITUDE_MULT = 20. - POWER_MULT = 10. AMIN = 1e-10 REF = 1.0 DB_MULT = math.log10(max(AMIN, REF)) From f68eb8cad7f5ce8cab9a254f85ffa723fc0929bd Mon Sep 17 00:00:00 2001 From: jcaw Date: Thu, 7 Jan 2021 00:34:52 +0000 Subject: [PATCH 17/35] Fix indentation --- test/torchaudio_unittest/functional/functional_cpu_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 6b00edc0b1..fbc6742c4e 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -111,7 +111,7 @@ def _check_top_db(self, spec): TOP_DB = 40. decibels = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=TOP_DB) + DB_MULT, top_db=TOP_DB) above_top = decibels >= 6.0205 assert above_top.all(), decibels From 50ab54b2ec05e0b971577f2db0359ba8108eb6ed Mon Sep 17 00:00:00 2001 From: Vincent QB Date: Thu, 7 Jan 2021 10:43:29 -0500 Subject: [PATCH 18/35] Update torchaudio/functional/functional.py --- torchaudio/functional/functional.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 52967106f6..52ef4b8a7a 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -229,9 +229,8 @@ def amplitude_to_DB( ) -> Tensor: r"""Turn a spectrogram from the power/amplitude scale to the decibel scale. - This output depends on the maximum value in the input tensor, and so - may return different values for an audio clip split into snippets vs. a - full clip. + The output of each tensor in a batch depends on the maximum value of that tensor, + and so may return different values for an audio clip split into snippets vs. a full clip. Args: From 2f0771751b9ec8cb4e05ff307b6ad8a4086c64d6 Mon Sep 17 00:00:00 2001 From: Vincent QB Date: Thu, 7 Jan 2021 10:43:36 -0500 Subject: [PATCH 19/35] Update torchaudio/functional/functional.py --- torchaudio/functional/functional.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 52ef4b8a7a..6214603e83 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -235,8 +235,8 @@ def amplitude_to_DB( Args: x (Tensor): Input spectrogram(s) before being converted to decibel scale. Input should take - the form `(..., freq, time)`. Batched inputs must include a channel dimension and should - take the form `(batch, channel, freq, time)`. + the form `(..., freq, time)`. Batched inputs should include a channel dimension and + have the form `(batch, channel, freq, time)`. multiplier (float): Use 10. for power and 20. for amplitude amin (float): Number to clamp ``x`` db_multiplier (float): Log10(max(reference value and amin)) From 0c0976ccb8c6504d0ff9fd381fb8cda0ab585678 Mon Sep 17 00:00:00 2001 From: jcaw Date: Thu, 7 Jan 2021 20:49:42 +0000 Subject: [PATCH 20/35] Change upcase local variables to lowercase --- .../functional/functional_cpu_test.py | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index fbc6742c4e..b0be0bf820 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -73,21 +73,21 @@ def test_pitch(self, frequency): class Testamplitude_to_DB(common_utils.TorchaudioTestCase): def _ensure_reversible(self, spec): """Check `amplitude_to_db` returns the original when reversed.""" - AMPLITUDE_MULT = 20. - POWER_MULT = 10. - AMIN = 1e-10 - REF = 1.0 - DB_MULT = math.log10(max(AMIN, REF)) + amplitude_mult = 20. + power_mult = 10. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) # Spectrogram amplitude -> DB -> amplitude - db = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, DB_MULT, top_db=None) - x2 = F.DB_to_amplitude(db, REF, 0.5) + db = F.amplitude_to_DB(spec, amplitude_mult, amin, db_mult, top_db=None) + x2 = F.DB_to_amplitude(db, ref, 0.5) torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) # Spectrogram power -> DB -> power - db = F.amplitude_to_DB(spec, POWER_MULT, AMIN, DB_MULT, top_db=None) - x2 = F.DB_to_amplitude(db, REF, 1.) + db = F.amplitude_to_DB(spec, power_mult, amin, db_mult, top_db=None) + x2 = F.DB_to_amplitude(db, ref, 1.) self.assertEqual(x2, spec) @@ -104,14 +104,14 @@ def test_amplitude_to_DB_freq(self): self._ensure_reversible(spec) def _check_top_db(self, spec): - AMPLITUDE_MULT = 20. - AMIN = 1e-10 - REF = 1.0 - DB_MULT = math.log10(max(AMIN, REF)) - TOP_DB = 40. - - decibels = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=TOP_DB) + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 40. + + decibels = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) above_top = decibels >= 6.0205 assert above_top.all(), decibels @@ -137,11 +137,11 @@ def test_top_db_freq(self): self._check_top_db(spec[0][0]) def test_batched(self): - AMPLITUDE_MULT = 20. - AMIN = 1e-10 - REF = 1.0 - DB_MULT = math.log10(max(AMIN, REF)) - TOP_DB = 40. + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 40. # Make a batch of noise spec = torch.rand([2, 2, 100, 100]) * 200 @@ -152,22 +152,22 @@ def test_batched(self): spec[1, 0, 0, 0] = 200 # Ensure separate clamps are applied per-item in a batch. - batchwise_dbs = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=TOP_DB) + batchwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) itemwise_dbs = torch.stack([ - F.amplitude_to_DB(item, AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=TOP_DB) + F.amplitude_to_DB(item, amplitude_mult, amin, + db_mult, top_db=top_db) for item in spec ]) self.assertEqual(batchwise_dbs, itemwise_dbs) def test_per_spectrogram(self): - AMPLITUDE_MULT = 20. - AMIN = 1e-10 - REF = 1.0 - DB_MULT = math.log10(max(AMIN, REF)) - TOP_DB = 40. + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 40. spec = torch.rand([1, 2, 100, 100]) * 200 # Make the second channel blow out the first @@ -177,11 +177,11 @@ def test_per_spectrogram(self): spec[0, 1, 0, 0] = 200 # Ensure the clamp applies per-item, not per-channel. - specwise_dbs = F.amplitude_to_DB(spec, AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=TOP_DB) + specwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) channelwise_dbs = torch.stack([ - F.amplitude_to_DB(spec[:, i], AMPLITUDE_MULT, AMIN, - DB_MULT, top_db=TOP_DB) + F.amplitude_to_DB(spec[:, i], amplitude_mult, amin, + db_mult, top_db=top_db) for i in range(spec.size(-3)) ]) From 2d7746dda8e319d3862a3504ecc3d2e100b616dc Mon Sep 17 00:00:00 2001 From: jcaw Date: Thu, 7 Jan 2021 20:54:37 +0000 Subject: [PATCH 21/35] Set seed when `rand` is called in tests --- .../torchaudio_unittest/functional/functional_cpu_test.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index b0be0bf820..e0946ff5ad 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -92,14 +92,17 @@ def _ensure_reversible(self, spec): self.assertEqual(x2, spec) def test_amplitude_to_DB_batch(self): + torch.manual_seed(0) spec = torch.rand([2, 2, 100, 100]) * 200 self._ensure_reversible(spec) def test_amplitude_to_DB_channels(self): + torch.manual_seed(0) spec = torch.rand([2, 100, 100]) * 200 self._ensure_reversible(spec) def test_amplitude_to_DB_freq(self): + torch.manual_seed(0) spec = torch.rand([100, 100]) * 200 self._ensure_reversible(spec) @@ -116,6 +119,7 @@ def _check_top_db(self, spec): assert above_top.all(), decibels def test_top_db_batch(self): + torch.manual_seed(0) spec = torch.rand([1, 2, 100, 100]) * 200 # Predictability spec[0, 0, 1] = 0 @@ -123,6 +127,7 @@ def test_top_db_batch(self): self._check_top_db(spec) def test_top_db_channel(self): + torch.manual_seed(0) spec = torch.rand([1, 2, 100, 100]) * 200 # Predictability spec[0, 0, 1] = 0 @@ -130,6 +135,7 @@ def test_top_db_channel(self): self._check_top_db(spec[0]) def test_top_db_freq(self): + torch.manual_seed(0) spec = torch.rand([1, 2, 100, 100]) * 200 # Predictability spec[0, 0, 1] = 0 @@ -144,6 +150,7 @@ def test_batched(self): top_db = 40. # Make a batch of noise + torch.manual_seed(0) spec = torch.rand([2, 2, 100, 100]) * 200 # Make the second item blow out the first spec[0] *= 0.5 @@ -169,6 +176,7 @@ def test_per_spectrogram(self): db_mult = math.log10(max(amin, ref)) top_db = 40. + torch.manual_seed(0) spec = torch.rand([1, 2, 100, 100]) * 200 # Make the second channel blow out the first spec[:, 0] *= 0.5 From ea026273995dcfc53c79f4f2fd01fe7c498b2194 Mon Sep 17 00:00:00 2001 From: jcaw Date: Thu, 7 Jan 2021 21:00:05 +0000 Subject: [PATCH 22/35] Make decibel limit test fail more informatively --- .../torchaudio_unittest/functional/functional_cpu_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index e0946ff5ad..0332c23cd6 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -115,8 +115,12 @@ def _check_top_db(self, spec): decibels = F.amplitude_to_DB(spec, amplitude_mult, amin, db_mult, top_db=top_db) - above_top = decibels >= 6.0205 - assert above_top.all(), decibels + below_limit = decibels < 6.0205 + assert not below_limit.any(), ( + "{} decibel values were below the expected cutoff:\n{}".format( + below_limit.sum().item(), decibels + ) + ) def test_top_db_batch(self): torch.manual_seed(0) From 258b8c7a3331e91513e6b0e9e858b6e8f22bb3a1 Mon Sep 17 00:00:00 2001 From: jcaw Date: Thu, 7 Jan 2021 21:06:34 +0000 Subject: [PATCH 23/35] More descriptive test names, plus overt docstrings --- .../functional/functional_cpu_test.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 0332c23cd6..7b1381019d 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -96,12 +96,14 @@ def test_amplitude_to_DB_batch(self): spec = torch.rand([2, 2, 100, 100]) * 200 self._ensure_reversible(spec) - def test_amplitude_to_DB_channels(self): + def test_amplitude_to_DB_3dims(self): + """Test on a spectrogram with no batch dimension.""" torch.manual_seed(0) spec = torch.rand([2, 100, 100]) * 200 self._ensure_reversible(spec) - def test_amplitude_to_DB_freq(self): + def test_amplitude_to_DB_2dims(self): + """Test on a spectrogram with no batch or channel dimensions.""" torch.manual_seed(0) spec = torch.rand([100, 100]) * 200 self._ensure_reversible(spec) @@ -130,7 +132,8 @@ def test_top_db_batch(self): spec[0, 0, 0] = 200 self._check_top_db(spec) - def test_top_db_channel(self): + def test_top_db_3dims(self): + """Test on a spectrogram with no batch dimension.""" torch.manual_seed(0) spec = torch.rand([1, 2, 100, 100]) * 200 # Predictability @@ -138,7 +141,8 @@ def test_top_db_channel(self): spec[0, 0, 0] = 200 self._check_top_db(spec[0]) - def test_top_db_freq(self): + def test_top_db_2dims(self): + """Test on a spectrogram with no batch or channel dimensions.""" torch.manual_seed(0) spec = torch.rand([1, 2, 100, 100]) * 200 # Predictability From a363968b1b725574c9d07011bb82a910b7bf36f0 Mon Sep 17 00:00:00 2001 From: jcaw Date: Thu, 7 Jan 2021 21:09:20 +0000 Subject: [PATCH 24/35] Reference original MFCC clamping issue in test doc --- .../functional/functional_cpu_test.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 7b1381019d..23b63541e2 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -178,6 +178,15 @@ def test_batched(self): self.assertEqual(batchwise_dbs, itemwise_dbs) def test_per_spectrogram(self): + """Ensure that the clamps are separate for each spectrogram in a batch. + + The clamp was determined per-batch in a prior implementation, which + meant items were not independent and information could leak between + them. + + https://github.com/pytorch/audio/issues/994 + + """ amplitude_mult = 20. amin = 1e-10 ref = 1.0 From da3b808e1d458c23f2af8adace1dd302c3141999 Mon Sep 17 00:00:00 2001 From: jcaw Date: Thu, 7 Jan 2021 21:42:03 +0000 Subject: [PATCH 25/35] Move docstring to correct function --- .../functional/functional_cpu_test.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 23b63541e2..ec2078491b 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -151,6 +151,15 @@ def test_top_db_2dims(self): self._check_top_db(spec[0][0]) def test_batched(self): + """Ensure that the clamps are separate for each spectrogram in a batch. + + The clamp was determined per-batch in a prior implementation, which + meant items were not independent and information could leak between + them. See: + + https://github.com/pytorch/audio/issues/994 + + """ amplitude_mult = 20. amin = 1e-10 ref = 1.0 @@ -178,15 +187,6 @@ def test_batched(self): self.assertEqual(batchwise_dbs, itemwise_dbs) def test_per_spectrogram(self): - """Ensure that the clamps are separate for each spectrogram in a batch. - - The clamp was determined per-batch in a prior implementation, which - meant items were not independent and information could leak between - them. - - https://github.com/pytorch/audio/issues/994 - - """ amplitude_mult = 20. amin = 1e-10 ref = 1.0 From f8e1943207439236363e8c56f2761f3c5273c38a Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 20 Jan 2021 16:57:09 +0000 Subject: [PATCH 26/35] Pass correct number of item dimensions for a batch `AmplitudeToDB` expects items in batches to have 3 dims, including channels. Use 3 dims to test batch consistency. --- test/torchaudio_unittest/batch_consistency_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/torchaudio_unittest/batch_consistency_test.py b/test/torchaudio_unittest/batch_consistency_test.py index d4edf65e98..e67870e1d8 100644 --- a/test/torchaudio_unittest/batch_consistency_test.py +++ b/test/torchaudio_unittest/batch_consistency_test.py @@ -103,7 +103,7 @@ class TestTransforms(common_utils.TorchaudioTestCase): """Test suite for classes defined in `transforms` module""" def test_batch_AmplitudeToDB(self): - spec = torch.rand((6, 201)) + spec = torch.rand((2, 6, 201)) # Single then transform then batch expected = torchaudio.transforms.AmplitudeToDB()(spec).repeat(3, 1, 1) From ba7e457225b343539a1d978d8e02ce248ed052d4 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 20 Jan 2021 16:58:50 +0000 Subject: [PATCH 27/35] Move dim tests to `test_batch_consistency.py` Also rename them since they're not enclosed in a specific `amplitude_to_DB` test class. --- .../batch_consistency_test.py | 59 +++++++++++++++++ .../functional/functional_cpu_test.py | 64 ------------------- 2 files changed, 59 insertions(+), 64 deletions(-) diff --git a/test/torchaudio_unittest/batch_consistency_test.py b/test/torchaudio_unittest/batch_consistency_test.py index e67870e1d8..3c08ceab8c 100644 --- a/test/torchaudio_unittest/batch_consistency_test.py +++ b/test/torchaudio_unittest/batch_consistency_test.py @@ -3,6 +3,8 @@ import itertools from parameterized import parameterized +import math + import torch import torchaudio import torchaudio.functional as F @@ -59,6 +61,63 @@ def test_detect_pitch_frequency(self, frequency, sample_rate, n_channels): n_channels=n_channels, duration=5) self.assert_batch_consistencies(F.detect_pitch_frequency, waveform, sample_rate) + def test_amplitude_to_DB_itemwise_clamps(self): + """Ensure that the clamps are separate for each spectrogram in a batch. + + The clamp was determined per-batch in a prior implementation, which + meant it was determined by the loudest item, thus items weren't + independent. See: + + https://github.com/pytorch/audio/issues/994 + + """ + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 20. + + # Make a batch of noise + torch.manual_seed(0) + spec = torch.rand([2, 2, 100, 100]) * 200 + # Make one item blow out the other + spec[0] += 50 + + batchwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) + itemwise_dbs = torch.stack([ + F.amplitude_to_DB(item, amplitude_mult, amin, + db_mult, top_db=top_db) + for item in spec + ]) + + self.assertEqual(batchwise_dbs, itemwise_dbs) + + def test_amplitude_to_DB_not_channelwise_clamps(self): + """Check that clamps are applied per-item, not per channel.""" + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 40. + + torch.manual_seed(0) + spec = torch.rand([1, 2, 100, 100]) * 200 + # Make one channel blow out the other + spec[:, 0] += 50 + + specwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) + channelwise_dbs = torch.stack([ + F.amplitude_to_DB(spec[:, i], amplitude_mult, amin, + db_mult, top_db=top_db) + for i in range(spec.size(-3)) + ]) + + # Just check channelwise gives a different answer. + difference = (specwise_dbs - channelwise_dbs).abs() + assert (difference >= 1e-5).any() + def test_contrast(self): waveform = torch.rand(2, 100) - 0.5 self.assert_batch_consistencies(F.contrast, waveform, enhancement_amount=80.) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index ec2078491b..95515c5c96 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -150,70 +150,6 @@ def test_top_db_2dims(self): spec[0, 0, 0] = 200 self._check_top_db(spec[0][0]) - def test_batched(self): - """Ensure that the clamps are separate for each spectrogram in a batch. - - The clamp was determined per-batch in a prior implementation, which - meant items were not independent and information could leak between - them. See: - - https://github.com/pytorch/audio/issues/994 - - """ - amplitude_mult = 20. - amin = 1e-10 - ref = 1.0 - db_mult = math.log10(max(amin, ref)) - top_db = 40. - - # Make a batch of noise - torch.manual_seed(0) - spec = torch.rand([2, 2, 100, 100]) * 200 - # Make the second item blow out the first - spec[0] *= 0.5 - # Predictability - spec[0, 0, 0, 0] = 0 - spec[1, 0, 0, 0] = 200 - - # Ensure separate clamps are applied per-item in a batch. - batchwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, - db_mult, top_db=top_db) - itemwise_dbs = torch.stack([ - F.amplitude_to_DB(item, amplitude_mult, amin, - db_mult, top_db=top_db) - for item in spec - ]) - - self.assertEqual(batchwise_dbs, itemwise_dbs) - - def test_per_spectrogram(self): - amplitude_mult = 20. - amin = 1e-10 - ref = 1.0 - db_mult = math.log10(max(amin, ref)) - top_db = 40. - - torch.manual_seed(0) - spec = torch.rand([1, 2, 100, 100]) * 200 - # Make the second channel blow out the first - spec[:, 0] *= 0.5 - # Predictability - spec[0, 0, 0, 0] = 0 - spec[0, 1, 0, 0] = 200 - - # Ensure the clamp applies per-item, not per-channel. - specwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, - db_mult, top_db=top_db) - channelwise_dbs = torch.stack([ - F.amplitude_to_DB(spec[:, i], amplitude_mult, amin, - db_mult, top_db=top_db) - for i in range(spec.size(-3)) - ]) - - # Just check channelwise gives a different answer. - difference = (specwise_dbs - channelwise_dbs).abs() - assert (difference >= 1e-5).any() - @pytest.mark.parametrize('complex_tensor', [ torch.randn(1, 2, 1025, 400, 2), From 6b8d6b7f5e2a44542116299420a502989889cdf0 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 20 Jan 2021 17:02:15 +0000 Subject: [PATCH 28/35] Add generic batch test for `amplitude_to_DB` --- .../torchaudio_unittest/batch_consistency_test.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/torchaudio_unittest/batch_consistency_test.py b/test/torchaudio_unittest/batch_consistency_test.py index 3c08ceab8c..41f3202d71 100644 --- a/test/torchaudio_unittest/batch_consistency_test.py +++ b/test/torchaudio_unittest/batch_consistency_test.py @@ -61,6 +61,21 @@ def test_detect_pitch_frequency(self, frequency, sample_rate, n_channels): n_channels=n_channels, duration=5) self.assert_batch_consistencies(F.detect_pitch_frequency, waveform, sample_rate) + def test_amplitude_to_DB(self): + torch.manual_seed(0) + spec = torch.rand(2, 100, 100) * 200 + + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + + # Test with & without a `top_db` clamp + self.assert_batch_consistencies(F.amplitude_to_DB, spec, amplitude_mult, + amin, db_mult, top_db=None) + self.assert_batch_consistencies(F.amplitude_to_DB, spec, amplitude_mult, + amin, db_mult, top_db=40.) + def test_amplitude_to_DB_itemwise_clamps(self): """Ensure that the clamps are separate for each spectrogram in a batch. From dda8744162dd67d3fdc5652251f56f77447f3902 Mon Sep 17 00:00:00 2001 From: jcaw Date: Wed, 20 Jan 2021 17:02:42 +0000 Subject: [PATCH 29/35] Expand test docstring --- test/torchaudio_unittest/functional/functional_cpu_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 95515c5c96..94097779a5 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -72,7 +72,11 @@ def test_pitch(self, frequency): class Testamplitude_to_DB(common_utils.TorchaudioTestCase): def _ensure_reversible(self, spec): - """Check `amplitude_to_db` returns the original when reversed.""" + """Check `amplitude_to_db` returns the original when reversed. + + This implicitly also tests `DB_to_amplitude`. + + """ amplitude_mult = 20. power_mult = 10. amin = 1e-10 From 8ba79921af0649c19c36bb06d22cca64a35baa0a Mon Sep 17 00:00:00 2001 From: jcaw Date: Mon, 1 Feb 2021 16:06:17 +0000 Subject: [PATCH 30/35] Parameterize `amplitude_to_DB` reversibility tests Simpler than maintaining separate tests for each --- .../functional/functional_cpu_test.py | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 94097779a5..8f519999c5 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -71,7 +71,12 @@ def test_pitch(self, frequency): class Testamplitude_to_DB(common_utils.TorchaudioTestCase): - def _ensure_reversible(self, spec): + @parameterized.expand([ + ([100, 100],), + ([2, 100, 100],), + ([2, 2, 100, 100],), + ]) + def test_reversible(self, shape): """Check `amplitude_to_db` returns the original when reversed. This implicitly also tests `DB_to_amplitude`. @@ -83,6 +88,9 @@ def _ensure_reversible(self, spec): ref = 1.0 db_mult = math.log10(max(amin, ref)) + torch.manual_seed(0) + spec = torch.rand(*shape) * 200 + # Spectrogram amplitude -> DB -> amplitude db = F.amplitude_to_DB(spec, amplitude_mult, amin, db_mult, top_db=None) x2 = F.DB_to_amplitude(db, ref, 0.5) @@ -95,22 +103,6 @@ def _ensure_reversible(self, spec): self.assertEqual(x2, spec) - def test_amplitude_to_DB_batch(self): - torch.manual_seed(0) - spec = torch.rand([2, 2, 100, 100]) * 200 - self._ensure_reversible(spec) - - def test_amplitude_to_DB_3dims(self): - """Test on a spectrogram with no batch dimension.""" - torch.manual_seed(0) - spec = torch.rand([2, 100, 100]) * 200 - self._ensure_reversible(spec) - - def test_amplitude_to_DB_2dims(self): - """Test on a spectrogram with no batch or channel dimensions.""" - torch.manual_seed(0) - spec = torch.rand([100, 100]) * 200 - self._ensure_reversible(spec) def _check_top_db(self, spec): amplitude_mult = 20. From 62efc262909387c9ecb17754e0ed81360a54bca6 Mon Sep 17 00:00:00 2001 From: jcaw Date: Mon, 1 Feb 2021 16:13:53 +0000 Subject: [PATCH 31/35] Parameterize `amplitude_to_DB` `top_db` tests Also change the way the spectrograms are generated to work with all the given shapes, and apply the correct range to all spectrograms. --- .../functional/functional_cpu_test.py | 46 ++++++++----------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 8f519999c5..d2785c78fb 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -103,14 +103,30 @@ def test_reversible(self, shape): self.assertEqual(x2, spec) - - def _check_top_db(self, spec): + @parameterized.expand([ + ([100, 100],), + ([2, 100, 100],), + ([2, 2, 100, 100],), + ]) + def test_top_db_clamp(self, shape): + """Ensure values are properly clamped when `top_db` is supplied.""" amplitude_mult = 20. amin = 1e-10 ref = 1.0 db_mult = math.log10(max(amin, ref)) top_db = 40. + torch.manual_seed(0) + # A random tensor is used for increased entropy, but the max and min for + # each spectrogram still need to be predictable. The min determines the + # decibel cutoff, and the max must be large enough that it gets clamped. + spec = torch.rand(*shape) + # Bring each spectrogram into the range (0, 1) + spec -= spec.amin([-2, -1])[..., None, None] + spec /= spec.amax([-2, -1])[..., None, None] + # Expand the range to (0, 200) - wide enough to properly test clamping. + spec *= 200 + decibels = F.amplitude_to_DB(spec, amplitude_mult, amin, db_mult, top_db=top_db) below_limit = decibels < 6.0205 @@ -120,32 +136,6 @@ def _check_top_db(self, spec): ) ) - def test_top_db_batch(self): - torch.manual_seed(0) - spec = torch.rand([1, 2, 100, 100]) * 200 - # Predictability - spec[0, 0, 1] = 0 - spec[0, 0, 0] = 200 - self._check_top_db(spec) - - def test_top_db_3dims(self): - """Test on a spectrogram with no batch dimension.""" - torch.manual_seed(0) - spec = torch.rand([1, 2, 100, 100]) * 200 - # Predictability - spec[0, 0, 1] = 0 - spec[0, 0, 0] = 200 - self._check_top_db(spec[0]) - - def test_top_db_2dims(self): - """Test on a spectrogram with no batch or channel dimensions.""" - torch.manual_seed(0) - spec = torch.rand([1, 2, 100, 100]) * 200 - # Predictability - spec[0, 0, 1] = 0 - spec[0, 0, 0] = 200 - self._check_top_db(spec[0][0]) - @pytest.mark.parametrize('complex_tensor', [ torch.randn(1, 2, 1025, 400, 2), From f4c7552a5f720b2e1bb8cc5cde67356e745fe2b1 Mon Sep 17 00:00:00 2001 From: jcaw Date: Mon, 1 Feb 2021 16:15:25 +0000 Subject: [PATCH 32/35] Check `top_db` doesn't over-clamp --- test/torchaudio_unittest/functional/functional_cpu_test.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index d2785c78fb..16193a8b9c 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -129,12 +129,18 @@ def test_top_db_clamp(self, shape): decibels = F.amplitude_to_DB(spec, amplitude_mult, amin, db_mult, top_db=top_db) + # Ensure the clamp was applied below_limit = decibels < 6.0205 assert not below_limit.any(), ( "{} decibel values were below the expected cutoff:\n{}".format( below_limit.sum().item(), decibels ) ) + # Ensure it didn't over-clamp + close_to_limit = decibels < 6.0207 + assert close_to_limit.any(), ( + f"No values were close to the limit. Did it over-clamp?\n{decibels}" + ) @pytest.mark.parametrize('complex_tensor', [ From 5992235317b98fdcb5e4924cd7502406e06b10bf Mon Sep 17 00:00:00 2001 From: jcaw Date: Mon, 1 Feb 2021 16:23:22 +0000 Subject: [PATCH 33/35] Clearer test docstring --- test/torchaudio_unittest/functional/functional_cpu_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 16193a8b9c..f2d1fdc567 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -77,7 +77,7 @@ class Testamplitude_to_DB(common_utils.TorchaudioTestCase): ([2, 2, 100, 100],), ]) def test_reversible(self, shape): - """Check `amplitude_to_db` returns the original when reversed. + """Round trip between amplitude and db should return the original for various shape This implicitly also tests `DB_to_amplitude`. From 6a14029a192cf0907f6ff7e7e8767cdec60ad227 Mon Sep 17 00:00:00 2001 From: jcaw Date: Mon, 1 Feb 2021 16:30:22 +0000 Subject: [PATCH 34/35] Clearer description of scaling operation --- test/torchaudio_unittest/functional/functional_cpu_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index f2d1fdc567..638612af0a 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -121,7 +121,7 @@ def test_top_db_clamp(self, shape): # each spectrogram still need to be predictable. The min determines the # decibel cutoff, and the max must be large enough that it gets clamped. spec = torch.rand(*shape) - # Bring each spectrogram into the range (0, 1) + # Ensure each spectrogram has a min of 0 and a max of 1. spec -= spec.amin([-2, -1])[..., None, None] spec /= spec.amax([-2, -1])[..., None, None] # Expand the range to (0, 200) - wide enough to properly test clamping. From 27d23a9ebde8680e39a674d875b6f42c01fdf542 Mon Sep 17 00:00:00 2001 From: jcaw Date: Mon, 1 Feb 2021 19:55:15 +0000 Subject: [PATCH 35/35] Correct description of `top_db` behaviour --- test/torchaudio_unittest/functional/functional_cpu_test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 638612af0a..84578061ee 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -118,8 +118,9 @@ def test_top_db_clamp(self, shape): torch.manual_seed(0) # A random tensor is used for increased entropy, but the max and min for - # each spectrogram still need to be predictable. The min determines the - # decibel cutoff, and the max must be large enough that it gets clamped. + # each spectrogram still need to be predictable. The max determines the + # decibel cutoff, and the distance from the min must be large enough + # that it triggers a clamp. spec = torch.rand(*shape) # Ensure each spectrogram has a min of 0 and a max of 1. spec -= spec.amin([-2, -1])[..., None, None]