diff --git a/README.md b/README.md index 97dd2d9..0cf7d4e 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ With **wavefile** you can: And more. -**wavefile** is extensively tested, and the test folder contains samples of all supported formats. Please note that some formats (like 8-bit A-Law and 64-bit floating point) are not widely supported and may not load in every player. +**wavefile** is extensively tested and contains samples of all supported formats. Please note that some formats (like 8-bit A-Law and 64-bit floating point) are not widely supported and may not load in every player. ## Install ``` @@ -190,6 +190,9 @@ console.log(wav.factChunkId); console.log(wav.factChunkSize); console.log(wav.dwSampleLength); +// "bext" +console.log(wav.bextChunkFields); + // "data" console.log(wav.dataChunkId); console.log(wav.dataChunkSize); @@ -198,6 +201,29 @@ console.log(wav.dataChunkSize); console.log(wav.samples); ``` +### BWF data +BWF data ("bext" chunk) is stored in the *bextChunkFields* property in human-readable form. +You may edit the data in the "bext" chunk by editing the *bextChunkFields* property on a WaveFile object. +```javascript +wav.bextChunkFields = { + "description": "", // 256 chars + "originator": "", // 32 chars + "originatorReference": "", // 32 chars + "originationDate": "", // 10 chars + "originationTime": "", // 8 chars + "timeReference": "", // 64-bit value kept as an array of 8 bytes + "version": "", // 16-bit number + "UMID": "", // 64 chars + "loudnessValue": "", // 16-bit number + "loudnessRange": "", // 16-bit number + "maxTruePeakLevel": "", // 16-bit number + "maxMomentaryLoudness": "", // 16-bit number + "maxShortTermLoudness": "", // 16-bit number + "reserved": "", // 180 chars + "codingHistory": "" // string, unlimited size +}; +``` + ### The samples Range: - 0 to 255 for 8-bit diff --git a/dist/wavefile-min.js b/dist/wavefile-min.js index 48527b1..06db779 100644 --- a/dist/wavefile-min.js +++ b/dist/wavefile-min.js @@ -1,14 +1,14 @@ /* - endianness - Swap endianness in byte arrays. - Copyright (c) 2017 Rafael da Silva Rocha. - https://github.com/rochars/endianness - byte-data Readable data to and from byte buffers. Copyright (c) 2017 Rafael da Silva Rocha. https://github.com/rochars/byte-data + endianness + Swap endianness in byte arrays. + Copyright (c) 2017 Rafael da Silva Rocha. + https://github.com/rochars/endianness + alawmulaw JavaScript A-Law and mu-Law codecs. Copyright (c) 2018 Rafael da Silva Rocha. @@ -40,85 +40,70 @@ https://wiki.multimedia.cx/index.php/IMA_ADPCM */ -var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.objectCreate=$jscomp.ASSUME_ES5||"function"==typeof Object.create?Object.create:function(a){var d=function(){};d.prototype=a;return new d};$jscomp.underscoreProtoCanBeSet=function(){var a={a:!0},d={};try{return d.__proto__=a,d.a}catch(h){}return!1}; -$jscomp.setPrototypeOf="function"==typeof Object.setPrototypeOf?Object.setPrototypeOf:$jscomp.underscoreProtoCanBeSet()?function(a,d){a.__proto__=d;if(a.__proto__!==d)throw new TypeError(a+" is not extensible");return a}:null; -$jscomp.inherits=function(a,d){a.prototype=$jscomp.objectCreate(d.prototype);a.prototype.constructor=a;if($jscomp.setPrototypeOf){var h=$jscomp.setPrototypeOf;h(a,d)}else for(h in d)if("prototype"!=h)if(Object.defineProperties){var g=Object.getOwnPropertyDescriptor(d,h);g&&Object.defineProperty(a,h,g)}else a[h]=d[h];a.superClass_=d.prototype};$jscomp.owns=function(a,d){return Object.prototype.hasOwnProperty.call(a,d)}; -$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,d,h){a!=Array.prototype&&a!=Object.prototype&&(a[d]=h.value)};$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this); -$jscomp.polyfill=function(a,d,h,g){if(d){h=$jscomp.global;a=a.split(".");for(g=0;gf[c].length&&(f[c]=Array(5-f[c].length).join("0")+f[c])}function b(f,e,c){(2==e||16==e)&&2>f[c].length&&(f[c]="0"+f[c])}function c(f,e){for(;f.lengthparseInt(e/2,10)-1&&(f-=e);return f};a.exports.padding=g;a.exports.paddingNibble=l;a.exports.paddingCrumb=b;a.exports.bytePadding=k;a.exports.lPadZeros=c;a.exports.fixFloat16Endianness=function(f,e){e.float&&16==e.bits&&m(f,2)};a.exports.getType=function(f,e,c){f=Object.assign({},f);f.base=e;f.single=c;64==f.bits&&(f.float=!0);f.float&&(f.signed=!0);f.offset=8>f.bits? -1:f.bits/8;return f};a.exports.turnToArray=function(f){Array.isArray(f)||"string"==typeof f||(f=[f]);return f}},function(a,d){a.exports=function(a,d){for(var k=a.length,l=0;lh?u=h:u>10,b=c&1023;return(e?Math.pow(2,e-15)*(1+b/1024):b/1024*.00006103515625)*(c>>15?-1:1)};a.exports.decodeFloat64=function(c){if("0,0,0,0,0,0,0,0"== -c.toString())return 0;c=g(c);for(var e="1"+c.substr(12,52),b=1,f=0,a=0;a=c&&(e=2147483648,c=-c);var b=Math.floor(Math.log(c)/Math.log(2)),f=Math.floor(c/Math.pow(2,b)*Math.pow(2,52));c=f&4294967295;f/=Math.pow(2,32);return[e|b+1023<<20|f&1048575,c]};a.exports.toHalf=function(c){l[0]=c;var e=b[0];c=e>>16&32768;var m= -e>>12&2047;e=e>>23&255;return 103>e?c:(c|e-112<<10|m>>1)+(m&1)}},function(a,d){function h(a){g[0]=a;return k[0]}d=new Int8Array(4);var g=new Int32Array(d.buffer,0,1),k=new Float32Array(d.buffer,0,1);a.exports=h;a.exports.pack=h;a.exports.unpack=function(a){k[0]=a;return g[0]}},function(a,d,h){function g(c){return c.signed&&!c.float?b.signed:function(e){return e}}var k=h(14),l=h(2),b=h(0);a.exports.fromBytes=function(c,e){var m=e.bits;b.fixFloat16Endianness(c,e);b.makeBigEndian(c,e.be,m);m=e.base; -if(10!=m)for(var f=0,a=c.length;fm?8:m)+"Bit"+(e.float?"Float":"")]);f=[];a=0;for(var d=c.length-(e.offset-1),h=g(e);athis.max&&(a-=2*this.max+2); -return a};d.prototype.overflow=function(a){a>this.max?a=this.max:athis.bits?1:this.realBits/8;this.setReader_();this.setWriter_();this.float||this.setMinMax_()};d.prototype.setReader_=function(){this.reader=this.char?g.BitReader.readChar:g.BitReader["read"+(8>this.bits?8:this.realBits)+"Bit"+(this.float?"Float":"")]};d.prototype.setWriter_=function(){this.writer=this.char?g.BitWriter.writeString:g.BitWriter["write"+ -this.realBits+"Bit"+(this.float?"Float":"")]};d.prototype.setMinMax_=function(){var a=Math.pow(2,this.bits);this.signed?(this.max=a/2-1,this.min=-a/2):(this.max=a-1,this.min=0)};d.prototype.setRealBits_=function(){this.realBits=8=this.bits?16:24>=this.bits?24:32>=this.bits?32:40>=this.bits?40:48>=this.bits?48:53>=this.bits?53:64:this.bits};a.exports=d},function(a,d,h){var g=new Float32Array(1),k=new Int32Array(g.buffer),l=new Float64Array(1),b=new Uint32Array(l.buffer),c=h(27);d=function(e){var b= -c.call(this,e)||this;b.char=e["char"];b.float=e["float"];b.buildType_();return b};$jscomp.inherits(d,c);d.decode=c.decode;d.encode=c.encode;d.decodeSample=c.decodeSample;d.encodeSample=c.encodeSample;d.prototype.read16F_=function(e,c){e=this.read_(e,c,{bits:16,offset:2});c=(e&31744)>>10;var f=e&1023;return(c?Math.pow(2,c-15)*(1+f/1024):f/1024*.00006103515625)*(e>>15?-1:1)};d.prototype.read32F_=function(e,c){k[0]=this.read_(e,c,{bits:32,offset:4});return g[0]};d.prototype.read64F_=function(e,c){b[0]= -this.read_(e,c,{bits:32,offset:4});b[1]=this.read_(e,c+4,{bits:32,offset:4});return l[0]};d.prototype.readChar_=function(e,c){for(var f="",b=0;b>16&32768;var a= -b>>12&2047;b=b>>23&255;103<=b&&(c=(c|b-112<<10|a>>1)+(a&1));e[f++]=c&255;e[f++]=c>>>8&255;return f};d.prototype.writeChar_=function(e,c,f){e[f++]=c.charCodeAt(0);return f};d.prototype.buildType_=function(){this.setReader_();this.setWriter_();this.float&&(this.min=-Infinity,this.max=Infinity)};d.prototype.setReader_=function(){this.float?16==this.bits?this.reader=this.read16F_:32==this.bits?this.reader=this.read32F_:64==this.bits&&(this.reader=this.read64F_):this.char?this.reader=this.readChar_:32< -this.bits&&(this.reader=this.readBits_)};d.prototype.setWriter_=function(){this.float?16==this.bits?this.writer=this.write16F_:32==this.bits?this.writer=this.write32F_:64==this.bits&&(this.writer=this.write64F_):this.char&&(this.writer=this.writeChar_)};a.exports=d},function(a,d,h){a.exports.alaw=h(28);a.exports.mulaw=h(29)},function(a,d,h){var g=h(3),k=g.uInt8,l=h(17),b=h(8),c=h(18),e=h(20),m=h(24),f=h(11).alaw,n=h(11).mulaw;a=function(f){var e=c.call(this)||this;f&&e.fromBuffer(f);return e};$jscomp.inherits(a, -c);a.prototype.fromScratch=function(f,e,c,b,a){a=void 0===a?{}:a;this.validBitsPerSample=this.cbSize=0;this.factChunkId="";this.factChunkSize=0;this.factChunkData=[];this.dwSampleLength=0;a.container||(a.container="RIFF");var m=parseInt(c,10)/8;this.chunkSize=36+b.length*m;this.fmtChunkSize=16;this.byteRate=f*m*e;this.blockAlign=f*m;this.chunkId=a.container;this.format="WAVE";this.fmtChunkId="fmt ";this.audioFormat=this.headerFormats_[c];this.numChannels=f;this.sampleRate=e;this.bitsPerSample=parseInt(c, -10);this.dataChunkId="data";this.dataChunkSize=b.length*m;this.samples=b;this.bitDepth=c;"4"==c&&(this.chunkSize=44+b.length,this.fmtChunkSize=20,this.byteRate=4055,this.blockAlign=256,this.bitsPerSample=4,this.dataChunkSize=b.length,this.cbSize=2,this.validBitsPerSample=505,this.factChunkId="fact",this.factChunkSize=4,this.dwSampleLength=2*b.length);if("8a"==c||"8m"==c)this.chunkSize=44+b.length,this.fmtChunkSize=20,this.cbSize=2,this.validBitsPerSample=8,this.factChunkId="fact",this.factChunkSize= -4,this.dwSampleLength=b.length};a.prototype.fromBuffer=function(f){this.readRIFFChunk_(f);var c="RIFX"==this.chunkId;f=e.read(f,c);this.readFmtChunk_(f.subChunks);this.readFactChunk_(f.subChunks);this.readBextChunk_(f.subChunks);this.readCueChunk_(f.subChunks);this.readDataChunk_(f.subChunks,{be:c,single:!0});this.bitDepth=3==this.audioFormat&&32==this.bitsPerSample?"32f":this.bitsPerSample.toString()};a.prototype.toBuffer=function(){this.checkWriteInput_();return new Uint8Array(this.createWaveFile_())}; -a.prototype.toRIFF=function(){this.chunkId="RIFF";this.LEorBE()};a.prototype.toRIFX=function(){this.chunkId="RIFX";this.LEorBE()};a.prototype.toBitDepth=function(f){l.toBitDepth(this.samples,this.bitDepth,f);this.fromScratch(this.numChannels,this.sampleRate,f,g.unpackArray(this.samples,k),{container:this.chunkId})};a.prototype.interleave=function(){var f=[],c,e,b=this.samples[0].length;for(c=0;cthis.numChannels||65535this.sampleRate||4294967295>>8&255;b[e++]=c>>>16&255;b[e++]=c>>>24&255;return e}var k=h(5),l=h(6);a.exports.write64BitFloat=function(b,c,e){c=k.toFloat64(c);e=g(b,c[1],e);return g(b,c[0],e)};a.exports.write48Bit=function(b,c,e){b[e++]=c&255;b[e++]=c>>8&255;b[e++]=c>>16&255;b[e++]=c>>24&255;b[e++]=c/4294967296&255;b[e++]=c/1099511627776&255;return e};a.exports.write40Bit=function(b,c,e){b[e++]=c&255;b[e++]=c>>8&255;b[e++]=c>>16&255;b[e++]=c>> -24&255;b[e++]=c/4294967296&255;return e};a.exports.write32BitFloat=function(b,c,e){c=l.unpack(c);b[e++]=c&255;b[e++]=c>>>8&255;b[e++]=c>>>16&255;b[e++]=c>>>24&255;return e};a.exports.write32Bit=g;a.exports.write24Bit=function(b,c,e){b[e++]=c&255;b[e++]=c>>>8&255;b[e++]=c>>>16&255;return e};a.exports.write16Bit=function(b,c,e){b[e++]=c&255;b[e++]=c>>>8&255;return e};a.exports.write16BitFloat=function(b,c,e){c=k.toHalf(c);b[e++]=c>>>8&255;b[e++]=c&255;return e};a.exports.write8Bit=function(b,c,e){b[e++]= -c&255;return e};a.exports.write4Bit=function(b,c,e){b[e++]=c&15;return e};a.exports.write2Bit=function(b,c,e){b[e++]=0>c?c+4:c;return e};a.exports.write1Bit=function(b,c,e){b[e++]=c?1:0;return e};a.exports.writeString=function(b,c,e){b[e++]=c.charCodeAt(0);return e}},function(a,d,h){function g(c,b,f){--f;for(var e="";0<=f;)e+=l.bytePadding(c[f+b].toString(2),2),f--;return parseInt(e,2)}function k(c,b){return(c[3+b]<<24|c[2+b]<<16|c[1+b]<<8|c[b])>>>0}var l=h(0),b=h(5),c=h(6);a.exports.readChar=function(c, -b,f){var e="",a=0;for(f=f.bits/8;ab[e].bits?1:b[e].bits/8;a=a.concat(k(c.slice(d,d+m),b[e],f));d+=m;e++}return a};a.exports.packStruct=function(c,b,f){f=void 0===f?10:f;if(c.lengtha.bits?a.bits:a.realBits/8),l.getType(a,b));return c=a.char?c.slice(0,a.bits/8):c[0]}var l=h(22),b=h(9);d.pack=g;d.unpack=k;d.packArray=function(c,a,b){return l.toBytes(c,l.getType(a,void 0===b?10:b))};d.unpackArray=function(c,a,b){return l.fromBytes(c,l.getType(a,void 0===b?10:b))};d.unpackStruct=function(a,b,d){d=void 0===d?10:d;for(var c=a.length,e=0,m=0;mb[e].bits?1:b[e].realBits/8;c=c.concat(k(a.slice(m,m+l),b[e],d));m+=l;e++}return c};d.packStruct=function(a,b,d){d=void 0===d?10:d;if(a.lengthb.realBits?(2==b.base?b.bits:5>b.bits?1:2)+1:(2==b.base?8:2)+1;a>10;c=b&1023;return(a?Math.pow(2,a-15)*(1+c/1024):c/1024*.00006103515625)*(b>>15?-1:1)},read24Bit:function(a,b){return a[2+b]<<16|c.read16Bit(a,b)},read32Bit:function(a,b){return(a[3+b]<<24|c.read24Bit(a,b))>>>0}, -read32BitFloat:function(a,b){k[0]=c.read32Bit(a,b);return g[0]},read40Bit:function(a,c){return h(a,c,5)},read48Bit:function(a,c){return h(a,c,6)},read53Bit:function(a,c){return h(a,c,7)},read64BitFloat:function(a,f){b[0]=c.read32Bit(a,f);b[1]=c.read32Bit(a,f+4);return l[0]},readChar:function(a,c,b){var f="",e=0;for(b=b.bits/8;e>>24&255;return b},write24Bit:function(a,c,b){b=e.write16Bit(a,c,b);a[b++]=c>>>16&255;return b},write16Bit:function(a, -c,b){a[b++]=c&255;a[b++]=c>>>8&255;return b},write16BitFloat:function(a,c,b){g[0]=c;var f=k[0];c=f>>16&32768;var e=f>>12&2047;f=f>>23&255;103<=f&&(c=(c|f-112<<10|e>>1)+(e&1));a[b]=c&255;a[b+1]=c>>>8&255;return b+2},write8Bit:function(a,c,b){a[b++]=c&255;return b},write4Bit:function(a,c,b){a[b++]=c&15;return b},write2Bit:function(a,c,b){a[b++]=0>c?c+4:c;return b},write1Bit:function(a,c,b){a[b++]=c?1:0;return b},writeString:function(a,c,b){a[b++]=c.charCodeAt(0);return b}};d.BitWriter=e;d.BitReader= -c},function(a,d,h){function g(a){a-=n;if(0<=a)var c=0;else c=8,a=-a;var b=f[t],e=b>>3;a>b&&(c|=4,a-=b,e+=b);b>>=1;a>b&&(c|=2,a-=b,e+=b);b>>=1;a>b&&(c|=1,e+=b);n=c&8?n-e:n+e;-32768>n?n=-32768:32767t?t=0:88>1);a&1&&(b+=r>>2);b+=r>>3;a&8&&(b=-b);q+=b;32767q&&(q=-32767);p+=m[a];0>p?p=0:88f.length;)f.push(0);return f}function b(a){q=c.unpack([a[0],a[1]],e);p=a[2];r=f[p];for(var b=[q,c.unpack([a[2],a[3]],e)],d=4;d>4;b.push(k(g<<4^h));b.push(k(g))}return b}var c=h(25),e=c.int16,m=[-1,-1,-1,-1,2,4,6,8,-1,-1,-1,-1,2,4,6,8],f=[7,8,9,10,11,12,13,14,16,17,19,21,23,25,28,31,34,37,41,45,50,55,60,66,73,80,88,97,107,118,130,143,157,173,190,209,230,253,279,307,337,371,408, -449,494,544,598,658,724,796,876,963,1060,1166,1282,1411,1552,1707,1878,2066,2272,2499,2749,3024,3327,3660,4026,4428,4871,5358,5894,6484,7132,7845,8630,9493,10442,11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794,32767],n=0,t=0,q=0,p=0,r=7;a.exports.encode=function(a){for(var b=[],c=[],e=0;eb.bits?b.bits:b.realBits/8),l.getType(b,d));return a=b.char?a.slice(0,b.bits/8):a[0]}var l=h(26),b=h(10);d.pack=g;d.unpack=k;d.packArray=function(a,b,d){return l.toBytes(a,l.getType(b, -void 0===d?10:d))};d.unpackArray=function(a,b,d){return l.fromBytes(a,l.getType(b,void 0===d?10:d))};d.unpackStruct=function(a,b,d){d=void 0===d?10:d;for(var c=a.length,e=0,h=0;hb[e].bits?1:b[e].realBits/8;c=c.concat(k(a.slice(h,h+g),b[e],d));h+=g;e++}return c};d.packStruct=function(a,b,d){d=void 0===d?10:d;if(a.lengththis.max&&(a-=2*this.max+2);return a};d.prototype.overflow=function(a){a>this.max?a=this.max:a>>0;return this.overflow(this.sign(g))}; -d.prototype.readBits_=function(a,d,k){k=void 0===k?this:k;for(var g="",b=0;bthis.bits?1:Math.ceil(this.realBits/8)};d.prototype.setMinMax_=function(){var a=Math.pow(2,this.bits);this.signed?(this.max=a/2-1,this.min=-a/2):(this.max=a-1,this.min=0)};d.prototype.validateWordSize_=function(){if(1>this.bits||64=this.bits?16:24>=this.bits?24:32>=this.bits?32:40>=this.bits?40:48>=this.bits?48:56>=this.bits?56: -64:this.bits};d.prototype.setLastByteMask_=function(){var a=8-(this.realBits-this.bits);this.lastByteMask=Math.pow(2,0l.bits?a[k++]=0>d?d+Math.pow(2,l.bits):d:a[k++]=d&255;return k};a.exports=d},function(a,d){function h(a){var d=[1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, -7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7],b;a=-32768==a?-32767:a;(b=~a>>8&128)||(a*=-1);32635>8&127],a=d<<4|a>>d+3&15):a>>=4;return a^b^85}function g(a){var d=0;a^=85;a&128&&(a&=-129,d=-1);var b=((a&240)>>4)+4;a=4!=b?1<a){a=132-a;var d=127}else a+=132,d=255;32767>7;c&240&&(c>>=4,b+=4);c&12&&(c>>=2,b+=2);c&2&&(b+=1);c=b;return(c<<4|a>>c+3&15)^d}function g(a){a=~a;var d=((a&15)<<3)+132<<((a&112)>>4);return a&128?132-d:d-132}a.exports.encodeSample=h;a.exports.decodeSample=g;a.exports.encode=function(a){for(var d=[],b=0;bb.bits?b.bits:b.realBits/8),e.getType(b,f));return a=b.char?a.slice(0,b.bits/8):a[0]}var e=h(7),b=h(1);a.pack=c;a.unpack=k;a.packArray=function(a,b,f){return e.toBytes(a,e.getType(b,void 0===f?10:f))};a.unpackArray=function(a,b,f){return e.fromBytes(a,e.getType(b,void 0===f?10:f))};a.unpackStruct=function(a, +b,f){f=void 0===f?10:f;for(var d=a.length,m=0,e=0;eb[m].bits?1:b[m].realBits/8;d=d.concat(k(a.slice(e,e+c),b[m],f));e+=c;m++}return d};a.packStruct=function(a,b,f){f=void 0===f?10:f;if(a.length>10;var d=a&1023;return(b?Math.pow(2,b-15)*(1+d/1024):d/1024*.00006103515625)*(a>>15?-1:1)};a.prototype.read32F_=function(a,b){k[0]=this.read_(a,b,{bits:32,offset:4});return c[0]};a.prototype.read64F_=function(a,f){b[0]=this.read_(a,f,{bits:32,offset:4});b[1]=this.read_(a,f+4,{bits:32,offset:4});return e[0]};a.prototype.readChar_=function(a,b){for(var d="",m=0;m>16&32768;var f=m>>12&2047;m=m>>23&255;103<=m&&(b=(b|m-112<<10|f>>1)+(f&1));a[d++]=b&255;a[d++]=b>>>8&255;return d};a.prototype.writeChar_=function(a,b,d){a[d++]=b.charCodeAt(0);return d};a.prototype.buildType_= +function(){this.setReader_();this.setWriter_();this.float&&(this.min=-Infinity,this.max=Infinity)};a.prototype.setReader_=function(){this.float?16==this.bits?this.reader=this.read16F_:32==this.bits?this.reader=this.read32F_:64==this.bits&&(this.reader=this.read64F_):this.char?this.reader=this.readChar_:32this.max&&(a-=2*this.max+2);return a};a.prototype.overflow=function(a){a>this.max?a=this.max:athis.bits?1:this.realBits/8;this.setReader_();this.setWriter_();this.float||this.setMinMax_()};a.prototype.setReader_=function(){this.reader=this.char?c.BitReader.readChar:c.BitReader["read"+(8>this.bits?8:this.realBits)+"Bit"+(this.float?"Float":"")]};a.prototype.setWriter_=function(){this.writer=this.char?c.BitWriter.writeString:c.BitWriter["write"+this.realBits+"Bit"+(this.float?"Float":"")]};a.prototype.setMinMax_=function(){var a=Math.pow(2,this.bits); +this.signed?(this.max=a/2-1,this.min=-a/2):(this.max=a-1,this.min=0)};a.prototype.setRealBits_=function(){this.realBits=8=this.bits?16:24>=this.bits?24:32>=this.bits?32:40>=this.bits?40:48>=this.bits?48:53>=this.bits?53:64:this.bits};g.exports=a},function(g,a,h){g.exports.alaw=h(17);g.exports.mulaw=h(18)},function(g,a,h){h(0);var c=h(9),k=h(3),e=h(10),b=h(12),l=h(16),n=h(5).alaw,f=h(5).mulaw;g=function(d){var a=e.call(this)||this;d&&a.fromBuffer(d);return a};$jscomp.inherits(g,e);g.prototype.fromScratch= +function(d,a,b,f,e){e=void 0===e?{}:e;this.validBitsPerSample=this.cbSize=0;this.factChunkId="";this.factChunkSize=0;this.factChunkData=[];this.dwSampleLength=0;e.container||(e.container="RIFF");var m=parseInt(b,10)/8;this.chunkSize=36+f.length*m;this.fmtChunkSize=16;this.byteRate=d*m*a;this.blockAlign=d*m;this.chunkId=e.container;this.format="WAVE";this.fmtChunkId="fmt ";this.audioFormat=this.headerFormats_[b];this.numChannels=d;this.sampleRate=a;this.bitsPerSample=parseInt(b,10);this.dataChunkId= +"data";this.dataChunkSize=f.length*m;this.samples=f;this.bitDepth=b;"4"==b&&(this.chunkSize=44+f.length,this.fmtChunkSize=20,this.byteRate=4055,this.blockAlign=256,this.bitsPerSample=4,this.dataChunkSize=f.length,this.cbSize=2,this.validBitsPerSample=505,this.factChunkId="fact",this.factChunkSize=4,this.dwSampleLength=2*f.length);if("8a"==b||"8m"==b)this.chunkSize=44+f.length,this.fmtChunkSize=20,this.cbSize=2,this.validBitsPerSample=8,this.factChunkId="fact",this.factChunkSize=4,this.dwSampleLength= +f.length};g.prototype.fromBuffer=function(d){this.readRIFFChunk_(d);var a="RIFX"==this.chunkId;d=b.read(d,a);this.readFmtChunk_(d.subChunks);this.readFactChunk_(d.subChunks);this.readBextChunk_(d.subChunks);this.readCueChunk_(d.subChunks);this.readDataChunk_(d.subChunks,{be:a,single:!0});this.bitDepth=3==this.audioFormat&&32==this.bitsPerSample?"32f":this.bitsPerSample.toString()};g.prototype.toBuffer=function(){this.checkWriteInput_();return new Uint8Array(this.createWaveFile_())};g.prototype.toRIFF= +function(){this.chunkId="RIFF";this.LEorBE()};g.prototype.toRIFX=function(){this.chunkId="RIFX";this.LEorBE()};g.prototype.toBitDepth=function(d){c.toBitDepth(this.samples,this.bitDepth,d);this.fromScratch(this.numChannels,this.sampleRate,d,this.samples,{container:this.chunkId})};g.prototype.interleave=function(){var d=[],a,b,f=this.samples[0].length;for(a=0;athis.numChannels||65535this.sampleRate||4294967295this.max&&(a-=2*this.max+2);return a};a.prototype.overflow=function(a){a> +this.max?a=this.max:a>>0;return this.overflow(this.sign(e))};a.prototype.readBits_=function(a,c,k){k=void 0===k?this:k;for(var e="",b=0;bthis.bits?1:Math.ceil(this.realBits/8)};a.prototype.setMinMax_=function(){var a=Math.pow(2,this.bits);this.signed?(this.max=a/2-1,this.min=-a/2):(this.max=a-1,this.min=0)};a.prototype.validateWordSize_=function(){if(1>this.bits||64=this.bits?16:24>=this.bits?24:32>=this.bits?32:40>=this.bits?40:48>=this.bits?48:56>=this.bits?56:64:this.bits};a.prototype.setLastByteMask_=function(){var a=8-(this.realBits-this.bits);this.lastByteMask=Math.pow(2,0e.bits?a[k++]=0>c?c+Math.pow(2,e.bits):c:a[k++]=c&255;return k};g.exports=a},function(g,a){var h=new Float32Array(1),c={8:256,16:65536,24:16777216, +32:4294967296,"32f":1,64:1},k={intToInt:function(a,b){return a=0b.bits?b.bits:b.realBits/8),e.getType(b,f));return a=b.char?a.slice(0,b.bits/8):a[0]}var e=h(14),b=h(4);a.pack=c;a.unpack=k;a.packArray=function(a, +b,f){return e.toBytes(a,e.getType(b,void 0===f?10:f))};a.unpackArray=function(a,b,f){return e.fromBytes(a,e.getType(b,void 0===f?10:f))};a.unpackStruct=function(a,b,f){f=void 0===f?10:f;for(var d=a.length,c=0,e=0;eb[c].bits?1:b[c].realBits/8;d=d.concat(k(a.slice(e,e+g),b[c],f));e+=g;c++}return d};a.packStruct=function(a,b,f){f=void 0===f?10:f;if(a.lengthb.realBits?(2==b.base?b.bits:5>b.bits?1:2)+1:(2==b.base?8:2)+1;a>10;b=d&1023;return(a?Math.pow(2,a-15)*(1+b/1024):b/1024*.00006103515625)*(d>>15?-1:1)},read24Bit:function(a,b){return a[2+b]<<16|l.read16Bit(a,b)},read32Bit:function(a,b){return(a[3+b]<<24|l.read24Bit(a,b))>>>0},read32BitFloat:function(a,b){k[0]=l.read32Bit(a,b);return c[0]},read40Bit:function(a,b){return h(a,b,5)},read48Bit:function(a,b){return h(a,b,6)},read53Bit:function(a,b){return h(a,b,7)},read64BitFloat:function(a,d){b[0]=l.read32Bit(a, +d);b[1]=l.read32Bit(a,d+4);return e[0]},readChar:function(a,b,c){var d="",e=0;for(c=c.bits/8;e>>24&255;return c},write24Bit:function(a,b,c){c=n.write16Bit(a,b,c);a[c++]=b>>>16&255;return c},write16Bit:function(a,b,c){a[c++]=b&255;a[c++]=b>>>8&255;return c},write16BitFloat:function(a,b,e){c[0]=b;var d=k[0];b=d>>16&32768;var f=d>>12&2047;d=d>>23&255;103<=d&&(b=(b|d-112<<10|f>>1)+(f&1));a[e]=b&255;a[e+1]=b>>>8&255;return e+2},write8Bit:function(a, +b,c){a[c++]=b&255;return c},write4Bit:function(a,b,c){a[c++]=b&15;return c},write2Bit:function(a,b,c){a[c++]=0>b?b+4:b;return c},write1Bit:function(a,b,c){a[c++]=b?1:0;return c},writeString:function(a,b,c){a[c++]=b.charCodeAt(0);return c}};a.BitWriter=n;a.BitReader=l},function(g,a,h){function c(a){a-=m;if(0<=a)var b=0;else b=8,a=-a;var c=d[r],e=c>>3;a>c&&(b|=4,a-=c,e+=c);c>>=1;a>c&&(b|=2,a-=c,e+=c);c>>=1;a>c&&(b|=1,e+=c);m=b&8?m-e:m+e;-32768>m?m=-32768:32767r?r=0:88>1);a&1&&(b+=t>>2);b+=t>>3;a&8&&(b=-b);p+=b;32767p&&(p=-32767);q+=f[a];0>q?q=0:88e.length;)e.push(0);return e}function b(a){p=l.unpack([a[0],a[1]],n);q=a[2];t=d[q];for(var b=[p,l.unpack([a[2],a[3]],n)],c=4;c>4;b.push(k(f<<4^e));b.push(k(f))}return b}var l=h(0),n=l.int16,f=[-1,-1,-1,-1,2,4,6,8,-1,-1,-1,-1,2,4,6,8],d=[7,8,9,10,11,12,13,14,16,17,19,21,23,25,28,31,34,37,41,45,50,55,60,66,73,80,88,97,107,118,130,143,157,173,190,209,230,253,279,307,337,371,408,449,494,544,598,658,724,796,876,963,1060,1166,1282,1411,1552,1707,1878,2066,2272,2499,2749,3024,3327,3660,4026,4428,4871,5358,5894,6484,7132,7845,8630,9493,10442,11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794,32767],m=0,r= +0,p=0,q=0,t=7;g.exports.encode=function(a){for(var b=[],c=[],d=0;d>8&128)||(a*=-1);32635>8&127],a=c<<4|a>>c+3&15):a>>=4;return a^b^85}function c(a){var c=0;a^=85;a&128&&(a&=-129,c=-1);var b=((a&240)>>4)+4;a=4!=b?1<a){a=132-a;var c=127}else a+=132,c=255;32767>7;g&240&&(g>>=4,b+=4);g&12&&(g>>=2,b+=2);g&2&&(b+=1);g=b;return(g<<4|a>>g+3&15)^c}function c(a){a=~a;var c=((a&15)<<3)+132<<((a&112)>>4);return a&128?132-c:c-132}g.exports.encodeSample=h;g.exports.decodeSample=c;g.exports.encode=function(a){for(var c=[],b=0;b} bytes The bytes as binary strings. - * @param {number} base The base. - * @param {number} index The byte to pad. + * Turn a number or fixed-length string into a byte buffer. + * @param {number|string} value The value. + * @param {Object} type One of the available types. + * @param {number} base The base of the output. Optional. Default is 10. + * Possible values are 2, 10 or 16. + * @return {!Array|!Array} */ -function padding(bytes, base, index) { - bytes[index] = bytePadding(bytes[index], base); +function pack(value, type, base=10) { + let values = []; + if (type.char) { + values = type.char ? value.slice(0, type.realBits / 8) : value; + } else if (!Array.isArray(value)) { + values = [value]; + } + return rw.toBytes(values, rw.getType(type, base)); } /** - * Padding with 0s for byte strings. - * @param {string} theByte The byte as a binary or hex string. - * @param {number} base The base. - * @returns {string} The padded byte. + * Turn a byte buffer into a number or a fixed-length string. + * @param {!Array|!Array|Uint8Array} buffer An array of bytes. + * @param {Object} type One of the available types. + * @param {number} base The base of the input. Optional. Default is 10. + * Possible values are 2, 10 or 16. + * @return {number|string} */ -function bytePadding(theByte, base) { - let offset = theByte.length + 1; - if (base == 2) { - offset = 8; - } else if (base == 16) { - offset = 2; +function unpack(buffer, type, base=10) { + let offset = type.bits < 8 ? type.bits : type.realBits / 8; + let values = rw.fromBytes( + buffer.slice(0, offset), + rw.getType(type, base) + ); + if (type.char) { + values = values.slice(0, type.bits / 8); + } else { + values = values[0]; } - return lPadZeros(theByte, offset); + return values; } /** - * Fix the size of nibbles. - * @param {!Array} nibbles The nibble as a binary or hex string. - * @param {number} base The base. - * @param {number} index The nibble offset. + * Turn a array of numbers or a string into a byte buffer. + * @param {!Array|string} values The values. + * @param {Object} type One of the available types. + * @param {number} base The base of the output. Optional. Default is 10. + * Possible values are 2, 10 or 16. + * @return {!Array|!Array} */ -function paddingNibble(nibbles, base, index) { - if (base == 2 && nibbles[index].length < 4) { - nibbles[index] = - new Array((5 - nibbles[index].length)).join("0") + nibbles[index]; - } -} +function packArray(values, type, base=10) { + return rw.toBytes(values, rw.getType(type, base)); +} /** - * Fix the size of crumbs. - * @param {!Array} crumbs The nibble as a binary or hex string. - * @param {number} base The base. - * @param {number} index The nibble offset. + * Turn a byte buffer into a array of numbers or a string. + * @param {!Array|!Array|Uint8Array} buffer The byte array. + * @param {Object} type One of the available types. + * @param {number} base The base of the input. Optional. Default is 10. + * Possible values are 2, 10 or 16. + * @return {!Array|string} */ -function paddingCrumb(crumbs, base, index) { - if ((base == 2 || base == 16) && crumbs[index].length < 2) { - crumbs[index] = '0' + crumbs[index]; - } -} +function unpackArray(buffer, type, base=10) { + return rw.fromBytes(buffer, rw.getType(type, base)); +} /** - * Pad a string with zeros to the left. - * TODO: This should support both arrays and strings. - * @param {string} value The string (representing a binary or hex value). - * @param {number} numZeros the max number of zeros. - * For 1 binary byte string it should be 8. + * Find and return the start index of some string. + * Return -1 if the string is not found. + * @param {!Array|Uint8Array} buffer A byte buffer. + * @param {string} text Some string to look for. + * @return {number} The start index of the first occurrence, -1 if not found */ -function lPadZeros(value, numZeros) { - while (value.length < numZeros) { - value = '0' + value; +function findString(buffer, text) { + let found = ""; + for (let i = 0; i < buffer.length; i++) { + found = unpack( + buffer.slice(i, i + text.length + 1), + new Type({"bits": text.length * 8, "char": true}) + ); + if (found == text) { + return i; + } } - return value; + return -1; } /** - * Swap the endianness to big endian. - * @param {!Array} bytes The values. - * @param {boolean} isBigEndian True if the bytes should be big endian. - * @param {number} bitDepth The bitDepth of the data. + * Turn a struct into a byte buffer. + * A struct is an array of values of not necessarily the same type. + * @param {Array} struct The struct values. + * @param {!Array} def The struct type definition. + * @param {number} base The base of the output. Optional. Default is 10. + * Possible values are 2, 10 or 16. + * @return {!Array|!Array} */ -function makeBigEndian(bytes, isBigEndian, bitDepth) { - if (isBigEndian) { - endianness(bytes, bitDepths.BitDepthOffsets[bitDepth]); +function packStruct(struct, def, base=10) { + if (struct.length < def.length) { + return []; } -} - -/** - * Turn bytes to base 2, 10 or 16. - * @param {!Array|!Array} bytes The bytes. - * @param {number} base The base. - * @param {Function} padFunction The function to use for padding. - */ -function bytesToBase(bytes, base, padFunction=padding) { - if (base != 10) { - let i = 0; - let len = bytes.length; - while (i < len) { - bytes[i] = bytes[i].toString(base); - padFunction(bytes, base, i); - i++; - } + let bytes = []; + for (let i = 0; i < def.length; i++) { + bytes = bytes.concat(pack(struct[i], def[i], base)); } + return bytes; } /** - * Turn the output to the correct base. - * @param {!Array} bytes The bytes. - * @param {number} bitDepth The bit depth of the data. - * @param {number} base The desired base for the output data. - */ -function outputToBase(bytes, bitDepth, base) { - if (bitDepth == 4) { - bytesToBase(bytes, base, paddingNibble); - } else if (bitDepth == 2) { - bytesToBase(bytes, base, paddingCrumb); - } else if(bitDepth == 1) { - bytesToBase(bytes, base, function(){}); - }else { - bytesToBase(bytes, base); + * Turn a byte buffer into a struct. + * A struct is an array of values of not necessarily the same type. + * @param {!Array|!Array|Uint8Array} buffer The byte buffer. + * @param {!Array} def The struct type definition. + * @param {number} base The base of the input. Optional. Default is 10. + * Possible values are 2, 10 or 16. + * @return {Array} + */ +function unpackStruct(buffer, def, base=10) { + if (buffer.length < getStructDefSize(def)) { + return []; + } + let struct = []; + let i = 0; + let j = 0; + while (i < def.length) { + let bits = def[i].bits < 8 ? 1 : def[i].realBits / 8; + struct = struct.concat( + unpack(buffer.slice(j, j + bits), def[i], base) + ); + j += bits; + i++; } + return struct; } /** - * Turn a unsigned number to a signed number. - * @param {number} num The number. - * @param {number} maxValue The max range for the number bit depth. + * Get the length in bytes of a struct definition. + * @param {!Array} def The struct type definition. + * @return {number} The length of the structure in bytes. + * @private */ -function signed(num, maxValue) { - if (num > parseInt(maxValue / 2, 10) - 1) { - num -= maxValue; +function getStructDefSize(def) { + let bits = 0; + for (let i = 0; i < def.length; i++) { + bits += def[i].realBits / 8; } - return num; + return bits; } +// interface +exports.pack = pack; +exports.unpack = unpack; +exports.packArray = packArray; +exports.unpackArray = unpackArray; +exports.unpackStruct = unpackStruct; +exports.packStruct = packStruct; +exports.findString = findString; +exports.Type = Type; +/** + * A char. + * @type {Object} + */ +exports.chr = new Type({"bits": 8, "char": true}); /** - * Fix the endianness of float16 bytes (r/w is always big-endian). - * @param {!Array|Uint8Array} bytes The bytes. - * @param {Object} options The type. + * A 4-char string + * @type {Object} */ -function fixFloat16Endianness(bytes, options) { - if (options.float && options.bits == 16) { - endianness(bytes, 2); - } -} - +exports.fourCC = new Type({"bits": 32, "char": true}); /** - * Get the full type spec for the reading/writing. - * @param {Object} atype One of the available types. - * @param {number} base The base of the input. - * @param {boolean} single True if its a single value, false for array. - * @return {Object} + * Booleans + * @type {Object} */ -function getType(atype, base, single) { - let theType = Object.assign({}, atype); - theType.base = base; - theType.single = single; - if (theType.bits == 64) { - theType.float = true; - } - if (theType.float) { - theType.signed = true; - } - theType.offset = theType.bits < 8 ? 1 : theType.bits / 8; - return theType; -} - +exports.bool = new Type({"bits": 1}); /** - * Make a single value an array in case it is not. - * If the value is a string it stays a string. - * @param {!Array|number|string} values The value or values. - * @return {!Array|string} + * Signed 2-bit integers + * @type {Object} */ -function turnToArray(values) { - if (!Array.isArray(values) && typeof values != "string") { - values = [values]; - } - return values; -} - -module.exports.makeBigEndian = makeBigEndian; -module.exports.bytesToBase = bytesToBase; -module.exports.outputToBase = outputToBase; -module.exports.signed = signed; -module.exports.padding = padding; -module.exports.paddingNibble = paddingNibble; -module.exports.paddingCrumb = paddingCrumb; -module.exports.bytePadding = bytePadding; -module.exports.lPadZeros = lPadZeros; -module.exports.fixFloat16Endianness = fixFloat16Endianness; -module.exports.getType = getType; -module.exports.turnToArray = turnToArray; - - -/***/ }), -/* 1 */ -/***/ (function(module, exports) { - -/*! - * endianness - * Swap endianness in byte arrays. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/endianness - * +exports.int2 = new Type({"bits": 2, "signed": true}); +/** + * Unsigned 2-bit integers + * @type {Object} */ - +exports.uInt2 = new Type({"bits": 2}); /** - * Swap the endianness of units of information in a byte array. - * The original array is modified in-place. - * @param {!Array|!Array|Uint8Array} bytes The bytes. - * @param {number} offset The number of bytes of each unit of information. + * Signed 4-bit integers + * @type {Object} */ -function endianness(bytes, offset) { - let len = bytes.length; - let i = 0; - while (i < len) { - swap(bytes, offset, i); - i += offset; - } -} - +exports.int4 = new Type({"bits": 4, "signed": true}); /** - * Swap the endianness of a unit of information in a byte array. - * The original array is modified in-place. - * @param {!Array|!Array|Uint8Array} bytes The bytes. - * @param {number} offset The number of bytes of the unit of information. - * @param {number} index The start index of the unit of information. + * Unsigned 4-bit integers + * @type {Object} */ -function swap(bytes, offset, index) { - let x = 0; - let y = offset - 1; - let limit = parseInt(offset / 2, 10); - while(x < limit) { - let theByte = bytes[index + x]; - bytes[index + x] = bytes[index + y]; - bytes[index + y] = theByte; - x++; - y--; - } -} - -module.exports = endianness; - - -/***/ }), -/* 2 */ -/***/ (function(module, exports) { - -/* - * bit-depth: Configurations based on bit depth. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data +exports.uInt4 = new Type({"bits": 4}); +/** + * Signed 8-bit integers + * @type {Object} */ - +exports.int8 = new Type({"bits": 8, "signed": true}); /** - * Offset for reading each bit depth. - * @enum {number} + * Unsigned 4-bit integers + * @type {Object} */ -const BitDepthOffsets = { - 1: 1, - 2: 1, - 4: 1, - 8: 1, - 16: 2, - 24: 3, - 32: 4, - 40: 5, - 48: 6, - 64: 8 -}; - +exports.uInt8 = new Type({"bits": 8}); +// LE /** - * Max value for each bit depth. - * @enum {number} + * Signed 16-bit integers little-endian + * @type {Object} */ -const BitDepthMaxValues = { - 1: 2, - 2: 4, - 4: 16, - 8: 256, - 16: 65536, - 24: 16777216, - 32: 4294967296, - 40: 1099511627776, - 48: 281474976710656, - 64: Infinity // FIXME 53-bit limit! -}; - -module.exports.BitDepthOffsets = BitDepthOffsets; -module.exports.BitDepthMaxValues = BitDepthMaxValues; - - -/***/ }), -/* 3 */ -/***/ (function(module, exports, __webpack_require__) { - -/*! - * byte-data - * Readable data to and from byte buffers. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data - * - */ - -let toBytes = __webpack_require__(4); -let fromBytes = __webpack_require__(7); -let bitPacker = __webpack_require__(15); -let api = __webpack_require__(16); - -// interface -module.exports.pack = api.pack; -module.exports.findString = api.findString; -module.exports.unpack = api.unpack; -module.exports.packArray = api.packArray; -module.exports.unpackArray = api.unpackArray; -module.exports.unpackStruct = api.unpackStruct; -module.exports.packStruct = api.packStruct; - -// types: LE -module.exports.chr = {"bits": 8, "char": true, "single": true}; -module.exports.fourCC = {"bits": 32, "char": true, "single": true}; -module.exports.bool = {"bits": 1, "single": true}; -module.exports.int2 = {"bits": 2, "signed": true, "single": true}; -module.exports.uInt2 = {"bits": 2, "single": true}; -module.exports.int4 = {"bits": 4, "signed": true, "single": true}; -module.exports.uInt4 = {"bits": 4, "single": true}; -module.exports.int8 = {"bits": 8, "signed": true, "single": true}; -module.exports.uInt8 = {"bits": 8, "single": true}; -module.exports.int16 = {"bits": 16, "signed": true, "single": true}; -module.exports.uInt16 = {"bits": 16, "single": true}; -module.exports.float16 = {"bits": 16, "float": true, "single": true}; -module.exports.int24 = {"bits": 24, "signed": true, "single": true}; -module.exports.uInt24 = {"bits": 24, "single": true}; -module.exports.int32 = {"bits": 32, "signed": true, "single": true}; -module.exports.uInt32 = {"bits": 32, "single": true}; -module.exports.float32 = {"bits": 32, "float": true, "single": true}; -module.exports.int40 = {"bits": 40, "signed": true, "single": true}; -module.exports.uInt40 = {"bits": 40, "single": true}; -module.exports.int48 = {"bits": 48, "signed": true, "single": true}; -module.exports.uInt48 = {"bits": 48, "single": true}; -module.exports.float64 = {"bits": 64, "float": true, "single": true}; - -// types: BE -module.exports.int16BE = { - "bits": 16, "signed": true, "single": true, "be": true}; -module.exports.uInt16BE = { - "bits": 16, "single": true, "be": true}; -module.exports.float16BE = { - "bits": 16, "float": true, "single": true, "be": true}; -module.exports.int24BE = { - "bits": 24, "signed": true, "single": true, "be": true}; -module.exports.uInt24BE = { - "bits": 24, "single": true, "be": true}; -module.exports.int32BE = { - "bits": 32, "signed": true, "single": true, "be": true}; -module.exports.uInt32BE = { - "bits": 32, "single": true, "be": true}; -module.exports.float32BE = { - "bits": 32, "float": true, "single": true, "be": true}; -module.exports.int40BE = { - "bits": 40, "signed": true, "single": true, "be": true}; -module.exports.uInt40BE = { - "bits": 40, "single": true, "be": true}; -module.exports.int48BE = { - "bits": 48, "signed": true, "single": true, "be": true}; -module.exports.uInt48BE = { - "bits": 48, "single": true, "be": true}; -module.exports.float64BE = { - "bits": 64, "float": true, "single": true, "be": true}; - -module.exports.toBytes = toBytes.toBytes; -module.exports.fromBytes = fromBytes.fromBytes; -module.exports.packBooleans = bitPacker.packBooleans; -module.exports.unpackBooleans = bitPacker.unpackBooleans; -module.exports.packCrumbs = bitPacker.packCrumbs; -module.exports.unpackCrumbs = bitPacker.unpackCrumbs; -module.exports.packNibbles = bitPacker.packNibbles; -module.exports.unpackNibbles = bitPacker.unpackNibbles; - - -/***/ }), -/* 4 */ -/***/ (function(module, exports, __webpack_require__) { - -/* - * to-bytes: bytes to numbers and strings. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data +exports.int16 = new Type({"bits": 16, "signed": true}); +/** + * Unsigned 16-bit integers little-endian + * @type {Object} */ - -const writer = __webpack_require__(13); -const helpers = __webpack_require__(0); -const bitDepthLib = __webpack_require__(2); - +exports.uInt16 = new Type({"bits": 16}); /** - * Turn numbers and strings to bytes. - * @param {!Array|number|string} values The data. - * @param {Object} type One of the available types. - * @return {!Array|!Array|Uint8Array} the data as a byte buffer. + * Half-precision floating-point numbers little-endian + * @type {Object} */ -function toBytes(values, type) { - let bytes = writeBytes(values, type); - helpers.makeBigEndian(bytes, type.be, type.bits); - helpers.outputToBase(bytes, type.bits, type.base); - helpers.fixFloat16Endianness(bytes, type); - return bytes; -} - +exports.float16 = new Type({"bits": 16, "float": true}); /** - * Write values as bytes. - * @param {!Array|number|string} values The data. - * @param {Object} type One of the available types. - * @return {!Array} the bytes. + * Signed 24-bit integers little-endian + * @type {Object} */ -function writeBytes(values, type) { - let bitWriter; - if (type.char) { - bitWriter = writer.writeString; - } else { - bitWriter = writer[ - 'write' + type.bits + 'Bit' + (type.float ? "Float" : "")]; - } - let i = 0; - let j = 0; - let len = values.length; - let bytes = []; - let minMax = getBitDepthMinMax(type); - while (i < len) { - j = bitWriter(bytes, checkOverflow(values[i], minMax, type), j); - i++; - } - return bytes; -} - +exports.int24 = new Type({"bits": 24, "signed": true}); /** - * Get the minimum and maximum values accordind to the type. - * This should be defined in bit-depth. - * @param {Object} type The options according to the type. - * @return {Object} + * Unsigned 24-bit integers little-endian + * @type {Object} */ -function getBitDepthMinMax(type) { - let minMax = {}; - if (type.signed) { - minMax.max = (bitDepthLib.BitDepthMaxValues[type.bits] / 2) - 1; - minMax.min = (bitDepthLib.BitDepthMaxValues[type.bits] / 2) * -1; - } else { - minMax.max = bitDepthLib.BitDepthMaxValues[type.bits] - 1; - minMax.min = 0; - } - return minMax; -} - +exports.uInt24 = new Type({"bits": 24}); /** - * Limit the value according to the bit depth in case of - * overflow or underflow. - * @param {!Array|number|string} value The data. - * @param {Object} minMax The minimum value. - * @param {Object} options The maximum value. + * Signed 32-bit integers little-endian + * @type {Object} */ -function checkOverflow(value, minMax, options) { - if (!options.float) { - if (value > minMax.max) { - value = minMax.max; - } else if(value < minMax.min) { - value = minMax.min; - } - } - return value; -} - -module.exports.toBytes = toBytes; - - -/***/ }), -/* 5 */ -/***/ (function(module, exports, __webpack_require__) { - -/* - * float: Functions to work with 16, 32 & 64 bit floats. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data +exports.int32 = new Type({"bits": 32, "signed": true}); +/** + * Unsigned 32-bit integers little-endian + * @type {Object} */ - -const helpers = __webpack_require__(0); - -function getBinary(bytes, rev=false) { - let binary = ""; - let i = 0; - let bytesLength = bytes.length; - while(i < bytesLength) { - let bits = helpers.lPadZeros(bytes[i].toString(2), 8); - if (rev) { - binary = binary + bits; - } else { - binary = bits + binary; - } - i++; - } - return binary; -} - +exports.uInt32 = new Type({"bits": 32}); /** - * Turn bytes to a float 16.. - * Thanks https://stackoverflow.com/a/8796597 - * @param {number} bytes 2 bytes representing a float 16. + * Single-precision floating-point numbers little-endian + * @type {Object} */ -function decodeFloat16(bytes) { - let binary = parseInt(getBinary(bytes, true), 2); - let exponent = (binary & 0x7C00) >> 10; - let fraction = binary & 0x03FF; - let floatValue; - if (exponent) { - floatValue = Math.pow(2, exponent - 15) * (1 + fraction / 0x400); - } else { - floatValue = 6.103515625e-5 * (fraction / 0x400); - } - return floatValue * (binary >> 15 ? -1 : 1); -} - +exports.float32 = new Type({"bits": 32, "float": true}); /** - * Turn an array of bytes into a float 64. - * Thanks https://gist.github.com/kg/2192799 - * @param {!Array} bytes 8 bytes representing a float 64. + * Signed 40-bit integers little-endian + * @type {Object} */ -function decodeFloat64(bytes) { - if (bytes.toString() == "0,0,0,0,0,0,0,0") { - return 0; - } - let binary = getBinary(bytes); - let significandBin = "1" + binary.substr(1 + 11, 52); - let val = 1; - let significand = 0; - let i = 0; - while (i < significandBin.length) { - significand += val * parseInt(significandBin.charAt(i), 10); - val = val / 2; - i++; - } - let sign = (binary.charAt(0) == "1") ? -1 : 1; - let doubleValue = sign * significand * - Math.pow(2, parseInt(binary.substr(1, 11), 2) - 1023); - return doubleValue; -} - +exports.int40 = new Type({"bits": 40, "signed": true}); /** - * Unpack a 64 bit float into two words. - * Thanks https://stackoverflow.com/a/16043259 - * @param {number} value A float64 number. - */ -function toFloat64(value) { - if (value == 0) { - return [0, 0]; - } - let hiWord = 0; - let loWord = 0; - if (value <= 0.0) { - hiWord = 0x80000000; - value = -value; - } - let exponent = Math.floor( - Math.log(value) / Math.log(2)); - let significand = Math.floor( - (value / Math.pow(2, exponent)) * Math.pow(2, 52)); - loWord = significand & 0xFFFFFFFF; - significand /= Math.pow(2, 32); - exponent += 1023; - hiWord = hiWord | (exponent << 20); - hiWord = hiWord | (significand & ~(-1 << 20)); - return [hiWord, loWord]; -} - -let floatView = new Float32Array(1); -let int32View = new Int32Array(floatView.buffer); - + * Unsigned 40-bit integers little-endian + * @type {Object} + */ +exports.uInt40 = new Type({"bits": 40}); /** - * to-half: int bits of half-precision floating point values - * Based on: - * https://mail.mozilla.org/pipermail/es-discuss/2017-April/047994.html - * https://github.com/rochars/byte-data + * Signed 48-bit integers little-endian + * @type {Object} */ -function toHalf(val) { - floatView[0] = val; - let x = int32View[0]; - let bits = (x >> 16) & 0x8000; - let m = (x >> 12) & 0x07ff; - let e = (x >> 23) & 0xff; - if (e < 103) { - return bits; - } - bits |= ((e - 112) << 10) | (m >> 1); - bits += m & 1; - return bits; -} - -module.exports.getBinary = getBinary; -module.exports.decodeFloat16 = decodeFloat16; -module.exports.decodeFloat64 = decodeFloat64; -module.exports.toFloat64 = toFloat64; -module.exports.toHalf = toHalf; - - -/***/ }), -/* 6 */ -/***/ (function(module, exports) { - -var int8 = new Int8Array(4) -var int32 = new Int32Array(int8.buffer, 0, 1) -var float32 = new Float32Array(int8.buffer, 0, 1) - -function pack(i) { - int32[0] = i - return float32[0] -} - -function unpack(f) { - float32[0] = f - return int32[0] -} - -module.exports = pack -module.exports.pack = pack -module.exports.unpack = unpack - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - -/* - * from-bytes: convert bytes to numbers and strings. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data +exports.int48 = new Type({"bits": 48, "signed": true}); +/** + * Unsigned 48-bit integers little-endian + * @type {Object} */ - -const reader = __webpack_require__(14); -const bitDepths = __webpack_require__(2); -const helpers = __webpack_require__(0); - +exports.uInt48 = new Type({"bits": 48}); /** - * Turn a byte buffer into what the bytes represent. - * @param {!Array|!Array|Uint8Array} buffer An array of bytes. - * @param {Object} type One of the available types. - * @return {!Array|number|string} + * Double-precision floating-point numbers little-endian + * @type {Object} */ -function fromBytes(buffer, type) { - let bitDepth = type.bits; - helpers.fixFloat16Endianness(buffer, type); - helpers.makeBigEndian(buffer, type.be, bitDepth); - bytesToInt(buffer, type.base); - let values = readBytes( - buffer, - type, - getBitReader(type) - ); - if (type.single) { - values = getSingleValue(values, type); - } - return values; -} - +exports.float64 = new Type({"bits": 64, "float": true}); +// BE /** - * Return a function to read binary data. - * @param {Object} type One of the available types. - * @return {Function} + * Signed 16-bit integers big-endian + * @type {Object} */ -function getBitReader(type) { - return type.char ? - reader.readChar : reader[getReaderName(type.bits, type.float)]; -} - +exports.int16BE = new Type({"bits": 16, "signed": true, "be": true}); /** - * Return the first value from the result value array. - * @param {!Array|string} values The values. - * @param {Object} type One of the available types. - * @return {number|string} + * Unsigned 16-bit integers big-endian + * @type {Object} */ -function getSingleValue(values, type) { - if (type.char) { - values = values.slice(0, type.bits / 8); - } else { - values = values[0]; - } - return values; -} - +exports.uInt16BE = new Type({"bits": 16, "be": true}); /** - * Turn a array of bytes into an array of what the bytes should represent. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {Object} type The type. - * @param {Function} bitReader The function to read the bytes. - * @return {!Array|string} + * Half-precision floating-point numbers big-endian + * @type {Object} */ -function readBytes(bytes, type, bitReader) { - let values = []; - let i = 0; - let len = bytes.length - (type.offset -1); - let theSignFunction = signFunction(type); - while (i < len) { - values.push( - theSignFunction( - bitReader(bytes, i, type), - bitDepths.BitDepthMaxValues[type.bits] - ) - ); - i += type.offset; - } - if (type.char) { - values = values.join(""); - } - return values; -} - +exports.float16BE = new Type({"bits": 16, "float": true, "be": true}); /** - * Return the function to apply sign or not to a type. - * @param {Object} type The type. - * @return {Function} + * Signed 24-bit integers big-endian + * @type {Object} */ -function signFunction(type) { - return type.signed && !type.float ? - helpers.signed : function(x){return x;}; -} - +exports.int24BE = new Type({"bits": 24, "signed": true, "be": true}); /** - * Build a bit reading function name based on the arguments. - * @param {number} bits The bit depth. 1, 2, 4, 8, 16, 24, 32, 40, 48, 64. - * @param {boolean} float True if the values are IEEE floating point numbers. - * @return {string} + * Unsigned 24-bit integers big-endian + * @type {Object} */ -function getReaderName(bits, float) { - return 'read' + (bits < 8 ? 8 : bits) + - 'Bit' + (float ? "Float" : ""); -} - +exports.uInt24BE = new Type({"bits": 24, "be": true}); /** - * Turn bytes to base 10. - * @param {!Array|Uint8Array} bytes The bytes as binary or hex strings. - * @param {number} base The base. + * Signed 32-bit integers big-endian + * @type {Object} */ -function bytesToInt(bytes, base) { - if (base != 10) { - let i = 0; - let len = bytes.length; - while(i < len) { - bytes[i] = parseInt(bytes[i], base); - i++; - } - } -} - -module.exports.fromBytes = fromBytes; - - -/***/ }), -/* 8 */ -/***/ (function(module, exports) { - -/* - * wavefile - * Read & write wave files with 8, 16, 24, 32 & 64-bit data. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/wavefile - * +exports.int32BE = new Type({"bits": 32, "signed": true, "be": true}); +/** + * Unsigned 32-bit integers big-endian + * @type {Object} */ - +exports.uInt32BE = new Type({"bits": 32, "be": true}); /** - * Error messages. - * @enum {string} + * Single-precision floating-point numbers big-endian + * @type {Object} */ -module.exports = { - "format": "Not a supported format.", - "wave": "Could not find the 'WAVE' format identifier", - "fmt ": "Could not find the 'fmt ' chunk", - "data": "Could not find the 'data' chunk", - "fact": "Could not find the 'fact' chunk", - "bitDepth": "Invalid bit depth.", - "numChannels": "Invalid number of channels.", - "sampleRate": "Invalid sample rate." -}; - -/***/ }), -/* 9 */ -/***/ (function(module, exports, __webpack_require__) { - +exports.float32BE = new Type({"bits": 32, "float": true, "be": true}); /** - * type: The Type class. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data + * Signed 40-bit integers big-endian + * @type {Object} */ - - -const bitParser = __webpack_require__(23); - +exports.int40BE = new Type({"bits": 40, "signed": true, "be": true}); /** - * A class to represent byte-data types. + * Unsigned 40-bit integers big-endian + * @type {Object} */ -class Type { - - /** - * @param {Object} options The type definition. - * @param {number} options.bits Number of bits used by data of this type. - * @param {boolean} options.char True for string/char types. - * @param {boolean} options.float True for float types. - * Available only for 16, 32 and 64-bit data. - * @param {boolean} options.be True for signed types. - * @param {boolean} options.signed True for signed types. - */ - constructor(options) { - /** - * The max number of bits used by data of this type. - * @type {number} - */ - this.bits = options["bits"]; - /** - * If this type represent floating-point values or not. - * @type {boolean} - */ - this.char = options["char"]; - /** - * If this type it is signed or not. - * @type {boolean} - */ - this.float = options["float"]; - /** - * If this type is big-endian or not. - * @type {boolean} - */ - this.be = options["be"]; - /** - * If this type it is signed or not. - * @type {boolean} - */ - this.signed = this.float ? true : options["signed"]; - /** - * The function to read values of this type from buffers. - * @type {Function} - */ - this.reader = null; - /** - * The function to write values of this type to buffers. - * @type {Function} - */ - this.writer = null; - /** - * The number of bytes used by data of this type. - * @type {number} - */ - this.offset = 0; - /** - * The base used to represent data of this type. - * Default is 10. - * @type {number} - */ - this.base = options["base"] ? options["base"] : 10; - /** - * Min value for numbers of this type. - * @type {number} - */ - this.min = -Infinity; - /** - * Max value for numbers of this type. - * @type {number} - */ - this.max = Infinity; - this.build_(); - this.realBits = this.bits; - } - - /** - * Sign a number according to the type. - * @param {number} num The number. - * @return {number} - */ - sign(num) { - if (num > this.max) { - num -= (this.max * 2) + 2; - } - return num; - } - - /** - * Limit the value according to the bit depth in case of - * overflow or underflow. - * @param {number} value The data. - * @return {number} - */ - overflow(value) { - if (value > this.max) { - value = this.max; - } else if (value < this.min) { - value = this.min; - } - return value; - } - - /** - * Build the type. - * @private - */ - build_() { - this.setRealBits_(); - this.offset = this.bits < 8 ? 1 : this.realBits / 8; - this.setReader_(); - this.setWriter_(); - if (!this.float) { - this.setMinMax_(); - } - } - - /** - * Set the function to read data of this type. - * @private - */ - setReader_() { - if (this.char) { - this.reader = bitParser.BitReader["readChar"]; - } else { - this.reader = bitParser.BitReader[ - 'read' + (this.bits < 8 ? 8 : this.realBits) + - 'Bit' + (this.float ? "Float" : "")]; - } - } - - /** - * Set the function to write data of this type. - * @private - */ - setWriter_() { - if (this.char) { - this.writer = bitParser.BitWriter["writeString"]; - } else { - this.writer = bitParser.BitWriter[ - 'write' + this.realBits + 'Bit' + (this.float ? "Float" : "")]; - } - } - - /** - * Set the minimum and maximum values for the type. - * @private - */ - setMinMax_() { - let max = Math.pow(2, this.bits); - if (this.signed) { - this.max = (max / 2) -1; - this.min = -max / 2; - } else { - this.max = max - 1; - this.min = 0; - } - } - - /** - * Set the real bit depth for data with bit count different from the - * standard types (1, 2, 4, 8, 16, 32, 40, 48, 64): the closest bigger - * standard number of bits. The data is then treated as data of the - * standard type on all aspects except for the min and max values. - * Ex: a 11-bit uInt is treated as 16-bit uInt with a max value of 2048. - * @private - */ - setRealBits_() { - if (this.bits > 8) { - if (this.bits <= 16) { - this.realBits = 16; - } else if (this.bits <= 24) { - this.realBits = 24; - } else if (this.bits <= 32) { - this.realBits = 32; - } else if (this.bits <= 40) { - this.realBits = 40; - } else if (this.bits <= 48) { - this.realBits = 48; - } else if (this.bits <= 53) { - this.realBits = 53; - } else { - this.realBits = 64; - } - } else { - this.realBits = this.bits; - } - } -} - -module.exports = Type; +exports.uInt40BE = new Type({"bits": 40, "be": true}); +/** + * Signed 48-bit integers big-endian + * @type {Object} + */ +exports.int48BE = new Type({"bits": 48, "signed": true, "be": true}); +/** + * Unsigned 48-bit integers big-endian + * @type {Object} + */ +exports.uInt48BE = new Type({"bits": 48, "be": true}); +/** + * Double-precision floating-point numbers big-endian + * @type {Object} + */ +exports.float64BE = new Type({"bits": 64, "float": true, "be": true}); /***/ }), -/* 10 */ +/* 1 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -1068,7 +432,7 @@ let f64 = new Float64Array(1); /** @private */ let ui32 = new Uint32Array(f64.buffer); /** @private */ -let GInt = __webpack_require__(27); +let GInt = __webpack_require__(8); /** * A class to represent byte-data types. @@ -1286,156 +650,438 @@ module.exports = Type; /***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { +/* 2 */ +/***/ (function(module, exports) { /*! - * alawmulaw - * JavaScript A-Law and mu-Law codecs. - * Copyright (c) 2018 Rafael da Silva Rocha. - * https://github.com/rochars/alawmulaw - * + * endianness + * Swap endianness in byte arrays. + * Copyright (c) 2017 Rafael da Silva Rocha. + * https://github.com/rochars/endianness + * */ -module.exports.alaw = __webpack_require__(28); -module.exports.mulaw = __webpack_require__(29); - - -/***/ }), -/* 12 */ -/***/ (function(module, exports, __webpack_require__) { - -/*! - * wavefile - * Read & write wave files with 4, 8, 16, 24, 32 & 64-bit data. - * Copyright (c) 2017-2018 Rafael da Silva Rocha. +/** + * Swap the endianness of units of information in a byte array. + * The original array is modified in-place. + * @param {!Array|!Array|Uint8Array} bytes The bytes. + * @param {number} offset The number of bytes of each unit of information. + */ +function endianness(bytes, offset) { + let len = bytes.length; + let i = 0; + while (i < len) { + swap(bytes, offset, i); + i += offset; + } +} + +/** + * Swap the endianness of a unit of information in a byte array. + * The original array is modified in-place. + * @param {!Array|!Array|Uint8Array} bytes The bytes. + * @param {number} offset The number of bytes of the unit of information. + * @param {number} index The start index of the unit of information. + */ +function swap(bytes, offset, index) { + let x = 0; + let y = offset - 1; + let limit = parseInt(offset / 2, 10); + while(x < limit) { + let theByte = bytes[index + x]; + bytes[index + x] = bytes[index + y]; + bytes[index + y] = theByte; + x++; + y--; + } +} + +module.exports = endianness; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + +/* + * wavefile + * Read & write wave files with 8, 16, 24, 32 & 64-bit data. + * Copyright (c) 2017 Rafael da Silva Rocha. * https://github.com/rochars/wavefile * */ -const byteData = __webpack_require__(3); -const uInt8 = byteData.uInt8; -const bitDepthLib = __webpack_require__(17); -const WaveErrors = __webpack_require__(8); -const WaveFileReaderWriter = __webpack_require__(18); -const riffChunks = __webpack_require__(20); -const adpcm = __webpack_require__(24); -const alaw = __webpack_require__(11).alaw; -const mulaw = __webpack_require__(11).mulaw; +/** + * Error messages. + * @enum {string} + */ +module.exports = { + "format": "Not a supported format.", + "wave": "Could not find the 'WAVE' format identifier", + "fmt ": "Could not find the 'fmt ' chunk", + "data": "Could not find the 'data' chunk", + "fact": "Could not find the 'fact' chunk", + "bitDepth": "Invalid bit depth.", + "numChannels": "Invalid number of channels.", + "sampleRate": "Invalid sample rate." +}; + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { /** - * WaveFile + * type: The Type class. + * Copyright (c) 2017 Rafael da Silva Rocha. + * https://github.com/rochars/byte-data */ -class WaveFile extends WaveFileReaderWriter { - /** - * @param {Uint8Array} bytes A wave file buffer. - */ - constructor(bytes) { - super(); - if(bytes) { - this.fromBuffer(bytes); - } - } + +const bitParser = __webpack_require__(15); + +/** + * A class to represent byte-data types. + */ +class Type { /** - * Create a WaveFile object based on the arguments passed. - * @param {number} numChannels The number of channels - * (Ints like 1 for mono, 2 stereo and so on). - * @param {number} sampleRate The sample rate. - * Integer numbers like 8000, 44100, 48000, 96000, 192000. - * @param {string} bitDepth The audio bit depth. - * One of "8", "16", "24", "32", "32f", "64". - * @param {!Array} samples Array of samples to be written. - * Samples must be in the correct range according to the bit depth. - * Samples of multi-channel data . + * @param {Object} options The type definition. + * @param {number} options.bits Number of bits used by data of this type. + * @param {boolean} options.char True for string/char types. + * @param {boolean} options.float True for float types. + * Available only for 16, 32 and 64-bit data. + * @param {boolean} options.be True for signed types. + * @param {boolean} options.signed True for signed types. */ - fromScratch(numChannels, sampleRate, bitDepth, samples, options={}) { - this.cbSize = 0; - this.validBitsPerSample = 0; - this.factChunkId = ""; - this.factChunkSize = 0; - this.factChunkData = []; - this.dwSampleLength = 0; - if (!options.container) { - options.container = "RIFF"; - } - let bytes = parseInt(bitDepth, 10) / 8; - this.chunkSize = 36 + samples.length * bytes; - this.fmtChunkSize = 16; - this.byteRate = (numChannels * bytes) * sampleRate; - this.blockAlign = numChannels * bytes; - this.chunkId = options.container; - this.format = "WAVE"; - this.fmtChunkId = "fmt "; - this.audioFormat = this.headerFormats_[bitDepth]; - this.numChannels = numChannels; - this.sampleRate = sampleRate; - this.bitsPerSample = parseInt(bitDepth, 10); - this.dataChunkId = "data"; - this.dataChunkSize = samples.length * bytes; - this.samples = samples; - this.bitDepth = bitDepth; - // adpcm - if (bitDepth == "4") { - this.chunkSize = 44 + samples.length; - this.fmtChunkSize = 20; - this.byteRate = 4055; - this.blockAlign = 256; - this.bitsPerSample = 4; - this.dataChunkSize = samples.length; - this.cbSize = 2; - this.validBitsPerSample = 505; - this.factChunkId = "fact"; - this.factChunkSize = 4; - this.dwSampleLength = samples.length * 2; - } - // A-Law or mu-Law - if (bitDepth == "8a" || bitDepth == "8m") { - this.chunkSize = 44 + samples.length; - this.fmtChunkSize = 20; - this.cbSize = 2; - this.validBitsPerSample = 8; - this.factChunkId = "fact"; - this.factChunkSize = 4; - this.dwSampleLength = samples.length; - } + constructor(options) { + /** + * The max number of bits used by data of this type. + * @type {number} + */ + this.bits = options["bits"]; + /** + * If this type represent floating-point values or not. + * @type {boolean} + */ + this.char = options["char"]; + /** + * If this type it is signed or not. + * @type {boolean} + */ + this.float = options["float"]; + /** + * If this type is big-endian or not. + * @type {boolean} + */ + this.be = options["be"]; + /** + * If this type it is signed or not. + * @type {boolean} + */ + this.signed = this.float ? true : options["signed"]; + /** + * The function to read values of this type from buffers. + * @type {Function} + */ + this.reader = null; + /** + * The function to write values of this type to buffers. + * @type {Function} + */ + this.writer = null; + /** + * The number of bytes used by data of this type. + * @type {number} + */ + this.offset = 0; + /** + * The base used to represent data of this type. + * Default is 10. + * @type {number} + */ + this.base = options["base"] ? options["base"] : 10; + /** + * Min value for numbers of this type. + * @type {number} + */ + this.min = -Infinity; + /** + * Max value for numbers of this type. + * @type {number} + */ + this.max = Infinity; + this.build_(); + this.realBits = this.bits; } /** - * Init a WaveFile object from a byte buffer. - * @param {Uint8Array} bytes The buffer. + * Sign a number according to the type. + * @param {number} num The number. + * @return {number} */ - fromBuffer(bytes) { - this.readRIFFChunk_(bytes); - let bigEndian = this.chunkId == "RIFX"; - let chunk = riffChunks.read(bytes, bigEndian); - this.readFmtChunk_(chunk.subChunks); - this.readFactChunk_(chunk.subChunks); - this.readBextChunk_(chunk.subChunks); - this.readCueChunk_(chunk.subChunks); - this.readDataChunk_( - chunk.subChunks, - {"be": bigEndian, "single": true} - ); - if (this.audioFormat == 3 && this.bitsPerSample == 32) { - this.bitDepth = "32f"; - }else { - this.bitDepth = this.bitsPerSample.toString(); + sign(num) { + if (num > this.max) { + num -= (this.max * 2) + 2; } + return num; } /** - * Turn the WaveFile object into a byte buffer. - * @return {Uint8Array} + * Limit the value according to the bit depth in case of + * overflow or underflow. + * @param {number} value The data. + * @return {number} */ - toBuffer() { - this.checkWriteInput_(); - return new Uint8Array(this.createWaveFile_()); + overflow(value) { + if (value > this.max) { + value = this.max; + } else if (value < this.min) { + value = this.min; + } + return value; } /** - * Turn the file to RIFF. + * Build the type. + * @private + */ + build_() { + this.setRealBits_(); + this.offset = this.bits < 8 ? 1 : this.realBits / 8; + this.setReader_(); + this.setWriter_(); + if (!this.float) { + this.setMinMax_(); + } + } + + /** + * Set the function to read data of this type. + * @private + */ + setReader_() { + if (this.char) { + this.reader = bitParser.BitReader["readChar"]; + } else { + this.reader = bitParser.BitReader[ + 'read' + (this.bits < 8 ? 8 : this.realBits) + + 'Bit' + (this.float ? "Float" : "")]; + } + } + + /** + * Set the function to write data of this type. + * @private + */ + setWriter_() { + if (this.char) { + this.writer = bitParser.BitWriter["writeString"]; + } else { + this.writer = bitParser.BitWriter[ + 'write' + this.realBits + 'Bit' + (this.float ? "Float" : "")]; + } + } + + /** + * Set the minimum and maximum values for the type. + * @private + */ + setMinMax_() { + let max = Math.pow(2, this.bits); + if (this.signed) { + this.max = (max / 2) -1; + this.min = -max / 2; + } else { + this.max = max - 1; + this.min = 0; + } + } + + /** + * Set the real bit depth for data with bit count different from the + * standard types (1, 2, 4, 8, 16, 32, 40, 48, 64): the closest bigger + * standard number of bits. The data is then treated as data of the + * standard type on all aspects except for the min and max values. + * Ex: a 11-bit uInt is treated as 16-bit uInt with a max value of 2048. + * @private + */ + setRealBits_() { + if (this.bits > 8) { + if (this.bits <= 16) { + this.realBits = 16; + } else if (this.bits <= 24) { + this.realBits = 24; + } else if (this.bits <= 32) { + this.realBits = 32; + } else if (this.bits <= 40) { + this.realBits = 40; + } else if (this.bits <= 48) { + this.realBits = 48; + } else if (this.bits <= 53) { + this.realBits = 53; + } else { + this.realBits = 64; + } + } else { + this.realBits = this.bits; + } + } +} + +module.exports = Type; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +/*! + * alawmulaw + * JavaScript A-Law and mu-Law codecs. + * Copyright (c) 2018 Rafael da Silva Rocha. + * https://github.com/rochars/alawmulaw + * + */ + +module.exports.alaw = __webpack_require__(17); +module.exports.mulaw = __webpack_require__(18); + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +/*! + * wavefile + * Read & write wave files with 4, 8, 16, 24, 32 & 64-bit data. + * Copyright (c) 2017-2018 Rafael da Silva Rocha. + * https://github.com/rochars/wavefile + * + */ + +const byteData = __webpack_require__(0); +const uInt8 = byteData.uInt8; +const bitDepthLib = __webpack_require__(9); +const WaveErrors = __webpack_require__(3); +const WaveFileReaderWriter = __webpack_require__(10); +const riffChunks = __webpack_require__(12); +const adpcm = __webpack_require__(16); +const alaw = __webpack_require__(5).alaw; +const mulaw = __webpack_require__(5).mulaw; + +/** + * WaveFile + */ +class WaveFile extends WaveFileReaderWriter { + + /** + * @param {Uint8Array} bytes A wave file buffer. + */ + constructor(bytes) { + super(); + if(bytes) { + this.fromBuffer(bytes); + } + } + + /** + * Create a WaveFile object based on the arguments passed. + * @param {number} numChannels The number of channels + * (Ints like 1 for mono, 2 stereo and so on). + * @param {number} sampleRate The sample rate. + * Integer numbers like 8000, 44100, 48000, 96000, 192000. + * @param {string} bitDepth The audio bit depth. + * One of "8", "16", "24", "32", "32f", "64". + * @param {!Array} samples Array of samples to be written. + * Samples must be in the correct range according to the bit depth. + * Samples of multi-channel data . + */ + fromScratch(numChannels, sampleRate, bitDepth, samples, options={}) { + this.cbSize = 0; + this.validBitsPerSample = 0; + this.factChunkId = ""; + this.factChunkSize = 0; + this.factChunkData = []; + this.dwSampleLength = 0; + if (!options.container) { + options.container = "RIFF"; + } + let bytes = parseInt(bitDepth, 10) / 8; + this.chunkSize = 36 + samples.length * bytes; + this.fmtChunkSize = 16; + this.byteRate = (numChannels * bytes) * sampleRate; + this.blockAlign = numChannels * bytes; + this.chunkId = options.container; + this.format = "WAVE"; + this.fmtChunkId = "fmt "; + this.audioFormat = this.headerFormats_[bitDepth]; + this.numChannels = numChannels; + this.sampleRate = sampleRate; + this.bitsPerSample = parseInt(bitDepth, 10); + this.dataChunkId = "data"; + this.dataChunkSize = samples.length * bytes; + this.samples = samples; + this.bitDepth = bitDepth; + // adpcm + if (bitDepth == "4") { + this.chunkSize = 44 + samples.length; + this.fmtChunkSize = 20; + this.byteRate = 4055; + this.blockAlign = 256; + this.bitsPerSample = 4; + this.dataChunkSize = samples.length; + this.cbSize = 2; + this.validBitsPerSample = 505; + this.factChunkId = "fact"; + this.factChunkSize = 4; + this.dwSampleLength = samples.length * 2; + } + // A-Law or mu-Law + if (bitDepth == "8a" || bitDepth == "8m") { + this.chunkSize = 44 + samples.length; + this.fmtChunkSize = 20; + this.cbSize = 2; + this.validBitsPerSample = 8; + this.factChunkId = "fact"; + this.factChunkSize = 4; + this.dwSampleLength = samples.length; + } + } + + /** + * Init a WaveFile object from a byte buffer. + * @param {Uint8Array} bytes The buffer. + */ + fromBuffer(bytes) { + this.readRIFFChunk_(bytes); + let bigEndian = this.chunkId == "RIFX"; + let chunk = riffChunks.read(bytes, bigEndian); + this.readFmtChunk_(chunk.subChunks); + this.readFactChunk_(chunk.subChunks); + this.readBextChunk_(chunk.subChunks); + this.readCueChunk_(chunk.subChunks); + this.readDataChunk_( + chunk.subChunks, + {"be": bigEndian, "single": true} + ); + if (this.audioFormat == 3 && this.bitsPerSample == 32) { + this.bitDepth = "32f"; + }else { + this.bitDepth = this.bitsPerSample.toString(); + } + } + + /** + * Turn the WaveFile object into a byte buffer. + * @return {Uint8Array} + */ + toBuffer() { + this.checkWriteInput_(); + return new Uint8Array(this.createWaveFile_()); + } + + /** + * Turn the file to RIFF. */ toRIFF() { this.chunkId = "RIFF"; @@ -1461,7 +1107,7 @@ class WaveFile extends WaveFileReaderWriter { this.numChannels, this.sampleRate, bitDepth, - byteData.unpackArray(this.samples, uInt8), + this.samples, {"container": this.chunkId} ); } @@ -1631,690 +1277,517 @@ window['WaveFile'] = WaveFile; /***/ }), -/* 13 */ +/* 7 */ /***/ (function(module, exports, __webpack_require__) { -/* - * write-bytes: Functions to turn data into bytes. +/** + * from-bytes: Numbers and strings from bytes. * Copyright (c) 2017 Rafael da Silva Rocha. * https://github.com/rochars/byte-data */ -const floats = __webpack_require__(5); -const intBits = __webpack_require__(6); - -function write64BitFloat(bytes, number, j) { - let bits = floats.toFloat64(number); - j = write32Bit(bytes, bits[1], j); - return write32Bit(bytes, bits[0], j); -} - -// https://github.com/majimboo/c-struct -function write48Bit(bytes, number, j) { - bytes[j++] = number & 0xFF; - bytes[j++] = number >> 8 & 0xFF; - bytes[j++] = number >> 16 & 0xFF; - bytes[j++] = number >> 24 & 0xFF; - bytes[j++] = number / 0x100000000 & 0xFF; - bytes[j++] = number / 0x10000000000 & 0xFF; - return j; -} - -// https://github.com/majimboo/c-struct -function write40Bit(bytes, number, j) { - bytes[j++] = number & 0xFF; - bytes[j++] = number >> 8 & 0xFF; - bytes[j++] = number >> 16 & 0xFF; - bytes[j++] = number >> 24 & 0xFF; - bytes[j++] = number / 0x100000000 & 0xFF; - return j; -} - -function write32BitFloat(bytes, number, j) { - let bits = intBits.unpack(number); - bytes[j++] = bits & 0xFF; - bytes[j++] = bits >>> 8 & 0xFF; - bytes[j++] = bits >>> 16 & 0xFF; - bytes[j++] = bits >>> 24 & 0xFF; - return j; -} +const Type = __webpack_require__(1); +const endianness = __webpack_require__(2); -function write32Bit(bytes, number, j) { - bytes[j++] = number & 0xFF; - bytes[j++] = number >>> 8 & 0xFF; - bytes[j++] = number >>> 16 & 0xFF; - bytes[j++] = number >>> 24 & 0xFF; - return j; +/** + * Turn a byte buffer into what the bytes represent. + * @param {!Array|!Array|Uint8Array} buffer An array of bytes. + * @param {Object} type One of the available types. + * @return {!Array|number|string} + */ +function fromBytes(buffer, type) { + if (type.be) { + endianness(buffer, type.offset); + } + if (type.base != 10) { + bytesFromBase(buffer, type.base); + } + return readBytes(buffer, type); } -function write24Bit(bytes, number, j) { - bytes[j++] = number & 0xFF; - bytes[j++] = number >>> 8 & 0xFF; - bytes[j++] = number >>> 16 & 0xFF; - return j; -} - -function write16Bit(bytes, number, j) { - bytes[j++] = number & 0xFF; - bytes[j++] = number >>> 8 & 0xFF; - return j; -} - -function write16BitFloat(bytes, number, j) { - let bits = floats.toHalf(number); - bytes[j++] = bits >>> 8 & 0xFF; - bytes[j++] = bits & 0xFF; - return j; -} - -function write8Bit(bytes, number, j) { - bytes[j++] = number & 0xFF; - return j; -} - -function write4Bit(bytes, number, j) { - bytes[j++] = number & 0xF; - return j; -} - -function write2Bit(bytes, number, j) { - bytes[j++] = number < 0 ? number + 4 : number; - return j; -} - -function write1Bit(bytes, number, j) { - bytes[j++] = number ? 1 : 0; - return j; -} - -function writeString(bytes, string, j) { - bytes[j++] = string.charCodeAt(0); - return j; -} - -module.exports.write64BitFloat = write64BitFloat; -module.exports.write48Bit = write48Bit; -module.exports.write40Bit = write40Bit; -module.exports.write32BitFloat = write32BitFloat; -module.exports.write32Bit = write32Bit; -module.exports.write24Bit = write24Bit; -module.exports.write16Bit = write16Bit; -module.exports.write16BitFloat = write16BitFloat; -module.exports.write8Bit = write8Bit; -module.exports.write4Bit = write4Bit; -module.exports.write2Bit = write2Bit; -module.exports.write1Bit = write1Bit; -module.exports.writeString = writeString; - - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { - -/* - * read-bytes: Function to read data from bytes. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data - */ - -let helpers = __webpack_require__(0); -const floats = __webpack_require__(5); -const intBits = __webpack_require__(6); - /** - * Read a group of bytes by turning it to bits. - * Useful for 40 & 48-bit, but underperform. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @param {number} numBytes The number of bytes - * (1 for 8-bit, 2 for 16-bit, etc). - * @return {number} + * Turn numbers and strings to bytes. + * @param {!Array|number|string} values The data. + * @param {Object} type One of the available types. + * @return {!Array|!Array} the data as a byte buffer. */ -function readBytesAsBits(bytes, i, numBytes) { - let j = numBytes-1; - let bits = ""; - while (j >= 0) { - bits += helpers.bytePadding(bytes[j + i].toString(2), 2); - j--; +function toBytes(values, type) { + let bytes = writeBytes(values, type); + if (type.be) { + endianness(bytes, type.offset); } - return parseInt(bits, 2); -} - -/** - * Read 1 8-bit int from from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {number} - */ -function read8Bit(bytes, i) { - return bytes[i]; -} - -/** - * Read 1 16-bit int from from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {number} - */ -function read16Bit(bytes, i) { - return bytes[1 + i] << 8 | bytes[i]; -} - -/** - * Read 1 16-bit float from from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {number} - */ -function read16BitFloat(bytes, i) { - return floats.decodeFloat16(bytes.slice(i,i+2)); -} - -/** - * Read 1 24-bit int from from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {number} - */ -function read24Bit(bytes, i) { - return bytes[2 + i] << 16 | - bytes[1 + i] << 8 | - bytes[i]; -} - -/** - * Read 1 32-bit int from from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {number} - */ -function read32Bit(bytes, i) { - return (bytes[3 + i] << 24 | - bytes[2 + i] << 16 | - bytes[1 + i] << 8 | - bytes[i]) >>> 0; -} - -/** - * Read 1 32-bit float from from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {number} - */ -function read32BitFloat(bytes, i) { - return intBits.pack(read32Bit(bytes, i)); -} - -/** - * Read 1 40-bit int from from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {number} - */ -function read40Bit(bytes, i) { - return readBytesAsBits(bytes, i, 5); -} - -/** - * Read 1 48-bit int from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {number} - */ -function read48Bit(bytes, i) { - return readBytesAsBits(bytes, i, 6); -} - -/** - * Read 1 64-bit double from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {number} - */ -function read64BitFloat(bytes, i) { - return floats.decodeFloat64(bytes.slice(i,i+8)); -} - -/** - * Read 1 char from bytes. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @return {string} - */ -function readChar(bytes, i, type) { - let chrs = ""; - let j = 0; - let len = type.bits / 8; - while(j < len) { - chrs += String.fromCharCode(bytes[i+j]); - j++; + if (type.base != 10) { + bytesToBase(bytes, type.base); + formatOutput(bytes, type); } - return chrs; + return bytes; } -module.exports.readChar = readChar; -module.exports.read8Bit = read8Bit; -module.exports.read16Bit = read16Bit; -module.exports.read16BitFloat = read16BitFloat; -module.exports.read24Bit = read24Bit; -module.exports.read32Bit = read32Bit; -module.exports.read32BitFloat = read32BitFloat; -module.exports.read40Bit = read40Bit; -module.exports.read48Bit = read48Bit; -module.exports.read64BitFloat = read64BitFloat; - - -/***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - -/* - * bit-packer: Pack and unpack nibbles, crumbs and booleans into bytes. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data - */ - -let helpers = __webpack_require__(0); - /** - * Pack 2 nibbles in 1 byte. - * @param {!Array} nibbles Array of nibbles. - * @return {!Array} Pairs of neebles packed as one byte. + * Turn a array of bytes into an array of what the bytes should represent. + * @param {!Array|Uint8Array} bytes An array of bytes. + * @param {Object} type The type. + * @return {!Array|string} */ -function packNibbles(nibbles) { - let packed = []; +function readBytes(bytes, type) { + let values = []; let i = 0; - let j = 0; - let len = nibbles.length; - if (len % 2) { - nibbles.push(0); - } + let len = bytes.length - (type.offset - 1); while (i < len) { - packed[j++] = parseInt( - nibbles[i].toString(16) + nibbles[i+1].toString(16), 16); - i+=2; + values.push(type.reader(bytes, i)); + i += type.offset; + } + if (type.char) { + values = values.join(""); } - return packed; + return values; } /** - * Unpack a byte into 2 nibbles. - * @param {!Array|Uint8Array} bytes Array of bytes. - * @return {!Array} The nibbles. + * Write values as bytes. + * @param {!Array|number|string} values The data. + * @param {Object} type One of the available types. + * @return {!Array} the bytes. */ -function unpackNibbles(bytes) { - let unpacked = []; +function writeBytes(values, type) { let i = 0; let j = 0; - let len = bytes.length; + let len = values.length; + let bytes = []; while (i < len) { - unpacked[j++] = parseInt(bytes[i].toString(16)[0], 16); - unpacked[j++] = parseInt(bytes[i].toString(16)[1], 16); - i++; + j = type.writer(bytes, values[i++], j); } - return unpacked; + return bytes; } /** - * Pack 4 crumbs in 1 byte. - * @param {!Array} crumbs Array of crumbs. - * @return {!Array} 4 crumbs packed as one byte. + * Get the full type spec for the reading/writing. + * @param {Object} type One of the available types. + * @param {number} base The base of the input. + * @return {Object} */ -function packCrumbs(crumbs) { - let packed = []; - let i = 0; - let j = 0; - fixByteArraySize(crumbs, 4); - let len = crumbs.length - 3; - while (i < len) { - packed[j++] = parseInt( - helpers.lPadZeros(crumbs[i].toString(2), 2) + - helpers.lPadZeros(crumbs[i+1].toString(2), 2) + - helpers.lPadZeros(crumbs[i+2].toString(2), 2) + - helpers.lPadZeros(crumbs[i+3].toString(2), 2), 2); - i+=4; - } - return packed; +function getType(type, base) { + let theType = Object.assign(new Type({}), type); + theType.base = base; + return theType; } /** - * Unpack a byte into 4 crumbs. - * @param {!Array|Uint8Array} crumbs Array of bytes. - * @return {!Array} The crumbs. + * Turn bytes to base 10 from base 2 or 16. + * @param {!Array|Uint8Array} bytes The bytes as binary or hex strings. + * @param {number} base The base. */ -function unpackCrumbs(crumbs) { - let unpacked = []; +function bytesFromBase(bytes, base) { let i = 0; - let j = 0; - let len = crumbs.length; - let bitCrumb; - while (i < len) { - bitCrumb = helpers.lPadZeros(crumbs[i].toString(2), 8); - unpacked[j++] = parseInt(bitCrumb[0] + bitCrumb[1], 2); - unpacked[j++] = parseInt(bitCrumb[2] + bitCrumb[3], 2); - unpacked[j++] = parseInt(bitCrumb[4] + bitCrumb[5], 2); - unpacked[j++] = parseInt(bitCrumb[6] + bitCrumb[7], 2); + let len = bytes.length; + while(i < len) { + bytes[i] = parseInt(bytes[i], base); i++; } - return unpacked; -} - -/** - * Pack 8 booleans in 1 byte. - * @param {!Array} booleans Array of booleans. - * @return {!Array} 4 crumbs packed as one byte. - */ -function packBooleans(booleans) { - let packed = []; - let i = 0; - let j = 0; - fixByteArraySize(booleans, 8); - let len = booleans.length - 7; - while (i < len) { - packed[j++] = parseInt( - booleans[i].toString(2) + - booleans[i+1].toString(2) + - booleans[i+2].toString(2) + - booleans[i+3].toString(2) + - booleans[i+4].toString(2) + - booleans[i+5].toString(2) + - booleans[i+6].toString(2) + - booleans[i+7].toString(2), 2); - i+=8; - } - return packed; } /** - * Unpack a byte into 8 booleans. - * @param {!Array|Uint8Array} booleans Array of bytes. - * @return {!Array} The booleans. + * Turn the output to the correct base. + * @param {Array} bytes The bytes. + * @param {Object} type The type. */ -function unpackBooleans(booleans) { - let unpacked = []; +function formatOutput(bytes, type) { let i = 0; - let j = 0; - let len = booleans.length; - let bitBoolean; - while (i < len) { - bitBoolean = helpers.lPadZeros(booleans[i].toString(2), 8); - unpacked[j++] = parseInt(bitBoolean[0], 2); - unpacked[j++] = parseInt(bitBoolean[1], 2); - unpacked[j++] = parseInt(bitBoolean[2], 2); - unpacked[j++] = parseInt(bitBoolean[3], 2); - unpacked[j++] = parseInt(bitBoolean[4], 2); - unpacked[j++] = parseInt(bitBoolean[5], 2); - unpacked[j++] = parseInt(bitBoolean[6], 2); - unpacked[j++] = parseInt(bitBoolean[7], 2); + let len = bytes.length; + let offset = (type.base == 2 ? 8 : 2) + 1; + while(i < len) { + bytes[i] = Array(offset - bytes[i].length).join("0") + bytes[i]; i++; } - return unpacked; } /** - * Pad a array with zeros to the right. - * @param {!Array} byteArray The array. - * @param {number} numZeros the max number of zeros. - * For 1 binary byte string it should be 8. - * TODO: better explanation of numZeros + * Turn bytes from base 10 to base 2 or 16. + * @param {!Array|Array} bytes The bytes. + * @param {number} base The base. */ -function fixByteArraySize(byteArray, numZeros) { +function bytesToBase(bytes, base) { let i = 0; - let fix = byteArray.length % numZeros; - if (fix) { - fix = (fix - numZeros) * -1; - while(i < fix) { - byteArray.push(0); - i++; - } + let len = bytes.length; + while (i < len) { + bytes[i] = bytes[i].toString(base); + i++; } } -module.exports.packBooleans = packBooleans; -module.exports.unpackBooleans = unpackBooleans; -module.exports.packCrumbs = packCrumbs; -module.exports.unpackCrumbs = unpackCrumbs; -module.exports.packNibbles = packNibbles; -module.exports.unpackNibbles = unpackNibbles; +exports.getType = getType; +exports.toBytes = toBytes; +exports.fromBytes = fromBytes; /***/ }), -/* 16 */ -/***/ (function(module, exports, __webpack_require__) { +/* 8 */ +/***/ (function(module, exports) { -/* - * byte-data - * Readable data to and from byte buffers. +/** + * gint: Generic integer. + * A class to represent any integer from 1 to 53-Bit. * Copyright (c) 2017 Rafael da Silva Rocha. * https://github.com/rochars/byte-data - * - */ - -let toBytes = __webpack_require__(4); -let fromBytes = __webpack_require__(7); -let helpers = __webpack_require__(0); - -/** - * Turn a number or string into a byte buffer. - * @param {number|string} value The value. - * @param {Object} type One of the available types. - * @param {number} base The base of the output. Optional. Default is 10. - * @return {!Array|!Array} - */ -function pack(value, type, base=10) { - let theType = helpers.getType(type, base, true); - value = theType.char ? value.slice(0, type.bits / 8) : value; - return toBytes.toBytes(helpers.turnToArray(value), theType); -} - -/** - * Turn a byte buffer into a readable value. - * @param {!Array|!Array|Uint8Array} buffer An array of bytes. - * @param {Object} type One of the available types. - * @param {number} base The base of the input. Optional. Default is 10. - * @return {number|string} - */ -function unpack(buffer, type, base=10) { - return fromBytes.fromBytes(buffer, helpers.getType(type, base, true)); -} - -/** - * Turn a array of numbers into a byte buffer. - * @param {!Array|string} values The values. - * @param {Object} type One of the available types. - * @param {number} base The base of the output. Optional. Default is 10. - * @return {!Array|!Array} */ -function packArray(values, type, base=10) { - return toBytes.toBytes(values, helpers.getType(type, base, false)); -} /** - * Turn a byte array into a sequence of readable values. - * @param {!Array|!Array|Uint8Array} buffer The byte array. - * @param {Object} type One of the available types. - * @param {number} base The base of the input. Optional. Default is 10. - * @return {!Array|string} + * A class to represent any integer from 1 to 53-Bit. */ -function unpackArray(buffer, type, base=10) { - return fromBytes.fromBytes(buffer, helpers.getType(type, base, false)); -} +class GInt { -/** - * Find and return the start index of some string. - * Return -1 if the string is not found. - * @param {!Array|Uint8Array} buffer A byte buffer. - * @param {string} text Some string to look for. - * @return {number} The start index of the first occurrence, -1 if not found - */ -function findString(buffer, text) { - let found = ""; - for (let i = 0; i < buffer.length; i++) { - found = unpack( - buffer.slice(i, i + text.length + 1), - {"bits": text.length * 8, "char": true}); - if (found == text) { - return i; - } - } - return -1; -} - -/** - * Turn a struct into a byte buffer. - * A struct is an array of values of not necessarily the same type. - * @param {Array} struct The struct values. - * @param {!Array} def The struct type definition. - * @param {number} base The base of the output. Optional. Default is 10. - * @return {!Array|!Array} - */ -function packStruct(struct, def, base=10) { - if (struct.length < def.length) { - return []; - } - let bytes = []; - for (let i = 0; i < def.length; i++) { - bytes = bytes.concat(pack(struct[i], def[i], base)); - } - return bytes; -} - -/** - * Turn a byte buffer into a structure. - * A struct is an array of values of not necessarily the same type. - * @param {!Array|!Array|Uint8Array} buffer The byte buffer. - * @param {!Array} def The struct type definition. - * @param {number} base The base of the input. Optional. Default is 10. - * @return {Array} - */ -function unpackStruct(buffer, def, base=10) { - if (buffer.length < getStructBits(def)) { - return []; - } - let struct = []; - let i = 0; - let j = 0; - while (i < def.length) { - let bits = def[i].bits < 8 ? 1 : def[i].bits / 8; - struct = struct.concat( - unpack(buffer.slice(j, j + bits), def[i], base) - ); - j += bits; - i++; - } - return struct; -} - -function getStructBits(def) { - let bits = 0; - for (let i = 0; i < def.length; i++) { - bits += def[i].bits / 8; + /** + * @param {Object} options The type definition. + * @param {number} options.bits Number of bits used by data of this type. + * @param {boolean} options.be True for big-endian. + * @param {boolean} options.signed True for signed types. + */ + constructor(options) { + /** + * The max number of bits used by data of this type. + * @type {number} + */ + this.bits = options["bits"]; + /** + * If this type is big-endian or not. + * @type {boolean} + */ + this.be = options["be"]; + /** + * If this type it is signed or not. + * @type {boolean} + */ + this.signed = options["signed"]; + /** + * The base used to represent data of this type. + * Default is 10. + * @type {number} + */ + this.base = options["base"] ? options["base"] : 10; + /** + * The function to read values of this type from buffers. + * @type {Function} + * @ignore + */ + this.reader = this.read_; + /** + * The function to write values of this type to buffers. + * @type {Function} + * @ignore + */ + this.writer = this.write_; + /** + * The number of bytes used by data of this type. + * @type {number} + * @ignore + */ + this.offset = 0; + /** + * Min value for numbers of this type. + * @type {number} + * @ignore + */ + this.min = -Infinity; + /** + * Max value for numbers of this type. + * @type {number} + * @ignore + */ + this.max = Infinity; + /** + * The word size. + * @type {number} + * @ignore + */ + this.realBits = this.bits; + /** + * The mask to be used in the last byte of this type. + * @type {number} + * @ignore + */ + this.lastByteMask = 255; + this.build_(); } - return bits; -} - -module.exports.pack = pack; -module.exports.findString = findString; -module.exports.unpack = unpack; -module.exports.packArray = packArray; -module.exports.unpackArray = unpackArray; -module.exports.unpackStruct = unpackStruct; -module.exports.packStruct = packStruct; - - -/***/ }), -/* 17 */ -/***/ (function(module, exports) { - -/*! - * bitdepth - * Change the bit depth of samples to and from 8, 16, 24, 32 & 64-bit. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/bitdepth - * - */ - -const f64f32 = new Float32Array(1); - -/** - * Max number of different values for each bit depth. - * @enum {number} - */ -const BitDepthMaxValues = { - "8": 256, - "16": 65536, - "24": 16777216, - "32": 4294967296, - "32f": 1, - "64": 1 -}; - -/** - * Functions to change the bit depth of a sample. - */ -const BitDepthFunctions = { /** - * Change the bit depth from int to int. - * @param {number} sample The sample. - * @param {Object} args Data about the original and target bit depths. + * Sign a number according to the type. + * @param {number} num The number. * @return {number} + * @ignore */ - "intToInt": function(sample, args) { - if (sample > 0) { - sample = parseInt( - (sample / args["oldPositive"]) * args["newPositive"], 10); - } else { - sample = parseInt( - (sample / args["oldNegative"]) * args["newNegative"], 10); + sign(num) { + if (num > this.max) { + num -= (this.max * 2) + 2; } - return sample; - }, + return num; + } /** - * Change the bit depth from float to int. - * @param {number} sample The sample. - * @param {Object} args Data about the original and target bit depths. + * Limit the value according to the bit depth in case of + * overflow or underflow. + * @param {number} value The data. * @return {number} + * @ignore */ - "floatToInt": function(sample, args) { - return sample > 0 ? - sample * args["newPositive"] : sample * args["newNegative"]; - }, + overflow(value) { + if (value > this.max) { + value = this.max; + } else if (value < this.min) { + value = this.min; + } + return value; + } /** - * Change the bit depth from int to float. - * @param {number} sample The sample. - * @param {Object} args Data about the original and target bit depths. + * Read a integer number from a byte buffer. + * @param {!Array|Uint8Array} bytes An array of bytes. + * @param {number} i The index to read. + * @param {Object} type The type if other than this. * @return {number} + * @private */ - "intToFloat": function(sample, args) { - return sample > 0 ? - sample / args["oldPositive"] : sample / args["oldNegative"]; - }, + read_(bytes, i, type=this) { + let num = 0; + let x = type.offset - 1; + while (x > 0) { + num = (bytes[x + i] << x * 8) | num; + x--; + } + num = (bytes[i] | num) >>> 0; + return this.overflow(this.sign(num)); + } /** - * Change the bit depth from float to float. - * @param {number} sample The sample. - * @param {Object} args Data about the original and target bit depths. + * Read a integer number from a byte buffer by turning the bytes + * to a string of bits. + * @param {!Array|Uint8Array} bytes An array of bytes. + * @param {number} i The index to read. + * @param {Object} type The type if other than this. * @return {number} + * @private */ - "floatToFloat": function(sample, args) { - if (args["original"] == "64" && args["target"] == "32f") { - f64f32[0] = sample; - sample = f64f32[0]; + readBits_(bytes, i, type=this) { + let binary = ""; + let j = 0; + while(j < type.offset) { + let bits = bytes[i + j].toString(2); + binary = Array(9 - bits.length).join("0") + bits + binary; + j++; } - return sample; + return this.overflow(this.sign(parseInt(binary, 2))); } -}; -/** - * Change the bit depth of the data in a array. - * The input array is modified in-place. - * @param {!Array} samples The samples. - * @param {string} originalBitDepth The original bit depth of the data. - * One of "8", "16", "24", "32", "32f", "64" - * @param {string} targetBitDepth The new bit depth of the data. + /** + * Write one integer number to a byte buffer. + * @param {!Array} bytes An array of bytes. + * @param {number} number The number. + * @param {number} j The index being written in the byte buffer. + * @param {Object} type The type. + * @return {number} The next index to write on the byte buffer. + * @private + */ + write_(bytes, number, j, type=this) { + number = this.overflow(number); + let mask = 255; + let len = type.offset; + j = this.writeFirstByte_(bytes, number, j, type); + for (let i = 2; i <= len; i++) { + if (i == len) { + mask = type.lastByteMask; + } + bytes[j++] = Math.floor(number / Math.pow(2, ((i - 1) * 8))) & mask; + } + return j; + } + + /** + * Build the type. + * @private + */ + build_() { + this.validateWordSize_(); + this.setRealBits_(); + this.setLastByteMask_(); + this.setMinMax_(); + this.offset = this.bits < 8 ? 1 : Math.ceil(this.realBits / 8); + } + + /** + * Set the minimum and maximum values for the type. + * @private + */ + setMinMax_() { + let max = Math.pow(2, this.bits); + if (this.signed) { + this.max = max / 2 -1; + this.min = -max / 2; + } else { + this.max = max - 1; + this.min = 0; + } + } + + validateWordSize_() { + if (this.bits < 1 || this.bits > 64) { + throw Error("Not a supported type."); + } + } + + /** + * Set the real bit depth for data with bit count different from the + * standard types (1, 2, 4, 8, 16, 32, 40, 48, 64): the closest bigger + * standard number of bits. The data is then treated as data of the + * standard type on all aspects except for the min and max values. + * Ex: a 11-bit uInt is treated as 16-bit uInt with a max value of 2048. + * @private + */ + setRealBits_() { + if (this.bits > 8) { + if (this.bits <= 16) { + this.realBits = 16; + } else if (this.bits <= 24) { + this.realBits = 24; + } else if (this.bits <= 32) { + this.realBits = 32; + } else if (this.bits <= 40) { + this.realBits = 40; + } else if (this.bits <= 48) { + this.realBits = 48; + } else if (this.bits <= 56) { + this.realBits = 56; + } else { + this.realBits = 64; + } + } else { + this.realBits = this.bits; + } + } + + /** + * Set the mask that should be used when writing the last byte of + * data of the type. + * @private + */ + setLastByteMask_() { + let r = 8 - (this.realBits - this.bits); + this.lastByteMask = Math.pow(2, r > 0 ? r : 8) -1; + } + + /** + * Write the first byte of a integer number. + * @param {!Array} bytes An array of bytes. + * @param {number} number The number. + * @param {number} j The index being written in the byte buffer. + * @param {Object} type The type. + * @return {number} The next index to write on the byte buffer. + * @private + */ + writeFirstByte_(bytes, number, j, type=this) { + if (type.bits < 8) { + bytes[j++] = number < 0 ? number + Math.pow(2, type.bits) : number; + } else { + bytes[j++] = number & 255; + } + return j; + } +} + +module.exports = GInt; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + +/*! + * bitdepth + * Change the bit depth of samples to and from 8, 16, 24, 32 & 64-bit. + * Copyright (c) 2017 Rafael da Silva Rocha. + * https://github.com/rochars/bitdepth + * + */ + +const f64f32 = new Float32Array(1); + +/** + * Max number of different values for each bit depth. + * @enum {number} + */ +const BitDepthMaxValues = { + "8": 256, + "16": 65536, + "24": 16777216, + "32": 4294967296, + "32f": 1, + "64": 1 +}; + +/** + * Functions to change the bit depth of a sample. + */ +const BitDepthFunctions = { + + /** + * Change the bit depth from int to int. + * @param {number} sample The sample. + * @param {Object} args Data about the original and target bit depths. + * @return {number} + */ + "intToInt": function(sample, args) { + if (sample > 0) { + sample = parseInt( + (sample / args["oldPositive"]) * args["newPositive"], 10); + } else { + sample = parseInt( + (sample / args["oldNegative"]) * args["newNegative"], 10); + } + return sample; + }, + + /** + * Change the bit depth from float to int. + * @param {number} sample The sample. + * @param {Object} args Data about the original and target bit depths. + * @return {number} + */ + "floatToInt": function(sample, args) { + return sample > 0 ? + sample * args["newPositive"] : sample * args["newNegative"]; + }, + + /** + * Change the bit depth from int to float. + * @param {number} sample The sample. + * @param {Object} args Data about the original and target bit depths. + * @return {number} + */ + "intToFloat": function(sample, args) { + return sample > 0 ? + sample / args["oldPositive"] : sample / args["oldNegative"]; + }, + + /** + * Change the bit depth from float to float. + * @param {number} sample The sample. + * @param {Object} args Data about the original and target bit depths. + * @return {number} + */ + "floatToFloat": function(sample, args) { + if (args["original"] == "64" && args["target"] == "32f") { + f64f32[0] = sample; + sample = f64f32[0]; + } + return sample; + } +}; + +/** + * Change the bit depth of the data in a array. + * The input array is modified in-place. + * @param {!Array} samples The samples. + * @param {string} originalBitDepth The original bit depth of the data. + * One of "8", "16", "24", "32", "32f", "64" + * @param {string} targetBitDepth The new bit depth of the data. * One of "8", "16", "24", "32", "32f", "64" */ function toBitDepth(samples, originalBitDepth, targetBitDepth) { @@ -2413,23 +1886,27 @@ module.exports.BitDepthMaxValues = BitDepthMaxValues; /***/ }), -/* 18 */ +/* 10 */ /***/ (function(module, exports, __webpack_require__) { /* * WaveFileReaderWriter - * Copyright (c) 2017-2018 Rafael da Silva Rocha. MIT License. + * Copyright (c) 2017-2018 Rafael da Silva Rocha. * https://github.com/rochars/wavefile * + * References: + * http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html + * https://tech.ebu.ch/docs/tech/tech3285.pdf + * */ -const byteData = __webpack_require__(3); -const WaveErrors = __webpack_require__(8); +const byteData = __webpack_require__(0); +const WaveErrors = __webpack_require__(3); const uInt8 = byteData.uInt8; const uInt16 = byteData.uInt16; const uInt32 = byteData.uInt32; const chr = byteData.chr; -let WaveFileHeader = __webpack_require__(19); +let WaveFileHeader = __webpack_require__(11); /** * Read and write wave files. @@ -2455,6 +1932,8 @@ class WaveFileReaderWriter extends WaveFileHeader { }; /** @type {!Array} */ this.samples = []; + /** @type {number} */ + this.head_ = 0; } /** @@ -2475,6 +1954,11 @@ class WaveFileReaderWriter extends WaveFileHeader { } } + /** + * Set up to work wih big-endian or little-endian files. + * The types used are changed from LE or BE. If the + * the file is big-endian (RIFX), true is returned. + */ LEorBE() { let bigEndian = this.chunkId == "RIFX"; uInt8.be = bigEndian; @@ -2554,9 +2038,103 @@ class WaveFileReaderWriter extends WaveFileHeader { this.bextChunkId = "bext"; this.bextChunkSize = chunk.chunkSize; this.bextChunkData = chunk.chunkData; + this.readBextChunkFields_(); + } + } + + /** + * Read the fields of the "bext" chunk. + */ + readBextChunkFields_() { + this.head_ = 0; + this.bextChunkFields = { + "description": this.readVariableSizeString_( + this.bextChunkData, 256), + "originator": this.readVariableSizeString_( + this.bextChunkData, 32), + "originatorReference": this.readVariableSizeString_( + this.bextChunkData, 32), + "originationDate": this.readVariableSizeString_( + this.bextChunkData, 10), + "originationTime": this.readVariableSizeString_( + this.bextChunkData, 8), + // timeReference is a 64-bit value + "timeReference": this.readBytes( + this.bextChunkData, 8), + "version": this.readFromChunk_( + this.bextChunkData, uInt16), + "UMID": this.readVariableSizeString_( + this.bextChunkData, 64), + "loudnessValue": this.readFromChunk_( + this.bextChunkData, uInt16), + "loudnessRange": this.readFromChunk_( + this.bextChunkData, uInt16), + "maxTruePeakLevel": this.readFromChunk_( + this.bextChunkData, uInt16), + "maxMomentaryLoudness": this.readFromChunk_( + this.bextChunkData, uInt16), + "maxShortTermLoudness": this.readFromChunk_( + this.bextChunkData, uInt16), + "reserved": this.readVariableSizeString_( + this.bextChunkData, 180), + "codingHistory": this.readVariableSizeString_( + this.bextChunkData, this.bextChunkData.length - 602), } } + /** + * Return a slice of the byte array while moving the reading head. + * @param {!Array} bytes The bytes. + * @param {number} size the number of bytes to read. + */ + readBytes(bytes, size) { + let v = this.head_; + this.head_ += size; + return bytes.slice(v, this.head_); + } + + /** + * Read bytes as a string from a RIFF chunk. + * @param {!Array} bytes The bytes. + * @param {number} maxSize the max size of the string. + */ + readVariableSizeString_(bytes, maxSize) { + let str = ""; + for (let i=0; i} bytes The bytes. + * @param {Object} bdType The byte-data corresponding type. + */ + readFromChunk_(bytes, bdType) { + let size = bdType.bits / 8; + let value = byteData.unpack( + bytes.slice(this.head_, this.head_ + size), bdType); + this.head_ += size; + return value; + } + + /** + * Write a variable size string as bytes. + * If the string is smaller than the max size it + * is filled with 0s. + * @param {string} str The string to be written as bytes. + * @param {number} maxSize the max size of the string. + */ + writeVariableSizeString_(str, maxSize) { + let bytes = byteData.packArray(str, chr); + for (let i=bytes.length; i} */ this.cueChunkData = []; /** @@ -2813,8 +2429,30 @@ class WaveFileHeader { * @type {string} */ this.bextChunkId = ""; + /** @type {number} */ this.bextChunkSize = 0; + /** @type {!Array} */ this.bextChunkData = []; + /** @type {!Object} */ + this.bextChunkFields = { + "description": "", //256 + "originator": "", //32 + "originatorReference": "", //32 + "originationDate": "", //10 + "originationTime": "", //8 + "timeReferenceLow": "", //DWORD + "timeReferenceHigh": "", //DWORD + "version": "", //WORD + "UMID_0 ": "", //byte + "UMID_63 ": "", //byte + "loudnessValue": "", //WORD + "loudnessRange": "", //WORD + "maxTruePeakLevel": "", //WORD + "maxMomentaryLoudness": "", //WORD + "maxShortTermLoudness": "", //WORD + "reserved": "", //180 + "codingHistory": "" // string, unlimited + }; } } @@ -2822,7 +2460,7 @@ module.exports = WaveFileHeader; /***/ }), -/* 20 */ +/* 12 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -2833,7 +2471,7 @@ module.exports = WaveFileHeader; * */ -const byteData = __webpack_require__(21); +const byteData = __webpack_require__(13); const uInt32 = byteData.uInt32; const chr = byteData.chr; @@ -2964,7 +2602,7 @@ module.exports.write = write; /***/ }), -/* 21 */ +/* 13 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -2976,8 +2614,8 @@ module.exports.write = write; */ /** @private */ -const rw = __webpack_require__(22); -let Type = __webpack_require__(9); +const rw = __webpack_require__(14); +let Type = __webpack_require__(4); /** * Turn a number or fixed-length string into a byte buffer. @@ -3316,7 +2954,7 @@ exports.float64BE = new Type({"bits": 64, "float": true, "be": true}); /***/ }), -/* 22 */ +/* 14 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -3325,8 +2963,8 @@ exports.float64BE = new Type({"bits": 64, "float": true, "be": true}); * https://github.com/rochars/byte-data */ -const Type = __webpack_require__(9); -const endianness = __webpack_require__(1); +const Type = __webpack_require__(4); +const endianness = __webpack_require__(2); /** * Turn a byte buffer into what the bytes represent. @@ -3476,7 +3114,7 @@ exports.fromBytes = fromBytes; /***/ }), -/* 23 */ +/* 15 */ /***/ (function(module, exports) { /** @@ -3820,1059 +3458,290 @@ let BitWriter = { * Write one char as a byte. * @param {!Array} bytes An array of bytes. * @param {string} string The string to write as bytes. - * @param {number} j The index being written in the byte buffer. - * @return {number} The next index to write on the byte buffer. - */ - "writeString": function (bytes, string, j) { - bytes[j++] = string.charCodeAt(0); - return j; - } -}; - -/** - * Get a binary string representation of a value described as bytes. - * @param {Array|number} bytes The bytes. - * @return {string} - */ -function getBinary(bytes) { - let binary = ""; - let i = 0; - let bytesLength = bytes.length; - while(i < bytesLength) { - let bits = bytes[i].toString(2); - binary = Array(9 - bits.length).join("0") + bits + binary; - i++; - } - return binary; -} - -/** - * Read a group of bytes by turning it to bits. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @param {number} numBytes The number of bytes - * (1 for 8-bit, 2 for 16-bit, etc). - * @return {number} - */ -function readBytesAsBits(bytes, i, numBytes) { - let j = numBytes-1; - let byte = ""; - while (j >= 0) { - let bits = bytes[j + i].toString(2); - byte += Array(9 - bits.length).join("0") + bits; - j--; - } - return parseInt(byte, 2); -} - -exports.BitWriter = BitWriter; -exports.BitReader = BitReader; - - -/***/ }), -/* 24 */ -/***/ (function(module, exports, __webpack_require__) { - -/*! - * imaadpcm - * JavaScript IMA ADPCM codec. - * Copyright (c) 2018 Rafael da Silva Rocha. - * https://github.com/rochars/imaadpcm - * - * References: - * http://www.cs.columbia.edu/~hgs/audio/dvi/ - * https://github.com/acida/pyima - * https://wiki.multimedia.cx/index.php/IMA_ADPCM - * - */ - -const byteData = __webpack_require__(25); -const int16 = byteData.int16; - -var indexTable = [ - -1, -1, -1, -1, 2, 4, 6, 8, - -1, -1, -1, -1, 2, 4, 6, 8]; - -var stepTable = [ - 7, 8, 9, 10, 11, 12, 13, 14, - 16, 17, 19, 21, 23, 25, 28, 31, - 34, 37, 41, 45, 50, 55, 60, 66, - 73, 80, 88, 97, 107, 118, 130, 143, - 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, - 724, 796, 876, 963, 1060, 1166, 1282, 1411, - 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, - 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, - 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, - 32767]; - -var encoderPredicted = 0; -var encoderIndex = 0; -var encoderStep = 7; -var decoderPredicted = 0; -var decoderIndex = 0; -var decoderStep = 7; - -/** - * Compress a 16-bit PCM sample into a 4-bit ADPCM sample. - * @param {number} sample The sample. - * @return {number} - */ -function encodeSample(sample) { - let delta = sample - encoderPredicted; - let value = 0; - if (delta >= 0) { - value = 0; - } - else { - value = 8; - delta = -delta; - } - let step = stepTable[encoderIndex]; - let diff = step >> 3; - if (delta > step) { - value |= 4; - delta -= step; - diff += step; - } - step >>= 1; - if (delta > step) { - value |= 2; - delta -= step; - diff += step; - } - step >>= 1; - if (delta > step) { - value |= 1; - diff += step; - } - if (value & 8) { - encoderPredicted -= diff; - } - else { - encoderPredicted += diff; - } - if (encoderPredicted < -0x8000) { - encoderPredicted = -0x8000; - } else if (encoderPredicted > 0x7fff) { - encoderPredicted = 0x7fff; - } - encoderIndex += indexTable[value & 7]; - if (encoderIndex < 0) { - encoderIndex = 0; - } else if (encoderIndex > 88) { - encoderIndex = 88; - } - return value; -} - -/** - * Decode a 4-bit ADPCM sample into a 16-bit PCM sample. - * @param {number} nibble A 4-bit adpcm sample. - * @return {number} - */ -function decodeSample(nibble) { - let difference = 0; - if (nibble & 4) { - difference += decoderStep; - } - if (nibble & 2) { - difference += decoderStep >> 1; - } - if (nibble & 1) { - difference += decoderStep >> 2; - } - difference += decoderStep >> 3; - if (nibble & 8) { - difference = -difference; - } - decoderPredicted += difference; - if (decoderPredicted > 32767) { - decoderPredicted = 32767; - } else if (decoderPredicted < -32767) { - decoderPredicted = -32767; - } - decoderIndex += indexTable[nibble]; - if (decoderIndex < 0) { - decoderIndex = 0; - } else if (decoderIndex > 88) { - decoderIndex = 88; - } - decoderStep = stepTable[decoderIndex]; - return decoderPredicted; -} - -/** - * Return the head of a ADPCM sample block. - * @param {number} sample The first sample of the block. - * @return {!Array} - */ -function blockHead(sample) { - encodeSample(sample); - let adpcmSamples = []; - adpcmSamples.push(byteData.pack(sample, int16)[0]); - adpcmSamples.push(byteData.pack(sample, int16)[1]); - adpcmSamples.push(encoderIndex); - adpcmSamples.push(0); - return adpcmSamples; -} - -/** - * Encode a block of 505 16-bit samples as 4-bit ADPCM samples. - * @param {!Array} block A sample block of 505 samples. - * @return {!Array} - */ -function encodeBlock(block) { - let adpcmSamples = blockHead(block[0]); - for (let i=3; i} block A adpcm sample block of 256 samples. - * @return {!Array} - */ -function decodeBlock(block) { - decoderPredicted = byteData.unpack([block[0], block[1]], int16); - decoderIndex = block[2]; - decoderStep = stepTable[decoderIndex]; - let result = [ - decoderPredicted, - byteData.unpack([block[2], block[3]], int16) - ]; - for (let i=4; i> 4; - let first_sample = (second_sample << 4) ^ original_sample; - result.push(decodeSample(first_sample)); - result.push(decodeSample(second_sample)); - } - return result; -} - -/** - * Encode 16-bit PCM samples into 4-bit IMA ADPCM samples. - * @param {!Array} samples A array of samples. - * @return {!Array} - */ -function encode(samples) { - let adpcmSamples = []; - let block = []; - for (let i=0; i} adpcmSamples A array of ADPCM samples. - * @param {number} blockAlign The block size. - * @return {!Array} - */ -function decode(adpcmSamples, blockAlign=256) { - let samples = []; - let block = []; - for (let i=0; i|!Array} - */ -function pack(value, type, base=10) { - let values = []; - if (type.char) { - values = type.char ? value.slice(0, type.realBits / 8) : value; - } else if (!Array.isArray(value)) { - values = [value]; - } - return rw.toBytes(values, rw.getType(type, base)); -} - -/** - * Turn a byte buffer into a number or a fixed-length string. - * @param {!Array|!Array|Uint8Array} buffer An array of bytes. - * @param {Object} type One of the available types. - * @param {number} base The base of the input. Optional. Default is 10. - * Possible values are 2, 10 or 16. - * @return {number|string} - */ -function unpack(buffer, type, base=10) { - let offset = type.bits < 8 ? type.bits : type.realBits / 8; - let values = rw.fromBytes( - buffer.slice(0, offset), - rw.getType(type, base) - ); - if (type.char) { - values = values.slice(0, type.bits / 8); - } else { - values = values[0]; - } - return values; -} - -/** - * Turn a array of numbers or a string into a byte buffer. - * @param {!Array|string} values The values. - * @param {Object} type One of the available types. - * @param {number} base The base of the output. Optional. Default is 10. - * Possible values are 2, 10 or 16. - * @return {!Array|!Array} - */ -function packArray(values, type, base=10) { - return rw.toBytes(values, rw.getType(type, base)); -} - -/** - * Turn a byte buffer into a array of numbers or a string. - * @param {!Array|!Array|Uint8Array} buffer The byte array. - * @param {Object} type One of the available types. - * @param {number} base The base of the input. Optional. Default is 10. - * Possible values are 2, 10 or 16. - * @return {!Array|string} - */ -function unpackArray(buffer, type, base=10) { - return rw.fromBytes(buffer, rw.getType(type, base)); -} - -/** - * Find and return the start index of some string. - * Return -1 if the string is not found. - * @param {!Array|Uint8Array} buffer A byte buffer. - * @param {string} text Some string to look for. - * @return {number} The start index of the first occurrence, -1 if not found - */ -function findString(buffer, text) { - let found = ""; - for (let i = 0; i < buffer.length; i++) { - found = unpack( - buffer.slice(i, i + text.length + 1), - new Type({"bits": text.length * 8, "char": true}) - ); - if (found == text) { - return i; - } - } - return -1; -} - -/** - * Turn a struct into a byte buffer. - * A struct is an array of values of not necessarily the same type. - * @param {Array} struct The struct values. - * @param {!Array} def The struct type definition. - * @param {number} base The base of the output. Optional. Default is 10. - * Possible values are 2, 10 or 16. - * @return {!Array|!Array} - */ -function packStruct(struct, def, base=10) { - if (struct.length < def.length) { - return []; - } - let bytes = []; - for (let i = 0; i < def.length; i++) { - bytes = bytes.concat(pack(struct[i], def[i], base)); - } - return bytes; -} - -/** - * Turn a byte buffer into a struct. - * A struct is an array of values of not necessarily the same type. - * @param {!Array|!Array|Uint8Array} buffer The byte buffer. - * @param {!Array} def The struct type definition. - * @param {number} base The base of the input. Optional. Default is 10. - * Possible values are 2, 10 or 16. - * @return {Array} - */ -function unpackStruct(buffer, def, base=10) { - if (buffer.length < getStructDefSize(def)) { - return []; - } - let struct = []; - let i = 0; - let j = 0; - while (i < def.length) { - let bits = def[i].bits < 8 ? 1 : def[i].realBits / 8; - struct = struct.concat( - unpack(buffer.slice(j, j + bits), def[i], base) - ); - j += bits; - i++; - } - return struct; -} - -/** - * Get the length in bytes of a struct definition. - * @param {!Array} def The struct type definition. - * @return {number} The length of the structure in bytes. - * @private - */ -function getStructDefSize(def) { - let bits = 0; - for (let i = 0; i < def.length; i++) { - bits += def[i].realBits / 8; - } - return bits; -} - -// interface -exports.pack = pack; -exports.unpack = unpack; -exports.packArray = packArray; -exports.unpackArray = unpackArray; -exports.unpackStruct = unpackStruct; -exports.packStruct = packStruct; -exports.findString = findString; -exports.Type = Type; -/** - * A char. - * @type {Object} - */ -exports.chr = new Type({"bits": 8, "char": true}); -/** - * A 4-char string - * @type {Object} - */ -exports.fourCC = new Type({"bits": 32, "char": true}); -/** - * Booleans - * @type {Object} - */ -exports.bool = new Type({"bits": 1}); -/** - * Signed 2-bit integers - * @type {Object} - */ -exports.int2 = new Type({"bits": 2, "signed": true}); -/** - * Unsigned 2-bit integers - * @type {Object} - */ -exports.uInt2 = new Type({"bits": 2}); -/** - * Signed 4-bit integers - * @type {Object} - */ -exports.int4 = new Type({"bits": 4, "signed": true}); -/** - * Unsigned 4-bit integers - * @type {Object} - */ -exports.uInt4 = new Type({"bits": 4}); -/** - * Signed 8-bit integers - * @type {Object} - */ -exports.int8 = new Type({"bits": 8, "signed": true}); -/** - * Unsigned 4-bit integers - * @type {Object} - */ -exports.uInt8 = new Type({"bits": 8}); -// LE -/** - * Signed 16-bit integers little-endian - * @type {Object} - */ -exports.int16 = new Type({"bits": 16, "signed": true}); -/** - * Unsigned 16-bit integers little-endian - * @type {Object} - */ -exports.uInt16 = new Type({"bits": 16}); -/** - * Half-precision floating-point numbers little-endian - * @type {Object} - */ -exports.float16 = new Type({"bits": 16, "float": true}); -/** - * Signed 24-bit integers little-endian - * @type {Object} - */ -exports.int24 = new Type({"bits": 24, "signed": true}); -/** - * Unsigned 24-bit integers little-endian - * @type {Object} - */ -exports.uInt24 = new Type({"bits": 24}); -/** - * Signed 32-bit integers little-endian - * @type {Object} - */ -exports.int32 = new Type({"bits": 32, "signed": true}); -/** - * Unsigned 32-bit integers little-endian - * @type {Object} - */ -exports.uInt32 = new Type({"bits": 32}); -/** - * Single-precision floating-point numbers little-endian - * @type {Object} - */ -exports.float32 = new Type({"bits": 32, "float": true}); -/** - * Signed 40-bit integers little-endian - * @type {Object} - */ -exports.int40 = new Type({"bits": 40, "signed": true}); -/** - * Unsigned 40-bit integers little-endian - * @type {Object} - */ -exports.uInt40 = new Type({"bits": 40}); -/** - * Signed 48-bit integers little-endian - * @type {Object} - */ -exports.int48 = new Type({"bits": 48, "signed": true}); -/** - * Unsigned 48-bit integers little-endian - * @type {Object} - */ -exports.uInt48 = new Type({"bits": 48}); -/** - * Double-precision floating-point numbers little-endian - * @type {Object} - */ -exports.float64 = new Type({"bits": 64, "float": true}); -// BE -/** - * Signed 16-bit integers big-endian - * @type {Object} - */ -exports.int16BE = new Type({"bits": 16, "signed": true, "be": true}); -/** - * Unsigned 16-bit integers big-endian - * @type {Object} - */ -exports.uInt16BE = new Type({"bits": 16, "be": true}); -/** - * Half-precision floating-point numbers big-endian - * @type {Object} - */ -exports.float16BE = new Type({"bits": 16, "float": true, "be": true}); -/** - * Signed 24-bit integers big-endian - * @type {Object} - */ -exports.int24BE = new Type({"bits": 24, "signed": true, "be": true}); -/** - * Unsigned 24-bit integers big-endian - * @type {Object} - */ -exports.uInt24BE = new Type({"bits": 24, "be": true}); -/** - * Signed 32-bit integers big-endian - * @type {Object} - */ -exports.int32BE = new Type({"bits": 32, "signed": true, "be": true}); -/** - * Unsigned 32-bit integers big-endian - * @type {Object} - */ -exports.uInt32BE = new Type({"bits": 32, "be": true}); -/** - * Single-precision floating-point numbers big-endian - * @type {Object} - */ -exports.float32BE = new Type({"bits": 32, "float": true, "be": true}); -/** - * Signed 40-bit integers big-endian - * @type {Object} - */ -exports.int40BE = new Type({"bits": 40, "signed": true, "be": true}); -/** - * Unsigned 40-bit integers big-endian - * @type {Object} - */ -exports.uInt40BE = new Type({"bits": 40, "be": true}); -/** - * Signed 48-bit integers big-endian - * @type {Object} - */ -exports.int48BE = new Type({"bits": 48, "signed": true, "be": true}); -/** - * Unsigned 48-bit integers big-endian - * @type {Object} - */ -exports.uInt48BE = new Type({"bits": 48, "be": true}); -/** - * Double-precision floating-point numbers big-endian - * @type {Object} - */ -exports.float64BE = new Type({"bits": 64, "float": true, "be": true}); - - -/***/ }), -/* 26 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * from-bytes: Numbers and strings from bytes. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data - */ - -const Type = __webpack_require__(10); -const endianness = __webpack_require__(1); - -/** - * Turn a byte buffer into what the bytes represent. - * @param {!Array|!Array|Uint8Array} buffer An array of bytes. - * @param {Object} type One of the available types. - * @return {!Array|number|string} - */ -function fromBytes(buffer, type) { - if (type.be) { - endianness(buffer, type.offset); - } - if (type.base != 10) { - bytesFromBase(buffer, type.base); - } - return readBytes(buffer, type); -} - -/** - * Turn numbers and strings to bytes. - * @param {!Array|number|string} values The data. - * @param {Object} type One of the available types. - * @return {!Array|!Array} the data as a byte buffer. - */ -function toBytes(values, type) { - let bytes = writeBytes(values, type); - if (type.be) { - endianness(bytes, type.offset); - } - if (type.base != 10) { - bytesToBase(bytes, type.base); - formatOutput(bytes, type); - } - return bytes; -} - -/** - * Turn a array of bytes into an array of what the bytes should represent. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {Object} type The type. - * @return {!Array|string} - */ -function readBytes(bytes, type) { - let values = []; - let i = 0; - let len = bytes.length - (type.offset - 1); - while (i < len) { - values.push(type.reader(bytes, i)); - i += type.offset; - } - if (type.char) { - values = values.join(""); - } - return values; -} - -/** - * Write values as bytes. - * @param {!Array|number|string} values The data. - * @param {Object} type One of the available types. - * @return {!Array} the bytes. - */ -function writeBytes(values, type) { - let i = 0; - let j = 0; - let len = values.length; - let bytes = []; - while (i < len) { - j = type.writer(bytes, values[i++], j); - } - return bytes; -} - -/** - * Get the full type spec for the reading/writing. - * @param {Object} type One of the available types. - * @param {number} base The base of the input. - * @return {Object} - */ -function getType(type, base) { - let theType = Object.assign(new Type({}), type); - theType.base = base; - return theType; -} - -/** - * Turn bytes to base 10 from base 2 or 16. - * @param {!Array|Uint8Array} bytes The bytes as binary or hex strings. - * @param {number} base The base. - */ -function bytesFromBase(bytes, base) { - let i = 0; - let len = bytes.length; - while(i < len) { - bytes[i] = parseInt(bytes[i], base); - i++; + * @param {number} j The index being written in the byte buffer. + * @return {number} The next index to write on the byte buffer. + */ + "writeString": function (bytes, string, j) { + bytes[j++] = string.charCodeAt(0); + return j; } -} +}; /** - * Turn the output to the correct base. - * @param {Array} bytes The bytes. - * @param {Object} type The type. + * Get a binary string representation of a value described as bytes. + * @param {Array|number} bytes The bytes. + * @return {string} */ -function formatOutput(bytes, type) { +function getBinary(bytes) { + let binary = ""; let i = 0; - let len = bytes.length; - let offset = (type.base == 2 ? 8 : 2) + 1; - while(i < len) { - bytes[i] = Array(offset - bytes[i].length).join("0") + bytes[i]; + let bytesLength = bytes.length; + while(i < bytesLength) { + let bits = bytes[i].toString(2); + binary = Array(9 - bits.length).join("0") + bits + binary; i++; } + return binary; } /** - * Turn bytes from base 10 to base 2 or 16. - * @param {!Array|Array} bytes The bytes. - * @param {number} base The base. + * Read a group of bytes by turning it to bits. + * @param {!Array|Uint8Array} bytes An array of bytes. + * @param {number} i The index to read. + * @param {number} numBytes The number of bytes + * (1 for 8-bit, 2 for 16-bit, etc). + * @return {number} */ -function bytesToBase(bytes, base) { - let i = 0; - let len = bytes.length; - while (i < len) { - bytes[i] = bytes[i].toString(base); - i++; +function readBytesAsBits(bytes, i, numBytes) { + let j = numBytes-1; + let byte = ""; + while (j >= 0) { + let bits = bytes[j + i].toString(2); + byte += Array(9 - bits.length).join("0") + bits; + j--; } + return parseInt(byte, 2); } -exports.getType = getType; -exports.toBytes = toBytes; -exports.fromBytes = fromBytes; +exports.BitWriter = BitWriter; +exports.BitReader = BitReader; /***/ }), -/* 27 */ -/***/ (function(module, exports) { +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * gint: Generic integer. - * A class to represent any integer from 1 to 53-Bit. - * Copyright (c) 2017 Rafael da Silva Rocha. - * https://github.com/rochars/byte-data +/*! + * imaadpcm + * JavaScript IMA ADPCM codec. + * Copyright (c) 2018 Rafael da Silva Rocha. + * https://github.com/rochars/imaadpcm + * + * References: + * http://www.cs.columbia.edu/~hgs/audio/dvi/ + * https://github.com/acida/pyima + * https://wiki.multimedia.cx/index.php/IMA_ADPCM + * */ +const byteData = __webpack_require__(0); +const int16 = byteData.int16; + +var indexTable = [ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8]; + +var stepTable = [ + 7, 8, 9, 10, 11, 12, 13, 14, + 16, 17, 19, 21, 23, 25, 28, 31, + 34, 37, 41, 45, 50, 55, 60, 66, + 73, 80, 88, 97, 107, 118, 130, 143, + 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, + 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, + 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, + 32767]; + +var encoderPredicted = 0; +var encoderIndex = 0; +var encoderStep = 7; +var decoderPredicted = 0; +var decoderIndex = 0; +var decoderStep = 7; + /** - * A class to represent any integer from 1 to 53-Bit. + * Compress a 16-bit PCM sample into a 4-bit ADPCM sample. + * @param {number} sample The sample. + * @return {number} */ -class GInt { - - /** - * @param {Object} options The type definition. - * @param {number} options.bits Number of bits used by data of this type. - * @param {boolean} options.be True for big-endian. - * @param {boolean} options.signed True for signed types. - */ - constructor(options) { - /** - * The max number of bits used by data of this type. - * @type {number} - */ - this.bits = options["bits"]; - /** - * If this type is big-endian or not. - * @type {boolean} - */ - this.be = options["be"]; - /** - * If this type it is signed or not. - * @type {boolean} - */ - this.signed = options["signed"]; - /** - * The base used to represent data of this type. - * Default is 10. - * @type {number} - */ - this.base = options["base"] ? options["base"] : 10; - /** - * The function to read values of this type from buffers. - * @type {Function} - * @ignore - */ - this.reader = this.read_; - /** - * The function to write values of this type to buffers. - * @type {Function} - * @ignore - */ - this.writer = this.write_; - /** - * The number of bytes used by data of this type. - * @type {number} - * @ignore - */ - this.offset = 0; - /** - * Min value for numbers of this type. - * @type {number} - * @ignore - */ - this.min = -Infinity; - /** - * Max value for numbers of this type. - * @type {number} - * @ignore - */ - this.max = Infinity; - /** - * The word size. - * @type {number} - * @ignore - */ - this.realBits = this.bits; - /** - * The mask to be used in the last byte of this type. - * @type {number} - * @ignore - */ - this.lastByteMask = 255; - this.build_(); +function encodeSample(sample) { + let delta = sample - encoderPredicted; + let value = 0; + if (delta >= 0) { + value = 0; } - - /** - * Sign a number according to the type. - * @param {number} num The number. - * @return {number} - * @ignore - */ - sign(num) { - if (num > this.max) { - num -= (this.max * 2) + 2; - } - return num; + else { + value = 8; + delta = -delta; } - - /** - * Limit the value according to the bit depth in case of - * overflow or underflow. - * @param {number} value The data. - * @return {number} - * @ignore - */ - overflow(value) { - if (value > this.max) { - value = this.max; - } else if (value < this.min) { - value = this.min; - } - return value; + let step = stepTable[encoderIndex]; + let diff = step >> 3; + if (delta > step) { + value |= 4; + delta -= step; + diff += step; } - - /** - * Read a integer number from a byte buffer. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @param {Object} type The type if other than this. - * @return {number} - * @private - */ - read_(bytes, i, type=this) { - let num = 0; - let x = type.offset - 1; - while (x > 0) { - num = (bytes[x + i] << x * 8) | num; - x--; - } - num = (bytes[i] | num) >>> 0; - return this.overflow(this.sign(num)); + step >>= 1; + if (delta > step) { + value |= 2; + delta -= step; + diff += step; + } + step >>= 1; + if (delta > step) { + value |= 1; + diff += step; + } + if (value & 8) { + encoderPredicted -= diff; + } + else { + encoderPredicted += diff; + } + if (encoderPredicted < -0x8000) { + encoderPredicted = -0x8000; + } else if (encoderPredicted > 0x7fff) { + encoderPredicted = 0x7fff; } - - /** - * Read a integer number from a byte buffer by turning the bytes - * to a string of bits. - * @param {!Array|Uint8Array} bytes An array of bytes. - * @param {number} i The index to read. - * @param {Object} type The type if other than this. - * @return {number} - * @private - */ - readBits_(bytes, i, type=this) { - let binary = ""; - let j = 0; - while(j < type.offset) { - let bits = bytes[i + j].toString(2); - binary = Array(9 - bits.length).join("0") + bits + binary; - j++; - } - return this.overflow(this.sign(parseInt(binary, 2))); + encoderIndex += indexTable[value & 7]; + if (encoderIndex < 0) { + encoderIndex = 0; + } else if (encoderIndex > 88) { + encoderIndex = 88; } + return value; +} - /** - * Write one integer number to a byte buffer. - * @param {!Array} bytes An array of bytes. - * @param {number} number The number. - * @param {number} j The index being written in the byte buffer. - * @param {Object} type The type. - * @return {number} The next index to write on the byte buffer. - * @private - */ - write_(bytes, number, j, type=this) { - number = this.overflow(number); - let mask = 255; - let len = type.offset; - j = this.writeFirstByte_(bytes, number, j, type); - for (let i = 2; i <= len; i++) { - if (i == len) { - mask = type.lastByteMask; - } - bytes[j++] = Math.floor(number / Math.pow(2, ((i - 1) * 8))) & mask; - } - return j; +/** + * Decode a 4-bit ADPCM sample into a 16-bit PCM sample. + * @param {number} nibble A 4-bit adpcm sample. + * @return {number} + */ +function decodeSample(nibble) { + let difference = 0; + if (nibble & 4) { + difference += decoderStep; } - - /** - * Build the type. - * @private - */ - build_() { - this.validateWordSize_(); - this.setRealBits_(); - this.setLastByteMask_(); - this.setMinMax_(); - this.offset = this.bits < 8 ? 1 : Math.ceil(this.realBits / 8); + if (nibble & 2) { + difference += decoderStep >> 1; } - - /** - * Set the minimum and maximum values for the type. - * @private - */ - setMinMax_() { - let max = Math.pow(2, this.bits); - if (this.signed) { - this.max = max / 2 -1; - this.min = -max / 2; - } else { - this.max = max - 1; - this.min = 0; - } + if (nibble & 1) { + difference += decoderStep >> 2; + } + difference += decoderStep >> 3; + if (nibble & 8) { + difference = -difference; + } + decoderPredicted += difference; + if (decoderPredicted > 32767) { + decoderPredicted = 32767; + } else if (decoderPredicted < -32767) { + decoderPredicted = -32767; } + decoderIndex += indexTable[nibble]; + if (decoderIndex < 0) { + decoderIndex = 0; + } else if (decoderIndex > 88) { + decoderIndex = 88; + } + decoderStep = stepTable[decoderIndex]; + return decoderPredicted; +} - validateWordSize_() { - if (this.bits < 1 || this.bits > 64) { - throw Error("Not a supported type."); - } +/** + * Return the head of a ADPCM sample block. + * @param {number} sample The first sample of the block. + * @return {!Array} + */ +function blockHead(sample) { + encodeSample(sample); + let adpcmSamples = []; + adpcmSamples.push(byteData.pack(sample, int16)[0]); + adpcmSamples.push(byteData.pack(sample, int16)[1]); + adpcmSamples.push(encoderIndex); + adpcmSamples.push(0); + return adpcmSamples; +} + +/** + * Encode a block of 505 16-bit samples as 4-bit ADPCM samples. + * @param {!Array} block A sample block of 505 samples. + * @return {!Array} + */ +function encodeBlock(block) { + let adpcmSamples = blockHead(block[0]); + for (let i=3; i 8) { - if (this.bits <= 16) { - this.realBits = 16; - } else if (this.bits <= 24) { - this.realBits = 24; - } else if (this.bits <= 32) { - this.realBits = 32; - } else if (this.bits <= 40) { - this.realBits = 40; - } else if (this.bits <= 48) { - this.realBits = 48; - } else if (this.bits <= 56) { - this.realBits = 56; - } else { - this.realBits = 64; - } - } else { - this.realBits = this.bits; - } +/** + * Decode a block of 256 ADPCM samples into 16-bit PCM samples. + * @param {!Array} block A adpcm sample block of 256 samples. + * @return {!Array} + */ +function decodeBlock(block) { + decoderPredicted = byteData.unpack([block[0], block[1]], int16); + decoderIndex = block[2]; + decoderStep = stepTable[decoderIndex]; + let result = [ + decoderPredicted, + byteData.unpack([block[2], block[3]], int16) + ]; + for (let i=4; i> 4; + let first_sample = (second_sample << 4) ^ original_sample; + result.push(decodeSample(first_sample)); + result.push(decodeSample(second_sample)); } + return result; +} - /** - * Set the mask that should be used when writing the last byte of - * data of the type. - * @private - */ - setLastByteMask_() { - let r = 8 - (this.realBits - this.bits); - this.lastByteMask = Math.pow(2, r > 0 ? r : 8) -1; +/** + * Encode 16-bit PCM samples into 4-bit IMA ADPCM samples. + * @param {!Array} samples A array of samples. + * @return {!Array} + */ +function encode(samples) { + let adpcmSamples = []; + let block = []; + for (let i=0; i} bytes An array of bytes. - * @param {number} number The number. - * @param {number} j The index being written in the byte buffer. - * @param {Object} type The type. - * @return {number} The next index to write on the byte buffer. - * @private - */ - writeFirstByte_(bytes, number, j, type=this) { - if (type.bits < 8) { - bytes[j++] = number < 0 ? number + Math.pow(2, type.bits) : number; - } else { - bytes[j++] = number & 255; +/** + * Decode IMA ADPCM samples into 16-bit PCM samples. + * @param {!Array} adpcmSamples A array of ADPCM samples. + * @param {number} blockAlign The block size. + * @return {!Array} + */ +function decode(adpcmSamples, blockAlign=256) { + let samples = []; + let block = []; + for (let i=0; i} samples A array of 16-bit PCM samples. * @return {!Array} */ -function encodeALaw(samples) { +function encode(samples) { let aLawSamples = []; for (let i=0; i} samples A array of 8-bit A-Law samples. * @return {!Array} */ -function decodeALaw(samples) { +function decode(samples) { let pcmSamples = []; for (let i=0; i} samples A array of 16-bit linear PCM samples. * @return {!Array} */ -function encodeMuLaw(samples) { +function encode(samples) { let muLawSamples = []; for (let i=0; i} samples A array of 8-bit mu-Law samples. * @return {!Array} */ -function decodeMuLaw(samples) { +function decode(samples) { let pcmSamples = []; for (let i=0; iThrows:
- Documentation generated by JSDoc 3.5.5 on Sun Apr 22 2018 15:25:20 GMT-0300 (Hora oficial do Brasil) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Apr 24 2018 23:24:21 GMT-0300 (Hora oficial do Brasil) using the docdash theme.
diff --git a/docs/index.html b/docs/index.html index 70477ca..717cdaa 100644 --- a/docs/index.html +++ b/docs/index.html @@ -58,7 +58,7 @@

