c@102: "use strict";
c@102:
c@102: var exampleModule = VampExamplePluginsModule();
c@102:
c@102: // It is possible to declare both parameters and return values as
c@102: // "string", in which case Emscripten will take care of
c@102: // conversions. But it's not clear how one would manage memory for
c@102: // newly-constructed returned C strings -- the returned pointer from
c@102: // vampipeRequestJson would appear (?) to be thrown away by the
c@102: // Emscripten string converter if we declare it as returning a string,
c@102: // so we have no opportunity to pass it to vampipeFreeJson, which
c@102: // suggests this would leak memory if the string isn't static. Not
c@102: // wholly sure though. Anyway, passing and returning pointers (as
c@102: // numbers) means we can manage the Emscripten heap memory however we
c@102: // want in our request wrapper function below.
c@102:
c@102: var vampipeRequestJson = exampleModule.cwrap(
c@102: 'vampipeRequestJson', 'number', ['number']
c@102: );
c@102:
c@102: var vampipeProcessRaw = exampleModule.cwrap(
c@102: "vampipeProcessRaw", "number", ["number", "number", "number", "number"]
c@102: );
c@102:
c@102: var vampipeFreeJson = exampleModule.cwrap(
c@102: 'vampipeFreeJson', 'void', ['number']
c@102: );
c@102:
c@102: function note(blah) {
c@102: document.getElementById("test-result").innerHTML += blah + "
";
c@102: }
c@102:
c@102: function comment(blah) {
c@102: note("
" + blah + "");
c@102: }
c@102:
c@102: function processRaw(request) {
c@102:
c@102: const nChannels = request.processInput.inputBuffers.length;
c@102: const nFrames = request.processInput.inputBuffers[0].values.length;
c@102:
c@102: const buffersPtr = exampleModule._malloc(nChannels * 4);
c@102: const buffers = new Uint32Array(
c@102: exampleModule.HEAPU8.buffer, buffersPtr, nChannels);
c@102:
c@102: for (let i = 0; i < nChannels; ++i) {
c@102: const framesPtr = exampleModule._malloc(nFrames * 4);
c@102: const frames = new Float32Array(
c@102: exampleModule.HEAPU8.buffer, framesPtr, nFrames);
c@102: frames.set(request.processInput.inputBuffers[i].values);
c@102: buffers[i] = framesPtr;
c@102: }
c@102:
c@102: const responseJson = vampipeProcessRaw(
c@102: request.pluginHandle,
c@102: buffersPtr,
c@102: request.processInput.timestamp.s,
c@102: request.processInput.timestamp.n);
c@102:
c@102: for (let i = 0; i < nChannels; ++i) {
c@102: exampleModule._free(buffers[i]);
c@102: }
c@102: exampleModule._free(buffersPtr);
c@102:
c@102: const response = JSON.parse(
c@102: exampleModule.Pointer_stringify(responseJson));
c@102:
c@102: vampipeFreeJson(responseJson);
c@102:
c@102: return response;
c@102: }
c@102:
c@102: function request(jsonStr) {
c@102: note("Request JSON = " + jsonStr);
c@102: var m = exampleModule;
c@102: // Inspection reveals that intArrayFromString converts the string
c@102: // from utf16 to utf8, which is what we want (though the docs
c@102: // don't mention this). Note the *Cstr values are Emscripten heap
c@102: // pointers
c@102: var inCstr = m.allocate(m.intArrayFromString(jsonStr), 'i8', m.ALLOC_NORMAL);
c@102: var outCstr = vampipeRequestJson(inCstr);
c@102: m._free(inCstr);
c@102: var result = m.Pointer_stringify(outCstr);
c@102: vampipeFreeJson(outCstr);
c@102: note("Returned JSON = " + result);
c@102: return result;
c@102: }
c@102:
c@102: function test() {
c@102:
c@102: comment("Loading zero crossings plugin...");
c@102: let result = request('{"type":"load","content": {"pluginKey":"vamp-example-plugins:zerocrossing","inputSampleRate":44100,"adapterFlags":["AdaptAllSafe"]}}');
c@102:
c@102: const blockSize = 1024;
c@102:
c@102: result = request('{"type":"configure","content":{"pluginHandle":1,"configuration":{"blockSize": ' + blockSize + ', "channelCount": 1, "stepSize": ' + blockSize + '}}}');
c@102:
c@102: const nblocks = 1000;
c@102:
c@102: let processInputBuffers = [new Float32Array(
c@102: Array.from(Array(blockSize).keys(), n => n / blockSize))
c@102: ];
c@102:
c@102: comment("Now processing " + nblocks + " blocks of 1024 samples each...");
c@102:
c@102: let start = (new Date()).getTime();
c@102: comment("Start at " + start);
c@102:
c@102: for (let i = 0; i < nblocks; ++i) {
c@102: let ts = { "s": i, "n": 0 }; // wholly bogus, but ZC plugin doesn't use it
c@102: result = processRaw({
c@102: "pluginHandle": 1,
c@102: "processInput": {
c@102: "timestamp": ts,
c@102: "inputBuffers": processInputBuffers
c@102: }
c@102: });
c@102: }
c@102:
c@102: let finish = (new Date()).getTime();
c@102: comment("Finish at " + finish + " for a time of " + (finish - start) + " ms");
c@102:
c@102: comment("Again...");
c@102:
c@102: start = (new Date()).getTime();
c@102: comment("Start at " + start);
c@102:
c@102: for (let i = 0; i < nblocks; ++i) {
c@102: let ts = { "s": i, "n": 0 }; // wholly bogus, but ZC plugin doesn't use it
c@102: result = processRaw({
c@102: "pluginHandle": 1,
c@102: "processInput": {
c@102: "timestamp": ts,
c@102: "inputBuffers": processInputBuffers
c@102: }
c@102: });
c@102: }
c@102:
c@102: finish = (new Date()).getTime();
c@102: comment("Finish at " + finish + " for a time of " + (finish - start) + " ms");
c@102:
c@102: comment("Cleaning up the plugin and getting any remaining features...");
c@102: result = request('{"type":"finish","content":{"pluginHandle":1}}');
c@102: }
c@102:
c@102: window.onload = function() {
c@102: test();
c@102: }