Merge branch 'feature/mfccparams'
[aubio.git] / python / tests / test_phasevoc.py
1 #! /usr/bin/env python
2
3 from numpy.testing import TestCase, assert_equal, assert_array_less
4 from aubio import fvec, cvec, pvoc, float_type
5 from nose2 import main
6 from nose2.tools import params
7 import numpy as np
8
9 if float_type == 'float32':
10     max_sq_error = 1.e-12
11 else:
12     max_sq_error = 1.e-29
13
14 def create_sine(hop_s, freq, samplerate):
15     t = np.arange(hop_s).astype(float_type)
16     return np.sin( 2. * np.pi * freq * t / float(samplerate))
17
18 def create_noise(hop_s):
19     return np.random.rand(hop_s).astype(float_type) * 2. - 1.
20
21 class aubio_pvoc_test_case(TestCase):
22     """ pvoc object test case """
23
24     def test_members_automatic_sizes_default(self):
25         """ check object creation with default parameters """
26         f = pvoc()
27         assert_equal ([f.win_s, f.hop_s], [1024, 512])
28
29     def test_members_unnamed_params(self):
30         """ check object creation with unnamed parameters """
31         f = pvoc(2048, 128)
32         assert_equal ([f.win_s, f.hop_s], [2048, 128])
33
34     def test_members_named_params(self):
35         """ check object creation with named parameters """
36         f = pvoc(hop_s = 128, win_s = 2048)
37         assert_equal ([f.win_s, f.hop_s], [2048, 128])
38
39     def test_zeros(self):
40         """ check the resynthesis of zeros gives zeros """
41         win_s, hop_s = 1024, 256
42         f = pvoc (win_s, hop_s)
43         t = fvec (hop_s)
44         for _ in range( int ( 4 * win_s / hop_s ) ):
45             s = f(t)
46             r = f.rdo(s)
47             assert_equal ( t, 0.)
48             assert_equal ( s.norm, 0.)
49             try:
50                 assert_equal ( s.phas, 0 )
51             except AssertionError:
52                 assert_equal (s.phas[s.phas > 0], +np.pi)
53                 assert_equal (s.phas[s.phas < 0], -np.pi)
54                 assert_equal (np.abs(s.phas[np.abs(s.phas) != np.pi]), 0)
55                 self.skipTest('pvoc(fvec(%d)).phas != +0, ' % win_s \
56                         + 'This is expected when using fftw3 on powerpc.')
57             assert_equal ( r, 0.)
58
59     @params(
60             ( 256, 8),
61             ( 256, 4),
62             ( 256, 2),
63             ( 512, 8),
64             ( 512, 4),
65             ( 512, 2),
66             #( 129, 2),
67             #( 320, 4),
68             #(  13, 8),
69             (1024, 8),
70             (1024, 4),
71             (1024, 2),
72             (2048, 8),
73             (2048, 4),
74             (2048, 2),
75             (4096, 8),
76             (4096, 4),
77             (4096, 2),
78             (8192, 8),
79             (8192, 4),
80             (8192, 2),
81             )
82     def test_resynth_steps_noise(self, hop_s, ratio):
83         """ check the resynthesis of a random signal is correct """
84         sigin = create_noise(hop_s)
85         self.reconstruction(sigin, hop_s, ratio)
86
87     @params(
88             (44100,  256, 8,   441),
89             (44100,  256, 4,  1203),
90             (44100,  256, 2,  3045),
91             (44100,  512, 8,   445),
92             (44100,  512, 4,   445),
93             (44100,  512, 2,   445),
94             (44100, 1024, 8,   445),
95             (44100, 1024, 4,   445),
96             (44100, 1024, 2,   445),
97             ( 8000, 1024, 2,   445),
98             (22050, 1024, 2,   445),
99             (22050,  256, 8,   445),
100             (96000, 1024, 8, 47000),
101             (96000, 1024, 8,    20),
102             )
103     def test_resynth_steps_sine(self, samplerate, hop_s, ratio, freq):
104         """ check the resynthesis of a sine is correct """
105         sigin = create_sine(hop_s, freq, samplerate)
106         self.reconstruction(sigin, hop_s, ratio)
107
108     def reconstruction(self, sigin, hop_s, ratio):
109         buf_s = hop_s * ratio
110         f = pvoc(buf_s, hop_s)
111         zeros = fvec(hop_s)
112         r2 = f.rdo( f(sigin) )
113         for _ in range(1, ratio):
114             r2 = f.rdo( f(zeros) )
115         # compute square errors
116         sq_error = (r2 - sigin)**2
117         # make sure all square errors are less than desired precision
118         assert_array_less(sq_error, max_sq_error)
119
120 class aubio_pvoc_strange_params(TestCase):
121
122     def test_win_size_short(self):
123         with self.assertRaises(RuntimeError):
124             pvoc(1, 1)
125
126     def test_hop_size_long(self):
127         with self.assertRaises(RuntimeError):
128             pvoc(1024, 1025)
129
130     def test_large_input_timegrain(self):
131         win_s = 1024
132         f = pvoc(win_s)
133         t = fvec(win_s + 1)
134         with self.assertRaises(ValueError):
135             f(t)
136
137     def test_small_input_timegrain(self):
138         win_s = 1024
139         f = pvoc(win_s)
140         t = fvec(1)
141         with self.assertRaises(ValueError):
142             f(t)
143
144     def test_large_input_fftgrain(self):
145         win_s = 1024
146         f = pvoc(win_s)
147         s = cvec(win_s + 5)
148         with self.assertRaises(ValueError):
149             f.rdo(s)
150
151     def test_small_input_fftgrain(self):
152         win_s = 1024
153         f = pvoc(win_s)
154         s = cvec(16)
155         with self.assertRaises(ValueError):
156             f.rdo(s)
157
158 class aubio_pvoc_wrong_params(TestCase):
159
160     def test_wrong_buf_size(self):
161         win_s = -1
162         with self.assertRaises(ValueError):
163             pvoc(win_s)
164
165     def test_buf_size_too_small(self):
166         win_s = 1
167         with self.assertRaises(RuntimeError):
168             pvoc(win_s)
169
170     def test_hop_size_negative(self):
171         win_s = 512
172         hop_s = -2
173         with self.assertRaises(ValueError):
174             pvoc(win_s, hop_s)
175
176     def test_hop_size_too_small(self):
177         win_s = 1
178         hop_s = 1
179         with self.assertRaises(RuntimeError):
180             pvoc(win_s, hop_s)
181
182     def test_buf_size_not_power_of_two(self):
183         win_s = 320
184         hop_s = win_s // 2
185         try:
186             with self.assertRaises(RuntimeError):
187                 pvoc(win_s, hop_s)
188         except AssertionError:
189             # when compiled with fftw3, aubio supports non power of two fft sizes
190             self.skipTest('creating aubio.pvoc with size %d did not fail' % win_s)
191
192 if __name__ == '__main__':
193     main()
194