108 lines
3.0 KiB
JavaScript
108 lines
3.0 KiB
JavaScript
var dataURI, audio, myAudioContext, mySource, myBuffer, bufferArray={};
|
|
|
|
if ('AudioContext' in window) {
|
|
myAudioContext = new AudioContext();
|
|
} else if ('webkitAudioContext' in window) {
|
|
myAudioContext = new webkitAudioContext();
|
|
} else {
|
|
alert('Your browser does not support yet Web Audio API');
|
|
}
|
|
|
|
var chr8 = function () {
|
|
return Array.prototype.map.call(arguments, function(a){
|
|
return String.fromCharCode(a&0xff)
|
|
}).join('');
|
|
}
|
|
var chr16 = function () {
|
|
return Array.prototype.map.call(arguments, function(a){
|
|
return String.fromCharCode(a&0xff, (a>>8)&0xff)
|
|
}).join('');
|
|
}
|
|
var chr32 = function () {
|
|
return Array.prototype.map.call(arguments, function(a){
|
|
return String.fromCharCode(a&0xff, (a>>8)&0xff,(a>>16)&0xff, (a>>24)&0xff);
|
|
}).join('');
|
|
}
|
|
var toUTF8 = function (str) {
|
|
var utf8 = [];
|
|
for (var i = 0; i < str.length; i++) {
|
|
var c = str.charCodeAt(i);
|
|
if (c <= 0x7f)
|
|
utf8.push(c);
|
|
else if (c <= 0x7ff) {
|
|
utf8.push(0xc0 | (c >>> 6));
|
|
utf8.push(0x80 | (c & 0x3f));
|
|
} else if (c <= 0xffff) {
|
|
utf8.push(0xe0 | (c >>> 12));
|
|
utf8.push(0x80 | ((c >>> 6) & 0x3f));
|
|
utf8.push(0x80 | (c & 0x3f));
|
|
} else {
|
|
var j = 4;
|
|
while (c >>> (6*j)) j++;
|
|
utf8.push(((0xff00 >>> j) & 0xff) | (c >>> (6*--j)));
|
|
while (j--)
|
|
utf8[idx++] = 0x80 | ((c >>> (6*j)) & 0x3f);
|
|
}
|
|
}
|
|
return utf8;
|
|
}
|
|
|
|
var fsk = {};
|
|
|
|
fsk.generate = function (str) {
|
|
if (str.length === 0) return;
|
|
//console.time('generate');
|
|
var utf8 = toUTF8(str);
|
|
//console.log(utf8);
|
|
|
|
var sampleRate = 29400;
|
|
var baud = 1225;
|
|
var freqHigh = 7350;
|
|
var freqLow = 4900;
|
|
var spb = sampleRate/baud; // 24 samples per bit
|
|
var preCarrierBits = Math.ceil(sampleRate*40/1000/spb); // 49 bits
|
|
var postCarrierBits = Math.ceil(sampleRate*5/1000/spb); // 6.125 bits => 7 bits
|
|
var size = (preCarrierBits + postCarrierBits + 10 * utf8.length) * spb;
|
|
|
|
var data = "RIFF" + chr32(size + 36) + "WAVE" +
|
|
"fmt " + chr32(16, 0x00010001, sampleRate, sampleRate, 0x00080001) +
|
|
"data" + chr32(size);
|
|
|
|
var pushData = function (freq, samples) {
|
|
for (var i = 0; i < samples; i++) {
|
|
var v = 128 + 127 * Math.sin((2 * Math.PI) * (i / sampleRate) * freq);
|
|
data += chr8(v);
|
|
}
|
|
}
|
|
pushData(freqHigh, preCarrierBits * spb);
|
|
for (var x in utf8) {
|
|
var c = (utf8[x] << 1) | 0x200;
|
|
for (var i = 0; i < 10; i++, c >>>= 1)
|
|
pushData((c&1) ? freqHigh : freqLow, spb);
|
|
}
|
|
pushData(freqHigh, postCarrierBits * spb);
|
|
|
|
//if (size+44 != data.length) alert("wrong size: " + size+44 + " != " + data.length);
|
|
|
|
dataURI = escape(btoa(data));
|
|
|
|
var arrayBuff = Base64Binary.decodeArrayBuffer(dataURI);
|
|
myAudioContext.decodeAudioData(arrayBuff, function (audioData) {
|
|
bufferArray[str] = audioData;
|
|
});
|
|
}
|
|
|
|
fsk.play = function (str) {
|
|
mySource = myAudioContext.createBufferSource();
|
|
if (typeof str !== 'undefined') {
|
|
mySource.buffer = bufferArray[str];
|
|
} else {
|
|
console.error('No AudioBuffer found for string "' + str + '"');
|
|
}
|
|
mySource.connect(myAudioContext.destination);
|
|
if ('AudioContext' in window) {
|
|
mySource.start(0);
|
|
} else if ('webkitAudioContext' in window) {
|
|
mySource.noteOn(0);
|
|
}
|
|
}; |