summaryrefslogtreecommitdiff
path: root/python/tests/test_phasevoc.py
blob: 957d3b1a4d206c92c657edfc697ad6e22106a202 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#! /usr/bin/env python

from numpy.testing import TestCase, assert_equal, assert_array_less
from aubio import fvec, cvec, pvoc, float_type
from nose2 import main
from nose2.tools import params
import numpy as np

if float_type == 'float32':
    max_sq_error = 1.e-12
else:
    max_sq_error = 1.e-29

def create_sine(hop_s, freq, samplerate):
    t = np.arange(hop_s).astype(float_type)
    return np.sin( 2. * np.pi * freq * t / float(samplerate))

def create_noise(hop_s):
    return np.random.rand(hop_s).astype(float_type) * 2. - 1.

class aubio_pvoc_test_case(TestCase):
    """ pvoc object test case """

    def test_members_automatic_sizes_default(self):
        """ check object creation with default parameters """
        f = pvoc()
        assert_equal ([f.win_s, f.hop_s], [1024, 512])

    def test_members_unnamed_params(self):
        """ check object creation with unnamed parameters """
        f = pvoc(2048, 128)
        assert_equal ([f.win_s, f.hop_s], [2048, 128])

    def test_members_named_params(self):
        """ check object creation with named parameters """
        f = pvoc(hop_s = 128, win_s = 2048)
        assert_equal ([f.win_s, f.hop_s], [2048, 128])

    def test_zeros(self):
        """ check the resynthesis of zeros gives zeros """
        win_s, hop_s = 1024, 256
        f = pvoc (win_s, hop_s)
        t = fvec (hop_s)
        for _ in range( int ( 4 * win_s / hop_s ) ):
            s = f(t)
            r = f.rdo(s)
            assert_equal ( t, 0.)
            assert_equal ( s.norm, 0.)
            try:
                assert_equal ( s.phas, 0 )
            except AssertionError:
                assert_equal (s.phas[s.phas > 0], +np.pi)
                assert_equal (s.phas[s.phas < 0], -np.pi)
                assert_equal (np.abs(s.phas[np.abs(s.phas) != np.pi]), 0)
                self.skipTest('pvoc(fvec(%d)).phas != +0, ' % win_s \
                        + 'This is expected when using fftw3 on powerpc.')
            assert_equal ( r, 0.)

    @params(
            ( 256, 8),
            ( 256, 4),
            ( 256, 2),
            ( 512, 8),
            ( 512, 4),
            ( 512, 2),
            #( 129, 2),
            #( 320, 4),
            #(  13, 8),
            (1024, 8),
            (1024, 4),
            (1024, 2),
            (2048, 8),
            (2048, 4),
            (2048, 2),
            (4096, 8),
            (4096, 4),
            (4096, 2),
            (8192, 8),
            (8192, 4),
            (8192, 2),
            )
    def test_resynth_steps_noise(self, hop_s, ratio):
        """ check the resynthesis of a random signal is correct """
        sigin = create_noise(hop_s)
        self.reconstruction(sigin, hop_s, ratio)

    @params(
            (44100,  256, 8,   441),
            (44100,  256, 4,  1203),
            (44100,  256, 2,  3045),
            (44100,  512, 8,   445),
            (44100,  512, 4,   445),
            (44100,  512, 2,   445),
            (44100, 1024, 8,   445),
            (44100, 1024, 4,   445),
            (44100, 1024, 2,   445),
            ( 8000, 1024, 2,   445),
            (22050, 1024, 2,   445),
            (22050,  256, 8,   445),
            (96000, 1024, 8, 47000),
            (96000, 1024, 8,    20),
            )
    def test_resynth_steps_sine(self, samplerate, hop_s, ratio, freq):
        """ check the resynthesis of a sine is correct """
        sigin = create_sine(hop_s, freq, samplerate)
        self.reconstruction(sigin, hop_s, ratio)

    def reconstruction(self, sigin, hop_s, ratio):
        buf_s = hop_s * ratio
        f = pvoc(buf_s, hop_s)
        zeros = fvec(hop_s)
        r2 = f.rdo( f(sigin) )
        for _ in range(1, ratio):
            r2 = f.rdo( f(zeros) )
        # compute square errors
        sq_error = (r2 - sigin)**2
        # make sure all square errors are less than desired precision
        assert_array_less(sq_error, max_sq_error)

class aubio_pvoc_strange_params(TestCase):

    def test_win_size_short(self):
        with self.assertRaises(RuntimeError):
            pvoc(1, 1)

    def test_hop_size_long(self):
        with self.assertRaises(RuntimeError):
            pvoc(1024, 1025)

    def test_large_input_timegrain(self):
        win_s = 1024
        f = pvoc(win_s)
        t = fvec(win_s + 1)
        with self.assertRaises(ValueError):
            f(t)

    def test_small_input_timegrain(self):
        win_s = 1024
        f = pvoc(win_s)
        t = fvec(1)
        with self.assertRaises(ValueError):
            f(t)

    def test_large_input_fftgrain(self):
        win_s = 1024
        f = pvoc(win_s)
        s = cvec(win_s + 5)
        with self.assertRaises(ValueError):
            f.rdo(s)

    def test_small_input_fftgrain(self):
        win_s = 1024
        f = pvoc(win_s)
        s = cvec(16)
        with self.assertRaises(ValueError):
            f.rdo(s)

class aubio_pvoc_wrong_params(TestCase):

    def test_wrong_buf_size(self):
        win_s = -1
        with self.assertRaises(ValueError):
            pvoc(win_s)

    def test_buf_size_too_small(self):
        win_s = 1
        with self.assertRaises(RuntimeError):
            pvoc(win_s)

    def test_hop_size_negative(self):
        win_s = 512
        hop_s = -2
        with self.assertRaises(ValueError):
            pvoc(win_s, hop_s)

    def test_hop_size_too_small(self):
        win_s = 1
        hop_s = 1
        with self.assertRaises(RuntimeError):
            pvoc(win_s, hop_s)

    def test_buf_size_not_power_of_two(self):
        win_s = 320
        hop_s = win_s // 2
        try:
            with self.assertRaises(RuntimeError):
                pvoc(win_s, hop_s)
        except AssertionError:
            # when compiled with fftw3, aubio supports non power of two fft sizes
            self.skipTest('creating aubio.pvoc with size %d did not fail' % win_s)

if __name__ == '__main__':
    main()