Chris@61: Chris@61: import vamp Chris@61: import numpy as np Chris@98: import vamp.frames as fr Chris@61: Chris@82: plugin_key = "vamp-test-plugin:vamp-test-plugin" Chris@82: plugin_key_freq = "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@76: # 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@112: results = list(vamp.process_audio(buf, rate, plugin_key, "input-summary")) Chris@68: assert len(results) == 1 Chris@68: Chris@68: def test_process_freq_n(): Chris@68: buf = input_data(blocksize) Chris@112: results = list(vamp.process_audio(buf, rate, plugin_key_freq, "input-summary", {})) Chris@68: assert len(results) == 2 # one complete block starting at zero, one half-full Chris@68: Chris@74: def test_process_default_output(): Chris@74: # If no output is specified, we should get the first one (instants) Chris@74: buf = input_data(blocksize) Chris@112: results = list(vamp.process_audio(buf, rate, plugin_key, "", {})) Chris@74: assert len(results) == 10 Chris@74: for i in range(len(results)): Chris@74: expectedTime = vamp.vampyhost.RealTime('seconds', i * 1.5) Chris@76: actualTime = results[i]["timestamp"] Chris@74: assert expectedTime == actualTime Chris@76: Chris@68: def test_process_summary_param(): Chris@68: buf = input_data(blocksize * 10) Chris@112: results = list(vamp.process_audio(buf, rate, plugin_key, "input-summary", { "produce_output": 0 })) Chris@76: assert len(results) == 0 Chris@76: Chris@76: def test_process_multi_summary_param(): Chris@76: buf = input_data(blocksize * 10) Chris@117: results = list(vamp.process_audio_multiple_outputs(buf, rate, plugin_key, [ "input-summary" ], { "produce_output": 0 })) Chris@68: assert len(results) == 0 Chris@68: Chris@68: def test_process_summary_param_bool(): Chris@68: buf = input_data(blocksize * 10) Chris@112: results = list(vamp.process_audio(buf, rate, plugin_key, "input-summary", { "produce_output": False })) Chris@76: assert len(results) == 0 Chris@76: Chris@76: def test_process_multi_summary_param_bool(): Chris@76: buf = input_data(blocksize * 10) Chris@117: results = list(vamp.process_audio_multiple_outputs(buf, rate, plugin_key, [ "input-summary" ], { "produce_output": False })) Chris@68: assert len(results) == 0 Chris@68: Chris@68: def test_process_summary(): Chris@68: buf = input_data(blocksize * 10) Chris@112: results = list(vamp.process_audio(buf, rate, plugin_key, "input-summary", {})) Chris@76: assert len(results) == 10 Chris@76: for i in range(len(results)): Chris@76: # Chris@76: # each feature has a single value, equal to the number of non-zero elts Chris@76: # in the input block (which is all of them, i.e. the blocksize) plus Chris@76: # the first elt (which is i * blockSize + 1) Chris@76: # Chris@76: expected = blocksize + i * blocksize + 1 Chris@76: actual = results[i]["values"][0] Chris@76: assert actual == expected Chris@76: Chris@101: def test_process_frames_summary(): Chris@98: buf = input_data(blocksize * 10) Chris@98: ff = fr.frames_from_array(buf, blocksize, blocksize) Chris@98: results = list(vamp.process_frames(ff, rate, blocksize, plugin_key, "input-summary", {})) Chris@98: assert len(results) == 10 Chris@98: for i in range(len(results)): Chris@98: # Chris@98: # each feature has a single value, equal to the number of non-zero elts Chris@98: # in the input block (which is all of them, i.e. the blocksize) plus Chris@98: # the first elt (which is i * blockSize + 1) Chris@98: # Chris@98: expected = blocksize + i * blocksize + 1 Chris@98: actual = results[i]["values"][0] Chris@98: assert actual == expected Chris@98: Chris@76: def test_process_multi_summary(): Chris@76: buf = input_data(blocksize * 10) Chris@117: results = list(vamp.process_audio_multiple_outputs(buf, rate, plugin_key, [ "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@101: def test_process_frames_multi_summary(): Chris@100: buf = input_data(blocksize * 10) Chris@100: ff = fr.frames_from_array(buf, blocksize, blocksize) Chris@100: results = list(vamp.process_frames_multiple_outputs(ff, rate, blocksize, plugin_key, [ "input-summary" ], {})) Chris@100: assert len(results) == 10 Chris@100: for i in range(len(results)): Chris@100: # Chris@100: # each feature has a single value, equal to the number of non-zero elts Chris@100: # in the input block (which is all of them, i.e. the blocksize) plus Chris@100: # the first elt (which is i * blockSize + 1) Chris@100: # Chris@100: expected = blocksize + i * blocksize + 1 Chris@100: actual = results[i]["input-summary"]["values"][0] Chris@100: assert actual == expected Chris@100: Chris@68: def test_process_freq_summary(): Chris@68: buf = input_data(blocksize * 10) Chris@112: results = list(vamp.process_audio(buf, rate, plugin_key_freq, "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@76: actual = results[i]["values"][0] Chris@76: eps = 1e-6 Chris@76: assert abs(actual - expected) < eps Chris@76: Chris@140: def test_process_freq_summary_shift(): Chris@140: buf = input_data(blocksize * 10) Chris@140: results = list(vamp.process_audio(buf, rate, plugin_key_freq, "input-summary", {}, process_timestamp_method = vamp.vampyhost.SHIFT_DATA)) Chris@140: assert len(results) == 20 Chris@140: for i in range(len(results)): Chris@140: # as test_process_freq_summary, except that the input is effectively Chris@140: # padded by the adapter with an additional half-blocksize of zeros Chris@140: # before conversion Chris@140: if i == 0: Chris@140: # this block doesn't interact at all well with our test, we get Chris@140: # spurious low values in the block converted back within the plugin Chris@140: # because of the big discontinuity & window ripple after fftshift Chris@140: pass Chris@140: else: Chris@140: expected = (i-1) * (blocksize/2) + blocksize/2 + 1 # for "first" elt Chris@140: expected = expected + blocksize - 1 # non-zero elts Chris@140: actual = results[i]["values"][0] Chris@140: eps = 1e-6 Chris@140: assert abs(actual - expected) < eps Chris@140: Chris@76: def test_process_multi_freq_summary(): Chris@76: buf = input_data(blocksize * 10) Chris@117: results = list(vamp.process_audio_multiple_outputs(buf, rate, plugin_key_freq, [ "input-summary" ], {})) Chris@76: assert len(results) == 20 Chris@76: for i in range(len(results)): Chris@76: expected = i * (blocksize/2) + blocksize/2 + 1 # "first" elt Chris@76: if (i == len(results)-1): Chris@76: expected = 0 Chris@76: 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@112: results = list(vamp.process_audio(buf, rate, plugin_key, "input-timestamp", {})) Chris@76: assert len(results) == 10 Chris@76: for i in range(len(results)): Chris@76: # The timestamp should be the frame number of the first frame in the Chris@76: # input buffer Chris@76: expected = i * blocksize Chris@76: actual = results[i]["values"][0] Chris@76: assert actual == expected Chris@76: Chris@76: def test_process_multi_timestamps(): Chris@76: buf = input_data(blocksize * 10) Chris@117: results = list(vamp.process_audio_multiple_outputs(buf, rate, plugin_key, [ "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@112: results = list(vamp.process_audio(buf, rate, plugin_key_freq, "input-timestamp", {})) Chris@76: assert len(results) == 20 Chris@76: for i in range(len(results)): Chris@76: # The timestamp should be the frame number of the frame just beyond Chris@76: # half-way through the input buffer Chris@76: expected = i * (blocksize/2) + blocksize/2 Chris@76: actual = results[i]["values"][0] Chris@116: if actual == 2047 and expected == 2048: Chris@116: print("This test fails because of a bug in the Vamp plugin SDK. Please update to SDK version 2.6.") Chris@76: assert actual == expected Chris@76: Chris@142: def test_process_freq_shift_timestamps(): Chris@142: buf = input_data(blocksize * 10) Chris@142: results = list(vamp.process_audio(buf, rate, plugin_key_freq, "input-timestamp", process_timestamp_method = vamp.vampyhost.SHIFT_DATA)) Chris@142: assert len(results) == 20 Chris@142: for i in range(len(results)): Chris@142: # The timestamp should be the frame number of the frame at the start of Chris@142: # the input buffer Chris@142: expected = i * (blocksize/2) Chris@142: actual = results[i]["values"][0] Chris@142: if actual == 2047 and expected == 2048: Chris@142: print("This test fails because of a bug in the Vamp plugin SDK. Please update to SDK version 2.6.") Chris@142: assert actual == expected Chris@142: Chris@76: def test_process_multi_freq_timestamps(): Chris@76: buf = input_data(blocksize * 10) Chris@117: results = list(vamp.process_audio_multiple_outputs(buf, rate, plugin_key_freq, [ "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@116: if actual == 2047 and expected == 2048: Chris@116: print("This test fails because of a bug in the Vamp plugin SDK. Please update to SDK version 2.6.") Chris@69: assert actual == expected Chris@74: Chris@142: def test_process_blocksize_timestamps(): Chris@142: buf = input_data(blocksize * 10) Chris@142: results = list(vamp.process_audio(buf, rate, plugin_key, "input-timestamp", {}, block_size = blocksize * 2)) # step size defaults to block size Chris@142: assert len(results) == 5 Chris@142: for i in range(len(results)): Chris@142: # The timestamp should be the frame number of the first frame in the Chris@142: # input buffer Chris@142: expected = i * blocksize * 2 Chris@142: actual = results[i]["values"][0] Chris@142: assert actual == expected Chris@142: Chris@142: def test_process_stepsize_timestamps(): Chris@142: buf = input_data(blocksize * 10) Chris@147: results = list(vamp.process_audio(buf, rate, plugin_key, "input-timestamp", {}, step_size = int(blocksize / 2))) Chris@142: assert len(results) == 20 Chris@142: for i in range(len(results)): Chris@142: # The timestamp should be the frame number of the first frame in the Chris@142: # input buffer Chris@142: expected = (i * blocksize) / 2 Chris@142: actual = results[i]["values"][0] Chris@142: assert actual == expected Chris@142: Chris@142: def test_process_stepsize_blocksize_timestamps(): Chris@142: buf = input_data(blocksize * 10) Chris@147: results = list(vamp.process_audio(buf, rate, plugin_key, "input-timestamp", {}, block_size = blocksize * 2, step_size = int(blocksize / 2))) Chris@142: assert len(results) == 20 Chris@142: for i in range(len(results)): Chris@142: # The timestamp should be the frame number of the first frame in the Chris@142: # input buffer Chris@142: expected = (i * blocksize) / 2 Chris@142: actual = results[i]["values"][0] Chris@142: assert actual == expected Chris@142: Chris@74: def test_process_multiple_outputs(): Chris@74: buf = input_data(blocksize * 10) Chris@117: results = list(vamp.process_audio_multiple_outputs(buf, rate, plugin_key, [ "input-summary", "input-timestamp" ], {})) Chris@74: assert len(results) == 20 Chris@74: si = 0 Chris@74: ti = 0 Chris@74: for r in results: Chris@74: assert "input-summary" in r or "input-timestamp" in r Chris@74: if "input-summary" in r: Chris@74: expected = blocksize + si * blocksize + 1 Chris@74: actual = r["input-summary"]["values"][0] Chris@74: assert actual == expected Chris@74: si = si + 1 Chris@74: if "input-timestamp" in r: Chris@74: expected = ti * blocksize Chris@74: actual = r["input-timestamp"]["values"][0] Chris@74: assert actual == expected Chris@74: ti = ti + 1