Files
PySoundConcat/src/tests/audiofile_tests.py
T

841 lines
32 KiB
Python

"""A set of unit tests to check the correct operation of the pysound module."""
import unittest
import numpy as np
from sppysound import AudioFile, analysis
from sppysound.database import AudioDatabase, Matcher
import subprocess
from scipy import signal
from fileops import pathops
import pdb
import os
import config
class globalTests(unittest.TestCase):
"""Includes functions that are accesible to all audiofile tests."""
def check_setup(self, Audio, channels=1, mode='r',
format=65539, samplerate=44100):
"""Check setup was correct."""
self.assertEquals(Audio.channels, channels)
self.assertEquals(Audio.pysndfile_object.channels(), channels)
self.assertEquals(Audio.mode, mode)
self.assertEquals(Audio.samplerate, samplerate)
self.assertEquals(Audio.pysndfile_object.samplerate(), samplerate)
self.assertEquals(Audio.format, format)
self.assertEquals(Audio.pysndfile_object.format(), format)
def check_result(self, Audio, channels, mode='r',
format=65539, samplerate=44100):
"""Check the output file is the correct size, format etc..."""
def create_test_audio(self, filename="./.TestAudio.wav", mode='w', channels=1):
"""Create a default audio file to test on"""
return AudioFile.gen_default_wav(
filename,
overwrite_existing=True,
mode=mode,
channels=channels,
)
class FileCreationTests(globalTests):
"""Audio file creation tests."""
def test_CreateAudioFile(self):
"""Check the creation of default audio files."""
self.assertFalse(os.path.exists("./.TestAudio.wav"))
self.TestAudio = self.create_test_audio()
self.assertTrue(os.path.exists("./.TestAudio.wav"))
self.assertEquals(self.TestAudio.channels, 1)
self.assertEquals(self.TestAudio.pysndfile_object.channels(), 1)
self.assertEquals(self.TestAudio.mode, 'w')
self.assertEquals(self.TestAudio.samplerate, 44100)
self.assertEquals(self.TestAudio.pysndfile_object.samplerate(), 44100)
self.assertEquals(self.TestAudio.format, 65539)
self.assertEquals(self.TestAudio.pysndfile_object.format(), 65539)
def test_ReadFail(self):
"""Check that opening a file that doesn't exist for reading fails."""
with self.assertRaises(IOError):
self.TestAudio = AudioFile.gen_default_wav(
"./.TestAudio.wav",
mode='r'
)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example, remove all temporary test audio files generated during the
tests.
"""
pathops.delete_if_exists("./.TestAudio.wav")
class SwitchModeTests(globalTests):
"""Test read/write mode switching functionality."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
def test_SwitchMode(self):
"""Check that pysndfile object mode switching works as expected."""
# Check setup was correct
self.check_setup(self.TestAudio, mode='w')
self.TestAudio.write_frames(np.linspace(-0.5, 0.5, 101))
self.TestAudio.switch_mode('r')
with self.assertRaises(IOError):
self.TestAudio.write_frames(np.zeros(10))
self.TestAudio.seek(0, 0)
self.assertEqual(self.TestAudio.read_frames().size, 101)
self.TestAudio.switch_mode('w')
self.TestAudio.seek(0, 0)
self.assertEqual(self.TestAudio.read_frames().size, 0)
self.assertEqual(
self.TestAudio.write_frames(np.linspace(-0.5, 0.5, 101)), 101
)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example, remove all temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
class ReadGrainTest(globalTests):
"""Test granular sample reading functionality."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
self.TestAudio.write_frames(np.linspace(-0.5, 0.5, 101))
self.TestAudio.switch_mode('r')
def test_AllGrains(self):
"""Check all samples are read correctly if no arguments are given."""
# TestAudio file has 100 samples
self.check_setup(self.TestAudio)
self.assertEqual(
self.TestAudio.read_grain(0, -1).size, 101, "Read Grain - all "
"grains test failed: Didn't Read all samples")
def test_SliceStartToMiddle(self):
"""Check that start slicing is read from and too the correct sample."""
self.check_setup(self.TestAudio)
grain = self.TestAudio.read_grain(0, 51)
self.assertEqual(grain.size, 51, "Read Grain - Start to middle test "
"failed: Didn't read correct number of samples.")
self.assertEqual(grain[0], -0.5, "Read Grain - Start to middle test "
"failed: Didn't read from correct start index.")
self.assertEqual(grain[-1], 0.0, "Read Grain - Start to middle test "
"failed: Didn't read to correct end index.")
def test_NegativeIndexing(self):
"""Check that end slicing is read from and too the correct sample."""
self.check_setup(self.TestAudio)
grain = self.TestAudio.read_grain(-51, 51)
self.assertEqual(grain.size, 51, "Read Grain - Negative indexing test "
"failed: Didn't return correct number of samples.")
self.assertEqual(grain[0], 0.0, "Read Grain - Negative indexing test "
"failed: Didn't start at correct grain index.")
self.assertEqual(grain[-1], 0.5, "Read Grain - Negative indexing test "
"failed: Didn't read to correct end index.")
def test_ZeroPadding(self):
"""
Check that reading samples further than the end sample results in zero
padding after the last sample.
"""
self.check_setup(self.TestAudio)
grain = self.TestAudio.read_grain(-26, 50)
self.assertEqual(grain.size, 50, "Read Grain - Zero padding test "
"failed: Didn't read correct number of samples.")
self.assertEqual(grain[0], 0.25, "Read Grain - Zero padding test "
"failed: Didn't read from correct start index")
self.assertEqual(grain[25:50].all(), 0, "Read Grain - Zero padding "
"test failed: Didn't pad zeroes to end of grain "
"correctly")
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example: delete temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
class GenerateWhiteNoiseTest(globalTests):
"""Test white noise generation."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
def test_CreateNoise(self):
"""Test that white noise is generated corectly without clipping."""
self.check_setup(self.TestAudio, mode='w',)
samples = AudioFile.gen_white_noise(2 * self.TestAudio.samplerate, 0.7)
# Check all samples are within the range of -1.0 to 1.0
self.assertFalse((samples < -1.0).any() and (samples > 1.0).any())
self.TestAudio.write_frames(samples)
self.TestAudio.switch_mode('r')
self.assertEqual(self.TestAudio.get_frames(), 88200)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example: delete temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
class MonoDownmixTest(globalTests):
"""Test mixing of audio files from multi-channel to mono."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio(channels=2)
samples = AudioFile.mono_arrays_to_stereo(
np.linspace(-0.5, 0.5, 101),
np.linspace(-0.5, 0.5, 101)
)
self.TestAudio.write_frames(
samples
)
self.TestAudio.switch_mode('r')
self.TestAudio.seek(0, 0)
def test_MixToMono(self):
"""Test that mixing audio to mono works as expected."""
self.check_setup(self.TestAudio, channels=2)
mono_file = self.TestAudio.convert_to_mono(overwrite_original=False)
mono_file.switch_mode('r')
mono_file.seek(0, 0)
stereo_frames = self.TestAudio.frames
self.assertGreater(stereo_frames, 0)
# Check new file exists
self.assertTrue(os.path.exists("./.TestAudio.mono.wav"))
# Check new file is mono
self.assertEqual(mono_file.channels, 1)
# Check original exists
self.assertTrue(os.path.exists("./.TestAudio.wav"))
# Check original is stereo
self.assertEqual(self.TestAudio.channels, 2)
# Check new file is the same length in frames as the original
self.assertEqual(stereo_frames, mono_file.frames)
# Check that if mono file already exists, it is used to replace the
# original if the function is run again with overwrite_original set to
# True
self.TestAudio.convert_to_mono(overwrite_original=True)
# Check that mono file no longer exists
self.assertFalse(os.path.exists("./.TestAudio.mono.wav"))
# Check new file is mono
self.assertEqual(self.TestAudio.channels, 1)
# Check original exists
self.assertTrue(os.path.exists("./.TestAudio.wav"))
# Check new file is the same length in frames as the original
self.assertEqual(stereo_frames, mono_file.frames)
self.TestAudio.seek(0, 0)
samples = self.TestAudio.read_frames()
self.TestAudio.switch_mode('r')
self.TestAudio.seek(0, 0)
samples = self.TestAudio.read_frames()
self.assertEqual(samples.size, 101)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example: delete temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
pathops.delete_if_exists("./.TestAudio.mono.wav")
class NormalizeTest(globalTests):
"""Test the audio normalization functionality."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
samples = np.linspace(-0.3, 0.3, 1000)
self.TestAudio.write_frames(
samples
)
self.TestAudio.seek(0, 0)
def test_Normalize(self):
"""Test that audio normalization works as expected."""
self.check_setup(self.TestAudio, mode='w')
normalized_file = self.TestAudio.normalize_file(
overwrite_original=False
)
normalized_frames = self.TestAudio.frames
self.assertGreater(normalized_frames, 0)
# Check new file exists
self.assertTrue(os.path.exists("./.TestAudio.norm.wav"))
# Check new file is normalized
self.assertEqual(normalized_file.channels, 1)
# Check original exists
self.assertTrue(os.path.exists("./.TestAudio.wav"))
# Check new file is the same length in frames as the original
self.assertEqual(normalized_frames, normalized_file.frames)
# Check that if normalized file already exists, it is used to replace
# the original if the function is run again with overwrite_original set
# to True
self.TestAudio.normalize_file(overwrite_original=True)
# Check that normalized file no longer exists
self.assertFalse(os.path.exists("./.TestAudio.norm.wav"))
# Check new file is normalized
self.assertEqual(normalized_file.channels, 1)
# Check original exists
self.assertTrue(os.path.exists("./.TestAudio.wav"))
# Check new file is the same length in frames as the original
self.assertEqual(normalized_frames, normalized_file.frames)
# Check that all samples have been normalized
self.TestAudio.switch_mode('r')
self.TestAudio.seek(0, 0)
self.assertGreater(self.TestAudio.read_frames().all(), 0.9)
self.assertEqual(self.TestAudio.frames, 1000)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example: delete temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
pathops.delete_if_exists("./.TestAudio.norm.wav")
class RenameFileTests(globalTests):
"""Test the audio file renaming functionality."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
self.TestAudio.write_frames(np.linspace(-0.5, 0.5, 101))
self.TestAudio.switch_mode('r')
def test_RenameFile(self):
"""Check that file renaming function works correctly."""
self.check_setup(self.TestAudio, mode='r')
original_framecount = self.TestAudio.frames
original_channels = self.TestAudio.channels
# Check original file exists
self.assertTrue(os.path.exists("./.TestAudio.wav"))
# Rename the file
self.TestAudio.rename_file("./.TestAudio.rename.wav")
# Check file has new name
self.assertTrue(os.path.exists("./.TestAudio.rename.wav"))
self.assertEqual(self.TestAudio.filepath, "./.TestAudio.rename.wav")
# Check new file has correct data
self.assertEqual(self.TestAudio.frames, original_framecount)
self.assertEqual(self.TestAudio.channels, original_channels)
# Check original file no longer exists
self.assertFalse(os.path.exists("./.TestAudio.wav"))
self.assertEqual(self.TestAudio.frames, 101)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example: delete temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
pathops.delete_if_exists("./.TestAudio.rename.wav")
class ReplaceFileTests(globalTests):
"""Test audio file replacement functionality."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
self.TestAudio.write_frames(np.zeros(101))
self.TestAudio2 = self.create_test_audio(
filename='./.TestAudio.replace.wav'
)
self.TestAudio2.write_frames(np.ones(50))
del self.TestAudio2
def test_ReplaceFile(self):
"""Check that file replacment function works correctly."""
self.check_setup(self.TestAudio, mode='w')
# Check that file to be replaced exists
self.assertTrue(os.path.exists("./.TestAudio.wav"))
# Check that file to replace file with exists
self.assertTrue(os.path.exists("./.TestAudio.replace.wav"))
# Check attempt to replace with a file that doesn't exists fails.
with self.assertRaises(IOError):
self.TestAudio.replace_audiofile("./.FileThatDoesntExist.wav")
# Replace file with replacement file
self.TestAudio.replace_audiofile("./.TestAudio.replace.wav")
# Check that the replacement file no longer exists
self.assertFalse(os.path.exists("./.TestAudio.replace.wav"))
# Check that currently open object is now refferencing the replacement
# file and that it has been renamed correctly
self.assertTrue(os.path.exists("./.TestAudio.wav"))
self.assertTrue(self.TestAudio.filepath, "./.TestAudio.wav")
self.assertEqual(self.TestAudio.frames, 50)
class FadeAudioTest(globalTests):
"""Test audio fade in/out functionality."""
def setUp(self):
"""Create functions and variables before each test is run."""
# Generate 2 second of ones at a samplerate of 44.1Khz
self.test_audio = np.ones(88200)
self.TestAudio = self.create_test_audio()
def test_FadeIn(self):
"""Check that audio is faded in and out correctly and accuratley."""
self.check_setup(self.TestAudio, mode='w')
faded_audio = self.TestAudio.fade_audio(
self.test_audio,
500,
1000,
"in"
)
self.assertEquals(faded_audio[0], 0)
self.assertEquals(faded_audio[self.TestAudio.ms_to_samps(500)], 0)
self.assertEquals(faded_audio[-1], 1)
self.assertEquals(faded_audio[self.TestAudio.ms_to_samps(1500)], 1)
# Reset test array
self.test_audio = np.ones(88200)
faded_audio = self.TestAudio.fade_audio(
self.test_audio,
500,
1000,
"out"
)
self.assertEquals(faded_audio[0], 1)
self.assertEquals(faded_audio[self.TestAudio.ms_to_samps(500)], 1)
self.assertEquals(faded_audio[-1], 0)
self.assertEquals(faded_audio[self.TestAudio.ms_to_samps(1500)], 0)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example: delete temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
pathops.delete_if_exists("./.TestAudio.rename.wav")
class RMSAnalysisTests(globalTests):
"""Tests RMS analysis generation"""
def setUp(self):
# TODO: Write this test...
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
def test_GenerateRMS(self):
"""Check that RMS values generated are the expected values"""
class PeakAnalysisTests(globalTests):
"""Tests Peak analysis generation"""
def setUp(self):
# TODO: Write this test...
"""Create functions and variables before each test is run."""
self.sr = 44100
self.f = 440
x = np.arange(88200)
self.sine_wave = np.sin(2*np.pi*self.f/self.sr*x)
def test_GeneratePeak(self):
"""Check that RMS values generated are the expected values"""
output = analysis.PeakAnalysis.create_peak_analysis(self.sine_wave)
self.assertTrue(np.all(output > 0.8))
class SpectralCentroidAnalysisTests(globalTests):
"""Tests Spectral Centroid analysis generation."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
# Specify frequency of the sine wave
self.sr = 44100
self.f = 440
x = np.arange(88200)
self.sine_wave = np.sin(2*np.pi*self.f/self.sr*x)
def test_GenerateSpectralCentroid(self):
fft = analysis.FFTAnalysis.stft(self.sine_wave, 512)
output = analysis.SpectralCentroidAnalysis.create_spccntr_analysis(fft, 512, self.sr)
average_output = np.median(output)
self.assertTrue(self.f-2 <= average_output <= self.f+2)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example, remove all temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
class SpectralSpreadAnalysisTests(globalTests):
"""Tests Spectral Spread analysis generation."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
# Specify frequency of the sine wave
self.sr = 44100
self.f = 440
x = np.arange(88200)
self.sine_wave = np.sin(2*np.pi*self.f/self.sr*x)
self.white_noise = np.random.random(88200)
def test_GenerateSpectralSpread(self):
fft = analysis.FFTAnalysis.stft(self.sine_wave, 512)
output = analysis.SpectralCentroidAnalysis.create_spccntr_analysis(fft, 512, self.sr, output_format = 'freq')
average_output = np.median(output)
output = analysis.SpectralSpreadAnalysis.create_spcsprd_analysis(fft, output, 512, self.sr, output_format='freq')
output = output / (44100/2.0)
average_output = np.median(output)
self.assertTrue(0 <= average_output <= 2)
fft = analysis.FFTAnalysis.stft(self.white_noise, 512)
output = analysis.SpectralCentroidAnalysis.create_spccntr_analysis(fft, 512, self.sr, output_format = 'ind')
output = analysis.SpectralSpreadAnalysis.create_spcsprd_analysis(fft, output, 512, self.sr, output_format='freq')
average_output = np.median(output)
output = output / (44100/2.0)
average_output = np.median(output)
# self.assertTrue(8000 <= average_output)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example, remove all temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
class SpectralFluxAnalysisTests(globalTests):
"""Tests Spectral Flux analysis generation."""
def setUp(self):
# Specify frequency of the sine wave
self.sr = 44100
self.f = 440
x = np.arange(44100)
self.sine_wave = np.sin(2*np.pi*self.f/self.sr*x)
self.white_noise = np.random.random(44100)
self.input = np.concatenate((self.sine_wave, self.white_noise))
def test_GenerateSpectralFlux(self):
fft = analysis.FFTAnalysis.stft(self.input, 512)
output = analysis.SpectralFluxAnalysis.create_spcflux_analysis(fft, 512, self.sr)
output_max_index = np.argmax(output)
self.assertTrue(output_max_index == output.size/2)
class SpectralCrestFactorAnalysisTests(globalTests):
"""Tests Spectral Crest Factor analysis generation."""
def setUp(self):
self.sr = 44100
self.f = 440
x = np.arange(44100)
sine_wave = np.sin(2*np.pi*self.f/self.sr*x)
white_noise = np.random.random(44100)
silence = np.zeros(44100)
self.input = np.concatenate((sine_wave, white_noise, silence))
def test_GenerateSpectralCrestFactor(self):
fft = analysis.FFTAnalysis.stft(self.input, 512)
output = analysis.SpectralCrestFactorAnalysis.create_spccf_analysis(fft, 512, self.sr)
# TODO: Write assertions for results. This isn't testing anything
# otherwise...
class SpectralFlatnessAnalysisTests(globalTests):
"""Tests Spectral Crest Factor analysis generation."""
def setUp(self):
self.sr = 44100
self.f = 440
x = np.arange(44100)
sine_wave = np.sin(2*np.pi*self.f/self.sr*x)
white_noise = np.random.random(44100)
silence = np.zeros(44100)
self.input = np.concatenate((sine_wave, white_noise, silence))
def test_GenerateSpectralFlatness(self):
fft = analysis.FFTAnalysis.stft(self.input, 512)
output = analysis.SpectralFlatnessAnalysis.create_spcflatness_analysis(fft, 512, self.sr)
# TODO: Write assertions for results. This isn't testing anything
# otherwise...
class KurtosisAnalysisTests(globalTests):
"""Tests Kurtosis analysis generation."""
def setUp(self):
self.sr = 44100
self.f = 440
x = np.arange(44100)
self.sine_wave = np.sin(2*np.pi*self.f/self.sr*x)
self.white_noise = np.random.random(44100)
self.silence = np.zeros(44100)
self.gausian = signal.gaussian(512, std=7)
def test_GenerateKurtosis(self):
sine_variance = analysis.VarianceAnalysis.create_variance_analysis(self.sine_wave)
sine_output = analysis.KurtosisAnalysis.create_kurtosis_analysis(self.sine_wave, sine_variance)
noise_variance = analysis.VarianceAnalysis.create_variance_analysis(self.white_noise)
noise_output = analysis.KurtosisAnalysis.create_kurtosis_analysis(self.white_noise, noise_variance)
silence_variance = analysis.VarianceAnalysis.create_variance_analysis(self.silence)
silence_output = analysis.KurtosisAnalysis.create_kurtosis_analysis(self.silence, silence_variance)
# TODO: Write assertions for results. This isn't testing anything
# otherwise...
class F0AnalysisTests(globalTests):
"""Tests Spectral Spread analysis generation."""
def setUp(self):
"""Create functions and variables before each test is run."""
self.TestAudio = self.create_test_audio()
# Specify frequency of the sine wave
self.sr = 44100
self.f = 440
x = np.arange(88200)+1
self.sine_wave = np.sin(2*np.pi*self.f/self.sr*x)
self.white_noise = 2 * np.random.random(88200) - 1
def test_Generatef0(self):
output = analysis.F0Analysis.create_f0_analysis(self.sine_wave, self.sr)
average_output = np.median(output[:, 0])
a = (average_output >= 437) & (average_output <= 443)
self.assertTrue(a.all())
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example, remove all temporary test audio files generated during the
tests.
"""
del self.TestAudio
pathops.delete_if_exists("./.TestAudio.wav")
class DatabaseTests(globalTests):
"""Tests database creation and analysis."""
def setUp(self):
"""Create functions and variables before each test is run."""
pathops.dir_must_exist("./.test_db")
self.sine_audio = self.create_test_audio(filename="./.test_db/test_sine.wav")
self.silent_audio = self.create_test_audio(filename="./.test_db/test_silent.wav")
self.noise_audio = self.create_test_audio(filename="./.test_db/test_noise.wav")
f = 440
x = np.arange(self.sine_audio.samplerate*2)+1
sine_wave = np.sin(2*np.pi*f/self.sine_audio.samplerate*x)
silence = np.zeros(self.silent_audio.samplerate*2)
white_noise = 2 * np.random.random(self.noise_audio.samplerate*2) - 1
self.sine_audio.write_frames(sine_wave)
del self.sine_audio
self.noise_audio.write_frames(white_noise)
del self.noise_audio
self.silent_audio.write_frames(silence)
del self.silent_audio
def test_DatabaseAnalysis(self):
# Create database object
database = AudioDatabase(
"./.test_db",
analysis_list=["rms", "zerox", "fft", "spccntr", "spcsprd", "f0"],
config=config
)
# Create/load a pre-existing database
database.load_database(reanalyse=True)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example, remove all temporary test audio files generated during the
tests.
"""
pathops.delete_if_exists("./.test_db")
class MatcherTests(globalTests):
"""Tests database creation and analysis."""
# Create database 1
def setUp(self):
"""Create matcher object to be tested"""
pathops.dir_must_exist("./.test_db1")
self.sine_audio = self.create_test_audio(filename="./.test_db1/test_sine.wav")
self.silent_audio = self.create_test_audio(filename="./.test_db1/test_silent.wav")
self.noise_audio = self.create_test_audio(filename="./.test_db1/test_noise.wav")
f = 440
x = np.arange(self.sine_audio.samplerate*2)+1
sine_wave = np.sin(2*np.pi*f/self.sine_audio.samplerate*x)
silence = np.zeros(self.silent_audio.samplerate*2)
white_noise = 2 * np.random.random(self.noise_audio.samplerate*2) - 1
self.sine_audio.write_frames(sine_wave)
del self.sine_audio
self.noise_audio.write_frames(white_noise)
del self.noise_audio
self.silent_audio.write_frames(silence)
del self.silent_audio
# Create database object
self.database1 = AudioDatabase(
"./.test_db1",
config=config
)
# Create/load a pre-existing database
self.database1.load_database(reanalyse=True)
# Create database 2
pathops.dir_must_exist("./.test_db2")
self.sine_audio = self.create_test_audio(filename="./.test_db2/test_sine.wav")
self.silent_audio = self.create_test_audio(filename="./.test_db2/test_silent.wav")
self.noise_audio = self.create_test_audio(filename="./.test_db2/test_noise.wav")
f = 440
x = np.arange(self.sine_audio.samplerate*2)+1
sine_wave = np.sin(2*np.pi*f/self.sine_audio.samplerate*x)
silence = np.zeros(self.silent_audio.samplerate*2)
white_noise = 2 * np.random.random(self.noise_audio.samplerate*2) - 1
self.sine_audio.write_frames(sine_wave)
del self.sine_audio
self.noise_audio.write_frames(white_noise)
del self.noise_audio
self.silent_audio.write_frames(silence)
del self.silent_audio
# Create database object
self.database2 = AudioDatabase(
"./.test_db2",
config=config
)
# Create/load a pre-existing database
self.database2.load_database(reanalyse=True)
self.matcher = Matcher(self.database1, self.database2, {}, config=config)
def test_DistanceCalc(self):
data1 = np.array([np.nan, 1,2,3,4, np.nan, np.nan, 7, 6, 5])
data2 = np.array([1, np.nan,2,3,4, 6, np.nan, 7, np.nan, 5])
output = self.matcher.distance_calc(data1, data2)
expected_output = np.array([[ 39.6, 0. , 39.6, 39.6, 39.6, 39.6, 0. , 39.6, 0. , 39.6],
[ 0. , 39.6, 1. , 4. , 9. , 25. , 39.6, 36. , 39.6, 16. ],
[ 1. , 39.6, 0. , 1. , 4. , 16. , 39.6, 25. , 39.6, 9. ],
[ 4. , 39.6, 1. , 0. , 1. , 9. , 39.6, 16. , 39.6, 4. ],
[ 9. , 39.6, 4. , 1. , 0. , 4. , 39.6, 9. , 39.6, 1. ],
[ 39.6, 0. , 39.6, 39.6, 39.6, 39.6, 0. , 39.6, 0. , 39.6],
[ 39.6, 0. , 39.6, 39.6, 39.6, 39.6, 0. , 39.6, 0. , 39.6],
[ 36. , 39.6, 25. , 16. , 9. , 1. , 39.6, 0. , 39.6, 4. ],
[ 25. , 39.6, 16. , 9. , 4. , 0. , 39.6, 1. , 39.6, 1. ],
[ 16. , 39.6, 9. , 4. , 1. , 1. , 39.6, 4. , 39.6, 0. ]])
np.testing.assert_array_equal(output, expected_output)
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example, remove all temporary test audio files generated during the
tests.
"""
pathops.delete_if_exists("./.test_db1")
pathops.delete_if_exists("./.test_db2")
class PitchShiftTests(globalTests):
"""Tests the pitch shifter function"""
def setUp(self):
# Generate a sine wave at 440hz
self.sr = 44100
x = np.arange(self.sr*2)+1
self.sine_wave = np.sin(2*np.pi*440/self.sr*x)
pathops.dir_must_exist("./.test_db3")
self.sine_audio = self.create_test_audio(filename="./.test_db3/test_sine.wav")
window = np.hanning(self.sine_wave.size)
self.sine_wave *= window
self.sine_audio.write_frames(self.sine_wave)
del self.sine_audio
def test_ShiftingAccuracy(self):
pitch = 2.
# TODO: Write a test here...
def tearDown(self):
"""
Delete anything that is left over once tests are complete.
For example, remove all temporary test audio files generated during the
tests.
"""
pathops.delete_if_exists("./.test_db3")
ReadGrainSuite = unittest.TestLoader().loadTestsFromTestCase(ReadGrainTest)
SwitchModeSuite = unittest.TestLoader().loadTestsFromTestCase(SwitchModeTests)
FileCreationSuite = unittest.TestLoader().loadTestsFromTestCase(
FileCreationTests
)
AllTestsSuite = unittest.TestSuite(
[ReadGrainSuite, SwitchModeSuite, FileCreationSuite]
)
if __name__ == "__main__":
unittest.main()