Chris@61
|
1
|
Chris@61
|
2 import vamp
|
Chris@61
|
3 import numpy as np
|
Chris@61
|
4
|
Chris@61
|
5 testPluginKey = "vamp-test-plugin:vamp-test-plugin"
|
Chris@66
|
6 testPluginKeyFreq = "vamp-test-plugin:vamp-test-plugin-freq"
|
Chris@61
|
7
|
Chris@61
|
8 rate = 44100
|
Chris@61
|
9
|
Chris@68
|
10 # Throughout this file we have the assumption that the plugin gets run with a
|
Chris@68
|
11 # blocksize of 1024, and with a step of 1024 for the time-domain version or 512
|
Chris@68
|
12 # for the frequency-domain one. That is certainly expected to be the norm for a
|
Chris@68
|
13 # plugin like this that declares no preference, and the Python Vamp module is
|
Chris@68
|
14 # expected to follow the norm
|
Chris@66
|
15
|
Chris@68
|
16 blocksize = 1024
|
Chris@68
|
17
|
Chris@68
|
18 def input_data(n):
|
Chris@68
|
19 # start at 1, not 0 so that all elts are non-zero
|
Chris@68
|
20 return np.arange(n) + 1
|
Chris@68
|
21
|
Chris@68
|
22 def test_process_n():
|
Chris@68
|
23 buf = input_data(blocksize)
|
Chris@68
|
24 results = list(vamp.process(buf, rate, testPluginKey, {}, [ "input-summary" ]))
|
Chris@68
|
25 assert len(results) == 1
|
Chris@68
|
26
|
Chris@68
|
27 def test_process_freq_n():
|
Chris@68
|
28 buf = input_data(blocksize)
|
Chris@68
|
29 results = list(vamp.process(buf, rate, testPluginKeyFreq, {}, [ "input-summary" ]))
|
Chris@68
|
30 assert len(results) == 2 # one complete block starting at zero, one half-full
|
Chris@68
|
31
|
Chris@74
|
32 def test_process_default_output():
|
Chris@74
|
33 # If no output is specified, we should get the first one (instants)
|
Chris@74
|
34 buf = input_data(blocksize)
|
Chris@74
|
35 results = list(vamp.process(buf, rate, testPluginKey, {}, []))
|
Chris@74
|
36 assert len(results) == 10
|
Chris@74
|
37 for i in range(len(results)):
|
Chris@74
|
38 expectedTime = vamp.vampyhost.RealTime('seconds', i * 1.5)
|
Chris@74
|
39 actualTime = results[i]["instants"]["timestamp"]
|
Chris@74
|
40 assert expectedTime == actualTime
|
Chris@74
|
41
|
Chris@68
|
42 def test_process_summary_param():
|
Chris@68
|
43 buf = input_data(blocksize * 10)
|
Chris@68
|
44 results = list(vamp.process(buf, rate, testPluginKey, { "produce_output": 0 }, [ "input-summary" ]))
|
Chris@68
|
45 assert len(results) == 0
|
Chris@68
|
46
|
Chris@68
|
47 def test_process_summary_param_bool():
|
Chris@68
|
48 buf = input_data(blocksize * 10)
|
Chris@68
|
49 results = list(vamp.process(buf, rate, testPluginKey, { "produce_output": False }, [ "input-summary" ]))
|
Chris@68
|
50 assert len(results) == 0
|
Chris@68
|
51
|
Chris@68
|
52 def test_process_summary():
|
Chris@68
|
53 buf = input_data(blocksize * 10)
|
Chris@68
|
54 results = list(vamp.process(buf, rate, testPluginKey, {}, [ "input-summary" ]))
|
Chris@68
|
55 assert len(results) == 10
|
Chris@68
|
56 for i in range(len(results)):
|
Chris@69
|
57 #
|
Chris@68
|
58 # each feature has a single value, equal to the number of non-zero elts
|
Chris@68
|
59 # in the input block (which is all of them, i.e. the blocksize) plus
|
Chris@68
|
60 # the first elt (which is i * blockSize + 1)
|
Chris@69
|
61 #
|
Chris@68
|
62 expected = blocksize + i * blocksize + 1
|
Chris@70
|
63 actual = results[i]["input-summary"]["values"][0]
|
Chris@68
|
64 assert actual == expected
|
Chris@68
|
65
|
Chris@68
|
66 def test_process_freq_summary():
|
Chris@68
|
67 buf = input_data(blocksize * 10)
|
Chris@68
|
68 results = list(vamp.process(buf, rate, testPluginKeyFreq, {}, [ "input-summary" ]))
|
Chris@68
|
69 assert len(results) == 20
|
Chris@68
|
70 for i in range(len(results)):
|
Chris@68
|
71 #
|
Chris@68
|
72 # sort of as above, but much much subtler:
|
Chris@68
|
73 #
|
Chris@68
|
74 # * the input block is converted to frequency domain but then converted
|
Chris@68
|
75 # back within the plugin, so the values being reported are time-domain
|
Chris@68
|
76 # ones but with windowing and FFT shift
|
Chris@68
|
77 #
|
Chris@68
|
78 # * the effect of FFT shift is that the first element in the
|
Chris@68
|
79 # re-converted frame is actually the one that was at the start of the
|
Chris@68
|
80 # second half of the original frame
|
Chris@68
|
81 #
|
Chris@68
|
82 # * and the last block is only half-full, so the "first" elt in that
|
Chris@68
|
83 # one, which actually comes from just after the middle of the block,
|
Chris@68
|
84 # will be zero
|
Chris@68
|
85 #
|
Chris@68
|
86 # * windowing does not affect the value of the first elt, because
|
Chris@68
|
87 # (before fft shift) it came from the peak of the window shape where
|
Chris@68
|
88 # the window value is 1
|
Chris@68
|
89 #
|
Chris@68
|
90 # * but windowing does affect the number of non-zero elts, because the
|
Chris@68
|
91 # asymmetric window used has one value very close to zero in it
|
Chris@68
|
92 #
|
Chris@68
|
93 # * the step size (the increment in input value from one block to the
|
Chris@68
|
94 # next) is only half the block size
|
Chris@68
|
95 #
|
Chris@68
|
96 expected = i * (blocksize/2) + blocksize/2 + 1 # "first" elt
|
Chris@68
|
97 if (i == len(results)-1):
|
Chris@68
|
98 expected = 0
|
Chris@68
|
99 expected = expected + blocksize - 1 # non-zero elts
|
Chris@70
|
100 actual = results[i]["input-summary"]["values"][0]
|
Chris@68
|
101 eps = 1e-6
|
Chris@68
|
102 assert abs(actual - expected) < eps
|
Chris@68
|
103
|
Chris@69
|
104 def test_process_timestamps():
|
Chris@69
|
105 buf = input_data(blocksize * 10)
|
Chris@69
|
106 results = list(vamp.process(buf, rate, testPluginKey, {}, [ "input-timestamp" ]))
|
Chris@69
|
107 assert len(results) == 10
|
Chris@69
|
108 for i in range(len(results)):
|
Chris@69
|
109 # The timestamp should be the frame number of the first frame in the
|
Chris@69
|
110 # input buffer
|
Chris@69
|
111 expected = i * blocksize
|
Chris@70
|
112 actual = results[i]["input-timestamp"]["values"][0]
|
Chris@69
|
113 assert actual == expected
|
Chris@69
|
114
|
Chris@69
|
115 def test_process_freq_timestamps():
|
Chris@69
|
116 buf = input_data(blocksize * 10)
|
Chris@69
|
117 results = list(vamp.process(buf, rate, testPluginKeyFreq, {}, [ "input-timestamp" ]))
|
Chris@69
|
118 assert len(results) == 20
|
Chris@69
|
119 for i in range(len(results)):
|
Chris@69
|
120 # The timestamp should be the frame number of the frame just beyond
|
Chris@69
|
121 # half-way through the input buffer
|
Chris@69
|
122 expected = i * (blocksize/2) + blocksize/2
|
Chris@70
|
123 actual = results[i]["input-timestamp"]["values"][0]
|
Chris@69
|
124 assert actual == expected
|
Chris@74
|
125
|
Chris@74
|
126 def test_process_multiple_outputs():
|
Chris@74
|
127 buf = input_data(blocksize * 10)
|
Chris@74
|
128 results = list(vamp.process(buf, rate, testPluginKey, {}, [ "input-summary", "input-timestamp" ]))
|
Chris@74
|
129 assert len(results) == 20
|
Chris@74
|
130 si = 0
|
Chris@74
|
131 ti = 0
|
Chris@74
|
132 for r in results:
|
Chris@74
|
133 assert "input-summary" in r or "input-timestamp" in r
|
Chris@74
|
134 if "input-summary" in r:
|
Chris@74
|
135 expected = blocksize + si * blocksize + 1
|
Chris@74
|
136 actual = r["input-summary"]["values"][0]
|
Chris@74
|
137 assert actual == expected
|
Chris@74
|
138 si = si + 1
|
Chris@74
|
139 if "input-timestamp" in r:
|
Chris@74
|
140 expected = ti * blocksize
|
Chris@74
|
141 actual = r["input-timestamp"]["values"][0]
|
Chris@74
|
142 assert actual == expected
|
Chris@74
|
143 ti = ti + 1
|