annotate test/test_process.py @ 74:78a4034c3830

Multi-output features & start on feature select/timestamp/collect
author Chris Cannam
date Wed, 21 Jan 2015 11:08:29 +0000
parents cb0380c92c42
children b2afd385586f
rev   line source
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