forked from Picovoice/porcupine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathporcupine.js
104 lines (88 loc) · 4.43 KB
/
porcupine.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
let Porcupine = (function () {
/**
* Binding for wake word detection object. It initializes the JS binding for WebAssembly module and exposes
* a factory method for creating new instances of wake word engine.
*/
let initWasm;
let releaseWasm;
let processWasm;
let sampleRate;
let frameLength;
let version;
Module.onRuntimeInitialized = async _ => {
initWasm = Module.cwrap('pv_porcupine_wasm_init', 'number', ['number', 'number', 'number', 'number']);
releaseWasm = Module.cwrap('pv_porcupine_wasm_delete', ['number']);
processWasm = Module.cwrap('pv_porcupine_wasm_process', 'number', ['number', 'number']);
sampleRate = Module.cwrap('pv_wasm_sample_rate', 'number', [])();
frameLength = Module.cwrap('pv_porcupine_wasm_frame_length', 'number', [])();
version = Module.cwrap('pv_porcupine_wasm_version', 'string', [])();
};
let create = function (keywordIDs, sensitivities) {
/**
* Creates an instance of wake word detection engine (aka porcupine).
* @param {Array} Array of keyword IDs. A keyword ID is the signature for a given phrase to be detected. Each
* keyword ID should be stored as UInt8Array.
* @param {Float32Array} Detection sensitivity. A higher sensitivity reduces miss rate at the cost of higher
* false alarm rate. Sensitivity is a number within [0, 1].
* @returns An instance of wake word detection engine.
*/
let keywordIDSizes = Int32Array.from(keywordIDs.map(keywordID => keywordID.byteLength));
let keywordIDSizesPointer = Module._malloc(keywordIDSizes.byteLength);
let keywordIDSizesBuffer = new Uint8Array(Module.HEAPU8.buffer, keywordIDSizesPointer, keywordIDSizes.byteLength);
keywordIDSizesBuffer.set(new Uint8Array(keywordIDSizes.buffer));
let keywordIDPointers = Uint32Array.from(keywordIDs.map(keywordID => {
let heapPointer = Module._malloc(keywordID.byteLength);
let heapBuffer = new Uint8Array(Module.HEAPU8.buffer, heapPointer, keywordID.byteLength);
heapBuffer.set(keywordID);
return heapPointer;
}));
let keywordIDPointersPointer = Module._malloc(keywordIDPointers.byteLength);
let keywordIDPointersBuffer = new Uint8Array(
Module.HEAPU8.buffer,
keywordIDPointersPointer,
keywordIDPointers.byteLength);
keywordIDPointersBuffer.set(new Uint8Array(keywordIDPointers.buffer));
let sensitivitiesPointer = Module._malloc(sensitivities.byteLength);
let sensitivitiesBuffer = new Uint8Array(Module.HEAPU8.buffer, sensitivitiesPointer, sensitivities.byteLength);
sensitivitiesBuffer.set(new Uint8Array(sensitivities.buffer));
let handleWasm = initWasm(
keywordIDs.length,
keywordIDSizesPointer,
keywordIDPointersPointer,
sensitivitiesPointer);
if (handleWasm === 0) {
throw new Error("failed to initialize porcupine.");
}
let pcmWasmPointer = Module._malloc(this.frameLength * 2);
let release = function () {
/**
* Releases resources acquired by WebAssembly module.
*/
releaseWasm(handleWasm);
Module._free(pcmWasmPointer);
};
let process = function (pcmInt16Array) {
/**
* Processes a frame of audio. The required sample rate can be retrieved from .sampleRate and the length of
* frame (number of samples within frame) can be retrieved from .frameLength.
* @param {Int16Array} A frame of audio with properties described above.
* @returns {Number} Index of detected keyword (phrase). When no keyword is detected it returns -1.
*/
let pcmWasmBuffer = new Uint8Array(Module.HEAPU8.buffer, pcmWasmPointer, pcmInt16Array.byteLength);
pcmWasmBuffer.set(new Uint8Array(pcmInt16Array.buffer));
let keyword_index = processWasm(handleWasm, pcmWasmPointer);
if (keyword_index === -2) {
throw new Error("porcupine failed to process audio");
}
return keyword_index;
};
return {
release: release,
process: process,
sampleRate: sampleRate,
frameLength: frameLength,
version: version
}
};
return {create: create}
})();