control frequency range and resolution multiplier via UI
This commit is contained in:
13
index.html
13
index.html
@@ -9,14 +9,15 @@
|
|||||||
<h1>Data Over Audio</h1>
|
<h1>Data Over Audio</h1>
|
||||||
<div class="panels">
|
<div class="panels">
|
||||||
<div>
|
<div>
|
||||||
Bit Duration: <input id="bit-duration-text" type="number" min="0" max="1000" value="190">ms<br>
|
Segment Duration: <input id="bit-duration-text" type="number" min="0" max="1000" value="190">ms<br>
|
||||||
Amplitude Threshold: <input id="amplitude-threshold-text" type="number" min="0" max="255" value="200"><br>
|
Amplitude Threshold: <input id="amplitude-threshold-text" type="number" min="0" max="100" value="75"><br>
|
||||||
Frequency High: <input id="frequency-high-text" type="number" min="20" max="20000" value="900"><br>
|
Minimum Frequency: <input id="minimum-frequency" type="number" min="20" max="20000" value="900"><br>
|
||||||
Frequency Low: <input id="frequency-low-text" type="number" min="20" max="20000" value="1200"><br>
|
Maximum Frequency: <input id="maximum-frequency" type="number" min="20" max="20000" value="1200"><br>
|
||||||
Last Bit Percent: <input id="last-bit-percent" type="number" min="0" max="100" value="90">%<br>
|
Last Segment Percent: <input id="last-bit-percent" type="number" min="0" max="100" value="90">%<br>
|
||||||
FFT Size: 2^<input id="fft-size-power-text" type="number" min="5" max="15" value="90"><br>
|
FFT Size: 2^<input id="fft-size-power-text" type="number" min="5" max="15" value="90"><br>
|
||||||
Frequency Resolution: <span id="frequency-resolution">N/A</span><br>
|
Frequency Resolution: <span id="frequency-resolution">N/A</span><br>
|
||||||
Frequency Count: <span id="frequency-count">N/A</span><br>
|
Frequency Count: <span id="frequency-count">N/A</span><br>
|
||||||
|
Frequency Resolution Multiplier: <input id="frequency-resolution-multiplier" type="number" min="1" max="10" value="2"><br >
|
||||||
Smoothing Time Constant: <input id="smoothing-time-constant-text" type="number" min="0.00" max="1.00" step="0.01" value="0.00"><br>
|
Smoothing Time Constant: <input id="smoothing-time-constant-text" type="number" min="0.00" max="1.00" step="0.01" value="0.00"><br>
|
||||||
<input type="text" id="text-to-send">
|
<input type="text" id="text-to-send">
|
||||||
<button id="send-button">Send</button>
|
<button id="send-button">Send</button>
|
||||||
@@ -31,6 +32,8 @@
|
|||||||
<textarea id="received-data" rows="10" cols="40"></textarea><br />
|
<textarea id="received-data" rows="10" cols="40"></textarea><br />
|
||||||
Samples Per Bit: <span id="samples-per-bit">0</span><br>
|
Samples Per Bit: <span id="samples-per-bit">0</span><br>
|
||||||
Sample Rate: <span id="audio-context-sample-rate">N/A</span> per second.<br />
|
Sample Rate: <span id="audio-context-sample-rate">N/A</span> per second.<br />
|
||||||
|
Segments per second: <span id="durations-per-second">N/A</span><br />
|
||||||
|
Bits per segment: <span id="bits-per-duration">N/A</span><br />
|
||||||
Speed: <span id="data-transfer-speed-bits-per-second">N/A</span> Baud<br>
|
Speed: <span id="data-transfer-speed-bits-per-second">N/A</span> Baud<br>
|
||||||
<span id="data-transfer-speed-bytes-per-second">N/A</span> Bytes/second<br />
|
<span id="data-transfer-speed-bytes-per-second">N/A</span> Bytes/second<br />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
208
index.js
208
index.js
@@ -17,10 +17,12 @@ var sampleIntervalId;
|
|||||||
|
|
||||||
// 20 to 20,000 - human
|
// 20 to 20,000 - human
|
||||||
var FREQUENCY_TONE = 18000;
|
var FREQUENCY_TONE = 18000;
|
||||||
var FREQUENCY_HIGH = 400;
|
var MINIMUM_FREQUENCY = 5000;
|
||||||
var FREQUENCY_LOW = 500;
|
var MAXIMUM_FREQUENCY = 10000;
|
||||||
var FREQUENCY_DURATION = 100;
|
var FREQUENCY_DURATION = 100;
|
||||||
var FREQUENCY_THRESHOLD = 200;
|
var FREQUENCY_THRESHOLD_PERCENT = .75;
|
||||||
|
var FREQUENCY_THRESHOLD = 150;
|
||||||
|
var FREQUENCY_RESOLUTION_MULTIPLIER = 2;
|
||||||
var SAMPLE_DELAY_MS = 1;
|
var SAMPLE_DELAY_MS = 1;
|
||||||
var FFT_POWER = 10;
|
var FFT_POWER = 10;
|
||||||
var LAST_BIT_PERCENT = 0.8;
|
var LAST_BIT_PERCENT = 0.8;
|
||||||
@@ -46,6 +48,11 @@ function handleWindowLoad() {
|
|||||||
PAUSE_AFTER_END = event.target.checked;
|
PAUSE_AFTER_END = event.target.checked;
|
||||||
if(!PAUSE_AFTER_END) resumeGraph();
|
if(!PAUSE_AFTER_END) resumeGraph();
|
||||||
})
|
})
|
||||||
|
document.getElementById('frequency-resolution-multiplier').value = FREQUENCY_RESOLUTION_MULTIPLIER;
|
||||||
|
document.getElementById('frequency-resolution-multiplier').addEventListener('input', event => {
|
||||||
|
FREQUENCY_RESOLUTION_MULTIPLIER = parseInt(event.target.value);
|
||||||
|
showSpeed();
|
||||||
|
})
|
||||||
document.getElementById('bit-duration-text').addEventListener('input', (event) => {
|
document.getElementById('bit-duration-text').addEventListener('input', (event) => {
|
||||||
FREQUENCY_DURATION = parseInt(event.target.value);
|
FREQUENCY_DURATION = parseInt(event.target.value);
|
||||||
bitSampleCount = 0;
|
bitSampleCount = 0;
|
||||||
@@ -57,21 +64,25 @@ function handleWindowLoad() {
|
|||||||
MAX_BITS_DISPLAYED_ON_GRAPH = parseInt(event.target.value);
|
MAX_BITS_DISPLAYED_ON_GRAPH = parseInt(event.target.value);
|
||||||
})
|
})
|
||||||
document.getElementById('bit-duration-text').value = FREQUENCY_DURATION;
|
document.getElementById('bit-duration-text').value = FREQUENCY_DURATION;
|
||||||
document.getElementById('amplitude-threshold-text').value = FREQUENCY_THRESHOLD;
|
document.getElementById('amplitude-threshold-text').value = Math.floor(FREQUENCY_THRESHOLD_PERCENT * 100);
|
||||||
document.getElementById('frequency-high-text').value = FREQUENCY_HIGH;
|
FREQUENCY_THRESHOLD = Math.floor(FREQUENCY_THRESHOLD_PERCENT * 255);
|
||||||
document.getElementById('frequency-low-text').value = FREQUENCY_LOW;
|
document.getElementById('maximum-frequency').value = MAXIMUM_FREQUENCY;
|
||||||
|
document.getElementById('minimum-frequency').value = MINIMUM_FREQUENCY;
|
||||||
document.getElementById('last-bit-percent').value = Math.floor(LAST_BIT_PERCENT * 100);
|
document.getElementById('last-bit-percent').value = Math.floor(LAST_BIT_PERCENT * 100);
|
||||||
document.getElementById('fft-size-power-text').value = FFT_POWER;
|
document.getElementById('fft-size-power-text').value = FFT_POWER;
|
||||||
document.getElementById('smoothing-time-constant-text').value = SMOOTHING_TIME_CONSTANT.toFixed(2);
|
document.getElementById('smoothing-time-constant-text').value = SMOOTHING_TIME_CONSTANT.toFixed(2);
|
||||||
|
|
||||||
document.getElementById('amplitude-threshold-text').addEventListener('input', (event) => {
|
document.getElementById('amplitude-threshold-text').addEventListener('input', (event) => {
|
||||||
FREQUENCY_THRESHOLD = parseInt(event.target.value);
|
FREQUENCY_THRESHOLD_PERCENT = parseInt(event.target.value) / 100;
|
||||||
|
FREQUENCY_THRESHOLD = Math.floor(FREQUENCY_THRESHOLD_PERCENT * 255);
|
||||||
});
|
});
|
||||||
document.getElementById('frequency-high-text').addEventListener('input', (event) => {
|
document.getElementById('maximum-frequency').addEventListener('input', (event) => {
|
||||||
FREQUENCY_HIGH = parseInt(event.target.value);
|
MAXIMUM_FREQUENCY = parseInt(event.target.value);
|
||||||
|
showSpeed();
|
||||||
});
|
});
|
||||||
document.getElementById('frequency-low-text').addEventListener('input', (event) => {
|
document.getElementById('minimum-frequency').addEventListener('input', (event) => {
|
||||||
FREQUENCY_LOW = parseInt(event.target.value);
|
MINIMUM_FREQUENCY = parseInt(event.target.value);
|
||||||
|
showSpeed();
|
||||||
});
|
});
|
||||||
document.getElementById('last-bit-percent').addEventListener('input', (event) => {
|
document.getElementById('last-bit-percent').addEventListener('input', (event) => {
|
||||||
LAST_BIT_PERCENT = parseInt(event.target.value) / 100;
|
LAST_BIT_PERCENT = parseInt(event.target.value) / 100;
|
||||||
@@ -102,11 +113,17 @@ function updateFrequencyResolution() {
|
|||||||
const frequencyCount = (sampleRate/2) / frequencyResolution;
|
const frequencyCount = (sampleRate/2) / frequencyResolution;
|
||||||
document.getElementById('frequency-resolution').innerText = frequencyResolution.toFixed(2);
|
document.getElementById('frequency-resolution').innerText = frequencyResolution.toFixed(2);
|
||||||
document.getElementById('frequency-count').innerText = frequencyCount.toFixed(2);
|
document.getElementById('frequency-count').innerText = frequencyCount.toFixed(2);
|
||||||
|
|
||||||
|
showSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showSpeed() {
|
function showSpeed() {
|
||||||
const baud = 1000 / FREQUENCY_DURATION;
|
const segmentsPerSecond = 1000 / FREQUENCY_DURATION;
|
||||||
|
const bitsPerSegment = getBitFrequencies().length;
|
||||||
|
const baud = bitsPerSegment * segmentsPerSecond;
|
||||||
const bytes = baud / 8;
|
const bytes = baud / 8;
|
||||||
|
document.getElementById('durations-per-second').innerText = segmentsPerSecond.toFixed(2);
|
||||||
|
document.getElementById('bits-per-duration').innerText = bitsPerSegment;
|
||||||
document.getElementById('data-transfer-speed-bits-per-second').innerText = baud.toFixed(2);
|
document.getElementById('data-transfer-speed-bits-per-second').innerText = baud.toFixed(2);
|
||||||
document.getElementById('data-transfer-speed-bytes-per-second').innerText = bytes.toFixed(2);
|
document.getElementById('data-transfer-speed-bytes-per-second').innerText = bytes.toFixed(2);
|
||||||
}
|
}
|
||||||
@@ -120,26 +137,51 @@ function handleTextToSendKeypress(event) {
|
|||||||
sendBits(bits);
|
sendBits(bits);
|
||||||
}
|
}
|
||||||
function getFrequency(bit) {
|
function getFrequency(bit) {
|
||||||
return bit ? FREQUENCY_HIGH : FREQUENCY_LOW;
|
return bit ? MAXIMUM_FREQUENCY : MINIMUM_FREQUENCY;
|
||||||
|
}
|
||||||
|
function getBitFrequencies() {
|
||||||
|
var audioContext = getAudioContext();
|
||||||
|
const sampleRate = audioContext.sampleRate;
|
||||||
|
const fftSize = 2 ** FFT_POWER;
|
||||||
|
const frequencyResolution = sampleRate / fftSize;
|
||||||
|
const frequencies = [];
|
||||||
|
const pairStep = frequencyResolution * 2 * FREQUENCY_RESOLUTION_MULTIPLIER;
|
||||||
|
for(let hz = MINIMUM_FREQUENCY; hz < MAXIMUM_FREQUENCY; hz+= pairStep * 2) {
|
||||||
|
const low = hz;
|
||||||
|
const high = hz + frequencyResolution * FREQUENCY_RESOLUTION_MULTIPLIER;
|
||||||
|
if(low < MINIMUM_FREQUENCY) continue;
|
||||||
|
if(high > MAXIMUM_FREQUENCY) continue;
|
||||||
|
frequencies.push([low, high]);
|
||||||
|
}
|
||||||
|
return frequencies;
|
||||||
}
|
}
|
||||||
function sendBits(bits) {
|
function sendBits(bits) {
|
||||||
sentDataTextArea.value += bits.join('') + '\n';
|
sentDataTextArea.value += bits.join('') + '\n';
|
||||||
sentDataTextArea.scrollTop = sentDataTextArea.scrollHeight;
|
sentDataTextArea.scrollTop = sentDataTextArea.scrollHeight;
|
||||||
var audioContext = getAudioContext();
|
var audioContext = getAudioContext();
|
||||||
var oscillator = audioContext.createOscillator();
|
|
||||||
var duration = bits.length * FREQUENCY_DURATION;
|
var duration = bits.length * FREQUENCY_DURATION;
|
||||||
for(var i = 0; i < bits.length; i++) {
|
const frequencies = getBitFrequencies();
|
||||||
if(i > 0 && bits[i] === bits[i-1]) continue;
|
const oscillators = [];
|
||||||
var offset = ((i * FREQUENCY_DURATION)/1000);
|
for(let j = 0; j < frequencies.length; j++) {
|
||||||
oscillator.frequency.setValueAtTime(
|
var oscillator = audioContext.createOscillator();
|
||||||
getFrequency(bits[i]),
|
const [low, high] = frequencies[j];
|
||||||
audioContext.currentTime + offset
|
for(let i = 0; i < bits.length; i++) {
|
||||||
);
|
if(i > 0 && bits[i] === bits[i-1]) continue;
|
||||||
|
var offset = ((i * FREQUENCY_DURATION)/1000);
|
||||||
|
oscillator.frequency.setValueAtTime(
|
||||||
|
bits[i] ? high : low,
|
||||||
|
audioContext.currentTime + offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
oscillator.connect(audioContext.destination);
|
||||||
|
oscillators.push(oscillator);
|
||||||
}
|
}
|
||||||
|
|
||||||
resumeGraph();
|
resumeGraph();
|
||||||
oscillator.connect(audioContext.destination);
|
oscillators.forEach(o => o.start());
|
||||||
oscillator.start();
|
window.setTimeout(function() {
|
||||||
window.setTimeout(function() { oscillator.stop(); }, duration);
|
oscillators.forEach(o => o.stop());
|
||||||
|
}, duration);
|
||||||
}
|
}
|
||||||
function stopGraph() {
|
function stopGraph() {
|
||||||
PAUSE = true;
|
PAUSE = true;
|
||||||
@@ -167,22 +209,30 @@ function collectSample() {
|
|||||||
const frequencies = new Uint8Array(analyser.frequencyBinCount);
|
const frequencies = new Uint8Array(analyser.frequencyBinCount);
|
||||||
const length = audioContext.sampleRate / analyser.fftSize;
|
const length = audioContext.sampleRate / analyser.fftSize;
|
||||||
const {
|
const {
|
||||||
isHigh: wasHigh,
|
hasSignal: hadPriorSignal,
|
||||||
isLow: wasLow,
|
|
||||||
streamStarted: initialStreamStart = time,
|
streamStarted: initialStreamStart = time,
|
||||||
streamEnded: priorStreamEnded,
|
streamEnded: priorStreamEnded,
|
||||||
bitIndex: priorBitIndex = -1
|
bitIndex: priorBitIndex = -1
|
||||||
} = frequencyOverTime[0] ?? {}
|
} = frequencyOverTime[0] ?? {}
|
||||||
analyser.getByteFrequencyData(frequencies);
|
analyser.getByteFrequencyData(frequencies);
|
||||||
const data = { time, frequencies, length };
|
const data = { time, frequencies, length };
|
||||||
const isHigh = canHear(FREQUENCY_HIGH, data);
|
let hasSignal = false;
|
||||||
const isLow = canHear(FREQUENCY_LOW, data);
|
data.pairs = getBitFrequencies().map(([low, high], i) => {
|
||||||
data.isHigh = isHigh;
|
const lowAmp = frequencies[Math.round(low / length)];
|
||||||
data.isLow = isLow;
|
const highAmp = frequencies[Math.round(high / length)];
|
||||||
if(isHigh || isLow) {
|
const isLow = lowAmp > FREQUENCY_THRESHOLD;
|
||||||
// in a bit
|
const isHigh = highAmp > FREQUENCY_THRESHOLD;
|
||||||
data.isBit = true;
|
if(isLow || isHigh ) hasSignal = true;
|
||||||
if(wasHigh || wasLow) {
|
return {
|
||||||
|
channel: i,
|
||||||
|
lowHz: low,
|
||||||
|
highHz: high,
|
||||||
|
isHigh: (isHigh && !isLow) || highAmp > lowAmp
|
||||||
|
};
|
||||||
|
});
|
||||||
|
data.hasSignal = hasSignal;
|
||||||
|
if(hasSignal) {
|
||||||
|
if(hadPriorSignal) {
|
||||||
// continued bit stream
|
// continued bit stream
|
||||||
data.streamStarted = initialStreamStart;
|
data.streamStarted = initialStreamStart;
|
||||||
} else {
|
} else {
|
||||||
@@ -195,9 +245,8 @@ function collectSample() {
|
|||||||
processBitsReceived();
|
processBitsReceived();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data.isBit = false;
|
|
||||||
data.bitIndex = -1;
|
data.bitIndex = -1;
|
||||||
if(wasHigh || wasLow) {
|
if(hadPriorSignal) {
|
||||||
// just stopped
|
// just stopped
|
||||||
data.streamStarted = -1;
|
data.streamStarted = -1;
|
||||||
data.streamEnded = time;
|
data.streamEnded = time;
|
||||||
@@ -226,7 +275,10 @@ function collectSample() {
|
|||||||
function processBitsReceived() {
|
function processBitsReceived() {
|
||||||
const {
|
const {
|
||||||
bitIndex,
|
bitIndex,
|
||||||
streamStarted
|
streamStarted,
|
||||||
|
pairs: {
|
||||||
|
length: channelCount
|
||||||
|
}
|
||||||
} = frequencyOverTime[0];
|
} = frequencyOverTime[0];
|
||||||
const bits = frequencyOverTime.filter(f =>
|
const bits = frequencyOverTime.filter(f =>
|
||||||
f.bitIndex === bitIndex &&
|
f.bitIndex === bitIndex &&
|
||||||
@@ -238,17 +290,17 @@ function processBitsReceived() {
|
|||||||
if(bitDuration < FREQUENCY_DURATION * LAST_BIT_PERCENT) {
|
if(bitDuration < FREQUENCY_DURATION * LAST_BIT_PERCENT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// make sure majority qualifies as high bit
|
|
||||||
const winnerIsHigh = bits.map(({isHigh, isLow, frequencies, length}) => {
|
const channels = new Array(channelCount).fill(0);
|
||||||
if(isHigh && isLow) {
|
const maxHighBits = bits.reduce((max, { pairs: { length } }) => max > length ? max : length, 0);
|
||||||
return amplitude(FREQUENCY_HIGH, {frequencies, length}) >
|
|
||||||
amplitude(FREQUENCY_LOW, {frequencies, length});
|
bits.forEach(({pairs}) => {
|
||||||
}
|
pairs.forEach(({ isHigh }, i) => {
|
||||||
return isHigh;
|
if(isHigh) channels[i]++;
|
||||||
|
})
|
||||||
});
|
});
|
||||||
const highCount = winnerIsHigh.filter(h => h).length;
|
const bitString = channels.map(count => count >= (maxHighBits / 2) ? '1' : '0').join('');
|
||||||
const lowCount = winnerIsHigh.filter(h => !h).length;
|
received(bitString + '\n');
|
||||||
if(highCount > lowCount) received('1'); else received('0');
|
|
||||||
}
|
}
|
||||||
function resetGraphData() {
|
function resetGraphData() {
|
||||||
frequencyOverTime.length = 0;
|
frequencyOverTime.length = 0;
|
||||||
@@ -416,6 +468,14 @@ function drawBitStart(ctx, color) {
|
|||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function hzAmplitude(hz, length, frequencies) {
|
||||||
|
var index = Math.round(hz / length);
|
||||||
|
return frequencies[index];
|
||||||
|
}
|
||||||
|
function getPercentY(percent) {
|
||||||
|
const { height } = receivedGraph;
|
||||||
|
return (1 - percent) * height;
|
||||||
|
}
|
||||||
function drawFrequencyLineGraph(ctx, hz, color) {
|
function drawFrequencyLineGraph(ctx, hz, color) {
|
||||||
const { width, height } = receivedGraph;
|
const { width, height } = receivedGraph;
|
||||||
const newest = frequencyOverTime[0].time;
|
const newest = frequencyOverTime[0].time;
|
||||||
@@ -424,41 +484,28 @@ function drawFrequencyLineGraph(ctx, hz, color) {
|
|||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
for(let i = 0; i < frequencyOverTime.length; i++) {
|
for(let i = 0; i < frequencyOverTime.length; i++) {
|
||||||
const {frequencies, time, length} = frequencyOverTime[i];
|
const {frequencies, time, length} = frequencyOverTime[i];
|
||||||
if(newest - time > duration) continue;
|
const x = getTimeX(time, newest);
|
||||||
const x = ((newest - time) / duration) * width;
|
if(x === -1) continue;
|
||||||
|
const amplitude = hzAmplitude(hz, length, frequencies);
|
||||||
var index = Math.round(hz / length);
|
const y = getPercentY(amplitude / MAX_DATA);
|
||||||
const amplitude = frequencies[index];
|
if(i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
|
||||||
const y = (1-(amplitude / MAX_DATA)) * height;
|
|
||||||
if(i === 0) {
|
|
||||||
ctx.moveTo(x, y);
|
|
||||||
} else {
|
|
||||||
ctx.lineTo(x, y)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
function drawFrequencyDots(ctx, hz, color) {
|
function drawFrequencyDots(ctx, hz, color) {
|
||||||
const { width, height } = receivedGraph;
|
|
||||||
const newest = frequencyOverTime[0].time;
|
const newest = frequencyOverTime[0].time;
|
||||||
const duration = FREQUENCY_DURATION * MAX_BITS_DISPLAYED_ON_GRAPH;
|
|
||||||
ctx.strokeStyle = color;
|
|
||||||
|
|
||||||
const radius = 2;
|
const radius = 2;
|
||||||
const border = 0.5;
|
const border = 0.5;
|
||||||
ctx.fillStyle = color;
|
ctx.fillStyle = color;
|
||||||
ctx.strokeStyle = 'white';
|
ctx.strokeStyle = 'white';
|
||||||
ctx.lineWidth = border;
|
ctx.lineWidth = border;
|
||||||
const fullCircle = 2 * Math.PI;
|
const fullCircle = 2 * Math.PI;
|
||||||
for(let i = 0; i < frequencyOverTime.length; i++) {
|
for(let i = 0; i < frequencyOverTime.length; i++) {
|
||||||
const {frequencies, time} = frequencyOverTime[i];
|
const {frequencies, time, length} = frequencyOverTime[i];
|
||||||
if(newest - time > duration) continue;
|
const x = getTimeX(time, newest);
|
||||||
const x = ((newest - time) / duration) * width;
|
if(x === -1) continue;
|
||||||
|
const amplitude = hzAmplitude(hz, length, frequencies);
|
||||||
var length = (audioContext.sampleRate / analyser.fftSize);
|
const y = getPercentY(amplitude / MAX_DATA);
|
||||||
var index = Math.round(hz / length);
|
|
||||||
const amplitude = frequencies[index];
|
|
||||||
const y = (1-(amplitude / MAX_DATA)) * height;
|
|
||||||
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(x, y, radius, 0, fullCircle);
|
ctx.arc(x, y, radius, 0, fullCircle);
|
||||||
@@ -469,6 +516,12 @@ for(let i = 0; i < frequencyOverTime.length; i++) {
|
|||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function getTimeX(time, newest) {
|
||||||
|
const { width } = receivedGraph;
|
||||||
|
const duration = FREQUENCY_DURATION * MAX_BITS_DISPLAYED_ON_GRAPH;
|
||||||
|
if(newest - time > duration) return -1;
|
||||||
|
return ((newest - time) / duration) * width;
|
||||||
|
}
|
||||||
function drawFrequencyData() {
|
function drawFrequencyData() {
|
||||||
if(PAUSE) return;
|
if(PAUSE) return;
|
||||||
if(frequencyOverTime.length === 0) {
|
if(frequencyOverTime.length === 0) {
|
||||||
@@ -488,10 +541,15 @@ function drawFrequencyData() {
|
|||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
drawBitDurationLines(ctx, 'yellow');
|
drawBitDurationLines(ctx, 'yellow');
|
||||||
drawBitStart(ctx, 'green');
|
drawBitStart(ctx, 'green');
|
||||||
drawFrequencyLineGraph(ctx, FREQUENCY_HIGH, 'red');
|
const frequencies = getBitFrequencies();
|
||||||
drawFrequencyLineGraph(ctx, FREQUENCY_LOW, 'blue');
|
// frequencies.forEach(([low, high]) => {
|
||||||
drawFrequencyDots(ctx, FREQUENCY_HIGH, 'red');
|
// drawFrequencyDots(ctx, high, 'red');
|
||||||
drawFrequencyDots(ctx, FREQUENCY_LOW, 'blue');
|
// drawFrequencyDots(ctx, low, 'blue');
|
||||||
|
// });
|
||||||
|
frequencies.forEach(([low, high]) => {
|
||||||
|
drawFrequencyLineGraph(ctx, high, 'red');
|
||||||
|
drawFrequencyLineGraph(ctx, low, 'blue');
|
||||||
|
});
|
||||||
|
|
||||||
requestAnimationFrame(drawFrequencyData);
|
requestAnimationFrame(drawFrequencyData);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user