intval2/webapp/js/fsk.js

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);
}
};