About

wavefile is a module to work with wav files. I

  • Turn RIFF files to RIFX and RIFX files to RIFF
  • And more.

    -

    wavefile is extensively tested, and the test folder contains samples of all supported formats. Please note that some formats (like 8-bit A-Law and 64-bit floating point) are not widely supported and may not load in every player.

    +

    wavefile is extensively tested and contains samples of all supported formats. Please note that some formats (like 8-bit A-Law and 64-bit floating point) are not widely supported and may not load in every player.

    Install

    npm install wavefile

    See it in action

    https://tr2099.github.io/

    Hit "Load in player" to generate wave files.

    This website uses wavefile to create the files. The effects are provided by other libraries.

    @@ -144,12 +144,33 @@

    Use

    let fs = requi
     console.log(wav.factChunkSize);
     console.log(wav.dwSampleLength);
     
    +// "bext"
    +console.log(wav.bextChunkFields);
    +
     // "data"
     console.log(wav.dataChunkId);
     console.log(wav.dataChunkSize);
     
     // array of numbers
    -console.log(wav.samples);

    The samples

    Range:

    +console.log(wav.samples);

    BWF data

    BWF data ("bext" chunk) is stored in the bextChunkFields property in human-readable form. +You may edit the data in the "bext" chunk by editing the bextChunkFields property on a WaveFile object.

    +
    wav.bextChunkFields = {
    +    "description": "", // 256 chars
    +    "originator": "", // 32 chars
    +    "originatorReference": "", // 32 chars
    +    "originationDate": "", // 10 chars
    +    "originationTime": "", // 8 chars
    +    "timeReference": "", // 64-bit value kept as an array of 8 bytes
    +    "version": "", // 16-bit number
    +    "UMID": "", // 64 chars
    +    "loudnessValue": "", // 16-bit number
    +    "loudnessRange": "", // 16-bit number
    +    "maxTruePeakLevel": "", // 16-bit number
    +    "maxMomentaryLoudness": "", // 16-bit number
    +    "maxShortTermLoudness": "", // 16-bit number
    +    "reserved": "", // 180 chars
    +    "codingHistory": "" // string, unlimited size
    +};

    The samples

    Range:

    • 0 to 255 for 8-bit
    • -32768 to 32767 for 16-bit
    • @@ -187,7 +208,7 @@

      LICENSE

      Copyright (c) 2017-2018 Rafael da Silva Rocha.


      - Documentation generated by JSDoc 3.5.5 on Sun Apr 22 2018 15:25:20 GMT-0300 (Hora oficial do Brasil) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Apr 24 2018 23:24:21 GMT-0300 (Hora oficial do Brasil) using the docdash theme.
      diff --git a/docs/index.js.html b/docs/index.js.html index 8b3f9ce..4363ce6 100644 --- a/docs/index.js.html +++ b/docs/index.js.html @@ -193,7 +193,7 @@

      index.js

      this.numChannels, this.sampleRate, bitDepth, - byteData.unpackArray(this.samples, uInt8), + this.samples, {"container": this.chunkId} ); } @@ -372,7 +372,7 @@

      index.js


      - Documentation generated by JSDoc 3.5.5 on Sun Apr 22 2018 15:25:20 GMT-0300 (Hora oficial do Brasil) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Apr 24 2018 23:24:21 GMT-0300 (Hora oficial do Brasil) using the docdash theme.
      diff --git a/index.js b/index.js index 54da63e..fc0c7ff 100644 --- a/index.js +++ b/index.js @@ -154,7 +154,7 @@ class WaveFile extends WaveFileReaderWriter { this.numChannels, this.sampleRate, bitDepth, - byteData.unpackArray(this.samples, uInt8), + this.samples, {"container": this.chunkId} ); } diff --git a/package.json b/package.json index eb17276..7984278 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wavefile", - "version": "2.3.6", + "version": "3.0.0", "description": "Read & write wave files with 4, 8, 16, 24, 32 & 64-bit data.", "homepage": "https://github.com/rochars/wavefile", "author": "Rafael da Silva Rocha ", @@ -11,11 +11,14 @@ "RIFX", "WAVE", "BWF", + "bext", "audio", "file", "read", "write", "create", + "edit", + "save", "server", "browser", "8-bit", @@ -63,9 +66,9 @@ "webpack": "^3.8.1" }, "dependencies": { - "alawmulaw": "^2.0.0", + "alawmulaw": "^2.0.1", "bitdepth": "^1.0.4", - "byte-data": "^2.1.0", + "byte-data": "^4.0.2", "imaadpcm": "^1.1.0", "riff-chunks": "^3.0.3" }, diff --git a/src/wavefile-header.js b/src/wavefile-header.js index 190c7b5..ec3b8fe 100644 --- a/src/wavefile-header.js +++ b/src/wavefile-header.js @@ -1,7 +1,7 @@ /* * WaveFileHeader class * A structure representing a WAVE file header. - * Copyright (c) 2017 Rafael da Silva Rocha. MIT License. + * Copyright (c) 2017-2018 Rafael da Silva Rocha. * https://github.com/rochars/wavefile * */ @@ -67,7 +67,9 @@ class WaveFileHeader { * @type {string} */ this.cueChunkId = ""; + /** @type {number} */ this.cueChunkSize = -1; + /** @type {!Array} */ this.cueChunkData = []; /** @@ -82,8 +84,30 @@ class WaveFileHeader { * @type {string} */ this.bextChunkId = ""; + /** @type {number} */ this.bextChunkSize = 0; + /** @type {!Array} */ this.bextChunkData = []; + /** @type {!Object} */ + this.bextChunkFields = { + "description": "", //256 + "originator": "", //32 + "originatorReference": "", //32 + "originationDate": "", //10 + "originationTime": "", //8 + "timeReferenceLow": "", //DWORD + "timeReferenceHigh": "", //DWORD + "version": "", //WORD + "UMID_0 ": "", //byte + "UMID_63 ": "", //byte + "loudnessValue": "", //WORD + "loudnessRange": "", //WORD + "maxTruePeakLevel": "", //WORD + "maxMomentaryLoudness": "", //WORD + "maxShortTermLoudness": "", //WORD + "reserved": "", //180 + "codingHistory": "" // string, unlimited + }; } } diff --git a/src/wavefile-reader-writer.js b/src/wavefile-reader-writer.js index 948839f..7fc1bc3 100644 --- a/src/wavefile-reader-writer.js +++ b/src/wavefile-reader-writer.js @@ -1,8 +1,12 @@ /* * WaveFileReaderWriter - * Copyright (c) 2017-2018 Rafael da Silva Rocha. MIT License. + * Copyright (c) 2017-2018 Rafael da Silva Rocha. * https://github.com/rochars/wavefile * + * References: + * http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html + * https://tech.ebu.ch/docs/tech/tech3285.pdf + * */ const byteData = require("byte-data"); @@ -37,6 +41,8 @@ class WaveFileReaderWriter extends WaveFileHeader { }; /** @type {!Array} */ this.samples = []; + /** @type {number} */ + this.head_ = 0; } /** @@ -57,6 +63,11 @@ class WaveFileReaderWriter extends WaveFileHeader { } } + /** + * Set up to work wih big-endian or little-endian files. + * The types used are changed from LE or BE. If the + * the file is big-endian (RIFX), true is returned. + */ LEorBE() { let bigEndian = this.chunkId == "RIFX"; uInt8.be = bigEndian; @@ -136,7 +147,101 @@ class WaveFileReaderWriter extends WaveFileHeader { this.bextChunkId = "bext"; this.bextChunkSize = chunk.chunkSize; this.bextChunkData = chunk.chunkData; + this.readBextChunkFields_(); + } + } + + /** + * Read the fields of the "bext" chunk. + */ + readBextChunkFields_() { + this.head_ = 0; + this.bextChunkFields = { + "description": this.readVariableSizeString_( + this.bextChunkData, 256), + "originator": this.readVariableSizeString_( + this.bextChunkData, 32), + "originatorReference": this.readVariableSizeString_( + this.bextChunkData, 32), + "originationDate": this.readVariableSizeString_( + this.bextChunkData, 10), + "originationTime": this.readVariableSizeString_( + this.bextChunkData, 8), + // timeReference is a 64-bit value + "timeReference": this.readBytes( + this.bextChunkData, 8), + "version": this.readFromChunk_( + this.bextChunkData, uInt16), + "UMID": this.readVariableSizeString_( + this.bextChunkData, 64), + "loudnessValue": this.readFromChunk_( + this.bextChunkData, uInt16), + "loudnessRange": this.readFromChunk_( + this.bextChunkData, uInt16), + "maxTruePeakLevel": this.readFromChunk_( + this.bextChunkData, uInt16), + "maxMomentaryLoudness": this.readFromChunk_( + this.bextChunkData, uInt16), + "maxShortTermLoudness": this.readFromChunk_( + this.bextChunkData, uInt16), + "reserved": this.readVariableSizeString_( + this.bextChunkData, 180), + "codingHistory": this.readVariableSizeString_( + this.bextChunkData, this.bextChunkData.length - 602), + } + } + + /** + * Return a slice of the byte array while moving the reading head. + * @param {!Array} bytes The bytes. + * @param {number} size the number of bytes to read. + */ + readBytes(bytes, size) { + let v = this.head_; + this.head_ += size; + return bytes.slice(v, this.head_); + } + + /** + * Read bytes as a string from a RIFF chunk. + * @param {!Array} bytes The bytes. + * @param {number} maxSize the max size of the string. + */ + readVariableSizeString_(bytes, maxSize) { + let str = ""; + for (let i=0; i} bytes The bytes. + * @param {Object} bdType The byte-data corresponding type. + */ + readFromChunk_(bytes, bdType) { + let size = bdType.bits / 8; + let value = byteData.unpack( + bytes.slice(this.head_, this.head_ + size), bdType); + this.head_ += size; + return value; + } + + /** + * Write a variable size string as bytes. + * If the string is smaller than the max size it + * is filled with 0s. + * @param {string} str The string to be written as bytes. + * @param {number} maxSize the max size of the string. + */ + writeVariableSizeString_(str, maxSize) { + let bytes = byteData.packArray(str, chr); + for (let i=bytes.length; i 0", function() { - console.log(wav.dwSampleLength); assert.ok(wav2.dwSampleLength > 0); }); it("dataChunkId should be 'data'",