Separate receiving text/images into own panel

This commit is contained in:
Lewis Moten
2024-05-13 03:53:42 -04:00
parent f548d9572b
commit 8cb5248fdf
5 changed files with 138 additions and 60 deletions

View File

@@ -117,15 +117,12 @@ export function stopAt(streamEndSeconds) {
} }
export function stop() { export function stop() {
const oscillators = getOscillators(); const oscillators = getOscillators();
if(this.audioContext) { oscillators.forEach(
const time = now(); oscillator => {
oscillators.forEach( oscillator?.stop();
oscillator => { oscillator?.disconnect();
oscillator?.stop(time); }
oscillator?.disconnect(); )
}
)
}
oscillators.length = 0; oscillators.length = 0;
futureEventIds.forEach(window.clearTimeout); futureEventIds.forEach(window.clearTimeout);
futureEventIds.length = 0; futureEventIds.length = 0;

View File

@@ -2,8 +2,7 @@ import BasePanel from './BasePanel';
class CommunicationsPanel extends BasePanel { class CommunicationsPanel extends BasePanel {
constructor() { constructor() {
super('Communications'); super('Audio Sender');
this.addSection('Send');
this.addRadios('send-via', [ this.addRadios('send-via', [
{text: 'Analyzer', id: 'send-via-analyzer', eventName: 'sendAnalyzerChange'}, {text: 'Analyzer', id: 'send-via-analyzer', eventName: 'sendAnalyzerChange'},
{text: 'Speakers', id: 'send-via-speaker', eventName: 'sendSpeakersChange'} {text: 'Speakers', id: 'send-via-speaker', eventName: 'sendSpeakersChange'}

View File

@@ -21,27 +21,25 @@ class MessagePanel extends BasePanel {
this.addImage('image-to-send', 'interlaced-sample.gif', {eventName: 'messageChange'}); this.addImage('image-to-send', 'interlaced-sample.gif', {eventName: 'messageChange'});
this.closeField(); this.closeField();
this.addButton('send-button', 'Send', 'send'); this.addButton('send-button', 'Send', 'send-button-click');
this.addNewLine(); this.addNewLine();
this.openField('Bytes'); this.openField('Bytes');
this.addDynamicText('bytes', 0); this.addDynamicText('bytes', 0);
this.closeField(); this.closeField();
this.addSection('Received'); this.addEventListener('send-button-click', () => {
if(this.getSendButtonText() === 'Send') {
this.addCode('decoded-text', '', 'small'); this.dispatcher.emit('sendClick');
this.addImage('decoded-image', undefined, {width: 32, height: 32}); } else {
this.dispatcher.emit('stopClick');
this.addProgressBar('received-progress', .50); }
})
this.addEventListener('dataTypeChange', ({values: [value]}) => { this.addEventListener('dataTypeChange', ({values: [value]}) => {
this.display('field-text', value === 'text');
this.display('field-image', value === 'image');
this.display('decoded-image', value === 'image');
this.display('decoded-text', value==='text');
// should be 487 bytes
this.setValueById('bytes', byteSize(this.getMessageBytes().length)); this.setValueById('bytes', byteSize(this.getMessageBytes().length));
this.display('field-image', value === 'image');
this.display('field-text', value === 'text');
}); });
this.addEventListener('messageChange', e => { this.addEventListener('messageChange', e => {
this.setValueById('bytes', byteSize(this.getMessageBytes().length)); this.setValueById('bytes', byteSize(this.getMessageBytes().length));
@@ -62,19 +60,11 @@ class MessagePanel extends BasePanel {
return urlToBytes(this.getElement('image-to-send').src); return urlToBytes(this.getElement('image-to-send').src);
} }
} }
setProgress = percent => this.setProgressById('received-progress', percent);
setReceived = (html) => this.setHtmlById('decoded-text', html);
setReceivedBytes = bytes => {
if(this.getDataType() === 'text') {
this.setReceived(bytesToText(bytes));
} else {
this.setValueById('decoded-image', bytesToUrl(bytes));
}
}
getDataType = () => this.getValueById('data-type'); getDataType = () => this.getValueById('data-type');
setDataType = (value) => { setDataType = (value) => {
this.setValueById('data-type', value); this.setValueById('data-type', value);
this.dispatcher.emit('dataTypeChange', {values: [value]}); this.dispatcher.emit('dataTypeChange', {values: [value]});
} }
} }

89
Panels/ReceivePanel.js Normal file
View File

@@ -0,0 +1,89 @@
import { bytesToText, bytesToUrl } from '../converters';
import BasePanel from './BasePanel';
import * as AudioReceiver from '../AudioReceiver';
import * as StreamManager from '../StreamManager';
class ReceivePanel extends BasePanel {
constructor() {
super('Audio Receiver');
this.addRadios('online', [
{id: 'is-offline', text: 'Offline', value: 'offline', checked: true, eventName: 'offlineChange'},
{id: 'is-online', text: 'Online', value: 'online', eventName: 'onlineChange'}
]);
this.addButton('reset', 'Reset Data', 'resetClick');
this.addNewLine();
this.addDynamicText('id-state', 'Offline.');
this.addProgressBar('progress', .50);
this.addCode('text', '', 'small');
this.addImage('image', undefined, {width: 32, height: 32});
this.setDataType('text');
this.dispatcher.addListener('onlineChange', (e) => {
this.setValueById('id-state', 'Ready');
AudioReceiver.start();
})
this.dispatcher.addListener('offlineChange', (e) => {
this.setValueById('id-state', 'Offline');
AudioReceiver.stop();
})
AudioReceiver.addEventListener('begin', (...args) => {
this.setValueById('id-state', 'Signal Started');
this.dispatcher.emit('begin', ...args)
});
AudioReceiver.addEventListener('receive', (...args) => {
this.setValueById('id-state', `Sample Period ${args[0].signalIndex}`)
this.dispatcher.emit('receive', ...args)
});
AudioReceiver.addEventListener('end', (...args) => {
this.setValueById('id-state', 'Signal Ended');
this.dispatcher.emit('end', ...args)
});
this.addEventListener('resetClick', () => {
AudioReceiver.reset();
StreamManager.reset();
});
}
isOnline = () => this.getCheckedById('is-online');
setIsOnline = isOnline => {
this.setCheckedById(isOnline ? 'is-online' : 'is-offline', true);
if(isOnline) {
AudioReceiver.start();
this.setValueById('id-state', 'Ready');
} else {
AudioReceiver.stop();
this.setValueById('id-state', 'offline');
}
}
// waitForSignal = () => {
// AudioReceiver.start();
// }
// reset = () => {
// AudioReceiver.reset();
// StreamManager.reset();
// }
// stopWaitingForSignal = () => {
// AudioReceiver.stop();
// }
setProgress = percent => this.setProgressById('progress', percent);
setReceivedHtml = (html) => this.setHtmlById('text', html);
setReceivedBytes = bytes => {
if(this.dataType === 'text') {
this.setValueById('text', bytesToText(bytes));
} else {
this.setValueById('image', bytesToUrl(bytes));
}
}
setDataType = (value) => {
this.dataType = value;
this.display('text', value === 'text');
this.display('image', value === 'image');
}
}
export default ReceivePanel;

View File

@@ -30,6 +30,7 @@ import {
textToBytes, textToBytes,
} from './converters'; } from './converters';
import MicrophonePanel from "./Panels/MicrophonePanel"; import MicrophonePanel from "./Panels/MicrophonePanel";
import ReceivePanel from "./Panels/ReceivePanel";
var audioContext; var audioContext;
var microphoneStream; var microphoneStream;
var microphoneNode; var microphoneNode;
@@ -70,6 +71,7 @@ const frequencyGraphPanel = new FrequencyGraphPanel();
const graphConfigurationPanel = new GraphConfigurationPanel(); const graphConfigurationPanel = new GraphConfigurationPanel();
const speedPanel = new SpeedPanel(); const speedPanel = new SpeedPanel();
const microphonePanel = new MicrophonePanel(); const microphonePanel = new MicrophonePanel();
const receivePanel = new ReceivePanel();
function handleWindowLoad() { function handleWindowLoad() {
const panelContainer = document.getElementById('panel-container'); const panelContainer = document.getElementById('panel-container');
@@ -82,9 +84,10 @@ function handleWindowLoad() {
panelContainer.prepend(signalPanel.getDomElement()); panelContainer.prepend(signalPanel.getDomElement());
panelContainer.prepend(bitsReceivedPanel.getDomElement()); panelContainer.prepend(bitsReceivedPanel.getDomElement());
panelContainer.prepend(bitsSentPanel.getDomElement()); panelContainer.prepend(bitsSentPanel.getDomElement());
panelContainer.prepend(messagePanel.getDomElement()); panelContainer.prepend(receivePanel.getDomElement());
panelContainer.prepend(communicationsPanel.getDomElement());
panelContainer.prepend(microphonePanel.getDomElement()); panelContainer.prepend(microphonePanel.getDomElement());
panelContainer.prepend(communicationsPanel.getDomElement());
panelContainer.prepend(messagePanel.getDomElement());
// Initialize Values // Initialize Values
microphonePanel.setListening(false); microphonePanel.setListening(false);
@@ -93,11 +96,16 @@ function handleWindowLoad() {
communicationsPanel.setSendAnalyzer(true); communicationsPanel.setSendAnalyzer(true);
messagePanel.setMessageText(Randomizer.text(5)); messagePanel.setMessageText(Randomizer.text(5));
messagePanel.setProgress(0);
messagePanel.setReceived('');
messagePanel.setDataType('image'); messagePanel.setDataType('image');
messagePanel.setSendButtonText('Send'); messagePanel.setSendButtonText('Send');
messagePanel.addEventListener('dataTypeChange', ({values: [dataType]}) => {
receivePanel.setDataType(dataType);
})
receivePanel.setDataType(messagePanel.getDataType());
receivePanel.setProgress(0);
receivePanel.setReceivedHtml('Ready.');
bitsSentPanel.setCode(''); bitsSentPanel.setCode('');
bitsReceivedPanel.setCode(''); bitsReceivedPanel.setCode('');
@@ -143,7 +151,8 @@ function handleWindowLoad() {
communicationsPanel.addEventListener('sendAnalyzerChange', handleChangeSendAnalyzer); communicationsPanel.addEventListener('sendAnalyzerChange', handleChangeSendAnalyzer);
messagePanel.addEventListener('messageChange', configurationChanged); messagePanel.addEventListener('messageChange', configurationChanged);
messagePanel.addEventListener('send', handleSendButtonClick); messagePanel.addEventListener('sendClick', handleSendButtonClick);
messagePanel.addEventListener('stopClick', handleStopButtonClick);
frequencyPanel.addEventListener('minimumFrequencyChange', configurationChanged); frequencyPanel.addEventListener('minimumFrequencyChange', configurationChanged);
frequencyPanel.addEventListener('maximumFrequencyChange', configurationChanged); frequencyPanel.addEventListener('maximumFrequencyChange', configurationChanged);
@@ -196,14 +205,14 @@ function handleWindowLoad() {
frequencyGraphPanel.setDurationMilliseconds(graphConfigurationPanel.getDurationMilliseconds()); frequencyGraphPanel.setDurationMilliseconds(graphConfigurationPanel.getDurationMilliseconds());
}); });
receivePanel.addEventListener('start', handleReceivePanelStart);
receivePanel.addEventListener('receive', handleReceivePanelReceive);
receivePanel.addEventListener('end', handleReceivePanelEnd);
// Setup audio sender // Setup audio sender
AudioSender.addEventListener('begin', () => messagePanel.setSendButtonText('Stop')); AudioSender.addEventListener('begin', () => messagePanel.setSendButtonText('Stop'));
AudioSender.addEventListener('send', handleAudioSenderSend); AudioSender.addEventListener('send', handleAudioSenderSend);
AudioSender.addEventListener('end', () => messagePanel.setSendButtonText('Send')); AudioSender.addEventListener('end', () => messagePanel.setSendButtonText('Send'));
// Setup audio receiver
AudioReceiver.addEventListener('begin', handleAudioReceiverStart);
AudioReceiver.addEventListener('receive', handleAudioReceiverReceive);
AudioReceiver.addEventListener('end', handleAudioReceiverEnd);
// Setup stream manager // Setup stream manager
StreamManager.addEventListener('change', handleStreamManagerChange); StreamManager.addEventListener('change', handleStreamManagerChange);
@@ -249,24 +258,23 @@ function updateAudioSender() {
waveForm: signalPanel.getWaveform() waveForm: signalPanel.getWaveform()
}); });
} }
const handleAudioReceiverStart = ({signalStart}) => { const handleReceivePanelStart = ({signalStart}) => {
StreamManager.reset();
frequencyGraphPanel.setSignalStart(signalStart); frequencyGraphPanel.setSignalStart(signalStart);
RECEIVED_STREAM_START_MS = signalStart; RECEIVED_STREAM_START_MS = signalStart;
} }
const handleAudioReceiverReceive = ({signalStart, signalIndex, indexStart, bits}) => { const handleReceivePanelReceive = ({signalStart, signalIndex, indexStart, bits}) => {
const packetIndex = PacketUtils.getPacketIndex(signalStart, indexStart); const packetIndex = PacketUtils.getPacketIndex(signalStart, indexStart);
const segmentIndex = PacketUtils.getPacketSegmentIndex(signalStart, indexStart); const segmentIndex = PacketUtils.getPacketSegmentIndex(signalStart, indexStart);
// Getting all 1's for only the first 5 segments? // Getting all 1's for only the first 5 segments?
// console.log(signalIndex, packetIndex, segmentIndex, bits.join('')); // console.log(signalIndex, packetIndex, segmentIndex, bits.join(''));
StreamManager.addBits(packetIndex, segmentIndex, bits); StreamManager.addBits(packetIndex, segmentIndex, bits);
} }
const handleAudioReceiverEnd = (e) => { const handleReceivePanelEnd = (e) => {
frequencyGraphPanel.setSignalEnd(e.signalEnd); frequencyGraphPanel.setSignalEnd(e.signalEnd);
if(graphConfigurationPanel.getPauseAfterEnd()) { if(graphConfigurationPanel.getPauseAfterEnd()) {
stopGraph(); stopGraph();
frequencyGraphPanel.stop(); frequencyGraphPanel.stop();
AudioSender.stop(); receivePanel.setIsOnline(false);
} }
} }
function updateAudioReceiver() { function updateAudioReceiver() {
@@ -407,10 +415,6 @@ function sendBytes(bytes) {
return; return;
} }
AudioReceiver.reset();
StreamManager.reset();
frequencyGraphPanel.start();
const bits = bytesToBits(bytes); const bits = bytesToBits(bytes);
SENT_ORIGINAL_TEXT = bytesToText(bytes); SENT_ORIGINAL_TEXT = bytesToText(bytes);
@@ -553,14 +557,14 @@ function padArray(values, length, value) {
function stopGraph() { function stopGraph() {
PAUSE = true; PAUSE = true;
AudioReceiver.stop(); receivePanel.setIsOnline(false);
} }
function resumeGraph() { function resumeGraph() {
if(microphonePanel.getListening()) { if(microphonePanel.getListening()) {
if(PAUSE) { if(PAUSE) {
PAUSE = false; PAUSE = false;
AudioReceiver.start(); receivePanel.setIsOnline(true);
resetGraphData(); resetGraphData();
requestAnimationFrame(drawFrequencyData); requestAnimationFrame(drawFrequencyData);
} else { } else {
@@ -610,7 +614,7 @@ function handleStreamManagerChange() {
const correctedDecodedBits = allDecodedBits.filter((b, i) => i < decodedBitCount && b === SENT_ORIGINAL_BITS[i]).length; const correctedDecodedBits = allDecodedBits.filter((b, i) => i < decodedBitCount && b === SENT_ORIGINAL_BITS[i]).length;
let percentReceived = StreamManager.sumTotalBits() / totalBitsTransferring; let percentReceived = StreamManager.sumTotalBits() / totalBitsTransferring;
messagePanel.setProgress(percentReceived); receivePanel.setProgress(percentReceived);
bitsReceivedPanel.setCode(allRawBits bitsReceivedPanel.setCode(allRawBits
.reduce( .reduce(
@@ -663,11 +667,11 @@ function handleStreamManagerChange() {
const receivedText = bytesToText(bytes); const receivedText = bytesToText(bytes);
if(messagePanel.getDataType() === 'text') { if(messagePanel.getDataType() === 'text') {
messagePanel.setReceived( receivePanel.setReceivedHtml(
receivedText.split('').reduce(textExpectorReducer(SENT_ORIGINAL_TEXT), '') receivedText.split('').reduce(textExpectorReducer(SENT_ORIGINAL_TEXT), '')
); );
} else { } else {
messagePanel.setReceivedBytes(bytes); receivePanel.setReceivedBytes(bytes);
} }
} }
function parseTotalBitsTransferring() { function parseTotalBitsTransferring() {
@@ -840,12 +844,11 @@ function getAudioContext() {
} }
return audioContext; return audioContext;
} }
function handleStopButtonClick() {
AudioSender.stop();
}
function handleSendButtonClick() { function handleSendButtonClick() {
if(messagePanel.getSendButtonText() === 'Stop') { sendBytes(messagePanel.getMessageBytes());
AudioSender.stop();
} else {
sendBytes(messagePanel.getMessageBytes());
}
} }
function getAnalyser() { function getAnalyser() {
if(analyser) return analyser; if(analyser) return analyser;