peterf@2
|
1 #!/usr/bin/env python
|
peterf@2
|
2 # CREATED:2013-03-08 15:25:18 by Brian McFee <brm2132@columbia.edu>
|
peterf@2
|
3 # unit tests for librosa.feature (feature.py)
|
peterf@2
|
4 #
|
peterf@2
|
5 # Run me as follows:
|
peterf@2
|
6 # cd tests/
|
peterf@2
|
7 # nosetests -v
|
peterf@2
|
8 #
|
peterf@2
|
9 # This test suite verifies that librosa core routines match (numerically) the output
|
peterf@2
|
10 # of various DPWE matlab implementations on a broad range of input parameters.
|
peterf@2
|
11 #
|
peterf@2
|
12 # All test data is generated by the Matlab script "makeTestData.m".
|
peterf@2
|
13 # Each test loads in a .mat file which contains the input and desired output for a given
|
peterf@2
|
14 # function. The test then runs the librosa implementation and verifies the results
|
peterf@2
|
15 # against the desired output, typically via numpy.allclose().
|
peterf@2
|
16 #
|
peterf@2
|
17 # CAVEATS:
|
peterf@2
|
18 #
|
peterf@2
|
19 # Currently, not all tests are exhaustive in parameter space. This is typically due
|
peterf@2
|
20 # restricted functionality of the librosa implementations. Similarly, there is no
|
peterf@2
|
21 # fuzz-testing here, so behavior on invalid inputs is not yet well-defined.
|
peterf@2
|
22 #
|
peterf@2
|
23
|
peterf@2
|
24 import librosa
|
peterf@2
|
25 import os, glob
|
peterf@2
|
26 import numpy, scipy.io
|
peterf@2
|
27
|
peterf@2
|
28 from nose.tools import nottest
|
peterf@2
|
29
|
peterf@2
|
30 #-- utilities --#
|
peterf@2
|
31 def files(pattern):
|
peterf@2
|
32 test_files = glob.glob(pattern)
|
peterf@2
|
33 test_files.sort()
|
peterf@2
|
34 return test_files
|
peterf@2
|
35
|
peterf@2
|
36 def load(infile):
|
peterf@2
|
37 DATA = scipy.io.loadmat(infile, chars_as_strings=True)
|
peterf@2
|
38 return DATA
|
peterf@2
|
39 #-- --#
|
peterf@2
|
40
|
peterf@2
|
41 #-- Tests --#
|
peterf@2
|
42 def test_hz_to_mel():
|
peterf@2
|
43 def __test_to_mel(infile):
|
peterf@2
|
44 DATA = load(infile)
|
peterf@2
|
45 z = librosa.hz_to_mel(DATA['f'], DATA['htk'])
|
peterf@2
|
46
|
peterf@2
|
47 assert numpy.allclose(z, DATA['result'])
|
peterf@2
|
48
|
peterf@2
|
49 for infile in files('data/feature-hz_to_mel-*.mat'):
|
peterf@2
|
50 yield (__test_to_mel, infile)
|
peterf@2
|
51
|
peterf@2
|
52 pass
|
peterf@2
|
53
|
peterf@2
|
54 def test_mel_to_hz():
|
peterf@2
|
55
|
peterf@2
|
56 def __test_to_hz(infile):
|
peterf@2
|
57 DATA = load(infile)
|
peterf@2
|
58 z = librosa.mel_to_hz(DATA['f'], DATA['htk'])
|
peterf@2
|
59
|
peterf@2
|
60 assert numpy.allclose(z, DATA['result'])
|
peterf@2
|
61
|
peterf@2
|
62 for infile in files('data/feature-mel_to_hz-*.mat'):
|
peterf@2
|
63 yield (__test_to_hz, infile)
|
peterf@2
|
64
|
peterf@2
|
65 pass
|
peterf@2
|
66
|
peterf@2
|
67 def test_hz_to_octs():
|
peterf@2
|
68 def __test_to_octs(infile):
|
peterf@2
|
69 DATA = load(infile)
|
peterf@2
|
70 z = librosa.hz_to_octs(DATA['f'])
|
peterf@2
|
71
|
peterf@2
|
72 assert numpy.allclose(z, DATA['result'])
|
peterf@2
|
73
|
peterf@2
|
74 for infile in files('data/feature-hz_to_octs-*.mat'):
|
peterf@2
|
75 yield (__test_to_octs, infile)
|
peterf@2
|
76
|
peterf@2
|
77 pass
|
peterf@2
|
78
|
peterf@2
|
79 def test_melfb():
|
peterf@2
|
80
|
peterf@2
|
81 def __test(infile):
|
peterf@2
|
82 DATA = load(infile)
|
peterf@2
|
83
|
peterf@2
|
84 wts = librosa.filters.mel( DATA['sr'][0],
|
peterf@2
|
85 DATA['nfft'][0],
|
peterf@2
|
86 n_mels = DATA['nfilts'][0],
|
peterf@2
|
87 fmin = DATA['fmin'][0],
|
peterf@2
|
88 fmax = DATA['fmax'][0],
|
peterf@2
|
89 htk = DATA['htk'][0])
|
peterf@2
|
90
|
peterf@2
|
91 # Our version only returns the real-valued part.
|
peterf@2
|
92 # Pad out.
|
peterf@2
|
93 wts = numpy.pad(wts, [ (0, 0), (0, int(DATA['nfft'][0]/2 - 1))], mode='constant')
|
peterf@2
|
94
|
peterf@2
|
95 assert wts.shape == DATA['wts'].shape
|
peterf@2
|
96
|
peterf@2
|
97 assert numpy.allclose(wts, DATA['wts'])
|
peterf@2
|
98
|
peterf@2
|
99 for infile in files('data/feature-melfb-*.mat'):
|
peterf@2
|
100 yield (__test, infile)
|
peterf@2
|
101 pass
|
peterf@2
|
102
|
peterf@2
|
103 def test_chromafb():
|
peterf@2
|
104
|
peterf@2
|
105 def __test(infile):
|
peterf@2
|
106 DATA = load(infile)
|
peterf@2
|
107
|
peterf@2
|
108 octwidth = DATA['octwidth'][0,0]
|
peterf@2
|
109 if octwidth == 0:
|
peterf@2
|
110 octwidth = None
|
peterf@2
|
111
|
peterf@2
|
112 wts = librosa.filters.chroma( DATA['sr'][0,0],
|
peterf@2
|
113 DATA['nfft'][0,0],
|
peterf@2
|
114 DATA['nchroma'][0,0],
|
peterf@2
|
115 A440 = DATA['a440'][0,0],
|
peterf@2
|
116 ctroct = DATA['ctroct'][0,0],
|
peterf@2
|
117 octwidth= octwidth)
|
peterf@2
|
118
|
peterf@2
|
119 # Our version only returns the real-valued part.
|
peterf@2
|
120 # Pad out.
|
peterf@2
|
121 wts = numpy.pad(wts, [ (0, 0), (0, DATA['nfft'][0,0]/2 - 1)], mode='constant')
|
peterf@2
|
122
|
peterf@2
|
123 assert wts.shape == DATA['wts'].shape
|
peterf@2
|
124
|
peterf@2
|
125 assert numpy.allclose(wts, DATA['wts'])
|
peterf@2
|
126
|
peterf@2
|
127 for infile in files('data/feature-chromafb-*.mat'):
|
peterf@2
|
128 yield (__test, infile)
|
peterf@2
|
129 pass
|