annotate test/node-load-test.js @ 58:f6220d293bff

Simple test that can be run with any library name and plugin key
author Chris Cannam
date Thu, 10 Nov 2016 15:07:24 +0000
parents
children a1eb63b9ba6f
rev   line source
Chris@58 1 "use strict";
Chris@58 2
Chris@58 3 function note(blah) {
Chris@58 4 console.log(blah);
Chris@58 5 }
Chris@58 6
Chris@58 7 if (process.argv.length < 4) {
Chris@58 8 note("\nUsage: " + process.argv[0] + " <LibraryPath> <pluginKey>");
Chris@58 9 note("e.g. " + process.argv[0] + " ./VampExamplePlugins.js vamp-example-plugins:zerocrossing");
Chris@58 10 throw "Wrong number of command-line args (2 expected)"
Chris@58 11 }
Chris@58 12
Chris@58 13 var libraryPath = process.argv[2];
Chris@58 14 var pluginKey = process.argv[3];
Chris@58 15
Chris@58 16 var base64 = require("./base64");
Chris@58 17
Chris@58 18 note("Loading library \"" + libraryPath + "\"...");
Chris@58 19 var extractor = require(libraryPath);
Chris@58 20 var extractorModule = extractor();
Chris@58 21
Chris@58 22 var piperRequestJson = extractorModule.cwrap(
Chris@58 23 'piperRequestJson', 'number', ['number']
Chris@58 24 );
Chris@58 25
Chris@58 26 var piperProcessRaw = extractorModule.cwrap(
Chris@58 27 "piperProcessRaw", "number", ["number", "number", "number", "number"]
Chris@58 28 );
Chris@58 29
Chris@58 30 var piperFreeJson = extractorModule.cwrap(
Chris@58 31 'piperFreeJson', 'void', ['number']
Chris@58 32 );
Chris@58 33
Chris@58 34 function processRaw(request) {
Chris@58 35
Chris@58 36 const nChannels = request.processInput.inputBuffers.length;
Chris@58 37 const nFrames = request.processInput.inputBuffers[0].length;
Chris@58 38
Chris@58 39 const buffersPtr = extractorModule._malloc(nChannels * 4);
Chris@58 40 const buffers = new Uint32Array(
Chris@58 41 extractorModule.HEAPU8.buffer, buffersPtr, nChannels);
Chris@58 42
Chris@58 43 for (let i = 0; i < nChannels; ++i) {
Chris@58 44 const framesPtr = extractorModule._malloc(nFrames * 4);
Chris@58 45 const frames = new Float32Array(
Chris@58 46 extractorModule.HEAPU8.buffer, framesPtr, nFrames);
Chris@58 47 frames.set(request.processInput.inputBuffers[i]);
Chris@58 48 buffers[i] = framesPtr;
Chris@58 49 }
Chris@58 50
Chris@58 51 const responseJson = piperProcessRaw(
Chris@58 52 request.handle,
Chris@58 53 buffersPtr,
Chris@58 54 request.processInput.timestamp.s,
Chris@58 55 request.processInput.timestamp.n);
Chris@58 56
Chris@58 57 for (let i = 0; i < nChannels; ++i) {
Chris@58 58 extractorModule._free(buffers[i]);
Chris@58 59 }
Chris@58 60 extractorModule._free(buffersPtr);
Chris@58 61
Chris@58 62 const responseJstr = extractorModule.Pointer_stringify(responseJson);
Chris@58 63 const response = JSON.parse(responseJstr);
Chris@58 64
Chris@58 65 piperFreeJson(responseJson);
Chris@58 66
Chris@58 67 return response;
Chris@58 68 }
Chris@58 69
Chris@58 70 function makeTimestamp(seconds) {
Chris@58 71 if (seconds >= 0.0) {
Chris@58 72 return {
Chris@58 73 s: Math.floor(seconds),
Chris@58 74 n: Math.floor((seconds - Math.floor(seconds)) * 1e9 + 0.5)
Chris@58 75 };
Chris@58 76 } else {
Chris@58 77 const { s, n } = makeTimestamp(-seconds);
Chris@58 78 return { s: -s, n: -n };
Chris@58 79 }
Chris@58 80 }
Chris@58 81
Chris@58 82 function frame2timestamp(frame, rate) {
Chris@58 83 return makeTimestamp(frame / rate);
Chris@58 84 }
Chris@58 85
Chris@58 86 function request(req) {
Chris@58 87 var jsonStr = JSON.stringify(req);
Chris@58 88 var m = extractorModule;
Chris@58 89 // Inspection reveals that intArrayFromString converts the string
Chris@58 90 // from utf16 to utf8, which is what we want (though the docs
Chris@58 91 // don't mention this). Note the *Cstr values are Emscripten heap
Chris@58 92 // pointers
Chris@58 93 let inCstr = m.allocate(m.intArrayFromString(jsonStr), 'i8', m.ALLOC_NORMAL);
Chris@58 94 let outCstr = piperRequestJson(inCstr);
Chris@58 95 m._free(inCstr);
Chris@58 96 const responseJstr = m.Pointer_stringify(outCstr);
Chris@58 97 const response = JSON.parse(responseJstr);
Chris@58 98 piperFreeJson(outCstr);
Chris@58 99 return response;
Chris@58 100 }
Chris@58 101
Chris@58 102 function myFromBase64(b64) {
Chris@58 103 while (b64.length % 4 > 0) { b64 += "="; }
Chris@58 104 let conv = new Float32Array(base64.toByteArray(b64).buffer);
Chris@58 105 return conv;
Chris@58 106 }
Chris@58 107
Chris@58 108 function convertWireFeature(wfeature) {
Chris@58 109 let out = {};
Chris@58 110 if (wfeature.timestamp != null) {
Chris@58 111 out.timestamp = wfeature.timestamp;
Chris@58 112 }
Chris@58 113 if (wfeature.duration != null) {
Chris@58 114 out.duration = wfeature.duration;
Chris@58 115 }
Chris@58 116 if (wfeature.label != null) {
Chris@58 117 out.label = wfeature.label;
Chris@58 118 }
Chris@58 119 const vv = wfeature.featureValues;
Chris@58 120 if (vv != null) {
Chris@58 121 if (typeof vv === "string") {
Chris@58 122 out.featureValues = myFromBase64(vv);
Chris@58 123 } else {
Chris@58 124 out.featureValues = new Float32Array(vv);
Chris@58 125 }
Chris@58 126 }
Chris@58 127 return out;
Chris@58 128 }
Chris@58 129
Chris@58 130 function convertWireFeatureList(wfeatures) {
Chris@58 131 return wfeatures.map(convertWireFeature);
Chris@58 132 }
Chris@58 133
Chris@58 134 function responseToFeatureSet(response) {
Chris@58 135 const features = new Map();
Chris@58 136 const processResponse = response.result;
Chris@58 137 const wireFeatures = processResponse.features;
Chris@58 138 Object.keys(wireFeatures).forEach(key => {
Chris@58 139 return features.set(key, convertWireFeatureList(wireFeatures[key]));
Chris@58 140 });
Chris@58 141 return features;
Chris@58 142 }
Chris@58 143
Chris@58 144 function test() {
Chris@58 145
Chris@58 146 const rate = 44100;
Chris@58 147
Chris@58 148 note("Loading plugin \"" + pluginKey + "\"...");
Chris@58 149 let response = request({
Chris@58 150 method: "load",
Chris@58 151 params: {
Chris@58 152 key: pluginKey,
Chris@58 153 inputSampleRate: rate,
Chris@58 154 adapterFlags: ["AdaptAllSafe"]
Chris@58 155 }
Chris@58 156 });
Chris@58 157
Chris@58 158 const blockSize = 1024;
Chris@58 159
Chris@58 160 response = request({
Chris@58 161 method: "configure",
Chris@58 162 params: {
Chris@58 163 handle: 1,
Chris@58 164 configuration: {
Chris@58 165 blockSize: blockSize,
Chris@58 166 channelCount: 1,
Chris@58 167 stepSize: blockSize
Chris@58 168 }
Chris@58 169 }
Chris@58 170 });
Chris@58 171
Chris@58 172 const nblocks = 1000;
Chris@58 173
Chris@58 174 const makeBlock = (n => {
Chris@58 175 return {
Chris@58 176 timestamp : frame2timestamp(n * blockSize, rate),
Chris@58 177 inputBuffers : [
Chris@58 178 new Float32Array(Array.from(Array(blockSize).keys(),
Chris@58 179 n => n / blockSize))
Chris@58 180 ],
Chris@58 181 }
Chris@58 182 });
Chris@58 183
Chris@58 184 const blocks = Array.from(Array(nblocks).keys(), makeBlock);
Chris@58 185
Chris@58 186 note("Now processing " + nblocks + " blocks of 1024 samples each...");
Chris@58 187
Chris@58 188 let featureCount = 0;
Chris@58 189
Chris@58 190 for (let i = 0; i < nblocks; ++i) {
Chris@58 191 response = processRaw({
Chris@58 192 "handle": 1,
Chris@58 193 "processInput": blocks[i]
Chris@58 194 });
Chris@58 195 let features = responseToFeatureSet(response);
Chris@58 196 for (let featureList of features.values()) {
Chris@58 197 featureCount += featureList.length;
Chris@58 198 }
Chris@58 199 console.log(i);
Chris@58 200 }
Chris@58 201
Chris@58 202 note("Cleaning up the plugin and getting any remaining features...");
Chris@58 203 response = request({
Chris@58 204 method: "finish",
Chris@58 205 params: {
Chris@58 206 handle: 1
Chris@58 207 }
Chris@58 208 });
Chris@58 209
Chris@58 210 let features = responseToFeatureSet(response);
Chris@58 211 for (let featureList of features.values()) {
Chris@58 212 featureCount += featureList.length;
Chris@58 213 }
Chris@58 214
Chris@58 215 note("Done, total number of features across all outputs = " + featureCount);
Chris@58 216 }
Chris@58 217
Chris@58 218 test();
Chris@58 219