Skip to content

Commit

Permalink
testing with sox only when sox is available (#419)
Browse files Browse the repository at this point in the history
* testing with sox only when sox is available.

* use wav instead of mp3 for testing functions.

* typo.

* guard against not sox.

* backends definition.

* grouping backend functions into a separate file.

* remove duplicated code.

* requires sox.

* replace by wav, requires sox.

* require with scope.

* undo alignment.

* requires sox for these two, because of mp3.

* no longer need first mp3.

* cleaning.

* new wav version of file.

* flake8.

* remove unnecessary load.

* flake8.

* lint.

* lint.

* revert formatting of file.

* merging into common_utils.

* docstring.

* rename to common_utils.
  • Loading branch information
vincentqb committed Mar 30, 2020
1 parent dbed5b1 commit d63d851
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 57 deletions.
Binary file added test/assets/whitenoise.wav
Binary file not shown.
37 changes: 36 additions & 1 deletion test/common_utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import os
from shutil import copytree
import tempfile
from contextlib import contextmanager
from shutil import copytree

import torch
import torchaudio

TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__))
BACKENDS = torchaudio._backend._audio_backends


def create_temp_assets_dir():
Expand Down Expand Up @@ -48,3 +51,35 @@ def random_int_tensor(seed, size, low=0, high=2 ** 32, a=22695477, c=1, m=2 ** 3
""" Same as random_float_tensor but integers between [low, high)
"""
return torch.floor(random_float_tensor(seed, size, a, c, m) * (high - low)) + low


@contextmanager
def AudioBackendScope(new_backend):
previous_backend = torchaudio.get_audio_backend()
try:
torchaudio.set_audio_backend(new_backend)
yield
finally:
torchaudio.set_audio_backend(previous_backend)


def filter_backends_with_mp3(backends):
# Filter out backends that do not support mp3

test_dirpath, _ = create_temp_assets_dir()
test_filepath = os.path.join(
test_dirpath, "assets", "steam-train-whistle-daniel_simon.mp3"
)

def supports_mp3(backend):
try:
with AudioBackendScope(backend):
torchaudio.load(test_filepath)
return True
except RuntimeError:
return False

return [backend for backend in backends if supports_mp3(backend)]


BACKENDS_MP3 = filter_backends_with_mp3(BACKENDS)
37 changes: 12 additions & 25 deletions test/test.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,25 @@
import unittest
import common_utils
import torch
import torchaudio
import math
import os


class AudioBackendScope:
def __init__(self, backend):
self.new_backend = backend
self.previous_backend = torchaudio.get_audio_backend()

def __enter__(self):
torchaudio.set_audio_backend(self.new_backend)
return self.new_backend

def __exit__(self, type, value, traceback):
backend = self.previous_backend
torchaudio.set_audio_backend(backend)
from common_utils import AudioBackendScope, BACKENDS, BACKENDS_MP3, create_temp_assets_dir


class Test_LoadSave(unittest.TestCase):
test_dirpath, test_dir = common_utils.create_temp_assets_dir()
test_dirpath, test_dir = create_temp_assets_dir()
test_filepath = os.path.join(test_dirpath, "assets",
"steam-train-whistle-daniel_simon.mp3")
test_filepath_wav = os.path.join(test_dirpath, "assets",
"steam-train-whistle-daniel_simon.wav")

def test_1_save(self):
for backend in ["sox"]:
for backend in BACKENDS_MP3:
with self.subTest():
with AudioBackendScope(backend):
self._test_1_save(self.test_filepath, False)

for backend in ["sox", "soundfile"]:
for backend in BACKENDS:
with self.subTest():
with AudioBackendScope(backend):
self._test_1_save(self.test_filepath_wav, True)
Expand Down Expand Up @@ -79,7 +65,7 @@ def _test_1_save(self, test_filepath, normalization):
torchaudio.save(new_filepath, x, sr)

def test_1_save_sine(self):
for backend in ["sox", "soundfile"]:
for backend in BACKENDS:
with self.subTest():
with AudioBackendScope(backend):
self._test_1_save_sine()
Expand Down Expand Up @@ -112,12 +98,12 @@ def _test_1_save_sine(self):
os.unlink(new_filepath)

def test_2_load(self):
for backend in ["sox"]:
for backend in BACKENDS_MP3:
with self.subTest():
with AudioBackendScope(backend):
self._test_2_load(self.test_filepath, 278756)

for backend in ["sox", "soundfile"]:
for backend in BACKENDS:
with self.subTest():
with AudioBackendScope(backend):
self._test_2_load(self.test_filepath_wav, 276858)
Expand Down Expand Up @@ -153,7 +139,7 @@ def _test_2_load(self, test_filepath, length):
torchaudio.load(tdir)

def test_2_load_nonormalization(self):
for backend in ["sox"]:
for backend in BACKENDS_MP3:
with self.subTest():
with AudioBackendScope(backend):
self._test_2_load_nonormalization(self.test_filepath, 278756)
Expand All @@ -170,7 +156,7 @@ def _test_2_load_nonormalization(self, test_filepath, length):
self.assertTrue(isinstance(x, torch.LongTensor))

def test_3_load_and_save_is_identity(self):
for backend in ["sox", "soundfile"]:
for backend in BACKENDS:
with self.subTest():
with AudioBackendScope(backend):
self._test_3_load_and_save_is_identity()
Expand All @@ -185,6 +171,7 @@ def _test_3_load_and_save_is_identity(self):
self.assertEqual(sample_rate, sample_rate2)
os.unlink(output_path)

@unittest.skipIf(set(["sox", "soundfile"]) not in set(BACKENDS), "sox and soundfile are not available")
def test_3_load_and_save_is_identity_across_backend(self):
with self.subTest():
self._test_3_load_and_save_is_identity_across_backend("sox", "soundfile")
Expand All @@ -208,7 +195,7 @@ def _test_3_load_and_save_is_identity_across_backend(self, backend1, backend2):
os.unlink(output_path)

def test_4_load_partial(self):
for backend in ["sox"]:
for backend in BACKENDS_MP3:
with self.subTest():
with AudioBackendScope(backend):
self._test_4_load_partial()
Expand Down Expand Up @@ -250,7 +237,7 @@ def _test_4_load_partial(self):
torchaudio.load(input_sine_path, offset=100000)

def test_5_get_info(self):
for backend in ["sox", "soundfile"]:
for backend in BACKENDS:
with self.subTest():
with AudioBackendScope(backend):
self._test_5_get_info()
Expand Down
12 changes: 10 additions & 2 deletions test/test_compliance_kaldi.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import math
import os
import common_utils
import compliance.utils
import torch
import torchaudio
import torchaudio.compliance.kaldi as kaldi
import unittest
from common_utils import AudioBackendScope, BACKENDS, create_temp_assets_dir


def extract_window(window, wave, f, frame_length, frame_shift, snip_edges):
Expand Down Expand Up @@ -45,7 +45,7 @@ def first_sample_of_frame(frame, window_size, window_shift, snip_edges):


class Test_Kaldi(unittest.TestCase):
test_dirpath, test_dir = common_utils.create_temp_assets_dir()
test_dirpath, test_dir = create_temp_assets_dir()
test_filepath = os.path.join(test_dirpath, 'assets', 'kaldi_file.wav')
test_8000_filepath = os.path.join(test_dirpath, 'assets', 'kaldi_file_8000.wav')
kaldi_output_dir = os.path.join(test_dirpath, 'assets', 'kaldi')
Expand Down Expand Up @@ -159,6 +159,8 @@ def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_fil
self.assertTrue(output.shape, kaldi_output.shape)
self.assertTrue(torch.allclose(output, kaldi_output, atol=atol, rtol=rtol))

@unittest.skipIf("sox" not in BACKENDS, "sox not available")
@AudioBackendScope("sox")
def test_spectrogram(self):
def get_output_fn(sound, args):
output = kaldi.spectrogram(
Expand All @@ -179,6 +181,8 @@ def get_output_fn(sound, args):

self._compliance_test_helper(self.test_filepath, 'spec', 131, 13, get_output_fn, atol=1e-3, rtol=0)

@unittest.skipIf("sox" not in BACKENDS, "sox not available")
@AudioBackendScope("sox")
def test_fbank(self):
def get_output_fn(sound, args):
output = kaldi.fbank(
Expand Down Expand Up @@ -209,6 +213,8 @@ def get_output_fn(sound, args):

self._compliance_test_helper(self.test_filepath, 'fbank', 97, 22, get_output_fn, atol=1e-3, rtol=1e-1)

@unittest.skipIf("sox" not in BACKENDS, "sox not available")
@AudioBackendScope("sox")
def test_mfcc(self):
def get_output_fn(sound, args):
output = kaldi.mfcc(
Expand Down Expand Up @@ -243,6 +249,8 @@ def test_mfcc_empty(self):
# Passing in an empty tensor should result in an error
self.assertRaises(AssertionError, kaldi.mfcc, torch.empty(0))

@unittest.skipIf("sox" not in BACKENDS, "sox not available")
@AudioBackendScope("sox")
def test_resample_waveform(self):
def get_output_fn(sound, args):
output = kaldi.resample_waveform(sound, args[1], args[2])
Expand Down
9 changes: 6 additions & 3 deletions test/test_dataloader.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import unittest
import common_utils
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
import torchaudio
import math
import os
from common_utils import AudioBackendScope, BACKENDS, create_temp_assets_dir


@unittest.skipIf("sox" not in BACKENDS, "sox not available")
class TORCHAUDIODS(Dataset):

test_dirpath, test_dir = common_utils.create_temp_assets_dir()
test_dirpath, test_dir = create_temp_assets_dir()

def __init__(self):
self.asset_dirpath = os.path.join(self.test_dirpath, "assets")
Expand All @@ -33,6 +34,7 @@ def __len__(self):
return len(self.data)


@unittest.skipIf("sox" not in BACKENDS, "sox not available")
class Test_DataLoader(unittest.TestCase):
@classmethod
def setUpClass(cls):
Expand All @@ -50,4 +52,5 @@ def test_1(self):
self.assertTrue(x.size() == expected_size)

if __name__ == '__main__':
unittest.main()
with AudioBackendScope("sox"):
unittest.main()
9 changes: 8 additions & 1 deletion test/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import unittest
import common_utils

from common_utils import AudioBackendScope, BACKENDS
from torchaudio.common_utils import IMPORT_LIBROSA

if IMPORT_LIBROSA:
Expand Down Expand Up @@ -39,7 +40,7 @@ class TestFunctional(unittest.TestCase):
test_dirpath, test_dir = common_utils.create_temp_assets_dir()

test_filepath = os.path.join(test_dirpath, 'assets',
'steam-train-whistle-daniel_simon.mp3')
'steam-train-whistle-daniel_simon.wav')
waveform_train, sr_train = torchaudio.load(test_filepath)

def test_torchscript_spectrogram(self):
Expand Down Expand Up @@ -433,6 +434,8 @@ def test_create_fb(self):
self._test_create_fb(n_mels=56, fmin=1900.0, fmax=900.0)
self._test_create_fb(n_mels=10, fmin=1900.0, fmax=900.0)

@unittest.skipIf("sox" not in BACKENDS, "sox not available")
@AudioBackendScope("sox")
def test_gain(self):
waveform_gain = F.gain(self.waveform_train, 3)
self.assertTrue(waveform_gain.abs().max().item(), 1.)
Expand All @@ -444,6 +447,8 @@ def test_gain(self):

self.assertTrue(torch.allclose(waveform_gain, sox_gain_waveform, atol=1e-04))

@unittest.skipIf("sox" not in BACKENDS, "sox not available")
@AudioBackendScope("sox")
def test_dither(self):
waveform_dithered = F.dither(self.waveform_train)
waveform_dithered_noiseshaped = F.dither(self.waveform_train, noise_shaping=True)
Expand All @@ -461,6 +466,8 @@ def test_dither(self):

self.assertTrue(torch.allclose(waveform_dithered_noiseshaped, sox_dither_waveform_ns, atol=1e-02))

@unittest.skipIf("sox" not in BACKENDS, "sox not available")
@AudioBackendScope("sox")
def test_vctk_transform_pipeline(self):
test_filepath_vctk = os.path.join(self.test_dirpath, "assets/VCTK-Corpus/wav48/p224/", "p224_002.wav")
wf_vctk, sr_vctk = torchaudio.load(test_filepath_vctk)
Expand Down
Loading

0 comments on commit d63d851

Please sign in to comment.