removing old frequency graph code

This commit is contained in:
Lewis Moten
2024-05-12 04:32:22 -04:00
parent 015dd3eae3
commit 99a972e165
4 changed files with 15 additions and 294 deletions

View File

@@ -18,7 +18,7 @@ class FrequencyGraphPanel extends BasePanel {
}; };
setDurationMilliseconds = (millseconds) => { setDurationMilliseconds = (millseconds) => {
this.duration = millseconds; this.duration = millseconds;
this.draw(false); if(!this.isRunning()) this.draw();
} }
setSignalStart = milliseconds => { setSignalStart = milliseconds => {
this.signalStart = milliseconds; this.signalStart = milliseconds;
@@ -30,12 +30,14 @@ class FrequencyGraphPanel extends BasePanel {
setAmplitudeThreshold = value => { setAmplitudeThreshold = value => {
this.amplitudeThreshold = value; this.amplitudeThreshold = value;
if(!this.isRunning()) this.draw();
} }
setSampleRate = (value) => { setSampleRate = (value) => {
this.sampleRate = value; this.sampleRate = value;
} }
setFskPairs = fskPairs => { setFskPairs = fskPairs => {
this.fskPairs = fskPairs; this.fskPairs = fskPairs;
if(!this.isRunning()) this.draw();
} }
setAnalyser = (analyser) => { setAnalyser = (analyser) => {
this.analyser = analyser; this.analyser = analyser;
@@ -185,7 +187,7 @@ class FrequencyGraphPanel extends BasePanel {
} }
// sample counts // sample counts
this.drawSampleCount(ctx, width, height, time, end, leftX, samplePeriodWidth); this.drawSampleCount(ctx, time, end, leftX, samplePeriodWidth);
} }
this.drawSignalStart(ctx, width, height, now); this.drawSignalStart(ctx, width, height, now);
@@ -195,7 +197,7 @@ class FrequencyGraphPanel extends BasePanel {
this.animationFrameId = requestAnimationFrame(this.draw); this.animationFrameId = requestAnimationFrame(this.draw);
} }
} }
drawSampleCount = (ctx, width, height, start, end, leftX, samplePeriodWidth) => { drawSampleCount = (ctx, start, end, leftX, samplePeriodWidth) => {
const count = this.samples.filter(sample => { const count = this.samples.filter(sample => {
return sample.time >= start && sample.time < end; return sample.time >= start && sample.time < end;
}).length; }).length;

View File

@@ -7,7 +7,7 @@ class GraphConfigurationPanel extends BasePanel {
{text: 'Pause after signal ends', id: 'pause-after-end', eventName: 'pauseAfterEndChange'} {text: 'Pause after signal ends', id: 'pause-after-end', eventName: 'pauseAfterEndChange'}
]) ])
this.openField('Duration'); this.openField('Duration');
this.addInputNumber('duration', 1, {min: 0.03, step: 0.001, eventName: 'durationChange'}); this.addInputNumber('duration', 1, {min: 0.03, max: 10, step: 0.001, eventName: 'durationChange'});
this.addText('s'); this.addText('s');
this.closeField(); this.closeField();
}; };

View File

@@ -11,14 +11,9 @@
<h1>Data Over Audio</h1> <h1>Data Over Audio</h1>
<div class="panels" id="panel-container"> <div class="panels" id="panel-container">
<div class="chart"> <div class="chart">
<h2>Frequency Graph</h2> <h2>Channel Graph</h2>
<div> <div>
<canvas id="received-graph" width="800" height="150"></canvas><br> <canvas id="received-channel-graph" width="800" height="300"></canvas>
<canvas id="received-channel-graph" width="800" height="300"></canvas><br>
<label>
<input type="checkbox" id="pause-after-end" checked>Pause after end
</label><br>
Max Segments Displayed: <input id="max-bits-displayed-on-graph" type="number" min="1" max="2000"><br>
</div> </div>
</div> </div>

290
index.js
View File

