1

8ビットのデータとそれに続く1パリティビットのビットのバッファがあります。このパターンは繰り返されます。バッファは現在、オクテットの配列として格納されています。

例(pはパリティビット):

0001 0001 p000 0100 0p00 0001 00p011100..。

になる必要があります

0001 0001 0000 1000 0000 0100 011100..。

基本的に、データビットを取得するには、9ビットごとにストリップする必要があります。どうすればこれを達成できますか?

これは、いつかここで尋ねられた別の質問に関連しています。

これは32ビットマシン上にあるため、関連する質問の解決策が適用できない場合があります。可能な最大ビット数は45、つまり5データオクテットです。

これは私がこれまでに試したことです。「ブール」配列を作成し、オクテットのビットセットに基づいて配列にビットを追加しました。次に、配列の9つおきのインデックスを調べます。次に、残りの配列を1つのインデックス下に移動します。次に、データビットだけが残っています。これを行うにはもっと良い方法があるのではないかと思っていました。

4

4 に答える 4

2

擬似コードでは(何かを試した証拠を提供していないため)、簡単にするために、おそらく次のようにします。

  • データ(パリティビットを含む)をビットのストリームとして表示します
  • 読むべきビットが残っていますが:
    • 次の8ビットを読む
    • 出力に書き込む
    • もう1ビット読んで、それを破棄します

これにより、バイトの読み取りについて心配する必要がなくなります。これは、バイトが破棄するビットとインターリーブされるため、もはや有用な操作ではありません。

于 2012-06-11T10:48:34.593 に答える
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)
于 2012-06-11T10:51:47.197 に答える
1

アラインされていないビットバッファを読み取るためのヘルパー関数を作成しました(これはAVCストリーム用でした。元のソースは、こちらを参照してください)。コード自体は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 */

このコードは非常に完璧であり、適切な境界チェックを実装する必要があることを強調する必要がありますが、私のユースケースでは正常に機能します。

インスピレーションを得るためにこれを使用して適切なビットバッファリーダーを実装するための演習として残しておきます。

于 2012-06-11T10:36:06.133 に答える
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)
        }
    }
}
于 2012-06-11T13:19:35.223 に答える