Chris@61: Chris@61: import vamp Chris@61: import numpy as np Chris@61: Chris@61: testPluginKey = "vamp-test-plugin:vamp-test-plugin" Chris@66: testPluginKeyFreq = "vamp-test-plugin:vamp-test-plugin-freq" Chris@61: Chris@61: rate = 44100 Chris@61: Chris@68: # Throughout this file we have the assumption that the plugin gets run with a Chris@68: # blocksize of 1024, and with a step of 1024 for the time-domain version or 512 Chris@68: # for the frequency-domain one. That is certainly expected to be the norm for a Chris@68: # plugin like this that declares no preference, and the Python Vamp module is Chris@68: # expected to follow the norm Chris@66: Chris@68: blocksize = 1024 Chris@68: Chris@68: def input_data(n): Chris@68: # start at 1, not 0 so that all elts are non-zero Chris@68: return np.arange(n) + 1 Chris@68: Chris@68: def test_process_n(): Chris@68: buf = input_data(blocksize) Chris@68: results = list(vamp.process(buf, rate, testPluginKey, {}, [ "input-summary" ])) Chris@68: assert len(results) == 1 Chris@68: Chris@68: def test_process_freq_n(): Chris@68: buf = input_data(blocksize) Chris@68: results = list(vamp.process(buf, rate, testPluginKeyFreq, {}, [ "input-summary" ])) Chris@68: assert len(results) == 2 # one complete block starting at zero, one half-full Chris@68: Chris@68: def test_process_summary_param(): Chris@68: buf = input_data(blocksize * 10) Chris@68: results = list(vamp.process(buf, rate, testPluginKey, { "produce_output": 0 }, [ "input-summary" ])) Chris@68: assert len(results) == 0 Chris@68: Chris@68: def test_process_summary_param_bool(): Chris@68: buf = input_data(blocksize * 10) Chris@68: results = list(vamp.process(buf, rate, testPluginKey, { "produce_output": False }, [ "input-summary" ])) Chris@68: assert len(results) == 0 Chris@68: Chris@68: def test_process_summary(): Chris@68: buf = input_data(blocksize * 10) Chris@68: results = list(vamp.process(buf, rate, testPluginKey, {}, [ "input-summary" ])) Chris@68: assert len(results) == 10 Chris@68: for i in range(len(results)): Chris@69: # Chris@68: # each feature has a single value, equal to the number of non-zero elts Chris@68: # in the input block (which is all of them, i.e. the blocksize) plus Chris@68: # the first elt (which is i * blockSize + 1) Chris@69: # Chris@68: expected = blocksize + i * blocksize + 1 Chris@70: actual = results[i]["input-summary"]["values"][0] Chris@68: assert actual == expected Chris@68: Chris@68: def test_process_freq_summary(): Chris@68: buf = input_data(blocksize * 10) Chris@68: results = list(vamp.process(buf, rate, testPluginKeyFreq, {}, [ "input-summary" ])) Chris@68: assert len(results) == 20 Chris@68: for i in range(len(results)): Chris@68: # Chris@68: # sort of as above, but much much subtler: Chris@68: # Chris@68: # * the input block is converted to frequency domain but then converted Chris@68: # back within the plugin, so the values being reported are time-domain Chris@68: # ones but with windowing and FFT shift Chris@68: # Chris@68: # * the effect of FFT shift is that the first element in the Chris@68: # re-converted frame is actually the one that was at the start of the Chris@68: # second half of the original frame Chris@68: # Chris@68: # * and the last block is only half-full, so the "first" elt in that Chris@68: # one, which actually comes from just after the middle of the block, Chris@68: # will be zero Chris@68: # Chris@68: # * windowing does not affect the value of the first elt, because Chris@68: # (before fft shift) it came from the peak of the window shape where Chris@68: # the window value is 1 Chris@68: # Chris@68: # * but windowing does affect the number of non-zero elts, because the Chris@68: # asymmetric window used has one value very close to zero in it Chris@68: # Chris@68: # * the step size (the increment in input value from one block to the Chris@68: # next) is only half the block size Chris@68: # Chris@68: expected = i * (blocksize/2) + blocksize/2 + 1 # "first" elt Chris@68: if (i == len(results)-1): Chris@68: expected = 0 Chris@68: expected = expected + blocksize - 1 # non-zero elts Chris@70: actual = results[i]["input-summary"]["values"][0] Chris@68: eps = 1e-6 Chris@68: assert abs(actual - expected) < eps Chris@68: Chris@69: def test_process_timestamps(): Chris@69: buf = input_data(blocksize * 10) Chris@69: results = list(vamp.process(buf, rate, testPluginKey, {}, [ "input-timestamp" ])) Chris@69: assert len(results) == 10 Chris@69: for i in range(len(results)): Chris@69: # The timestamp should be the frame number of the first frame in the Chris@69: # input buffer Chris@69: expected = i * blocksize Chris@70: actual = results[i]["input-timestamp"]["values"][0] Chris@69: assert actual == expected Chris@69: Chris@69: def test_process_freq_timestamps(): Chris@69: buf = input_data(blocksize * 10) Chris@69: results = list(vamp.process(buf, rate, testPluginKeyFreq, {}, [ "input-timestamp" ])) Chris@69: assert len(results) == 20 Chris@69: for i in range(len(results)): Chris@69: # The timestamp should be the frame number of the frame just beyond Chris@69: # half-way through the input buffer Chris@69: expected = i * (blocksize/2) + blocksize/2 Chris@70: actual = results[i]["input-timestamp"]["values"][0] Chris@69: print("actual = " + str(actual) + ", expected = " + str(expected)) Chris@69: assert actual == expected