Attempting to use an external library to handle bitstreams. Isn't going the grreatest.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "bitstream/bitstream.h"
|
||||
|
||||
/**
|
||||
* @class FECEncoder
|
||||
@@ -30,26 +30,30 @@ public:
|
||||
* @param data The input BitStream to be encoded.
|
||||
* @return The encoded BitStream.
|
||||
*/
|
||||
BitStream encode(const BitStream& data) {
|
||||
BitStream input_data(data);
|
||||
BitStream output_data;
|
||||
void encode(bitstream::growing_bit_writer<std::vector<uint8_t>>& output_data, bitstream::fixed_bit_reader& input_data) {
|
||||
std::vector<uint8_t> intermediate_buffer;
|
||||
bitstream::growing_bit_writer<std::vector<uint8_t>> intermediate_data(intermediate_buffer);
|
||||
|
||||
while (input_data.get_remaining_bits() > 0) {
|
||||
uint32_t bit;
|
||||
input_data.serialize_bits(bit, 1);
|
||||
|
||||
while (input_data.hasNext()) {
|
||||
uint8_t bit = input_data.getNextBit();
|
||||
// Shift the input bit into the shift register
|
||||
shift_register = ((shift_register << 1) | bit) & 0x7F;
|
||||
|
||||
// Calculate T1 and T2 using the generator polynomials
|
||||
uint8_t t1 = calculateT1();
|
||||
uint8_t t2 = calculateT2();
|
||||
uint32_t t1 = calculateT1();
|
||||
uint32_t t2 = calculateT2();
|
||||
|
||||
// Append T1 and T2 to the encoded data
|
||||
output_data.putBit(t1);
|
||||
output_data.putBit(t2);
|
||||
intermediate_data.serialize_bits(t1, 1);
|
||||
intermediate_data.serialize_bits(t2, 1);
|
||||
}
|
||||
|
||||
bitstream::fixed_bit_reader intermediate_reader(intermediate_buffer.data(), intermediate_data.get_num_bits_serialized());
|
||||
|
||||
// Apply repetition or puncturing based on baud rate and operation mode
|
||||
return adjustRate(output_data);
|
||||
return adjustRate(output_data, intermediate_reader);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -62,7 +66,9 @@ private:
|
||||
* @return The calculated T1 bit.
|
||||
*/
|
||||
uint8_t calculateT1() {
|
||||
return (shift_register >> 6) ^ ((shift_register >> 4) & 0x01) ^ ((shift_register >> 3) & 0x01) ^ ((shift_register >> 1) & 0x01) ^ (shift_register & 0x01);
|
||||
return (shift_register >> 6) ^ ((shift_register >> 4) & 0x01) ^
|
||||
((shift_register >> 3) & 0x01) ^ ((shift_register >> 1) & 0x01) ^
|
||||
(shift_register & 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,7 +76,9 @@ private:
|
||||
* @return The calculated T2 bit.
|
||||
*/
|
||||
uint8_t calculateT2() {
|
||||
return (shift_register >> 6) ^ ((shift_register >> 5) & 0x01) ^ ((shift_register >> 4) & 0x01) ^ ((shift_register >> 1) & 0x01) ^ (shift_register & 0x01);
|
||||
return (shift_register >> 6) ^ ((shift_register >> 5) & 0x01) ^
|
||||
((shift_register >> 4) & 0x01) ^ ((shift_register >> 1) & 0x01) ^
|
||||
(shift_register & 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,32 +86,46 @@ private:
|
||||
* @param encoded_data The encoded BitStream to be adjusted.
|
||||
* @return The adjusted BitStream.
|
||||
*/
|
||||
BitStream adjustRate(const BitStream& encoded_data) {
|
||||
BitStream adjusted_data;
|
||||
void adjustRate(bitstream::growing_bit_writer<std::vector<uint8_t>>& adjusted_data, bitstream::fixed_bit_reader& encoded_data) {
|
||||
size_t repetition_factor = getRepetitionFactor();
|
||||
|
||||
if ((baud_rate == 300 || baud_rate == 150 || baud_rate == 75) && is_frequency_hopping) {
|
||||
// Repetition for frequency-hopping operation at lower baud rates
|
||||
size_t repetition_factor = (baud_rate == 300) ? 2 : (baud_rate == 150) ? 4 : 8;
|
||||
for (size_t i = 0; i < encoded_data.getMaxBitIndex(); i += 2) {
|
||||
for (size_t j = 0; j < repetition_factor; j++) {
|
||||
adjusted_data.putBit(encoded_data.getBitVal(i));
|
||||
adjusted_data.putBit(encoded_data.getBitVal(i + 1));
|
||||
}
|
||||
if (repetition_factor == 1) {
|
||||
while (encoded_data.get_remaining_bits() > 0) {
|
||||
uint32_t bit;
|
||||
encoded_data.serialize_bits(bit, 1);
|
||||
adjusted_data.serialize_bits(bit, 1);
|
||||
}
|
||||
} else if ((baud_rate == 300 || baud_rate == 150) && !is_frequency_hopping) {
|
||||
// Repetition for fixed-frequency operation at lower baud rates
|
||||
size_t repetition_factor = (baud_rate == 300) ? 2 : 4;
|
||||
for (size_t i = 0; i < encoded_data.getMaxBitIndex(); i += 2) {
|
||||
for (size_t j = 0; j < repetition_factor; j++) {
|
||||
adjusted_data.putBit(encoded_data.getBitVal(i));
|
||||
adjusted_data.putBit(encoded_data.getBitVal(i + 1));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
adjusted_data = encoded_data;
|
||||
return;
|
||||
}
|
||||
|
||||
return adjusted_data;
|
||||
while (encoded_data.get_remaining_bits() >= 2) {
|
||||
uint32_t t1, t2;
|
||||
encoded_data.serialize_bits(t1, 1);
|
||||
encoded_data.serialize_bits(t2, 1);
|
||||
|
||||
for (size_t j = 0; j < repetition_factor; j++) {
|
||||
adjusted_data.serialize_bits(t1, 1);
|
||||
adjusted_data.serialize_bits(t2, 1);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t getRepetitionFactor() const {
|
||||
if (is_frequency_hopping) {
|
||||
switch (baud_rate) {
|
||||
case 300: return 2;
|
||||
case 150: return 4;
|
||||
case 75: return 8;
|
||||
default: return 1;
|
||||
}
|
||||
} else {
|
||||
switch (baud_rate) {
|
||||
case 300: return 2;
|
||||
case 150: return 4;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "bitstream/bitstream.h"
|
||||
|
||||
/**
|
||||
* @class Interleaver
|
||||
@@ -34,30 +34,43 @@ public:
|
||||
* @param input_data The input BitStream to be interleaved.
|
||||
* @return A new BitStream containing the interleaved data.
|
||||
*/
|
||||
std::vector<uint8_t> interleaveStream(const BitStream& input_data) {
|
||||
BitStream data = input_data;
|
||||
BitStream interleaved_data;
|
||||
std::vector<uint8_t> interleaveStream(bitstream::fixed_bit_reader& input_data) {
|
||||
std::vector<uint8_t> interleaved_buffer;
|
||||
|
||||
bitstream::growing_bit_writer<std::vector<uint8_t>> interleaved_data(interleaved_buffer);
|
||||
|
||||
size_t chunk_size = rows * columns;
|
||||
size_t input_index = 0;
|
||||
|
||||
while (input_index < data.getMaxBitIndex()) {
|
||||
size_t end_index = std::min(input_index + chunk_size, data.getMaxBitIndex());
|
||||
BitStream chunk = data.getSubStream(input_index, end_index);
|
||||
if (chunk.getMaxBitIndex() > rows * columns) {
|
||||
throw std::invalid_argument("Input data exceeds interleaver matrix size in loadChunk()");
|
||||
std::vector<uint8_t> chunk_data((chunk_size + 7) / 8, 0);
|
||||
|
||||
while (input_data.get_remaining_bits() >= chunk_size) {
|
||||
std::fill(chunk_data.begin(), chunk_data.end(), 0);
|
||||
|
||||
if (!input_data.serialize_bytes(chunk_data.data(), chunk_size)) {
|
||||
throw std::runtime_error("Failed to serialize chunk from input data");
|
||||
}
|
||||
BitStream interleaved_chunk = interleaveChunk(chunk);
|
||||
interleaved_data += interleaved_chunk;
|
||||
input_index = end_index;
|
||||
|
||||
bitstream::fixed_bit_reader chunk_reader(chunk_data.data(), chunk_size);
|
||||
|
||||
interleaveChunk(interleaved_data, chunk_reader);
|
||||
}
|
||||
|
||||
// Apply puncturing for 2400 bps in frequency-hopping mode (Rate 2/3)
|
||||
if (baud_rate == 2400 && is_frequency_hopping) {
|
||||
return applyPuncturing(interleaved_data);
|
||||
std::vector<uint8_t> punctured_buffer;
|
||||
|
||||
bitstream::growing_bit_writer<std::vector<uint8_t>> punctured_writer(punctured_buffer);
|
||||
bitstream::fixed_bit_reader interleaved_reader(interleaved_buffer.data(), interleaved_buffer.size() * 8);
|
||||
|
||||
applyPuncturing(punctured_writer, interleaved_reader);
|
||||
|
||||
interleaved_buffer = punctured_buffer;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> final_interleaved_data = groupSymbols(interleaved_data);
|
||||
return final_interleaved_data;
|
||||
bitstream::fixed_bit_reader final_reader(interleaved_buffer.data(), interleaved_buffer.size() * 8);
|
||||
|
||||
return groupSymbols(final_reader);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +78,7 @@ public:
|
||||
* @return The number of bits needed for a complete flush.
|
||||
*/
|
||||
size_t getFlushBits() const {
|
||||
return rows * columns;
|
||||
return (interleave_setting == 0) ? 0 : (rows * columns);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -84,21 +97,16 @@ private:
|
||||
* @param input_data The input BitStream to be grouped into symbols.
|
||||
* @return A vector of grouped symbols.
|
||||
*/
|
||||
std::vector<uint8_t> groupSymbols(BitStream& input_data) {
|
||||
std::vector<uint8_t> groupSymbols(bitstream::fixed_bit_reader& input_data) {
|
||||
std::vector<uint8_t> grouped_data;
|
||||
size_t max_index = input_data.getMaxBitIndex();
|
||||
size_t bits_per_symbol = (baud_rate == 2400) ? 3 : (baud_rate == 1200 || (baud_rate == 75 && !is_frequency_hopping)) ? 2 : 1;
|
||||
size_t current_index = 0;
|
||||
|
||||
while (input_data.get_remaining_bits() >= bits_per_symbol) {
|
||||
uint32_t symbol = 0;
|
||||
|
||||
while ((current_index + bits_per_symbol) < max_index) {
|
||||
uint8_t symbol = 0;
|
||||
input_data.serialize_bits(symbol, bits_per_symbol);
|
||||
|
||||
for (int i = 0; i < bits_per_symbol; i++) {
|
||||
symbol = (symbol << 1) | input_data.getBitVal(current_index + i);
|
||||
}
|
||||
|
||||
grouped_data.push_back(symbol);
|
||||
current_index += bits_per_symbol;
|
||||
grouped_data.push_back(static_cast<uint8_t>(symbol));
|
||||
}
|
||||
|
||||
return grouped_data;
|
||||
@@ -109,16 +117,16 @@ private:
|
||||
* @param input_data The input BitStream chunk.
|
||||
* @return A BitStream representing the interleaved chunk.
|
||||
*/
|
||||
BitStream interleaveChunk(const BitStream& input_data) {
|
||||
void interleaveChunk(bitstream::growing_bit_writer<std::vector<uint8_t>>& interleaved_writer, bitstream::fixed_bit_reader& input_data) {
|
||||
loadChunk(input_data);
|
||||
return fetchChunk();
|
||||
return fetchChunk(interleaved_writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Loads bits from the input BitStream into the interleaver matrix.
|
||||
* @param data The input BitStream to load.
|
||||
*/
|
||||
void loadChunk(const BitStream& data) {
|
||||
void loadChunk(bitstream::fixed_bit_reader& data) {
|
||||
size_t row = 0;
|
||||
size_t col = 0;
|
||||
size_t index = 0;
|
||||
@@ -127,13 +135,19 @@ private:
|
||||
|
||||
// Load bits into the matrix
|
||||
std::fill(matrix.begin(), matrix.end(), 0); // Clear previous data
|
||||
while (index < data.getMaxBitIndex() && col < columns) {
|
||||
|
||||
while (data.get_remaining_bits() > 0 && col < columns) {
|
||||
size_t matrix_idx = row * columns + col;
|
||||
if (matrix_idx >= matrix.size()) {
|
||||
throw std::out_of_range("Matrix index out of bounds in loadChunk()");
|
||||
}
|
||||
|
||||
matrix[matrix_idx] = data.getBitVal(index++);
|
||||
uint32_t bit = 0;
|
||||
if (!data.serialize_bits(bit, 1)) {
|
||||
throw std::runtime_error("Failed to read bit from chunk_reader in loadChunk()");
|
||||
}
|
||||
matrix[matrix_idx] = static_cast<uint8_t>(bit);
|
||||
|
||||
row = (row + row_increment) % rows;
|
||||
|
||||
if (row == 0) {
|
||||
@@ -146,21 +160,23 @@ private:
|
||||
* @brief Fetches bits from the interleaver matrix in the interleaved order.
|
||||
* @return A BitStream containing the fetched interleaved data.
|
||||
*/
|
||||
BitStream fetchChunk() {
|
||||
BitStream fetched_data;
|
||||
void fetchChunk(bitstream::growing_bit_writer<std::vector<uint8_t>>& interleaved_writer) {
|
||||
size_t row = 0;
|
||||
size_t col = 0;
|
||||
|
||||
size_t column_decrement = (baud_rate == 75 && interleave_setting == 2) ? 7 : 17;
|
||||
|
||||
// Fetch bits from the matrix
|
||||
while (fetched_data.getMaxBitIndex() < rows * columns) {
|
||||
for (size_t i = 0; i < rows * columns; i++) {
|
||||
size_t matrix_idx = row * columns + col;
|
||||
if (matrix_idx >= matrix.size()) {
|
||||
throw std::out_of_range("Matrix index out of bounds in fetchChunk()");
|
||||
}
|
||||
|
||||
fetched_data.putBit(matrix[matrix_idx]);
|
||||
uint32_t bit = static_cast<uint32_t>(matrix[matrix_idx]);
|
||||
if (!interleaved_writer.serialize_bits(bit, 1)) {
|
||||
throw std::runtime_error("Failed to write bit to interleaved_writer in fetchChunk()");
|
||||
}
|
||||
|
||||
row++;
|
||||
|
||||
if (row == rows) {
|
||||
@@ -170,8 +186,6 @@ private:
|
||||
col = (col + columns - column_decrement) % columns;
|
||||
}
|
||||
}
|
||||
|
||||
return fetched_data;
|
||||
}
|
||||
|
||||
|
||||
@@ -210,14 +224,18 @@ private:
|
||||
* @param interleaved_data The interleaved data to be punctured.
|
||||
* @return A BitStream containing punctured data.
|
||||
*/
|
||||
BitStream applyPuncturing(const BitStream& interleaved_data) {
|
||||
BitStream punctured_data;
|
||||
for (size_t i = 0; i < interleaved_data.getMaxBitIndex(); i++) {
|
||||
if ((i % 4) != 1) { // Skip every fourth bit (the second value of T2)
|
||||
punctured_data.putBit(interleaved_data.getBitVal(i));
|
||||
void applyPuncturing(bitstream::growing_bit_writer<std::vector<uint8_t>>& punctured_data, bitstream::fixed_bit_reader& interleaved_data) {
|
||||
size_t bit_index = 0;
|
||||
|
||||
while (interleaved_data.get_remaining_bits() > 0) {
|
||||
uint32_t bit = 0;
|
||||
interleaved_data.serialize_bits(bit, 1);
|
||||
|
||||
if ((bit_index % 4) != 3) {
|
||||
punctured_data.serialize_bits(bit, 1);
|
||||
}
|
||||
bit_index++;
|
||||
}
|
||||
return punctured_data;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "bitstream/bitstream.h"
|
||||
#include "FECEncoder.h"
|
||||
#include "Interleaver.h"
|
||||
#include "MGDDecoder.h"
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
* @param data The input data stream to be transmitted. The `is_voice` parameter controls whether the modem treats it as binary file data,
|
||||
* or a binary stream from the MELPe (or other) voice codec.
|
||||
*/
|
||||
ModemController(const size_t _baud_rate, const bool _is_voice, const bool _is_frequency_hopping, const size_t _interleave_setting, BitStream _data)
|
||||
ModemController(const size_t _baud_rate, const bool _is_voice, const bool _is_frequency_hopping, const size_t _interleave_setting)
|
||||
: baud_rate(_baud_rate),
|
||||
is_voice(_is_voice),
|
||||
is_frequency_hopping(_is_frequency_hopping),
|
||||
@@ -49,7 +49,6 @@ public:
|
||||
scrambler(),
|
||||
fec_encoder(baud_rate, is_frequency_hopping),
|
||||
interleaver(baud_rate, interleave_setting, is_frequency_hopping),
|
||||
input_data(std::move(_data)),
|
||||
mgd_decoder(baud_rate, is_frequency_hopping),
|
||||
modulator(baud_rate, 48000, 0.5, is_frequency_hopping) {}
|
||||
|
||||
@@ -58,36 +57,47 @@ public:
|
||||
* @return The scrambled data ready for modulation.
|
||||
* @note The modulated signal is generated internally but is intended to be handled externally.
|
||||
*/
|
||||
std::vector<int16_t> transmit() {
|
||||
// Step 1: Append EOM Symbols
|
||||
BitStream eom_appended_data = appendEOMSymbols(input_data);
|
||||
std::vector<int16_t> transmit(bitstream::fixed_bit_reader& input_data) {
|
||||
// Step 1: Append EOM Symbols using a uint32_t aligned output buffer
|
||||
std::vector<uint8_t> output_buffer;
|
||||
bitstream::growing_bit_writer<std::vector<uint8_t>> output_writer(output_buffer);
|
||||
appendEOMSymbols(output_writer, input_data);
|
||||
|
||||
// Step 2: Handle Baud Rate Specific Encoding
|
||||
std::vector<uint8_t> processed_data;
|
||||
if (baud_rate == 4800) {
|
||||
processed_data = splitTribitSymbols(eom_appended_data);
|
||||
// For 4800 baud, perform tribit symbol splitting
|
||||
bitstream::fixed_bit_reader eom_appended_reader(output_buffer.data(), output_writer.get_num_bits_serialized());
|
||||
processed_data = splitTribitSymbols(eom_appended_reader);
|
||||
} else {
|
||||
// Step 2: FEC Encoding
|
||||
BitStream fec_encoded_data = fec_encoder.encode(eom_appended_data);
|
||||
// Step 3: FEC Encoding
|
||||
bitstream::fixed_bit_reader eom_appended_reader(output_buffer.data(), output_writer.get_num_bits_serialized());
|
||||
std::vector<uint8_t> fec_encoded_buffer;
|
||||
bitstream::growing_bit_writer<std::vector<uint8_t>> fec_encoded_writer(fec_encoded_buffer);
|
||||
fec_encoder.encode(fec_encoded_writer, eom_appended_reader);
|
||||
|
||||
// Step 3: Interleaving
|
||||
processed_data = interleaver.interleaveStream(fec_encoded_data);
|
||||
// Step 4: Interleaving
|
||||
bitstream::fixed_bit_reader fec_encoded_reader(fec_encoded_buffer.data(), fec_encoded_writer.get_num_bits_serialized());
|
||||
processed_data = interleaver.interleaveStream(fec_encoded_reader);
|
||||
}
|
||||
|
||||
// Step 5: MGD Decoding
|
||||
std::vector<uint8_t> mgd_decoded_data = mgd_decoder.mgdDecode(processed_data);
|
||||
|
||||
// Step 4: Symbol Formation. This function injects the sync preamble symbols. Scrambling is built-in.
|
||||
// Step 6: Symbol Formation (including sync preamble and scrambling)
|
||||
std::vector<uint8_t> symbol_stream = symbol_formation.formSymbols(mgd_decoded_data);
|
||||
|
||||
// Step 7: Modulation
|
||||
std::vector<int16_t> modulated_signal = modulator.modulate(symbol_stream);
|
||||
|
||||
return modulated_signal;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
size_t baud_rate; ///< The baud rate for the modem.
|
||||
bool is_voice; ///< Indicates if the data being transmitted is voice.
|
||||
bool is_frequency_hopping; ///< Indicates if frequency hopping is used.
|
||||
BitStream input_data; ///< The input data stream.
|
||||
size_t interleave_setting; ///< The interleave setting to be used.
|
||||
size_t sample_rate;
|
||||
|
||||
@@ -106,38 +116,38 @@ private:
|
||||
* the FEC encoder and interleaver matrices. The function calculates the number of flush bits required
|
||||
* based on the FEC and interleaver settings.
|
||||
*/
|
||||
BitStream appendEOMSymbols(const BitStream& input_data) const {
|
||||
BitStream eom_data = input_data;
|
||||
void appendEOMSymbols(bitstream::growing_bit_writer<std::vector<uint8_t>>& output_data, bitstream::fixed_bit_reader& input_data) const {
|
||||
while (input_data.get_num_bits_serialized() < input_data.get_total_bits()) {
|
||||
uint32_t value;
|
||||
uint32_t bits_to_read = std::min(32U, input_data.get_remaining_bits());
|
||||
input_data.serialize_bits(value, bits_to_read);
|
||||
output_data.serialize_bits(value, bits_to_read);
|
||||
}
|
||||
|
||||
// Append the EOM sequence (4B65A5B2 in hexadecimal)
|
||||
BitStream eom_sequence({0x4B, 0x65, 0xA5, 0xB2}, 32);
|
||||
eom_data += eom_sequence;
|
||||
uint32_t eom_sequence = 0x4B65A5B2;
|
||||
output_data.serialize_bits(eom_sequence, 32);
|
||||
|
||||
// Append additional zeros to flush the FEC encoder and interleaver
|
||||
size_t fec_flush_bits = 144; // FEC encoder flush bits
|
||||
size_t interleave_flush_bits = interleaver.getFlushBits();
|
||||
size_t total_flush_bits = fec_flush_bits + ((interleave_setting == 0) ? 0 : interleave_flush_bits);
|
||||
while ((eom_data.getMaxBitIndex() + total_flush_bits) % interleave_flush_bits)
|
||||
total_flush_bits++;
|
||||
|
||||
size_t total_bytes = (total_flush_bits + 7) / 8; // Round up to ensure we have enough bytes to handle all bits.
|
||||
BitStream flush_bits(std::vector<uint8_t>(total_bytes, 0), total_flush_bits);
|
||||
eom_data += flush_bits;
|
||||
|
||||
return eom_data;
|
||||
size_t current_bit_index = output_data.get_num_bits_serialized();
|
||||
size_t alignment_bits_needed = (interleave_flush_bits - (current_bit_index + fec_flush_bits) % interleave_flush_bits) % interleave_flush_bits;
|
||||
total_flush_bits += alignment_bits_needed;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> splitTribitSymbols(const BitStream& input_data) {
|
||||
std::vector<uint8_t> splitTribitSymbols(bitstream::fixed_bit_reader& input_data) {
|
||||
std::vector<uint8_t> return_vector;
|
||||
size_t max_index = input_data.getMaxBitIndex();
|
||||
size_t current_index = 0;
|
||||
size_t total_bits = input_data.get_total_bits();
|
||||
size_t num_bits_serialized = input_data.get_num_bits_serialized();
|
||||
|
||||
while (current_index + 2 < max_index) {
|
||||
uint8_t symbol = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
symbol = (symbol << 1) | input_data.getBitVal(current_index + i);
|
||||
}
|
||||
return_vector.push_back(symbol);
|
||||
current_index += 3;
|
||||
while (num_bits_serialized + 3 <= total_bits) {
|
||||
uint32_t symbol = 0;
|
||||
input_data.serialize_bits(symbol, 3);
|
||||
return_vector.push_back(static_cast<uint8_t>(symbol));
|
||||
num_bits_serialized = input_data.get_num_bits_serialized();
|
||||
}
|
||||
|
||||
return return_vector;
|
||||
|
||||
Reference in New Issue
Block a user