From 8cb5248fdfeba9dab6ec90fd91c9ca96de08b13d Mon Sep 17 00:00:00 2001 From: Lewis Moten Date: Mon, 13 May 2024 03:53:42 -0400 Subject: [PATCH] Separate receiving text/images into own panel --- AudioSender.js | 15 +++--- Panels/CommunicationsPanel.js | 3 +- Panels/MessagePanel.js | 32 +++++-------- Panels/ReceivePanel.js | 89 +++++++++++++++++++++++++++++++++++ index.js | 59 ++++++++++++----------- 5 files changed, 138 insertions(+), 60 deletions(-) create mode 100644 Panels/ReceivePanel.js diff --git a/AudioSender.js b/AudioSender.js index 23391d7..6c202a8 100644 --- a/AudioSender.js +++ b/AudioSender.js @@ -117,15 +117,12 @@ export function stopAt(streamEndSeconds) { } export function stop() { const oscillators = getOscillators(); - if(this.audioContext) { - const time = now(); - oscillators.forEach( - oscillator => { - oscillator?.stop(time); - oscillator?.disconnect(); - } - ) - } + oscillators.forEach( + oscillator => { + oscillator?.stop(); + oscillator?.disconnect(); + } + ) oscillators.length = 0; futureEventIds.forEach(window.clearTimeout); futureEventIds.length = 0; diff --git a/Panels/CommunicationsPanel.js b/Panels/CommunicationsPanel.js index cf50a13..0313550 100644 --- a/Panels/CommunicationsPanel.js +++ b/Panels/CommunicationsPanel.js @@ -2,8 +2,7 @@ import BasePanel from './BasePanel'; class CommunicationsPanel extends BasePanel { constructor() { - super('Communications'); - this.addSection('Send'); + super('Audio Sender'); this.addRadios('send-via', [ {text: 'Analyzer', id: 'send-via-analyzer', eventName: 'sendAnalyzerChange'}, {text: 'Speakers', id: 'send-via-speaker', eventName: 'sendSpeakersChange'} diff --git a/Panels/MessagePanel.js b/Panels/MessagePanel.js index 3ba7270..e00db63 100644 --- a/Panels/MessagePanel.js +++ b/Panels/MessagePanel.js @@ -21,27 +21,25 @@ class MessagePanel extends BasePanel { this.addImage('image-to-send', 'interlaced-sample.gif', {eventName: 'messageChange'}); this.closeField(); - this.addButton('send-button', 'Send', 'send'); + this.addButton('send-button', 'Send', 'send-button-click'); this.addNewLine(); this.openField('Bytes'); this.addDynamicText('bytes', 0); this.closeField(); - this.addSection('Received'); - - this.addCode('decoded-text', '', 'small'); - this.addImage('decoded-image', undefined, {width: 32, height: 32}); - - this.addProgressBar('received-progress', .50); + this.addEventListener('send-button-click', () => { + if(this.getSendButtonText() === 'Send') { + this.dispatcher.emit('sendClick'); + } else { + this.dispatcher.emit('stopClick'); + } + }) 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.display('field-image', value === 'image'); + this.display('field-text', value === 'text'); }); this.addEventListener('messageChange', e => { this.setValueById('bytes', byteSize(this.getMessageBytes().length)); @@ -62,19 +60,11 @@ class MessagePanel extends BasePanel { 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'); setDataType = (value) => { this.setValueById('data-type', value); + this.dispatcher.emit('dataTypeChange', {values: [value]}); } } diff --git a/Panels/ReceivePanel.js b/Panels/ReceivePanel.js new file mode 100644 index 0000000..924a5fd --- /dev/null +++ b/Panels/ReceivePanel.js @@ -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; \ No newline at end of file diff --git a/index.js b/index.js index a763fdf..c507515 100644 --- a/index.js +++ b/index.js @@ -30,6 +30,7 @@ import { textToBytes, } from './converters'; import MicrophonePanel from "./Panels/MicrophonePanel"; +import ReceivePanel from "./Panels/ReceivePanel"; var audioContext; var microphoneStream; var microphoneNode; @@ -70,6 +71,7 @@ const frequencyGraphPanel = new FrequencyGraphPanel(); const graphConfigurationPanel = new GraphConfigurationPanel(); const speedPanel = new SpeedPanel(); const microphonePanel = new MicrophonePanel(); +const receivePanel = new ReceivePanel(); function handleWindowLoad() { const panelContainer = document.getElementById('panel-container'); @@ -82,9 +84,10 @@ function handleWindowLoad() { panelContainer.prepend(signalPanel.getDomElement()); panelContainer.prepend(bitsReceivedPanel.getDomElement()); panelContainer.prepend(bitsSentPanel.getDomElement()); - panelContainer.prepend(messagePanel.getDomElement()); - panelContainer.prepend(communicationsPanel.getDomElement()); + panelContainer.prepend(receivePanel.getDomElement()); panelContainer.prepend(microphonePanel.getDomElement()); + panelContainer.prepend(communicationsPanel.getDomElement()); + panelContainer.prepend(messagePanel.getDomElement()); // Initialize Values microphonePanel.setListening(false); @@ -93,11 +96,16 @@ function handleWindowLoad() { communicationsPanel.setSendAnalyzer(true); messagePanel.setMessageText(Randomizer.text(5)); - messagePanel.setProgress(0); - messagePanel.setReceived(''); messagePanel.setDataType('image'); messagePanel.setSendButtonText('Send'); + messagePanel.addEventListener('dataTypeChange', ({values: [dataType]}) => { + receivePanel.setDataType(dataType); + }) + receivePanel.setDataType(messagePanel.getDataType()); + receivePanel.setProgress(0); + receivePanel.setReceivedHtml('Ready.'); + bitsSentPanel.setCode(''); bitsReceivedPanel.setCode(''); @@ -143,7 +151,8 @@ function handleWindowLoad() { communicationsPanel.addEventListener('sendAnalyzerChange', handleChangeSendAnalyzer); messagePanel.addEventListener('messageChange', configurationChanged); - messagePanel.addEventListener('send', handleSendButtonClick); + messagePanel.addEventListener('sendClick', handleSendButtonClick); + messagePanel.addEventListener('stopClick', handleStopButtonClick); frequencyPanel.addEventListener('minimumFrequencyChange', configurationChanged); frequencyPanel.addEventListener('maximumFrequencyChange', configurationChanged); @@ -196,14 +205,14 @@ function handleWindowLoad() { frequencyGraphPanel.setDurationMilliseconds(graphConfigurationPanel.getDurationMilliseconds()); }); + receivePanel.addEventListener('start', handleReceivePanelStart); + receivePanel.addEventListener('receive', handleReceivePanelReceive); + receivePanel.addEventListener('end', handleReceivePanelEnd); + // Setup audio sender AudioSender.addEventListener('begin', () => messagePanel.setSendButtonText('Stop')); AudioSender.addEventListener('send', handleAudioSenderSend); AudioSender.addEventListener('end', () => messagePanel.setSendButtonText('Send')); - // Setup audio receiver - AudioReceiver.addEventListener('begin', handleAudioReceiverStart); - AudioReceiver.addEventListener('receive', handleAudioReceiverReceive); - AudioReceiver.addEventListener('end', handleAudioReceiverEnd); // Setup stream manager StreamManager.addEventListener('change', handleStreamManagerChange); @@ -249,24 +258,23 @@ function updateAudioSender() { waveForm: signalPanel.getWaveform() }); } -const handleAudioReceiverStart = ({signalStart}) => { - StreamManager.reset(); +const handleReceivePanelStart = ({signalStart}) => { frequencyGraphPanel.setSignalStart(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 segmentIndex = PacketUtils.getPacketSegmentIndex(signalStart, indexStart); // Getting all 1's for only the first 5 segments? // console.log(signalIndex, packetIndex, segmentIndex, bits.join('')); StreamManager.addBits(packetIndex, segmentIndex, bits); } -const handleAudioReceiverEnd = (e) => { +const handleReceivePanelEnd = (e) => { frequencyGraphPanel.setSignalEnd(e.signalEnd); if(graphConfigurationPanel.getPauseAfterEnd()) { stopGraph(); frequencyGraphPanel.stop(); - AudioSender.stop(); + receivePanel.setIsOnline(false); } } function updateAudioReceiver() { @@ -407,10 +415,6 @@ function sendBytes(bytes) { return; } - AudioReceiver.reset(); - StreamManager.reset(); - frequencyGraphPanel.start(); - const bits = bytesToBits(bytes); SENT_ORIGINAL_TEXT = bytesToText(bytes); @@ -553,14 +557,14 @@ function padArray(values, length, value) { function stopGraph() { PAUSE = true; - AudioReceiver.stop(); + receivePanel.setIsOnline(false); } function resumeGraph() { if(microphonePanel.getListening()) { if(PAUSE) { PAUSE = false; - AudioReceiver.start(); + receivePanel.setIsOnline(true); resetGraphData(); requestAnimationFrame(drawFrequencyData); } else { @@ -610,7 +614,7 @@ function handleStreamManagerChange() { const correctedDecodedBits = allDecodedBits.filter((b, i) => i < decodedBitCount && b === SENT_ORIGINAL_BITS[i]).length; let percentReceived = StreamManager.sumTotalBits() / totalBitsTransferring; - messagePanel.setProgress(percentReceived); + receivePanel.setProgress(percentReceived); bitsReceivedPanel.setCode(allRawBits .reduce( @@ -663,11 +667,11 @@ function handleStreamManagerChange() { const receivedText = bytesToText(bytes); if(messagePanel.getDataType() === 'text') { - messagePanel.setReceived( + receivePanel.setReceivedHtml( receivedText.split('').reduce(textExpectorReducer(SENT_ORIGINAL_TEXT), '') ); } else { - messagePanel.setReceivedBytes(bytes); + receivePanel.setReceivedBytes(bytes); } } function parseTotalBitsTransferring() { @@ -840,12 +844,11 @@ function getAudioContext() { } return audioContext; } +function handleStopButtonClick() { + AudioSender.stop(); +} function handleSendButtonClick() { - if(messagePanel.getSendButtonText() === 'Stop') { - AudioSender.stop(); - } else { - sendBytes(messagePanel.getMessageBytes()); - } + sendBytes(messagePanel.getMessageBytes()); } function getAnalyser() { if(analyser) return analyser;