我有一个8位数据的位缓冲区,后跟1个奇偶校验位。这种模式重演。缓冲区当前存储为八位字节数组。
示例(p是奇偶校验位):
0001 0001 p000 0100 0p00 0001 00p01 1100 ...
应该成为
0001 0001 0000 1000 0000 0100 0111 00 ...
基本上,我需要剥离每第9位才能获得数据位。我怎样才能做到这一点?
这与another question在某个时候提到的问题有关。
这是在32位机器上,因此相关问题的解决方案可能不适用。最大可能的比特数是45,即5个数据八位字节
这是我到目前为止所尝试的。我创建了一个“布尔”数组,并根据八位字节的位集将这些位添加到数组中。然后我查看数组的每个第九个索引并通过它。然后将剩余的数组向下移动一个索引。然后我只剩下数据位。我在想可能有更好的方法来做到这一点。
答案 0 :(得分:2)
在伪代码中(因为你没有提供任何证明你已尝试过的东西),为了简单起见,我可能会这样做:
这让你“担心”读取字节,这不再是一个有用的操作,因为你的字节与想要丢弃的位交错。
答案 1 :(得分:2)
你有一个位数组的想法是好的。只需用32位数字(缓冲区)实现位数组。
从缓冲区中间删除一位:
void remove_bit(uint32_t* buffer, int* occupancy, int pos)
{
assert(*occupancy > 0);
uint32_t high_half = *buffer >> pos >> 1;
uint32_t low_half = *buffer << (32 - pos) >> (32 - pos);
*buffer = high_half | low_half;
--*occupancy;
}
向缓冲区添加一个字节:
void add_byte(uint32_t* buffer, int* occupancy, uint8_t byte)
{
assert(*occupancy <= 24);
*buffer = (*buffer << 8) | byte;
*occupancy += 8;
}
从缓冲区中删除一个字节:
uint8_t remove_byte(uint32_t* buffer, int* occupancy)
{
uint8_t result = *buffer >> (*occupancy - 8);
assert(*occupancy >= 8);
*occupancy -= 8;
return result;
}
您必须安排调用,以便缓冲区永不溢出。例如:
buffer = 0;
occupancy = 0;
add_byte(buffer, occupancy, *input++);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 7);
*output++ = remove_byte(buffer, occupancy);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 6);
*output++ = remove_byte(buffer, occupancy);
... (there are only 6 input bytes, so this should be easy)
答案 2 :(得分:1)
我编写了辅助函数来读取未对齐的位缓冲区(这适用于AVC流,请参阅原始源here)。代码本身就是GPL,我在这里粘贴了有趣的(修改过的)位。
typedef struct bit_buffer_ {
uint8_t * start;
size_t size;
uint8_t * current;
uint8_t read_bits;
} bit_buffer;
/* reads one bit and returns its value as a 8-bit integer */
uint8_t get_bit(bit_buffer * bb) {
uint8_t ret;
ret = (*(bb->current) >> (7 - bb->read_bits)) & 0x1;
if (bb->read_bits == 7) {
bb->read_bits = 0;
bb->current++;
}
else {
bb->read_bits++;
}
return ret;
}
/* reads up to 32 bits and returns the value as a 32-bit integer */
uint32_t get_bits(bit_buffer * bb, size_t nbits) {
uint32_t i, ret;
ret = 0;
for (i = 0; i < nbits; i++) {
ret = (ret << 1) + get_bit(bb);
}
return ret;
}
您可以使用以下结构:
uint_8 * buffer;
size_t buffer_size;
/* assumes buffer points to your data */
bit_buffer bb;
bb.start = buffer;
bb.size = buffer_size;
bb.current = buffer;
bb.read_bits = 0;
uint32_t value = get_bits(&bb, 8);
uint8_t parity = get_bit(&bb);
uint32_t value2 = get_bits(&bb, 8);
uint8_t parity2 = get_bit(&bb);
/* etc */
我必须强调这段代码是完全可靠的,必须实现正确的绑定检查,但它在我的用例中工作正常。
我把它作为练习留给你来实现一个适当的位缓冲读取器,用它作为灵感。
答案 3 :(得分:1)
这也有效
void RemoveParity(unsigned char buffer[], int size)
{
int offset = 0;
int j = 0;
for(int i = 1; i + j < size; i++)
{
if (offset == 0)
{
printf("%u\n", buffer[i + j - 1]);
}
else
{
unsigned char left = buffer[i + j - 1] << offset;
unsigned char right = buffer[i + j] >> (8 - offset);
printf("%u\n", (unsigned char)(left | right));
}
offset++;
if (offset == 8)
{
offset = 0;
j++; // advance buffer (8 parity bit consumed)
}
}
}