@excaliburjs/plugin-jsfxr
Version:
excalibur-jsfxr provides sound effect generation utilizing a wrapper around jsfxr
132 lines (119 loc) • 4.15 kB
JavaScript
/*
* 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