├── .gitignore ├── .gitmodules ├── .npmignore ├── LICENSE ├── Makefile ├── README.md ├── build ├── COPYING.libopus ├── opusscript_native_nasm.js ├── opusscript_native_wasm.js └── opusscript_native_wasm.wasm ├── index.d.ts ├── index.js ├── package.json └── src └── opusscript_encoder.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "opus-native"] 2 | path = opus-native 3 | url = https://github.com/xiph/opus.git 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .git* 3 | Makefile 4 | opus-native 5 | src 6 | test 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2021 abalabahaha 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OPUS_NATIVE_DIR=./opus-native 2 | 3 | EMCC_OPTS=-Wall -O3 --llvm-lto 3 -flto --closure 1 -s ALLOW_MEMORY_GROWTH=1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s EXPORTED_RUNTIME_METHODS="['setValue', 'getValue']" -s EXPORTED_FUNCTIONS="['_malloc', '_opus_strerror', '_free']" -s MODULARIZE=1 -s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 4 | 5 | EMCC_NASM_OPTS=-s WASM=0 -s WASM_ASYNC_COMPILATION=0 6 | EMCC_WASM_OPTS=-s WASM=1 -s WASM_ASYNC_COMPILATION=0 -s WASM_BIGINT 7 | 8 | all: init compile 9 | autogen: 10 | cd $(OPUS_NATIVE_DIR); \ 11 | ./autogen.sh 12 | configure: 13 | cd $(OPUS_NATIVE_DIR); \ 14 | emconfigure ./configure --disable-extra-programs --disable-doc --disable-intrinsics --disable-stack-protector 15 | bind: 16 | cd $(OPUS_NATIVE_DIR); \ 17 | emmake make; \ 18 | rm -f a.wasm 19 | init: autogen configure bind 20 | compile: 21 | rm -rf ./build; \ 22 | mkdir -p ./build; \ 23 | em++ ${EMCC_OPTS} ${EMCC_NASM_OPTS} --bind -o build/opusscript_native_nasm.js src/opusscript_encoder.cpp ${OPUS_NATIVE_DIR}/.libs/libopus.a; \ 24 | em++ ${EMCC_OPTS} ${EMCC_WASM_OPTS} --bind -o build/opusscript_native_wasm.js src/opusscript_encoder.cpp ${OPUS_NATIVE_DIR}/.libs/libopus.a; \ 25 | cp -f opus-native/COPYING build/COPYING.libopus; 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpusScript 2 | 3 | JS bindings for libopus 1.4, ported with Emscripten. 4 | 5 | ---- 6 | 7 | ## Usage 8 | 9 | ```js 10 | var OpusScript = require("opusscript"); 11 | 12 | // 48kHz sampling rate, 20ms frame duration, stereo audio (2 channels) 13 | var samplingRate = 48000; 14 | var frameDuration = 20; 15 | var channels = 2; 16 | 17 | // Optimize encoding for audio. Available applications are VOIP, AUDIO, and RESTRICTED_LOWDELAY 18 | var encoder = new OpusScript(samplingRate, channels, OpusScript.Application.AUDIO); 19 | 20 | var frameSize = samplingRate * frameDuration / 1000; 21 | 22 | // Get PCM data from somewhere and encode it into opus 23 | var pcmData = new Buffer(pcmSource); 24 | var encodedPacket = encoder.encode(pcmData, frameSize); 25 | 26 | // Decode the opus packet back into PCM 27 | var decodedPacket = encoder.decode(encodedPacket); 28 | 29 | // Delete the encoder when finished with it (Emscripten does not automatically call C++ object destructors) 30 | encoder.delete(); 31 | ``` 32 | 33 | ## Note: WASM 34 | 35 | If your environment doesn't support WASM, you can try the JS-only module. Do note that the JS-only version barely has optimizations due to compiler/toolchain limitations, and should only be used as a last resort. 36 | 37 | ```js 38 | var encoder = new OpusScript(samplingRate, channels, OpusScript.Application.AUDIO, { 39 | wasm: false 40 | }); 41 | ``` 42 | 43 | ## Note: TypeScript 44 | 45 | Since this module wasn't written for TypeScript, you need to use `import = require` syntax. 46 | 47 | ```ts 48 | // Import using: 49 | import OpusScript = require("opusscript"); 50 | 51 | // and NOT: 52 | import OpusScript from "opusscript"; 53 | ``` 54 | -------------------------------------------------------------------------------- /build/COPYING.libopus: -------------------------------------------------------------------------------- 1 | Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic, 2 | Jean-Marc Valin, Timothy B. Terriberry, 3 | CSIRO, Gregory Maxwell, Mark Borgerding, 4 | Erik de Castro Lopo 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | - Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | - Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | - Neither the name of Internet Society, IETF or IETF Trust, nor the 18 | names of specific contributors, may be used to endorse or promote 19 | products derived from this software without specific prior written 20 | permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 26 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | Opus is subject to the royalty-free patent licenses which are 35 | specified at: 36 | 37 | Xiph.Org Foundation: 38 | https://datatracker.ietf.org/ipr/1524/ 39 | 40 | Microsoft Corporation: 41 | https://datatracker.ietf.org/ipr/1914/ 42 | 43 | Broadcom Corporation: 44 | https://datatracker.ietf.org/ipr/1526/ 45 | -------------------------------------------------------------------------------- /build/opusscript_native_wasm.js: -------------------------------------------------------------------------------- 1 | 2 | var Module = (() => { 3 | var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; 4 | if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; 5 | return ( 6 | function(Module = {}) { 7 | 8 | var h;h||(h=typeof Module !== 'undefined' ? Module : {});var aa,ba;h.ready=new Promise(function(b,a){aa=b;ba=a});var ca=Object.assign({},h),da="object"==typeof window,ea="function"==typeof importScripts,p="",fa,ha; 9 | if("object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node){var fs=require("fs"),ia=require("path");p=ea?ia.dirname(p)+"/":__dirname+"/";fa=(b,a)=>{b=b.startsWith("file://")?new URL(b):ia.normalize(b);return fs.readFileSync(b,a?void 0:"utf8")};ha=b=>{b=fa(b,!0);b.buffer||(b=new Uint8Array(b));return b};process.argv.slice(2);h.inspect=function(){return"[Emscripten Module object]"}}else if(da||ea)ea?p=self.location.href:"undefined"!=typeof document&&document.currentScript&& 10 | (p=document.currentScript.src),_scriptDir&&(p=_scriptDir),0!==p.indexOf("blob:")?p=p.substr(0,p.replace(/[?#].*/,"").lastIndexOf("/")+1):p="",fa=b=>{var a=new XMLHttpRequest;a.open("GET",b,!1);a.send(null);return a.responseText},ea&&(ha=b=>{var a=new XMLHttpRequest;a.open("GET",b,!1);a.responseType="arraybuffer";a.send(null);return new Uint8Array(a.response)});var ja=h.print||console.log.bind(console),u=h.printErr||console.warn.bind(console);Object.assign(h,ca);ca=null;var ka;h.wasmBinary&&(ka=h.wasmBinary); 11 | var noExitRuntime=h.noExitRuntime||!0;"object"!=typeof WebAssembly&&w("no native wasm support detected");var la,ma=!1,x,y,z,na,A,B,oa,pa,qa,ra;function sa(){var b=la.buffer;h.HEAP8=x=new Int8Array(b);h.HEAP16=z=new Int16Array(b);h.HEAP32=A=new Int32Array(b);h.HEAPU8=y=new Uint8Array(b);h.HEAPU16=na=new Uint16Array(b);h.HEAPU32=B=new Uint32Array(b);h.HEAPF32=oa=new Float32Array(b);h.HEAPF64=ra=new Float64Array(b);h.HEAP64=pa=new BigInt64Array(b);h.HEAPU64=qa=new BigUint64Array(b)} 12 | var ta,ua=[],va=[],wa=[];function xa(){var b=h.preRun.shift();ua.unshift(b)}var D=0,ya=null,E=null;function w(b){if(h.onAbort)h.onAbort(b);b="Aborted("+b+")";u(b);ma=!0;b=new WebAssembly.RuntimeError(b+". Build with -sASSERTIONS for more info.");ba(b);throw b;}var F;F="opusscript_native_wasm.wasm";if(!F.startsWith("data:application/octet-stream;base64,")){var za=F;F=h.locateFile?h.locateFile(za,p):p+za} 13 | function Aa(b){var a=F;try{a:{try{if(a==F&&ka){var c=new Uint8Array(ka);break a}if(ha){c=ha(a);break a}throw"sync fetching of the wasm failed: you can preload it to Module['wasmBinary'] manually, or emcc.py will do that for you when generating HTML (but not JS)";}catch(g){w(g)}c=void 0}var d=new WebAssembly.Module(c);var e=new WebAssembly.Instance(d,b)}catch(g){throw b=g.toString(),u("failed to compile wasm module: "+b),(b.includes("imported Memory")||b.includes("memory import"))&&u("Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time)."), 14 | g;}return[e,d]}var G,Ba;function Ca(b){for(;0>2]=a};this.W=function(a){B[this.F+8>>2]=a};this.K=function(a,c){this.V();this.Z(a);this.W(c)};this.V=function(){B[this.F+16>>2]=0}}var Ea=0,Fa=0;function H(b){if(null===b)return"null";var a=typeof b;return"object"===a||"array"===a||"function"===a?b.toString():""+b}var Ga=void 0;function I(b){for(var a="";y[b];)a+=Ga[y[b++]];return a}var J={},K={},Ha={}; 15 | function Ja(b){if(void 0===b)return"_unknown";b=b.replace(/[^a-zA-Z0-9_]/g,"$");var a=b.charCodeAt(0);return 48<=a&&57>=a?"_"+b:b}function Ka(b,a){b=Ja(b);return{[b]:function(){return a.apply(this,arguments)}}[b]} 16 | function La(b){var a=Error,c=Ka(b,function(d){this.name=b;this.message=d;d=Error(d).stack;void 0!==d&&(this.stack=this.toString()+"\n"+d.replace(/^Error(:[^\n]*)?\n/,""))});c.prototype=Object.create(a.prototype);c.prototype.constructor=c;c.prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message};return c}var L=void 0;function M(b){throw new L(b);}var Ma=void 0;function Na(b){throw new Ma(b);} 17 | function N(b,a,c){function d(f){f=c(f);f.length!==b.length&&Na("Mismatched type converter count");for(var l=0;l{K.hasOwnProperty(f)?e[l]=K[f]:(g.push(f),J.hasOwnProperty(f)||(J[f]=[]),J[f].push(()=>{e[l]=K[f];++k;k===g.length&&d(e)}))});0===g.length&&d(e)} 18 | function O(b,a,c={}){if(!("argPackAdvance"in a))throw new TypeError("registerType registeredInstance requires argPackAdvance");var d=a.name;b||M('type "'+d+'" must have a positive integer typeid pointer');if(K.hasOwnProperty(b)){if(c.ia)return;M("Cannot register type '"+d+"' twice")}K[b]=a;delete Ha[b];J.hasOwnProperty(b)&&(a=J[b],delete J[b],a.forEach(e=>e()))} 19 | function Oa(b,a,c){switch(a){case 0:return c?function(d){return x[d]}:function(d){return y[d]};case 1:return c?function(d){return z[d>>1]}:function(d){return na[d>>1]};case 2:return c?function(d){return A[d>>2]}:function(d){return B[d>>2]};case 3:return c?function(d){return pa[d>>3]}:function(d){return qa[d>>3]};default:throw new TypeError("Unknown integer type: "+b);}} 20 | function Pa(b){switch(b){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+b);}}function Qa(b){M(b.C.G.D.name+" instance already deleted")}var Ra=!1;function Sa(){}function Ta(b){--b.count.value;0===b.count.value&&(b.I?b.J.O(b.I):b.G.D.O(b.F))}function Ua(b,a,c){if(a===c)return b;if(void 0===c.L)return null;b=Ua(b,a,c.L);return null===b?null:c.fa(b)}var Va={},P=[];function Wa(){for(;P.length;){var b=P.pop();b.C.R=!1;b["delete"]()}} 21 | var Q=void 0,S={};function Xa(b,a){for(void 0===a&&M("ptr should not be undefined");b.L;)a=b.U(a),b=b.L;return S[a]}function Ya(b,a){a.G&&a.F||Na("makeClassHandle requires ptr and ptrType");!!a.J!==!!a.I&&Na("Both smartPtrType and smartPtr must be specified");a.count={value:1};return T(Object.create(b,{C:{value:a}}))} 22 | function T(b){if("undefined"===typeof FinalizationRegistry)return T=a=>a,b;Ra=new FinalizationRegistry(a=>{Ta(a.C)});T=a=>{var c=a.C;c.I&&Ra.register(a,{C:c},a);return a};Sa=a=>{Ra.unregister(a)};return T(b)}function U(){} 23 | function Za(b,a,c){if(void 0===b[a].H){var d=b[a];b[a]=function(){b[a].H.hasOwnProperty(arguments.length)||M("Function '"+c+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+b[a].H+")!");return b[a].H[arguments.length].apply(this,arguments)};b[a].H=[];b[a].H[d.P]=d}} 24 | function $a(b,a){h.hasOwnProperty(b)?(M("Cannot register public name '"+b+"' twice"),Za(h,b,b),h.hasOwnProperty(void 0)&&M("Cannot register multiple overloads of a function with the same number of arguments (undefined)!"),h[b].H[void 0]=a):h[b]=a}function ab(b,a,c,d,e,g,k,f){this.name=b;this.constructor=a;this.S=c;this.O=d;this.L=e;this.ga=g;this.U=k;this.fa=f;this.ka=[]} 25 | function bb(b,a,c){for(;a!==c;)a.U||M("Expected null or instance of "+c.name+", got an instance of "+a.name),b=a.U(b),a=a.L;return b}function cb(b,a){if(null===a)return this.$&&M("null is not a valid "+this.name),0;a.C||M('Cannot pass "'+H(a)+'" as a '+this.name);a.C.F||M("Cannot pass deleted object as a pointer of type "+this.name);return bb(a.C.F,a.C.G.D,this.D)} 26 | function db(b,a){if(null===a){this.$&&M("null is not a valid "+this.name);if(this.Y){var c=this.la();null!==b&&b.push(this.O,c);return c}return 0}a.C||M('Cannot pass "'+H(a)+'" as a '+this.name);a.C.F||M("Cannot pass deleted object as a pointer of type "+this.name);!this.X&&a.C.G.X&&M("Cannot convert argument of type "+(a.C.J?a.C.J.name:a.C.G.name)+" to parameter type "+this.name);c=bb(a.C.F,a.C.G.D,this.D);if(this.Y)switch(void 0===a.C.I&&M("Passing raw pointer to smart pointer is illegal"),this.oa){case 0:a.C.J=== 27 | this?c=a.C.I:M("Cannot convert argument of type "+(a.C.J?a.C.J.name:a.C.G.name)+" to parameter type "+this.name);break;case 1:c=a.C.I;break;case 2:if(a.C.J===this)c=a.C.I;else{var d=a.clone();c=this.ma(c,eb(function(){d["delete"]()}));null!==b&&b.push(this.O,c)}break;default:M("Unsupporting sharing policy")}return c} 28 | function fb(b,a){if(null===a)return this.$&&M("null is not a valid "+this.name),0;a.C||M('Cannot pass "'+H(a)+'" as a '+this.name);a.C.F||M("Cannot pass deleted object as a pointer of type "+this.name);a.C.G.X&&M("Cannot convert argument of type "+a.C.G.name+" to parameter type "+this.name);return bb(a.C.F,a.C.G.D,this.D)}function gb(b){return this.fromWireType(A[b>>2])} 29 | function V(b,a,c,d){this.name=b;this.D=a;this.$=c;this.X=d;this.Y=!1;this.O=this.ma=this.la=this.ba=this.oa=this.ja=void 0;void 0!==a.L?this.toWireType=db:(this.toWireType=d?cb:fb,this.M=null)}function jb(b,a){h.hasOwnProperty(b)||Na("Replacing nonexistant public symbol");h[b]=a;h[b].P=void 0}var kb=[];function W(b,a){b=I(b);var c=kb[a];c||(a>=kb.length&&(kb.length=a+1),kb[a]=c=ta.get(a));"function"!=typeof c&&M("unknown function pointer with signature "+b+": "+a);return c}var lb=void 0; 30 | function mb(b){b=nb(b);var a=I(b);X(b);return a}function ob(b,a){function c(g){e[g]||K[g]||(Ha[g]?Ha[g].forEach(c):(d.push(g),e[g]=!0))}var d=[],e={};a.forEach(c);throw new lb(b+": "+d.map(mb).join([", "]));}function pb(b){for(;b.length;){var a=b.pop();b.pop()(a)}} 31 | function qb(b){var a=Function;if(!(a instanceof Function))throw new TypeError("new_ called with constructor type "+typeof a+" which is not a function");var c=Ka(a.name||"unknownFunctionName",function(){});c.prototype=a.prototype;c=new c;b=a.apply(c,b);return b instanceof Object?b:c} 32 | function rb(b,a,c,d,e,g){var k=a.length;2>k&&M("argTypes array size mismatch! Must at least get return value and 'this' types!");var f=null!==a[1]&&null!==c,l=!1;for(c=1;c>2]);return c} 35 | var Y=new function(){this.K=[void 0];this.V=[];this.get=function(b){return this.K[b]};this.Z=function(b){let a=this.V.pop()||this.K.length;this.K[a]=b;return a};this.da=function(b){this.K[b]=void 0;this.V.push(b)}},eb=b=>{switch(b){case void 0:return 1;case null:return 2;case !0:return 3;case !1:return 4;default:return Y.Z({na:1,value:b})}}; 36 | function tb(b,a){switch(a){case 2:return function(c){return this.fromWireType(oa[c>>2])};case 3:return function(c){return this.fromWireType(ra[c>>3])};default:throw new TypeError("Unknown float type: "+b);}}var ub="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0; 37 | function vb(b,a,c){var d=a+c;for(c=a;b[c]&&!(c>=d);)++c;if(16e?d+=String.fromCharCode(e):(e-=65536,d+=String.fromCharCode(55296|e>>10,56320|e&1023))}}else d+=String.fromCharCode(e)}return d} 38 | var wb="undefined"!=typeof TextDecoder?new TextDecoder("utf-16le"):void 0;function xb(b,a){var c=b>>1;for(var d=c+a/2;!(c>=d)&&na[c];)++c;c<<=1;if(32=a/2);++d){var e=z[b+2*d>>1];if(0==e)break;c+=String.fromCharCode(e)}return c}function yb(b,a,c){void 0===c&&(c=2147483647);if(2>c)return 0;c-=2;var d=a;c=c<2*b.length?c/2:b.length;for(var e=0;e>1]=b.charCodeAt(e),a+=2;z[a>>1]=0;return a-d}function zb(b){return 2*b.length} 39 | function Ab(b,a){for(var c=0,d="";!(c>=a/4);){var e=A[b+4*c>>2];if(0==e)break;++c;65536<=e?(e-=65536,d+=String.fromCharCode(55296|e>>10,56320|e&1023)):d+=String.fromCharCode(e)}return d}function Bb(b,a,c){void 0===c&&(c=2147483647);if(4>c)return 0;var d=a;c=d+c-4;for(var e=0;e=g){var k=b.charCodeAt(++e);g=65536+((g&1023)<<10)|k&1023}A[a>>2]=g;a+=4;if(a+4>c)break}A[a>>2]=0;return a-d} 40 | function Cb(b){for(var a=0,c=0;c=d&&++c;a+=4}return a}for(var Db=[null,[],[]],Eb=Array(256),Fb=0;256>Fb;++Fb)Eb[Fb]=String.fromCharCode(Fb);Ga=Eb;L=h.BindingError=La("BindingError");Ma=h.InternalError=La("InternalError");U.prototype.isAliasOf=function(b){if(!(this instanceof U&&b instanceof U))return!1;var a=this.C.G.D,c=this.C.F,d=b.C.G.D;for(b=b.C.F;a.L;)c=a.U(c),a=a.L;for(;d.L;)b=d.U(b),d=d.L;return a===d&&c===b}; 41 | U.prototype.clone=function(){this.C.F||Qa(this);if(this.C.T)return this.C.count.value+=1,this;var b=T,a=Object,c=a.create,d=Object.getPrototypeOf(this),e=this.C;b=b(c.call(a,d,{C:{value:{count:e.count,R:e.R,T:e.T,F:e.F,G:e.G,I:e.I,J:e.J}}}));b.C.count.value+=1;b.C.R=!1;return b};U.prototype["delete"]=function(){this.C.F||Qa(this);this.C.R&&!this.C.T&&M("Object already scheduled for deletion");Sa(this);Ta(this.C);this.C.T||(this.C.I=void 0,this.C.F=void 0)};U.prototype.isDeleted=function(){return!this.C.F}; 42 | U.prototype.deleteLater=function(){this.C.F||Qa(this);this.C.R&&!this.C.T&&M("Object already scheduled for deletion");P.push(this);1===P.length&&Q&&Q(Wa);this.C.R=!0;return this};h.getInheritedInstanceCount=function(){return Object.keys(S).length};h.getLiveInheritedInstances=function(){var b=[],a;for(a in S)S.hasOwnProperty(a)&&b.push(S[a]);return b};h.flushPendingDeletes=Wa;h.setDelayFunction=function(b){Q=b;P.length&&Q&&Q(Wa)};V.prototype.ha=function(b){this.ba&&(b=this.ba(b));return b}; 43 | V.prototype.aa=function(b){this.O&&this.O(b)};V.prototype.argPackAdvance=8;V.prototype.readValueFromPointer=gb;V.prototype.deleteObject=function(b){if(null!==b)b["delete"]()}; 44 | V.prototype.fromWireType=function(b){function a(){return this.Y?Ya(this.D.S,{G:this.ja,F:c,J:this,I:b}):Ya(this.D.S,{G:this,F:b})}var c=this.ha(b);if(!c)return this.aa(b),null;var d=Xa(this.D,c);if(void 0!==d){if(0===d.C.count.value)return d.C.F=c,d.C.I=b,d.clone();d=d.clone();this.aa(b);return d}d=this.D.ga(c);d=Va[d];if(!d)return a.call(this);d=this.X?d.ea:d.pointerType;var e=Ua(c,this.D,d.D);return null===e?a.call(this):this.Y?Ya(d.D.S,{G:d,F:e,J:this,I:b}):Ya(d.D.S,{G:d,F:e})}; 45 | lb=h.UnboundTypeError=La("UnboundTypeError");Y.K.push({value:void 0},{value:null},{value:!0},{value:!1});Y.W=Y.K.length;h.count_emval_handles=function(){for(var b=0,a=Y.W;ae)throw new TypeError('Passing a number "'+H(f)+'" from JS side to C/C++ side to an argument of type "'+a+'", which is outside the valid range ['+d+", "+e+"]!");return f}, 47 | argPackAdvance:8,readValueFromPointer:Oa(a,c,!g),M:null})},j:function(b,a,c,d,e){var g=Pa(c);a=I(a);O(b,{name:a,fromWireType:function(k){return!!k},toWireType:function(k,f){return f?d:e},argPackAdvance:8,readValueFromPointer:function(k){if(1===c)var f=x;else if(2===c)f=z;else if(4===c)f=A;else throw new TypeError("Unknown boolean type size: "+a);return this.fromWireType(f[k>>g])},M:null})},t:function(b,a,c,d,e,g,k,f,l,n,m,q,r){m=I(m);g=W(e,g);f&&(f=W(k,f));n&&(n=W(l,n));r=W(q,r);var t=Ja(m);$a(t, 48 | function(){ob("Cannot construct "+m+" due to unbound types",[d])});N([b,a,c],d?[d]:[],function(v){v=v[0];if(d){var C=v.D;var Z=C.S}else Z=U.prototype;v=Ka(t,function(){if(Object.getPrototypeOf(this)!==Ia)throw new L("Use 'new' to construct "+m);if(void 0===R.N)throw new L(m+" has no accessible constructor");var hb=R.N[arguments.length];if(void 0===hb)throw new L("Tried to invoke ctor of "+m+" with invalid number of parameters ("+arguments.length+") - expected ("+Object.keys(R.N).toString()+") parameters instead!"); 49 | return hb.apply(this,arguments)});var Ia=Object.create(Z,{constructor:{value:v}});v.prototype=Ia;var R=new ab(m,v,Ia,r,C,g,f,n);C=new V(m,R,!0,!1);Z=new V(m+"*",R,!1,!1);var ib=new V(m+" const*",R,!1,!0);Va[b]={pointerType:Z,ea:ib};jb(t,v);return[C,Z,ib]})},l:function(b,a,c,d,e,g,k,f){var l=sb(c,d);a=I(a);g=W(e,g);N([],[b],function(n){function m(){ob("Cannot call "+q+" due to unbound types",l)}n=n[0];var q=n.name+"."+a;a.startsWith("@@")&&(a=Symbol[a.substring(2)]);var r=n.D.constructor;void 0=== 50 | r[a]?(m.P=c-1,r[a]=m):(Za(r,a,q),r[a].H[c-1]=m);N([],l,function(t){t=[t[0],null].concat(t.slice(1));t=rb(q,t,null,g,k,f);void 0===r[a].H?(t.P=c-1,r[a]=t):r[a].H[c-1]=t;return[]});return[]})},s:function(b,a,c,d,e,g){0{ob("Cannot construct "+f.name+" due to unbound types",k)};N([],k,function(n){n.splice(1,0,null);f.D.N[a-1]=rb(l,n,null,e,g);return[]});return[]})},c:function(b,a,c,d,e,g,k,f,l){var n=sb(c,d);a=I(a);g=W(e,g);N([],[b],function(m){function q(){ob("Cannot call "+r+" due to unbound types",n)}m=m[0];var r=m.name+"."+a;a.startsWith("@@")&&(a=Symbol[a.substring(2)]);f&&m.D.ka.push(a);var t=m.D.S,v=t[a];void 0===v||void 0===v.H&&v.className!==m.name&&v.P===c-2?(q.P=c-2,q.className=m.name,t[a]= 52 | q):(Za(t,a,r),t[a].H[c-2]=q);N([],n,function(C){C=rb(r,C,m,g,k,l);void 0===t[a].H?(C.P=c-2,t[a]=C):t[a].H[c-2]=C;return[]});return[]})},r:function(b,a){a=I(a);O(b,{name:a,fromWireType:function(c){c||M("Cannot use deleted val. handle = "+c);var d=Y.get(c).value;c>=Y.W&&0===--Y.get(c).na&&Y.da(c);return d},toWireType:function(c,d){return eb(d)},argPackAdvance:8,readValueFromPointer:gb,M:null})},h:function(b,a,c){c=Pa(c);a=I(a);O(b,{name:a,fromWireType:function(d){return d},toWireType:function(d,e){return e}, 53 | argPackAdvance:8,readValueFromPointer:tb(a,c),M:null})},b:function(b,a,c,d,e){a=I(a);-1===e&&(e=4294967295);e=Pa(c);var g=f=>f;if(0===d){var k=32-8*c;g=f=>f<>>k}c=a.includes("unsigned")?function(f,l){return l>>>0}:function(f,l){return l};O(b,{name:a,fromWireType:g,toWireType:c,argPackAdvance:8,readValueFromPointer:Oa(a,e,0!==d),M:null})},a:function(b,a,c){function d(g){g>>=2;var k=B;return new e(k.buffer,k[g+1],k[g])}var e=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array, 54 | Float64Array,BigInt64Array,BigUint64Array][a];c=I(c);O(b,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{ia:!0})},e:function(b,a){a=I(a);var c="std::string"===a;O(b,{name:a,fromWireType:function(d){var e=B[d>>2],g=d+4;if(c)for(var k=g,f=0;f<=e;++f){var l=g+f;if(f==e||0==y[l]){k=k?vb(y,k,l-k):"";if(void 0===n)var n=k;else n+=String.fromCharCode(0),n+=k;k=l+1}}else{n=Array(e);for(f=0;f=l?f++:2047>=l?f+=2:55296<=l&&57343>=l?(f+=4,++g):f+=3}else f=e.length;g=f;f=Gb(4+g+1);l=f+4;B[f>>2]=g;if(c&&k){if(k=l,l=g+1,g=y,0=m){var q=e.charCodeAt(++n);m=65536+ 56 | ((m&1023)<<10)|q&1023}if(127>=m){if(k>=l)break;g[k++]=m}else{if(2047>=m){if(k+1>=l)break;g[k++]=192|m>>6}else{if(65535>=m){if(k+2>=l)break;g[k++]=224|m>>12}else{if(k+3>=l)break;g[k++]=240|m>>18;g[k++]=128|m>>12&63}g[k++]=128|m>>6&63}g[k++]=128|m&63}}g[k]=0}}else if(k)for(k=0;kna;var f=1}else 4===a&&(d=Ab,e=Bb,g=Cb,k=()=>B,f=2);O(b,{name:c,fromWireType:function(l){for(var n=B[l>>2],m=k(),q,r=l+4,t=0;t<=n;++t){var v=l+4+t*a;if(t==n||0==m[v>>f])r=d(r,v-r),void 0===q?q=r:(q+=String.fromCharCode(0),q+=r),r=v+a}X(l);return q},toWireType:function(l,n){"string"!=typeof n&&M("Cannot pass non-string to C++ string type "+c);var m=g(n),q=Gb(4+m+a);B[q>>2]=m>>f;e(n,q+4,m+a);null!==l&&l.push(X,q);return q},argPackAdvance:8, 58 | readValueFromPointer:gb,M:function(l){X(l)}})},k:function(b,a){a=I(a);O(b,{pa:!0,name:a,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},f:function(){w("")},q:function(b,a,c){y.copyWithin(b,a,a+c)},m:function(b){var a=y.length;b>>>=0;if(2147483648=c;c*=2){var d=a*(1+.2/c);d=Math.min(d,b+100663296);var e=Math,g=e.min;d=Math.max(b,d);d+=(65536-d%65536)%65536;a:{var k=la.buffer;try{la.grow(g.call(e,2147483648,d)-k.byteLength+65535>>>16);sa();var f=1;break a}catch(l){}f= 59 | void 0}if(f)return!0}return!1},p:function(){return 52},n:function(){return 70},o:function(b,a,c,d){for(var e=0,g=0;g>2],f=B[a+4>>2];a+=8;for(var l=0;l>2]=e;return 0}},Ib=function(){function b(c){c=c.exports;h.asm=c;la=h.asm.u;sa();ta=h.asm.z;va.unshift(h.asm.v);D--;h.monitorRunDependencies&&h.monitorRunDependencies(D);if(0==D&&(null!==ya&&(clearInterval(ya),ya=null),E)){var d=E;E=null; 60 | d()}return c}var a={a:Hb};D++;h.monitorRunDependencies&&h.monitorRunDependencies(D);if(h.instantiateWasm)try{return h.instantiateWasm(a,b)}catch(c){u("Module.instantiateWasm callback failed with error: "+c),ba(c)}a=Aa(a);return b(a[0])}();h._opus_strerror=Ib.w;var Gb=h._malloc=Ib.x,X=h._free=Ib.y,nb=h.___getTypeName=Ib.A;h.__embind_initialize_bindings=Ib.B; 61 | h.setValue=function(b,a,c="i8"){c.endsWith("*")&&(c="*");switch(c){case "i1":x[b>>0]=a;break;case "i8":x[b>>0]=a;break;case "i16":z[b>>1]=a;break;case "i32":A[b>>2]=a;break;case "i64":Ba=[a>>>0,(G=a,1<=+Math.abs(G)?0>>0:~~+Math.ceil((G-+(~~G>>>0))/4294967296)>>>0:0)];A[b>>2]=Ba[0];A[b+4>>2]=Ba[1];break;case "float":oa[b>>2]=a;break;case "double":ra[b>>3]=a;break;case "*":B[b>>2]=a;break;default:w("invalid type for setValue: "+c)}}; 62 | h.getValue=function(b,a="i8"){a.endsWith("*")&&(a="*");switch(a){case "i1":return x[b>>0];case "i8":return x[b>>0];case "i16":return z[b>>1];case "i32":return A[b>>2];case "i64":return pa[b>>3];case "float":return oa[b>>2];case "double":return ra[b>>3];case "*":return B[b>>2];default:w("invalid type for getValue: "+a)}};var Jb;E=function Kb(){Jb||Lb();Jb||(E=Kb)}; 63 | function Lb(){function b(){if(!Jb&&(Jb=!0,h.calledRun=!0,!ma)){Ca(va);aa(h);if(h.onRuntimeInitialized)h.onRuntimeInitialized();if(h.postRun)for("function"==typeof h.postRun&&(h.postRun=[h.postRun]);h.postRun.length;){var a=h.postRun.shift();wa.unshift(a)}Ca(wa)}}if(!(0 2 | 3 | #include "../opus-native/include/opus.h" 4 | 5 | #define APPLICATION OPUS_APPLICATION_AUDIO 6 | #define MAX_PACKET_SIZE 1276 * 3 7 | #define MAX_FRAME_SIZE 960 * 6 8 | 9 | using namespace emscripten; 10 | 11 | class OpusScriptHandler { 12 | private: 13 | int channels; 14 | 15 | OpusEncoder* encoder; 16 | OpusDecoder* decoder; 17 | 18 | opus_int16* out_pcm; 19 | public: 20 | OpusScriptHandler(opus_int32 sampling_rate, int channels, int application): 21 | channels(channels) { 22 | 23 | out_pcm = new opus_int16[MAX_FRAME_SIZE * channels * 2]; 24 | 25 | int encoder_error; 26 | encoder = opus_encoder_create(sampling_rate, channels, application, &encoder_error); 27 | if(encoder_error < 0) { 28 | throw encoder_error; 29 | } 30 | 31 | int decoder_error; 32 | decoder = opus_decoder_create(sampling_rate, channels, &decoder_error); 33 | if(decoder_error < 0) { 34 | throw decoder_error; 35 | } 36 | } 37 | 38 | ~OpusScriptHandler() { 39 | opus_encoder_destroy(encoder); 40 | opus_decoder_destroy(decoder); 41 | delete out_pcm; 42 | } 43 | 44 | int _encode(int input_buffer, int bytes, int output_buffer, int frame_size) { 45 | opus_int16* input = reinterpret_cast(input_buffer); 46 | unsigned char* output = reinterpret_cast(output_buffer); 47 | 48 | for(int i = 0; i < bytes; i++) { 49 | input[i] = input[2 * i + 1] << 8 | input[2 * i]; 50 | } 51 | 52 | return opus_encode(encoder, input, frame_size, output, MAX_PACKET_SIZE); 53 | } 54 | 55 | int _decode(int input_buffer, int bytes, int output_buffer) { 56 | unsigned char* input = reinterpret_cast(input_buffer); 57 | short* pcm = reinterpret_cast(output_buffer); 58 | 59 | int len = opus_decode(decoder, input, bytes, out_pcm, MAX_FRAME_SIZE, 0); 60 | 61 | for(int i = 0; i < len * channels; i++) { 62 | pcm[2 * i] = out_pcm[i] & 0xFF; 63 | pcm[2 * i + 1] = (out_pcm[i] >> 8) & 0xFF; 64 | } 65 | 66 | return len; 67 | } 68 | 69 | int _encoder_ctl(int ctl, int arg) { 70 | return opus_encoder_ctl(encoder, ctl, arg); 71 | } 72 | 73 | int _decoder_ctl(int ctl, int arg) { 74 | return opus_decoder_ctl(decoder, ctl, arg); 75 | } 76 | 77 | static void destroy_handler(OpusScriptHandler *handler) { 78 | delete handler; 79 | } 80 | }; 81 | 82 | EMSCRIPTEN_BINDINGS(OpusScriptHandler) { 83 | class_("OpusScriptHandler") 84 | .constructor() 85 | .function("_encode", &OpusScriptHandler::_encode) 86 | .function("_decode", &OpusScriptHandler::_decode) 87 | .function("_encoder_ctl", &OpusScriptHandler::_encoder_ctl) 88 | .function("_decoder_ctl", &OpusScriptHandler::_decoder_ctl) 89 | .class_function("destroy_handler", &OpusScriptHandler::destroy_handler, allow_raw_pointers()); 90 | } 91 | --------------------------------------------------------------------------------