UNPKG

@excaliburjs/plugin-jsfxr

Version:

excalibur-jsfxr provides sound effect generation utilizing a wrapper around jsfxr

132 lines (119 loc) 4.15 kB
/* * RIFFWAVE.js v0.03 - Audio encoder for HTML5 <audio> elements. * Copyleft 2011 by Pedro Ladaria <pedro.ladaria at Gmail dot com> * * Public Domain * * Changelog: * * 0.01 - First release * 0.02 - New faster base64 encoding * 0.03 - Support for 16bit samples * * Notes: * * 8 bit data is unsigned: 0..255 * 16 bit data is signed: -32,768..32,767 * */ let FastBase64 = { chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", encLookup: [], Init: function () { for (var i = 0; i < 4096; i++) { this.encLookup[i] = this.chars[i >> 6] + this.chars[i & 0x3f]; } }, Encode: function (src) { var len = src.length; var dst = ""; var i = 0; while (len > 2) { let n = (src[i] << 16) | (src[i + 1] << 8) | src[i + 2]; dst += this.encLookup[n >> 12] + this.encLookup[n & 0xfff]; len -= 3; i += 3; } if (len > 0) { var n1 = (src[i] & 0xfc) >> 2; var n2 = (src[i] & 0x03) << 4; if (len > 1) n2 |= (src[++i] & 0xf0) >> 4; dst += this.chars[n1]; dst += this.chars[n2]; if (len == 2) { var n3 = (src[i++] & 0x0f) << 2; n3 |= (src[i] & 0xc0) >> 6; dst += this.chars[n3]; } if (len == 1) dst += "="; dst += "="; } return dst; }, // end Encode }; FastBase64.Init(); var RIFFWAVE; export default RIFFWAVE = function (data) { this.data; this.wav; this.dataURI; this.data = []; // Array containing audio samples this.wav = []; // Array containing the generated wave file this.dataURI = ""; // http://en.wikipedia.org/wiki/Data_URI_scheme this.header = { // OFFS SIZE NOTES chunkId: [0x52, 0x49, 0x46, 0x46], // 0 4 "RIFF" = 0x52494646 chunkSize: 0, // 4 4 36+SubChunk2Size = 4+(8+SubChunk1Size)+(8+SubChunk2Size) format: [0x57, 0x41, 0x56, 0x45], // 8 4 "WAVE" = 0x57415645 subChunk1Id: [0x66, 0x6d, 0x74, 0x20], // 12 4 "fmt " = 0x666d7420 subChunk1Size: 16, // 16 4 16 for PCM audioFormat: 1, // 20 2 PCM = 1 numChannels: 1, // 22 2 Mono = 1, Stereo = 2... sampleRate: 8000, // 24 4 8000, 44100... byteRate: 0, // 28 4 SampleRate*NumChannels*BitsPerSample/8 blockAlign: 0, // 32 2 NumChannels*BitsPerSample/8 bitsPerSample: 8, // 34 2 8 bits = 8, 16 bits = 16 subChunk2Id: [0x64, 0x61, 0x74, 0x61], // 36 4 "data" = 0x64617461 subChunk2Size: 0, // 40 4 data size = NumSamples*NumChannels*BitsPerSample/8 }; function u32ToArray(i) { return [i & 0xff, (i >> 8) & 0xff, (i >> 16) & 0xff, (i >> 24) & 0xff]; } function u16ToArray(i) { return [i & 0xff, (i >> 8) & 0xff]; } function split16bitArray(data) { var r = []; var j = 0; var len = data.length; for (var i = 0; i < len; i++) { r[j++] = data[i] & 0xff; r[j++] = (data[i] >> 8) & 0xff; } return r; } this.Make = function (data) { if (data instanceof Array) this.data = data; this.header.byteRate = (this.header.sampleRate * this.header.numChannels * this.header.bitsPerSample) >> 3; this.header.blockAlign = (this.header.numChannels * this.header.bitsPerSample) >> 3; this.header.subChunk2Size = this.data.length; this.header.chunkSize = 36 + this.header.subChunk2Size; this.wav = this.header.chunkId.concat( u32ToArray(this.header.chunkSize), this.header.format, this.header.subChunk1Id, u32ToArray(this.header.subChunk1Size), u16ToArray(this.header.audioFormat), u16ToArray(this.header.numChannels), u32ToArray(this.header.sampleRate), u32ToArray(this.header.byteRate), u16ToArray(this.header.blockAlign), u16ToArray(this.header.bitsPerSample), this.header.subChunk2Id, u32ToArray(this.header.subChunk2Size), this.data ); this.dataURI = "data:audio/wav;base64," + FastBase64.Encode(this.wav); }; if (data instanceof Array) this.Make(data); }; // end RIFFWAVE