[tests] run phase vocoder with hop_s = win_s
[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     def test_no_overlap(self):
60         win_s, hop_s = 1024, 1024
61         f = pvoc (win_s, hop_s)
62         t = fvec (hop_s)
63         for _ in range(4):
64             s = f(t)
65             r = f.rdo(s)
66             assert_equal ( t, 0.)
67
68     @params(
69             ( 256, 8),
70             ( 256, 4),
71             ( 256, 2),
72             ( 512, 8),
73             ( 512, 4),
74             ( 512, 2),
75             #( 129, 2),
76             #( 320, 4),
77             #(  13, 8),
78             (1024, 8),
79             (1024, 4),
80             (1024, 2),
81             (2048, 8),
82             (2048, 4),
83             (2048, 2),
84             (4096, 8),
85             (4096, 4),
86             (4096, 2),
87             (8192, 8),
88             (8192, 4),
89             (8192, 2),
90             )
91     def test_resynth_steps_noise(self, hop_s, ratio):
92         """ check the resynthesis of a random signal is correct """
93         sigin = create_noise(hop_s)
94         self.reconstruction(sigin, hop_s, ratio)
95
96     @params(
97             (44100,  256, 8,   441),
98             (44100,  256, 4,  1203),
99             (44100,  256, 2,  3045),
100             (44100,  512, 8,   445),
101             (44100,  512, 4,   445),
102             (44100,  512, 2,   445),
103             (44100, 1024, 8,   445),
104             (44100, 1024, 4,   445),
105             (44100, 1024, 2,   445),
106             ( 8000, 1024, 2,   445),
107             (22050, 1024, 2,   445),
108             (22050,  256, 8,   445),
109             (96000, 1024, 8, 47000),
110             (96000, 1024, 8,    20),
111             )
112     def test_resynth_steps_sine(self, samplerate, hop_s, ratio, freq):
113         """ check the resynthesis of a sine is correct """
114         sigin = create_sine(hop_s, freq, samplerate)
115         self.reconstruction(sigin, hop_s, ratio)
116
117     def reconstruction(self, sigin, hop_s, ratio):
118         buf_s = hop_s * ratio
119         f = pvoc(buf_s, hop_s)
120         zeros = fvec(hop_s)
121         r2 = f.rdo( f(sigin) )
122         for _ in range(1, ratio):
123             r2 = f.rdo( f(zeros) )
124         # compute square errors
125         sq_error = (r2 - sigin)**2
126         # make sure all square errors are less than desired precision
127         assert_array_less(sq_error, max_sq_error)
128
129 class aubio_pvoc_strange_params(TestCase):
130
131     def test_win_size_short(self):
132         with self.assertRaises(RuntimeError):
133             pvoc(1, 1)
134
135     def test_hop_size_long(self):
136         with self.assertRaises(RuntimeError):
137             pvoc(1024, 1025)
138
139     def test_large_input_timegrain(self):
140         win_s = 1024
141         f = pvoc(win_s)
142         t = fvec(win_s + 1)
143         with self.assertRaises(ValueError):
144             f(t)
145
146     def test_small_input_timegrain(self):
147         win_s = 1024
148         f = pvoc(win_s)
149         t = fvec(1)
150         with self.assertRaises(ValueError):
151             f(t)
152
153     def test_large_input_fftgrain(self):
154         win_s = 1024
155         f = pvoc(win_s)
156         s = cvec(win_s + 5)
157         with self.assertRaises(ValueError):
158             f.rdo(s)
159
160     def test_small_input_fftgrain(self):
161         win_s = 1024
162         f = pvoc(win_s)
163         s = cvec(16)
164         with self.assertRaises(ValueError):
165             f.rdo(s)
166
167 class aubio_pvoc_wrong_params(TestCase):
168
169     def test_wrong_buf_size(self):
170         win_s = -1
171         with self.assertRaises(ValueError):
172             pvoc(win_s)
173
174     def test_buf_size_too_small(self):
175         win_s = 1
176         with self.assertRaises(RuntimeError):
177             pvoc(win_s)
178
179     def test_hop_size_negative(self):
180         win_s = 512
181         hop_s = -2
182         with self.assertRaises(ValueError):
183             pvoc(win_s, hop_s)
184
185     def test_hop_size_too_small(self):
186         win_s = 1
187         hop_s = 1
188         with self.assertRaises(RuntimeError):
189             pvoc(win_s, hop_s)
190
191     def test_buf_size_not_power_of_two(self):
192         win_s = 320
193         hop_s = win_s // 2
194         try:
195             with self.assertRaises(RuntimeError):
196                 pvoc(win_s, hop_s)
197         except AssertionError:
198             # when compiled with fftw3, aubio supports non power of two fft sizes
199             self.skipTest('creating aubio.pvoc with size %d did not fail' % win_s)
200
201 if __name__ == '__main__':
202     main()
203