d5d58f63656f1bbd4b748556075420b26f718e43
[aubio.git] / python / tests / test_specdesc.py
1 #! /usr/bin/env python
2
3 from unittest import main
4 from numpy.testing import TestCase, assert_equal, assert_almost_equal
5 from numpy import random, arange, log, zeros
6 from aubio import specdesc, cvec, float_type
7
8 methods = ["default",
9      "energy",
10      "hfc",
11      "complex",
12      "phase",
13      "specdiff",
14      "kl",
15      "mkl",
16      "specflux",
17      "centroid",
18      "spread",
19      "skewness",
20      "kurtosis",
21      "slope",
22      "decrease",
23      "rolloff"]
24 buf_size = 2048
25
26 class aubio_specdesc(TestCase):
27
28     def test_members(self):
29         o = specdesc()
30
31         for method in methods:
32             o = specdesc(method, buf_size)
33             assert_equal ([o.buf_size, o.method], [buf_size, method])
34
35             spec = cvec(buf_size)
36             spec.norm[0] = 1
37             spec.norm[1] = 1./2.
38             #print "%20s" % method, str(o(spec))
39             o(spec)
40             spec.norm = random.random_sample((len(spec.norm),)).astype(float_type)
41             spec.phas = random.random_sample((len(spec.phas),)).astype(float_type)
42             #print "%20s" % method, str(o(spec))
43             assert (o(spec) != 0.)
44
45     def test_phase(self):
46         o = specdesc("phase", buf_size)
47         spec = cvec(buf_size)
48         # phase of zeros is zero
49         assert_equal (o(spec), 0.)
50         spec.phas = random.random_sample((len(spec.phas),)).astype(float_type)
51         # phase of random is not zero
52         spec.norm[:] = 1
53         assert (o(spec) != 0.)
54
55     def test_specdiff(self):
56         o = specdesc("phase", buf_size)
57         spec = cvec(buf_size)
58         # specdiff of zeros is zero
59         assert_equal (o(spec), 0.)
60         spec.phas = random.random_sample((len(spec.phas),)).astype(float_type)
61         # phase of random is not zero
62         spec.norm[:] = 1
63         assert (o(spec) != 0.)
64     
65     def test_hfc(self):
66         o = specdesc("hfc")
67         c = cvec()
68         assert_equal( 0., o(c))
69         a = arange(c.length, dtype=float_type)
70         c.norm = a
71         assert_equal (a, c.norm)
72         assert_equal ( sum(a*(a+1)), o(c))
73
74     def test_complex(self):
75         o = specdesc("complex")
76         c = cvec()
77         assert_equal( 0., o(c))
78         a = arange(c.length, dtype=float_type)
79         c.norm = a
80         assert_equal (a, c.norm)
81         # the previous run was on zeros, so previous frames are still 0
82         # so we have sqrt ( abs ( r2 ^ 2) ) == r2
83         assert_equal ( sum(a), o(c))
84         # second time. c.norm = a, so, r1 = r2, and the euclidian distance is 0
85         assert_equal ( 0, o(c))
86
87     def test_kl(self):
88         o = specdesc("kl")
89         c = cvec()
90         assert_equal( 0., o(c))
91         a = arange(c.length, dtype=float_type)
92         c.norm = a
93         assert_almost_equal( sum(a * log(1.+ a/1.e-1 ) ) / o(c), 1., decimal=6)
94
95     def test_mkl(self):
96         o = specdesc("mkl")
97         c = cvec()
98         assert_equal( 0., o(c))
99         a = arange(c.length, dtype=float_type)
100         c.norm = a
101         assert_almost_equal( sum(log(1.+ a/1.e-1 ) ) / o(c), 1, decimal=6)
102
103     def test_specflux(self):
104         o = specdesc("specflux")
105         c = cvec()
106         assert_equal( 0., o(c))
107         a = arange(c.length, dtype=float_type)
108         c.norm = a
109         assert_equal( sum(a), o(c))
110         assert_equal( 0, o(c))
111         c.norm = zeros(c.length, dtype=float_type)
112         assert_equal( 0, o(c))
113
114     def test_centroid(self):
115         o = specdesc("centroid")
116         c = cvec()
117         # make sure centroid of zeros is zero
118         assert_equal( 0., o(c))
119         a = arange(c.length, dtype=float_type)
120         c.norm = a
121         centroid = sum(a*a) / sum(a)
122         assert_almost_equal (centroid, o(c), decimal = 2)
123
124         c.norm = a * .5 
125         assert_almost_equal (centroid, o(c), decimal = 2)
126
127     def test_spread(self):
128         o = specdesc("spread")
129         c = cvec(2048)
130         ramp = arange(c.length, dtype=float_type)
131         assert_equal( 0., o(c))
132
133         a = ramp
134         c.norm = a
135         centroid = sum(a*a) / sum(a)
136         spread = sum( a * pow(ramp - centroid, 2.) ) / sum(a)
137         assert_almost_equal (o(c), spread, decimal = 1)
138
139     def test_skewness(self):
140         o = specdesc("skewness")
141         c = cvec()
142         assert_equal( 0., o(c))
143         a = arange(c.length, dtype=float_type)
144         c.norm = a
145         centroid = sum(a*a) / sum(a)
146         spread = sum( (a - centroid)**2 *a) / sum(a)
147         skewness = sum( (a - centroid)**3 *a) / sum(a) / spread **1.5
148         assert_almost_equal (skewness, o(c), decimal = 2)
149
150         c.norm = a * 3
151         assert_almost_equal (skewness, o(c), decimal = 2)
152
153     def test_kurtosis(self):
154         o = specdesc("kurtosis")
155         c = cvec()
156         assert_equal( 0., o(c))
157         a = arange(c.length, dtype=float_type)
158         c.norm = a
159         centroid = sum(a*a) / sum(a)
160         spread = sum( (a - centroid)**2 *a) / sum(a)
161         kurtosis = sum( (a - centroid)**4 *a) / sum(a) / spread **2
162         assert_almost_equal (kurtosis, o(c), decimal = 2)
163
164     def test_slope(self):
165         o = specdesc("slope")
166         c = cvec()
167         assert_equal( 0., o(c))
168         a = arange(c.length * 2, 0, -2, dtype=float_type)
169         k = arange(c.length, dtype=float_type)
170         c.norm = a
171         num = len(a) * sum(k*a) - sum(k)*sum(a)
172         den = (len(a) * sum(k**2) - sum(k)**2)
173         slope = num/den/sum(a)
174         assert_almost_equal (slope, o(c), decimal = 5)
175
176         a = arange(0, c.length * 2, +2, dtype=float_type)
177         c.norm = a
178         num = len(a) * sum(k*a) - sum(k)*sum(a)
179         den = (len(a) * sum(k**2) - sum(k)**2)
180         slope = num/den/sum(a)
181         assert_almost_equal (slope, o(c), decimal = 5)
182
183         a = arange(0, c.length * 2, +2, dtype=float_type)
184         c.norm = a * 2
185         assert_almost_equal (slope, o(c), decimal = 5)
186
187     def test_decrease(self):
188         o = specdesc("decrease")
189         c = cvec()
190         assert_equal( 0., o(c))
191         a = arange(c.length * 2, 0, -2, dtype=float_type)
192         k = arange(c.length, dtype=float_type)
193         c.norm = a
194         decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) 
195         assert_almost_equal (decrease, o(c), decimal = 5)
196
197         a = arange(0, c.length * 2, +2, dtype=float_type)
198         c.norm = a
199         decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) 
200         assert_almost_equal (decrease, o(c), decimal = 5)
201
202         a = arange(0, c.length * 2, +2, dtype=float_type)
203         c.norm = a * 2
204         decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) 
205         assert_almost_equal (decrease, o(c), decimal = 5)
206
207     def test_rolloff(self):
208         o = specdesc("rolloff")
209         c = cvec()
210         assert_equal( 0., o(c))
211         a = arange(c.length * 2, 0, -2, dtype=float_type)
212         c.norm = a
213         cumsum = .95*sum(a*a)
214         i = 0; rollsum = 0
215         while rollsum < cumsum:
216             rollsum += a[i]*a[i]
217             i+=1
218         rolloff = i 
219         assert_equal (rolloff, o(c))
220
221 class aubio_specdesc_wrong(TestCase):
222
223     def test_negative(self):
224         with self.assertRaises(ValueError):
225             specdesc("default", -10)
226
227     def test_unknown(self):
228         # FIXME should fail?
229         with self.assertRaises(ValueError):
230             specdesc("unknown", 512)
231             self.skipTest('todo: new_specdesc should fail on wrong method')
232
233 if __name__ == '__main__':
234     main()