@@ -21,8 +21,6 @@ var microphoneStream;
var microphoneNode; var microphoneNode;
var analyser; var analyser;
var sentDataTextArea; var sentDataTextArea;
var receivedGraph;
var receivedData = [];
const MAXIMUM_PACKETIZATION_SIZE_BITS = 16; const MAXIMUM_PACKETIZATION_SIZE_BITS = 16;
const CRC_BIT_COUNT = 8; const CRC_BIT_COUNT = 8;
@@ -34,8 +32,6 @@ let SENT_TRANSFER_BITS = []; // bits sent in the transfer
let EXCLUDED_CHANNELS = []; let EXCLUDED_CHANNELS = [];
var MAX_BITS_DISPLAYED_ON_GRAPH = 79;
const ERROR_CORRECTION_BLOCK_SIZE = 7; const ERROR_CORRECTION_BLOCK_SIZE = 7;
const ERROR_CORRECTION_DATA_SIZE = 4; const ERROR_CORRECTION_DATA_SIZE = 4;
let CHANNEL_OVER = -1; let CHANNEL_OVER = -1;
@@ -182,17 +178,12 @@ function handleWindowLoad() {
StreamManager.addEventListener('change', handleStreamManagerChange); StreamManager.addEventListener('change', handleStreamManagerChange);
// grab dom elements // grab dom elements
receivedGraph = document.getElementById('received-graph');
sentDataTextArea = document.getElementById('sent-data'); sentDataTextArea = document.getElementById('sent-data');
const receivedChannelGraph = document.getElementById('received-channel-graph'); const receivedChannelGraph = document.getElementById('received-channel-graph');
receivedChannelGraph.addEventListener('mouseover', handleReceivedChannelGraphMouseover); receivedChannelGraph.addEventListener('mouseover', handleReceivedChannelGraphMouseover);
receivedChannelGraph.addEventListener('mouseout', handleReceivedChannelGraphMouseout); receivedChannelGraph.addEventListener('mouseout', handleReceivedChannelGraphMouseout);
receivedChannelGraph.addEventListener('mousemove', handleReceivedChannelGraphMousemove); receivedChannelGraph.addEventListener('mousemove', handleReceivedChannelGraphMousemove);
receivedChannelGraph.addEventListener('click', handleReceivedChannelGraphClick); receivedChannelGraph.addEventListener('click', handleReceivedChannelGraphClick);
document.getElementById('max-bits-displayed-on-graph').value= MAX_BITS_DISPLAYED_ON_GRAPH;
document.getElementById('max-bits-displayed-on-graph').addEventListener('input', (event) => {
MAX_BITS_DISPLAYED_ON_GRAPH = parseInt(event.target.value);
})
document.getElementById('audio-context-sample-rate').innerText = getAudioContext().sampleRate.toLocaleString(); document.getElementById('audio-context-sample-rate').innerText = getAudioContext().sampleRate.toLocaleString();
// wire up events // wire up events
configurationChanged(); configurationChanged();
@@ -910,206 +901,6 @@ function handleChangeListening({checked}) {
} }
} }
} }
function drawSegmentIndexes(ctx, width, height) {
// Do/did we have a stream?
if(!RECEIVED_STREAM_START_MS) return;
const latest = SAMPLES[0].time;
// will any of the stream appear?
const segmentCount = PacketUtils.getPacketSegmentCount();
const transferDuration = parseDataTransferDurationMilliseconds();
const lastStreamEnded = RECEIVED_STREAM_START_MS + transferDuration;
const graphDuration = signalPanel.getSegmentDuration() * MAX_BITS_DISPLAYED_ON_GRAPH;
const graphEarliest = latest - graphDuration;
// ended too long ago?
if(lastStreamEnded < graphEarliest) return;
const segmentWidth = width / MAX_BITS_DISPLAYED_ON_GRAPH;
const latestSegmentEnded = Math.min(latest, lastStreamEnded);
for(let time = latestSegmentEnded; time > graphEarliest; time -= signalPanel.getSegmentDuration()) {
// too far back?
if(time < RECEIVED_STREAM_START_MS) break;
const transferSegmentIndex = PacketUtils.getTranserSegmentIndex(RECEIVED_STREAM_START_MS, time);
const packetIndex = PacketUtils.getPacketIndex(RECEIVED_STREAM_START_MS, time);
const packetSegmentIndex = PacketUtils.getPacketSegmentIndex(RECEIVED_STREAM_START_MS, time);
const packetStarted = PacketUtils.getPacketStartMilliseconds(RECEIVED_STREAM_START_MS, packetIndex);
const segmentStart = PacketUtils.getPacketSegmentStartMilliseconds(RECEIVED_STREAM_START_MS, packetIndex, packetSegmentIndex);
const segmentEnd = PacketUtils.getPacketSegmentEndMilliseconds(RECEIVED_STREAM_START_MS, packetIndex, packetSegmentIndex);
// where is the segments left x coordinate?
const leftX = ((latest - segmentEnd) / graphDuration) * width;
// Draw segment index
ctx.fontSize = '24px';
if(segmentStart < lastStreamEnded) {
let text = packetSegmentIndex.toString();
let size = ctx.measureText(text);
let textX = leftX + (segmentWidth / 2) - (size.width / 2);
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
ctx.textBaseline = 'bottom';
let textY = transferSegmentIndex % 2 === 0 ? height : height - 12;
ctx.strokeText(text, textX, textY);
ctx.fillStyle = 'white';
ctx.fillText(text, textX, textY);
}
// draw sample count
const sampleCount = SAMPLES
.filter(fot =>
fot.streamStarted === packetStarted &&
fot.segmentIndex === packetSegmentIndex &&
fot.packetIndex === packetIndex
)
.length;
// if(sampleCount === 0) {
// console.log({
// packetStarted,
// packetSegmentIndex,
// packetIndex,
// startTimes: SAMPLES.reduce((all, fot) => all.includes(fot.streamStarted) ? all : [...all, fot.streamStarted], [])
// })
// }
let text = sampleCount.toString();
let size = ctx.measureText(text);
let textX = leftX + (segmentWidth / 2) - (size.width / 2);
let textY = transferSegmentIndex % 2 === 0 ? 5 : 17;
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
ctx.textBaseline = 'top';
ctx.strokeText(text, textX, textY);
if(sampleCount === 0) ctx.fillStyle = 'red';
else if(sampleCount < 3) ctx.fillStyle = 'yellow';
else ctx.fillStyle = 'white';
ctx.fillText(text, textX, textY);
}
}
function drawBitDurationLines(ctx, color) {
const { width, height } = receivedGraph;
const newest = SAMPLES[0].time;
const duration = signalPanel.getSegmentDuration() * MAX_BITS_DISPLAYED_ON_GRAPH;
const streamTimes = SAMPLES.filter(({
streamStarted
}) => {
return streamStarted !== -1
}).reduce((unique, {
streamStarted,
streamEnded = newest
}) => {
if(unique.every(u => u.streamStarted != streamStarted)) {
unique.push({streamStarted, streamEnded})
}
return unique;
}, []);
ctx.strokeStyle = color;
streamTimes.forEach(({ streamStarted, streamEnded = newest}) => {
for(let time = streamStarted; time < streamEnded; time += signalPanel.getSegmentDuration()) {
if(newest - time > duration) continue;
const x = ((newest - time) / duration) * width;
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
// write end as well
const x = ((newest - streamEnded) / duration) * width;
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
});
}
function drawBitStart(ctx, color) {
const { width, height } = receivedGraph;
const newest = SAMPLES[0].time;
const duration = signalPanel.getSegmentDuration() * MAX_BITS_DISPLAYED_ON_GRAPH;
ctx.strokeStyle = color;
for(let i = 0; i < bitStart.length; i++) {
if(!bitStart[i]) continue;
const {time} = SAMPLES[i];
if(newest - time > duration) continue;
const x = ((newest - time) / duration) * width;
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
}
function getPercentY(percent) {
const { height } = receivedGraph;
return (1 - percent) * height;
}
function drawFrequencyLineGraph(ctx, channel, highLowIndex, color, lineWidth, dashed) {
const { width, height } = receivedGraph;
const newest = SAMPLES[0].time;
const duration = signalPanel.getSegmentDuration() * MAX_BITS_DISPLAYED_ON_GRAPH;
const isSelected = channel === CHANNEL_SELECTED;
const isOver = channel === CHANNEL_OVER;
if(dashed) {
ctx.setLineDash([5, 5]);
}
ctx.beginPath();
for(let i = 0; i < SAMPLES.length; i++) {
const {pairs, time} = SAMPLES[i];
const x = getTimeX(time, newest);
if(x === -1) continue;
if(channel >= pairs.length) continue;
const amplitude = pairs[channel][highLowIndex];
const y = getPercentY(amplitude / 300);
if(i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
}
if(isSelected || isOver) {
ctx.lineWidth = lineWidth + 5;
ctx.strokeStyle = 'white';
ctx.stroke();
}
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
ctx.stroke();
if(dashed) {
ctx.setLineDash([]);
}
}
function drawFrequencyDots(ctx, channel, highLowIndex, color) {
const newest = SAMPLES[0].time;
const radius = 2;
const border = 0.5;
ctx.fillStyle = color;
ctx.strokeStyle = 'white';
ctx.lineWidth = border;
const fullCircle = 2 * Math.PI;
for(let i = 0; i < SAMPLES.length; i++) {
const {pairs, time} = SAMPLES[i];
const x = getTimeX(time, newest);
if(x === -1) continue;
const amplitude = pairs[channel][highLowIndex];
const y = getPercentY(amplitude / 300);
ctx.beginPath();
ctx.arc(x, y, radius, 0, fullCircle);
ctx.fill();
ctx.beginPath();
ctx.arc(x, y, radius + border, 0, fullCircle);
ctx.stroke();
}
}
function getTimeX(time, newest) {
return getTimePercent(time, newest) * receivedGraph.width;
}
function getTimePercent(time, newest) {
const duration = signalPanel.getSegmentDuration() * MAX_BITS_DISPLAYED_ON_GRAPH;
if(newest - time > duration) return -1;
return ((newest - time) / duration);
}
function drawChannelData() { function drawChannelData() {
// Do/did we have a stream? // Do/did we have a stream?
@@ -1122,7 +913,7 @@ function drawChannelData() {
const packetDuration = PacketUtils.getPacketDurationMilliseconds(); const packetDuration = PacketUtils.getPacketDurationMilliseconds();
const lastStreamEnded = RECEIVED_STREAM_START_MS + packetDuration; const lastStreamEnded = RECEIVED_STREAM_START_MS + packetDuration;
const graphDuration = signalPanel.getSegmentDuration() * MAX_BITS_DISPLAYED_ON_GRAPH; const graphDuration = graphConfigurationPanel.getDurationMilliseconds();
const graphEarliest = latest - graphDuration; const graphEarliest = latest - graphDuration;
// ended too long ago? // ended too long ago?
if(lastStreamEnded < graphEarliest) return; if(lastStreamEnded < graphEarliest) return;
@@ -1225,7 +1016,7 @@ function drawSegmentBackground(
width, width,
height height
) { ) {
const segmentWidth = width / MAX_BITS_DISPLAYED_ON_GRAPH; const segmentWidth = width / (graphConfigurationPanel.getDurationMilliseconds() / signalPanel.getSegmentDuration());
const hue = 120; const hue = 120;
let luminance = segmentIndex % 2 === 0 ? 30 : 25; let luminance = segmentIndex % 2 === 0 ? 30 : 25;
@@ -1246,7 +1037,7 @@ function drawChannelSegmentForeground(
expectedBit expectedBit
) { ) {
const channelHeight = height / channelCount; const channelHeight = height / channelCount;
const segmentWidth = width / MAX_BITS_DISPLAYED_ON_GRAPH; const segmentWidth = width / (graphConfigurationPanel.getDurationMilliseconds() / signalPanel.getSegmentDuration());
let fontHeight = Math.min(24, channelHeight, segmentWidth); let fontHeight = Math.min(24, channelHeight, segmentWidth);
let top = channelHeight * channelIndex; let top = channelHeight * channelIndex;
ctx.font = `${fontHeight}px Arial`; ctx.font = `${fontHeight}px Arial`;
@@ -1286,7 +1077,7 @@ function drawChannelSegmentBackground(
if(isSelectedOrOver) luminance += 15; if(isSelectedOrOver) luminance += 15;
const channelHeight = height / channelCount; const channelHeight = height / channelCount;
const segmentWidth = width / MAX_BITS_DISPLAYED_ON_GRAPH; const segmentWidth = width / (graphConfigurationPanel.getDurationMilliseconds() / signalPanel.getSegmentDuration());
let top = channelHeight * channelIndex; let top = channelHeight * channelIndex;
ctx.fillStyle = `hsl(${hue}, 100%, ${luminance}%)`; ctx.fillStyle = `hsl(${hue}, 100%, ${luminance}%)`;
ctx.fillRect(endX, top, segmentWidth, channelHeight); ctx.fillRect(endX, top, segmentWidth, channelHeight);
@@ -1323,7 +1114,7 @@ function drawChannelNumbers(ctx, channelCount, width, height) {
const offset = 0; const offset = 0;
const channels = availableFskPairsPanel.getSelectedFskPairs(); const channels = availableFskPairsPanel.getSelectedFskPairs();
const channelHeight = height / channelCount; const channelHeight = height / channelCount;
const segmentWidth = width / MAX_BITS_DISPLAYED_ON_GRAPH; const segmentWidth = width / (graphConfigurationPanel.getDurationMilliseconds() / signalPanel.getSegmentDuration());
let fontHeight = Math.min(24, channelHeight, segmentWidth); let fontHeight = Math.min(24, channelHeight, segmentWidth);
ctx.font = `${fontHeight}px Arial`; ctx.font = `${fontHeight}px Arial`;
ctx.textBaseline = 'middle'; ctx.textBaseline = 'middle';
@@ -1356,80 +1147,13 @@ function drawFrequencyData(forcedDraw) {
return; return;
} }
drawChannelData(); drawChannelData();
const ctx = receivedGraph.getContext('2d');
const { width, height } = receivedGraph;
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, width, height);
const thresholdY = (1 - ((signalPanel.getAmplitudeThreshold() * 255)/300)) * height;
ctx.strokeStyle = 'grey';
ctx.beginPath();
ctx.moveTo(0, thresholdY);
ctx.lineTo(width, thresholdY);
ctx.stroke();
drawBitDurationLines(ctx, 'rgba(255, 255, 0, .25)');
drawBitStart(ctx, 'green');
const frequencies = availableFskPairsPanel.getSelectedFskPairs();
const high = 1;
const low = 0
const isSelectedOrOver = CHANNEL_OVER !== -1 || CHANNEL_SELECTED !== -1;
const highLuminance = isSelectedOrOver ? 25 : 50;
const lowLuminance = isSelectedOrOver ? 12 : 25;
frequencies.forEach((v, channel) => {
// const hue = channelHue(channel, frequencies.length);
const lowHue = hzHue(v[0]);
const highHue = hzHue(v[1]);
drawFrequencyLineGraph(ctx, channel, high, `hsl(${highHue}, 100%, ${highLuminance}%)`, 2, false);
drawFrequencyLineGraph(ctx, channel, low, `hsl(${lowHue}, 100%, ${lowLuminance}%)`, 1, true);
});
if(CHANNEL_OVER !== -1) {
// const hue = channelHue(CHANNEL_OVER, frequencies.length);
const lowHue = hzHue(frequencies[CHANNEL_OVER][0]);
const highHue = hzHue(frequencies[CHANNEL_OVER][1]);
drawFrequencyLineGraph(ctx, CHANNEL_OVER, high, `hsl(${highHue}, 100%, 50%)`, 2, false);
drawFrequencyLineGraph(ctx, CHANNEL_OVER, low, `hsl(${lowHue}, 100%, 25%)`, 1, true);
} else if(CHANNEL_SELECTED !== -1) {
const lowHue = hzHue(frequencies[CHANNEL_SELECTED][0]);
const highHue = hzHue(frequencies[CHANNEL_SELECTED][1]);
// const hue = channelHue(CHANNEL_SELECTED, frequencies.length);
drawFrequencyLineGraph(ctx, CHANNEL_SELECTED, high, `hsl(${highHue}, 100%, 50%)`, 2, false);
drawFrequencyLineGraph(ctx, CHANNEL_SELECTED, low, `hsl(${lowHue}, 100%, 25%)`, 1, true);
}
drawSegmentIndexes(ctx, width, height);
requestAnimationFrame(drawFrequencyData); requestAnimationFrame(drawFrequencyData);
} }
function channelHue(channelId, channelCount) {
return Math.floor((channelId / channelCount) * 360);
}
function hzHue(hz) { function hzHue(hz) {
return Math.floor((hz / 20000) * 360); return Math.floor((hz / 20000) * 360);
} }
function drawReceivedData() {
const ctx = receivedGraph.getContext('2d');
const { width, height } = receivedGraph;
const segmentWidth = (1 / MAX_BITS_DISPLAYED_ON_GRAPH) * width;
ctx.clearRect(0, 0, width, height);
const sorted = receivedData.slice().sort((a, b) => a - b);
const min = sorted[0];
const max = sorted[sorted.length - 1];
const range = max - min;
ctx.beginPath();
for(let i = 0; i < MAX_BITS_DISPLAYED_ON_GRAPH && i < receivedData.length; i++) {
const value = receivedData[i];
const y = (1-(value / range)) * height;
if(i === 0) {
ctx.moveTo(0, y);
} else {
ctx.lineTo(segmentWidth * i, y)
}
}
ctx.stroke();
}
function handleReceivedChannelGraphMouseover(e) { function handleReceivedChannelGraphMouseover(e) {
const {channelIndex, segmentIndex} = getChannelAndSegment(e); const {channelIndex, segmentIndex} = getChannelAndSegment(e);
CHANNEL_OVER = channelIndex; CHANNEL_OVER = channelIndex;
@@ -1583,7 +1307,7 @@ function getChannelAndSegment(e) {
// will any of the stream appear? // will any of the stream appear?
const packetDuration = PacketUtils.getPacketDurationMilliseconds(); const packetDuration = PacketUtils.getPacketDurationMilliseconds();
const lastStreamEnded = RECEIVED_STREAM_START_MS + packetDuration; const lastStreamEnded = RECEIVED_STREAM_START_MS + packetDuration;
const graphDuration = signalPanel.getSegmentDuration() * MAX_BITS_DISPLAYED_ON_GRAPH; const graphDuration = graphConfigurationPanel.getDurationMilliseconds();
const graphEarliest = latest - graphDuration; const graphEarliest = latest - graphDuration;
// ended too long ago? // ended too long ago?
if(lastStreamEnded < graphEarliest) { if(lastStreamEnded < graphEarliest) {
@@ -1593,7 +1317,7 @@ function getChannelAndSegment(e) {
}; };
} }
const segmentWidth = width / MAX_BITS_DISPLAYED_ON_GRAPH; const segmentWidth = width / (graphConfigurationPanel.getDurationMilliseconds() / signalPanel.getSegmentDuration());
const latestSegmentEnded = Math.min(latest, lastStreamEnded); const latestSegmentEnded = Math.min(latest, lastStreamEnded);