move sample interleaving to audio sender/receiver
This commit is contained in:
@@ -1,6 +1,11 @@
|
|||||||
import Dispatcher from "./Dispatcher";
|
import Dispatcher from "./Dispatcher";
|
||||||
|
|
||||||
const dispatcher = new Dispatcher('AudioReceiver', ['begin', 'end', 'receive']);
|
const dispatcher = new Dispatcher('AudioReceiver', ['begin', 'end', 'receive']);
|
||||||
|
const noEncoding = bits => bits;
|
||||||
|
let SAMPLE_ENCODING = {
|
||||||
|
encode: noEncoding,
|
||||||
|
decode: noEncoding
|
||||||
|
};
|
||||||
|
|
||||||
let sampleIntervalIds = [];
|
let sampleIntervalIds = [];
|
||||||
let SAMPLE_LAST_COLLECTED = 0;
|
let SAMPLE_LAST_COLLECTED = 0;
|
||||||
@@ -26,6 +31,11 @@ const setTimeoutMilliseconds = (milliseconds) => {
|
|||||||
signalTimeoutId = window.setTimeout(handleSignalLost, SIGNAL_TIMEOUT_MS, LAST_SIGNAL_BEFORE_TIMEOUT);
|
signalTimeoutId = window.setTimeout(handleSignalLost, SIGNAL_TIMEOUT_MS, LAST_SIGNAL_BEFORE_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export const setSampleEncoding = ({ encode, decode } = {}) => {
|
||||||
|
SAMPLE_ENCODING.encode = encode ?? noEncoding;
|
||||||
|
SAMPLE_ENCODING.decode = decode ?? noEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
const changeConfiguration = ({
|
const changeConfiguration = ({
|
||||||
fskSets,
|
fskSets,
|
||||||
signalIntervalMs,
|
signalIntervalMs,
|
||||||
@@ -154,7 +164,8 @@ function processSample({ signalStart, index }) {
|
|||||||
const samples = SAMPLES.filter(isSegment);
|
const samples = SAMPLES.filter(isSegment);
|
||||||
if(samples.length === 0) return;
|
if(samples.length === 0) return;
|
||||||
|
|
||||||
let bits = evaluateBits(samples);
|
let bits = SAMPLE_ENCODING.decode(evaluateBits(samples));
|
||||||
|
|
||||||
const { start, end } = samples[0];
|
const { start, end } = samples[0];
|
||||||
dispatcher.emit('receive', {
|
dispatcher.emit('receive', {
|
||||||
signalStart,
|
signalStart,
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import Dispatcher from "./Dispatcher";
|
import Dispatcher from "./Dispatcher";
|
||||||
|
|
||||||
const dispatcher = new Dispatcher('AudioSender', ['begin', 'end', 'send']);
|
const dispatcher = new Dispatcher('AudioSender', ['begin', 'end', 'send']);
|
||||||
|
const noEncoding = bits => bits;
|
||||||
|
let SAMPLE_ENCODING = {
|
||||||
|
encode: noEncoding,
|
||||||
|
decode: noEncoding
|
||||||
|
};
|
||||||
|
|
||||||
let audioContext;
|
let audioContext;
|
||||||
let CHANNELS = [];
|
let CHANNELS = [];
|
||||||
@@ -15,6 +20,11 @@ let stopOscillatorsTimeoutId;
|
|||||||
export const addEventListener = dispatcher.addListener;
|
export const addEventListener = dispatcher.addListener;
|
||||||
export const removeEventListener = dispatcher.removeListener;
|
export const removeEventListener = dispatcher.removeListener;
|
||||||
|
|
||||||
|
export const setSampleEncoding = ({ encode, decode } = {}) => {
|
||||||
|
SAMPLE_ENCODING.encode = encode ?? noEncoding;
|
||||||
|
SAMPLE_ENCODING.decode = decode ?? noEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
export const changeConfiguration = ({
|
export const changeConfiguration = ({
|
||||||
channels,
|
channels,
|
||||||
destination,
|
destination,
|
||||||
@@ -65,9 +75,17 @@ function getOscillators() {
|
|||||||
return CHANNEL_OSCILLATORS;
|
return CHANNEL_OSCILLATORS;
|
||||||
}
|
}
|
||||||
export function send(bits, startSeconds) {
|
export function send(bits, startSeconds) {
|
||||||
|
const fskPairs = getChannels();
|
||||||
|
if(bits.length < fskPairs.length) {
|
||||||
|
throw new Error(`Expected ${fskPairs.length} bits. Received ${bits.length}.`)
|
||||||
|
bits.push(...new Array(fskPairs.length - bits.length).fill(0));
|
||||||
|
} else if(bits.length > fskPairs.length) {
|
||||||
|
throw new Error(`Invalid bit length. Expected ${fskPairs.length}, but got ${bits.lengt}`);
|
||||||
|
}
|
||||||
|
bits = SAMPLE_ENCODING.encode(bits);
|
||||||
const oscillators = getOscillators();
|
const oscillators = getOscillators();
|
||||||
const sentBits = [];
|
const sentBits = [];
|
||||||
getChannels().forEach((channel, i) => {
|
fskPairs.forEach((fsk, i) => {
|
||||||
// send missing bits as zero
|
// send missing bits as zero
|
||||||
const isHigh = bits[i] ?? 0;
|
const isHigh = bits[i] ?? 0;
|
||||||
sentBits.push(isHigh);
|
sentBits.push(isHigh);
|
||||||
@@ -75,7 +93,7 @@ export function send(bits, startSeconds) {
|
|||||||
// already at correct frequency
|
// already at correct frequency
|
||||||
if(oscillator.on === isHigh) return;
|
if(oscillator.on === isHigh) return;
|
||||||
oscillator.on = isHigh;
|
oscillator.on = isHigh;
|
||||||
const hz = channel[isHigh ? 1 : 0];
|
const hz = fsk[isHigh ? 1 : 0];
|
||||||
oscillator.frequency.setValueAtTime(hz, startSeconds);
|
oscillator.frequency.setValueAtTime(hz, startSeconds);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ let BITS_PER_PACKET = 0;
|
|||||||
let SEGMENTS_PER_PACKET = 0;
|
let SEGMENTS_PER_PACKET = 0;
|
||||||
let BITS_PER_SEGMENT = 0;
|
let BITS_PER_SEGMENT = 0;
|
||||||
let STREAM_HEADERS = [];
|
let STREAM_HEADERS = [];
|
||||||
let SEGMENT_ENCODING = {
|
|
||||||
encode: bits => bits,
|
|
||||||
decode: bits => bits
|
|
||||||
};
|
|
||||||
let PACKET_ENCODING = {
|
let PACKET_ENCODING = {
|
||||||
encode: bits => bits,
|
encode: bits => bits,
|
||||||
decode: bits => bits
|
decode: bits => bits
|
||||||
@@ -111,10 +107,6 @@ export const changeConfiguration = ({
|
|||||||
STREAM_HEADERS = streamHeaders;
|
STREAM_HEADERS = streamHeaders;
|
||||||
}
|
}
|
||||||
const noEncoding = bits => bits;
|
const noEncoding = bits => bits;
|
||||||
export const setSegmentEncoding = ({ encode, decode } = {}) => {
|
|
||||||
SEGMENT_ENCODING.encode = encode ?? noEncoding;
|
|
||||||
SEGMENT_ENCODING.decode = decode ?? noEncoding;
|
|
||||||
}
|
|
||||||
export const setPacketEncoding = ({ encode, decode } = {}) => {
|
export const setPacketEncoding = ({ encode, decode } = {}) => {
|
||||||
PACKET_ENCODING.encode = encode ?? noEncoding;
|
PACKET_ENCODING.encode = encode ?? noEncoding;
|
||||||
PACKET_ENCODING.decode = decode ?? noEncoding;
|
PACKET_ENCODING.decode = decode ?? noEncoding;
|
||||||
@@ -171,7 +163,6 @@ export const getPacketBits = (packetIndex, defaultBit = 0) => {
|
|||||||
const packet = BITS[packetIndex] ?? [];
|
const packet = BITS[packetIndex] ?? [];
|
||||||
for(let segmentIndex = 0; segmentIndex < SEGMENTS_PER_PACKET; segmentIndex++) {
|
for(let segmentIndex = 0; segmentIndex < SEGMENTS_PER_PACKET; segmentIndex++) {
|
||||||
let segment = packet[segmentIndex] ?? [];
|
let segment = packet[segmentIndex] ?? [];
|
||||||
segment = SEGMENT_ENCODING.decode(segment);
|
|
||||||
for(let bitIndex = 0; bitIndex < BITS_PER_SEGMENT; bitIndex++) {
|
for(let bitIndex = 0; bitIndex < BITS_PER_SEGMENT; bitIndex++) {
|
||||||
const bit = segment[bitIndex];
|
const bit = segment[bitIndex];
|
||||||
bits.push(bit ?? defaultBit);
|
bits.push(bit ?? defaultBit);
|
||||||
|
|||||||
31
index.js
31
index.js
@@ -145,8 +145,6 @@ function handleWindowLoad() {
|
|||||||
speedPanel.setPacketizationBitsPerSecond(0);
|
speedPanel.setPacketizationBitsPerSecond(0);
|
||||||
speedPanel.setTransferDurationMilliseconds(0);
|
speedPanel.setTransferDurationMilliseconds(0);
|
||||||
|
|
||||||
AudioReceiver.setTimeoutMilliseconds(signalPanel.getTimeoutMilliseconds());
|
|
||||||
|
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
communicationsPanel.addEventListener('sendSpeakersChange', handleChangeSendSpeakers);
|
communicationsPanel.addEventListener('sendSpeakersChange', handleChangeSendSpeakers);
|
||||||
@@ -184,9 +182,9 @@ function handleWindowLoad() {
|
|||||||
|
|
||||||
packetizationPanel.addEventListener('sizePowerChange', configurationChanged);
|
packetizationPanel.addEventListener('sizePowerChange', configurationChanged);
|
||||||
packetizationPanel.addEventListener('interleavingChange', () => {
|
packetizationPanel.addEventListener('interleavingChange', () => {
|
||||||
StreamManager.setSegmentEncoding(
|
const encoding = packetizationPanel.getInterleaving() ? InterleaverEncoding : undefined;
|
||||||
packetizationPanel.getInterleaving() ? InterleaverEncoding : undefined
|
AudioReceiver.setSampleEncoding(encoding);
|
||||||
);
|
AudioSender.setSampleEncoding(encoding)
|
||||||
configurationChanged();
|
configurationChanged();
|
||||||
});
|
});
|
||||||
packetizationPanel.addEventListener('errorCorrectionChange', configurationChanged);
|
packetizationPanel.addEventListener('errorCorrectionChange', configurationChanged);
|
||||||
@@ -196,6 +194,11 @@ function handleWindowLoad() {
|
|||||||
packetizationPanel.addEventListener('packetCrcChange', configurationChanged);
|
packetizationPanel.addEventListener('packetCrcChange', configurationChanged);
|
||||||
packetizationPanel.addEventListener('sequenceNumberPowerChange', configurationChanged);
|
packetizationPanel.addEventListener('sequenceNumberPowerChange', configurationChanged);
|
||||||
|
|
||||||
|
AudioReceiver.setTimeoutMilliseconds(signalPanel.getTimeoutMilliseconds());
|
||||||
|
const encoding = packetizationPanel.getInterleaving() ? InterleaverEncoding : undefined;
|
||||||
|
AudioReceiver.setSampleEncoding(encoding);
|
||||||
|
AudioSender.setSampleEncoding(encoding)
|
||||||
|
|
||||||
availableFskPairsPanel.addEventListener('change', (event) => {
|
availableFskPairsPanel.addEventListener('change', (event) => {
|
||||||
frequencyGraphPanel.setFskPairs(event.selected);
|
frequencyGraphPanel.setFskPairs(event.selected);
|
||||||
configurationChanged();
|
configurationChanged();
|
||||||
@@ -477,21 +480,23 @@ function sendBytes(bytes) {
|
|||||||
|
|
||||||
const packer = PacketUtils.pack(bits);
|
const packer = PacketUtils.pack(bits);
|
||||||
|
|
||||||
|
try {
|
||||||
AudioSender.beginAt(startSeconds);
|
AudioSender.beginAt(startSeconds);
|
||||||
// send all packets
|
// send all packets
|
||||||
for(let i = 0; i < packetCount; i++) {
|
for(let i = 0; i < packetCount; i++) {
|
||||||
let packet = packer.getBits(i);
|
let packet = packer.getBits(i);
|
||||||
SENT_ENCODED_BITS.push(...packet);
|
|
||||||
if(packet.length > packetBitCount) {
|
if(packet.length > packetBitCount) {
|
||||||
console.error('Too many bits in the packet. tried to send %s, limited to %s', packet.length, packetBitCount);
|
throw new Error(`Too many bits in the packet. tried to send ${packet.length}, limited to ${packetBitCount}`);
|
||||||
AudioSender.stop();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
packet = padArray(packet, packetBitCount, 0);
|
packet.push(...new Array(packetBitCount - packet.length).fill(0));
|
||||||
sendPacket(packet, startSeconds + (i * packetDurationSeconds));
|
sendPacket(packet, startSeconds + (i * packetDurationSeconds));
|
||||||
}
|
}
|
||||||
AudioSender.stopAt(startSeconds + totalDurationSeconds);
|
AudioSender.stopAt(startSeconds + totalDurationSeconds);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
AudioSender.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
showSentBits();
|
showSentBits();
|
||||||
|
|
||||||
// start the graph moving again
|
// start the graph moving again
|
||||||
@@ -531,8 +536,8 @@ function sendPacket(bits, packetStartSeconds) {
|
|||||||
const segmentDurationSeconds = PacketUtils.getSegmentDurationSeconds();
|
const segmentDurationSeconds = PacketUtils.getSegmentDurationSeconds();
|
||||||
for(let i = 0; i < bitCount; i += channelCount) {
|
for(let i = 0; i < bitCount; i += channelCount) {
|
||||||
let segmentBits = bits.slice(i, i + channelCount);
|
let segmentBits = bits.slice(i, i + channelCount);
|
||||||
if(packetizationPanel.getInterleaving()) {
|
if(segmentBits.length !== channelCount) {
|
||||||
segmentBits = InterleaverEncoding.encode(segmentBits);
|
segmentBits.push(...new Array(channelCount - segmentBits.length).fill(0))
|
||||||
}
|
}
|
||||||
const segmentIndex = Math.floor(i / channelCount);
|
const segmentIndex = Math.floor(i / channelCount);
|
||||||
var offsetSeconds = segmentIndex * segmentDurationSeconds;
|
var offsetSeconds = segmentIndex * segmentDurationSeconds;
|
||||||
|
|||||||
Reference in New Issue
Block a user