App concept for slatesync

This commit is contained in:
mmcwilliams 2024-10-26 09:44:37 -04:00
commit cd22ac0f38
5 changed files with 189 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.DS_Store

81
www/fsk.js Normal file
View File

@ -0,0 +1,81 @@
function $(name) {
return document.getElementById(name);
}
function chr8() {
return Array.prototype.map.call(arguments, function(a){
return String.fromCharCode(a&0xff)
}).join('');
}
function chr16() {
return Array.prototype.map.call(arguments, function(a){
return String.fromCharCode(a&0xff, (a>>8)&0xff)
}).join('');
}
function chr32() {
return Array.prototype.map.call(arguments, function(a){
return String.fromCharCode(a&0xff, (a>>8)&0xff,(a>>16)&0xff, (a>>24)&0xff);
}).join('');
}
function toUTF8(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 dataURI, audio;
function generateFSK (str) {
if (str.length == 0) return;
var utf8 = toUTF8(str);
//console.log(utf8);
var sampleRate = 29400;
var baud = 1225;
var freqHigh = 4000; //7350;
var freqLow = 2450; //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);
function pushData(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 = "data:audio/wav;base64," + escape(btoa(data));
return new Audio(dataURI);
}

84
www/index.html Normal file
View File

@ -0,0 +1,84 @@
<!doctype html>
<html>
<head>
<title>digislate</title>
<style>
.hide {
display: none;
}
h1{
width: 256px;
height: 256px;
line-height: 256px;
text-align: center;
}
button{
background: black;
color: white;
appearance: none;
border: none;
outline: none;
width: 100px;
height: 33px;
font-weight: bold;
font-size: 20px;
margin-left: 78px;
margin-top: 111px;
}
</style>
</head>
<body>
<button id="slate" onclick="slate();">SLATE</button>
<div id="one" class="hide"><h1>1</h1></div>
<div id="two" class="hide"><h1>2</h1></div>
<div id="three" class="hide"><h1>3</h1></div>
<div id="display" class="hide">
<div id="qrcode"></div>
</div>
<script type="text/javascript" src="qrcode.min.js"></script>
<script type="text/javascript" src="fsk.js"></script>
<script type="text/javascript" src="tone.js"></script>
<script type="text/javascript">
function slate () {
const startingSecond = `${Math.round(Date.now() / 1000)}`;
const fskAudio = generateFSK(startingSecond);
let started;
fskAudio.onended = () => {
document.getElementById('display').classList.add('hide');
console.log(Date.now() - started);
};
const playTone = tone(300, 100, function () {
fskAudio.play();
});
var qrcode = new QRCode("qrcode", {
text: startingSecond,
width: 256,
height: 256,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.H
});
document.getElementById('slate').classList.add('hide');
document.getElementById('one').classList.remove('hide');
setTimeout(function () {
document.getElementById('one').classList.add('hide');
document.getElementById('two').classList.remove('hide');
}, 1000);
setTimeout(function () {
document.getElementById('two').classList.add('hide');
document.getElementById('three').classList.remove('hide');
}, 2000);
setTimeout(function () {
document.getElementById('three').classList.add('hide');
document.getElementById('display').classList.remove('hide');
started = Date.now();
playTone();
}, 3000);
/*setTimeout(function () {
document.getElementById('display').classList.add('hide');
}, 4000);*/
}
</script>
</body>
</html>

1
www/qrcode.min.js vendored Normal file

File diff suppressed because one or more lines are too long

22
www/tone.js Normal file
View File

@ -0,0 +1,22 @@
function tone (freq, len, cb) {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioCtx.createOscillator();
oscillator.type = 'sine'; // Use a sine wave for a pure tone
oscillator.frequency.value = freq; // Set the frequency to 300Hz
const gainNode = audioCtx.createGain();
gainNode.gain.value = 0.2; // Adjust the volume (0 to 1)
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
return function play () {
oscillator.start();
setTimeout(() => {
oscillator.stop();
cb();
}, len);
}
}