request failing packets

This commit is contained in:
Lewis Moten
2024-05-15 02:05:48 -04:00
parent c4a0d8afd1
commit d9b5391601
11 changed files with 187 additions and 823 deletions

View File

@@ -37,6 +37,16 @@ export const changeConfiguration = ({
export const setAudioContext = ctx => audioContext = ctx;
export const setDestination = destination => {
DESTINATION = destination;
const oscillators = getOscillators();
oscillators.forEach(
oscillator => {
oscillator?.disconnect();
oscillator?.connect(destination);
}
)
}
function getAudioContext() {
if(!audioContext) {
throw 'Audio context not provided.';
@@ -128,10 +138,7 @@ export function stopAt(streamEndSeconds) {
oscillator?.stop(streamEndSeconds);
}
stopTimeout();
stopOscillatorsTimeoutId = window.setTimeout(
stop,
delayMs(streamEndSeconds)
);
stopOscillatorsTimeoutId = window.setTimeout(stop, delayMs(streamEndSeconds));
}
export function stop() {
const oscillators = getOscillators();

View File

@@ -231,6 +231,14 @@ class BasePanel {
const element = this.getElement(id);
element.innerHTML = html;
}
getHtmlById = (id) => {
const element = this.getElement(id);
return element.innerHTML;
}
scrollToBottom = id => {
const element = this.getElement(id);
element.scrollIntoView(false);
}
getNumberById = id => {
const value = this.getValueById(id);
return parseFloat(value);

View File

@@ -1,3 +1,4 @@
import { htmlEncode } from '../converters';
import BasePanel from './BasePanel';
class CodePanel extends BasePanel {
@@ -6,6 +7,18 @@ class CodePanel extends BasePanel {
this.addCode('code');
}
setCode = (html) => this.setHtmlById('code', html);
appendCode = html => {
let current = this.getHtmlById('code');
if(current !== '') current += document.createElement('br').outerHTML;
this.setHtmlById('code', current + html);
this.scrollToBottom('code');
}
appendText = text => {
let current = this.getHtmlById('code');
if(current !== '') current += document.createElement('br').outerHTML;
this.setHtmlById('code', current + htmlEncode(text));
this.scrollToBottom('code');
}
}
export default CodePanel;

View File

@@ -109,7 +109,8 @@ class FrequencyGraphPanel extends BasePanel {
const canvas = this.getElement('frequency-graph');
const ctx = canvas.getContext('2d');
const {height, width} = canvas;
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, width, height);
let now;
if(this.samples.length > 1) {

View File

@@ -1,8 +1,8 @@
import BasePanel from './BasePanel';
class CommunicationsPanel extends BasePanel {
class OutputPanel extends BasePanel {
constructor() {
super('Audio Sender');
super('Outut');
this.addRadios('send-via', [
{text: 'Analyzer', id: 'send-via-analyzer', eventName: 'sendAnalyzerChange'},
{text: 'Speakers', id: 'send-via-speaker', eventName: 'sendSpeakersChange'}
@@ -12,4 +12,4 @@ class CommunicationsPanel extends BasePanel {
setSendAnalyzer = checked => this.setCheckedById('send-via-analyzer', checked);
}
export default CommunicationsPanel;
export default OutputPanel;

View File

@@ -20,8 +20,8 @@ class PacketErrorPanel extends BasePanel {
this.addSection('Packet Retransmission')
this.addRadios('repeat', [
{ text: 'Automatic Repeat Request', value: 'arq', checked: true, eventName: 'hi' },
{ text: 'Manual Repeat Request', value: 'manual', checked: true, eventName: 'hi' }
{ text: 'Automatic Repeat Request', id:'arq', value: 'arq', checked: true, eventName: 'automaticRepeatRequestChange' },
{ text: 'Manual Repeat Request', id:'manual', value: 'manual', checked: true, eventName: 'manualRepeatRequestChange' }
]);
this.openField('Packets');
@@ -30,6 +30,9 @@ class PacketErrorPanel extends BasePanel {
this.addButton('request-button', 'Request', 'requestPackets');
}
getAutomaticRepeatRequest = () => {
return this.getCheckedById('arq');
}
reset = () => {
this.setFailedPacketIndeces([]);
this.setSizeCrcUnavailable();
@@ -41,7 +44,7 @@ class PacketErrorPanel extends BasePanel {
}
getFailedPacketIndeces = () => {
let text = this.getValueById('request-packet-indexes');
return text.replace(/\s+/g, '').split(',').map(Number);
return text.replace(/\s+/g, '').split(',').filter(v => v !== '').map(Number);
}
setCrcPassed = (passed) => this.setValueById('crc', passed ? 'Pass' : 'Fail');
setCrcUnavailable = () => this.setValueById('crc', 'N/A');

View File

@@ -15,7 +15,7 @@ class ReceivePanel extends BasePanel {
this.addNewLine();
this.addDynamicText('id-state', 'Offline.');
this.addProgressBar('progress', .50, .25);
this.addProgressBar('progress', 0, 0);
this.addCode('text', '', 'small');
this.addImage('image', undefined, {width: 32, height: 32});
@@ -45,6 +45,10 @@ class ReceivePanel extends BasePanel {
this.addEventListener('resetClick', () => {
AudioReceiver.reset();
StreamManager.reset();
this.setReceivedBytes([]);
this.setExpectedPacketCount(0);
this.setFailedPacketCount(0);
this.setSuccessfulPacketCount(0);
});
}
isOnline = () => this.getCheckedById('is-online');
@@ -58,17 +62,6 @@ class ReceivePanel extends BasePanel {
this.setValueById('id-state', 'offline');
}
}
// waitForSignal = () => {
// AudioReceiver.start();
// }
// reset = () => {
// AudioReceiver.reset();
// StreamManager.reset();
// }
// stopWaitingForSignal = () => {
// AudioReceiver.stop();
// }
setProgress = (percent, percent2 = 0) => {
this.setProgressById('progress', percent, percent2);
}

View File

@@ -2,13 +2,9 @@ import Dispatcher from "./Dispatcher";
import * as CRC from './CRC';
import * as PacketUtils from './PacketUtils';
import {
bitsToBytes,
bitsToInt,
bytesToBits,
numberToBytes,
numberToHex,
numberToAscii,
bytesToNumber
} from "./converters";
const dispatcher = new Dispatcher('StreamManager', [
@@ -41,7 +37,9 @@ export const removeEventListener = dispatcher.removeListener;
const isPacketInRange = (packetIndex) => {
// Blindly accept. We can't do anything about it for now
if(!isSizeTrusted()) return true;
if(!isSizeTrusted()){
return packetIndex < PacketUtils.getMaxPackets();
}
const { packetCount } = PacketUtils.packetStats(getSize());
return packetIndex < packetCount;
}
@@ -125,11 +123,23 @@ export const applyPacket = ({
}
delete BITS[packetIndex]
}
export const getFailedPacketIndeces = () => FAILED_SEQUENCES;
export const getFailedPacketIndeces = () => {
return FAILED_SEQUENCES.filter(isPacketInRange);
}
export const getNeededPacketIndeces = () => {
if(!isSizeTrusted()) return getFailedPacketIndeces();
const packetCount = countExpectedPackets();
let indeces = [];
for(let i = 0; i < packetCount; i++) {
if(SUCCESS_SEQUENCES.includes(i)) continue;
indeces.push(i);
}
return indeces;
};
export const countFailedPackets = () => FAILED_SEQUENCES.length;
export const countSuccessfulPackets = () => SUCCESS_SEQUENCES.length;
export const countExpectedPackets = () => {
if(!isSizeTrusted()) return 0;
if(!isSizeTrusted()) return PacketUtils.getMaxPackets();
return PacketUtils.packetStats(getSize()).packetCount;
}
export const setPacketsExpected = packetCount => {
@@ -138,11 +148,27 @@ export const setPacketsExpected = packetCount => {
SAMPLES_EXPECTED = packetCount * PacketUtils.getPacketSegmentCount();
}
const hasPackets = (start, end) => {
for(let packetIndex = start; packetIndex <= end; packetIndex++) {
// We need this packet, but it failed to transfer
if(FAILED_SEQUENCES.includes(packetIndex)) return false;
// We need this packet, but it hasn't come through yet
if(!SUCCESS_SEQUENCES.includes(packetIndex)) return false;
}
return true;
}
const hasBytes = (index, length) => {
if(DATA.length < index + length) return false;
const packetSize = PacketUtils.getPacketDataByteCount();
const start = Math.floor(index / packetSize);
const end = Math.floor(index + length / packetSize);
return hasPackets(start, end);
}
export const getSizeAvailable = () => {
if(DATA_SIZE_BIT_COUNT === 0) return 1;
let lastBit = DATA_SIZE_BIT_COUNT;
let lastByte = Math.ceil(lastBit / 8);
if(DATA.length < lastByte) return false;
if(!hasBytes(0, lastByte)) return false;
// Do we have a crc check on the size?
if(DATA_SIZE_CRC_BIT_COUNT !== 0) {
@@ -209,13 +235,14 @@ export const getSizeCrcAvailable = () => {
if (DATA_SIZE_BIT_COUNT === 0) return false;
if (DATA_SIZE_CRC_BIT_COUNT === 0) return false;
const bitsNeeded = DATA_SIZE_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
return DATA.length >= Math.ceil(bitsNeeded / 8);
const bytesNeeded = Math.ceil(bitsNeeded / 8);
return hasBytes(0, bytesNeeded);
}
export const getCrcAvailable = () => {
if(DATA_CRC_BIT_COUNT === 0) return false;
if(!getSizeAvailable()) return false;
let byteCount = getSize();
if(DATA.length < byteCount) return false;
// Do we have enough bytes for the headers and underlying data?
let headerBitCount = DATA_SIZE_BIT_COUNT + DATA_CRC_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
if(headerBitCount % 8 !== 0)
@@ -223,7 +250,7 @@ export const getCrcAvailable = () => {
const headerByteCount = headerBitCount / 8;
byteCount += headerByteCount;
return DATA.length >= byteCount;
return hasBytes(0, byteCount);
}
export const getSizeCrcPassed = () => {
if(!getSizeCrcAvailable()) return false;

View File

@@ -90,3 +90,8 @@ export const bytesToUrl = bytes => {
const blob = new Blob([new Uint8Array(bytes)]);
return URL.createObjectURL(blob);
}
export function htmlEncode(text) {
const element = document.createElement('div');
element.textContent = text;
return element.innerHTML;
}

View File

@@ -10,12 +10,6 @@
<body>
<h1>Data Over Audio</h1>
<div class="panels" id="panel-container">
<div class="chart">
<h2>Channel Graph</h2>
<div>
<canvas id="received-channel-graph" width="800" height="300"></canvas>
</div>
</div>
<div>
<h2>Data</h2>
<div>
@@ -28,18 +22,6 @@
Unused bits in last packet: <span id="last-packet-unused-bit-count"></span><br>
</div>
</div>
<div>
<h2>Original Data to send</h2>
<div>
<div class="raw-data" id="sent-data"></div><br />
</div>
</div>
<div>
<h2>Encoded packets to send</h2>
<div>
<div class="raw-data" id="error-correcting-data"></div>
</div>
</div>
<div>
<h2>Decoded</h2>
<div>
@@ -52,18 +34,6 @@
Decoded Packets: <span id="received-decoded-bits-error-percent">N/A</span>%<br />
</div>
</div>
<div>
<h2>Encoded Packets Received</h2>
<div>
<div class="raw-data" id="received-encoded-bits"></div><br />
</div>
</div>
<div>
<h2>Decoded Packets Received</h2>
<div>
<div class="raw-data" id="received-decoded-bits"></div><br />
</div>
</div>
<div>
<h2>Selected</h2>
<div>

853
index.js

File diff suppressed because it is too large Load Diff