Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

12 Bit Input in C++

Tags:

c++

I'm trying to write a small application that enables 12-bit input and output. I have the output working, which by using 12 bits per word is able to write the numbers 4095 to 0 to a file. Essentially, the input is supposed to read that file (hence, read the numbers 4095 to 0). The input file has to have a 32-byte buffer (i.e. fill the buffer from the file, read in chunks of 12 bits, save the excess bits, refill buffer and repeat).

To test this, I have a loop that decreases 'i' from 4095 to 0. Inside the loop I request the 12Bit input class to give me the next 12bit number. Ideally, this should be equivalent to 'i'.

I believe I have the logic working, but for some reason the loop always fails once I get to 4078. The input class returns the value 3822 rather than the required 4078, despite it using the same logic and all numbers before that working as expected. I know it's not a problem reaching the end of the buffer (I haven't implemented that part yet), because this number is located from 25.5 - 27 bytes into the buffer. I have no idea why it is failing at this point.

Code for the input class:

int IStream12Bits::fetchCode()
{
    byte data[2];
    cout << "fByteCount: " << fByteCount << endl;
    if(!(fByteCount % 3)){
        cout << "!!! START OF BYTE !!!" << endl;
        data[0] = fBuffer[fByteCount];
        data[1] = (fBuffer[fByteCount + 1] & 0xF0);
        fByteCount++;
    }
    else{
        cout << "!!! MIDDLE OF BYTE !!!" << endl;
        data[0] = fBuffer[fByteCount];
        data[1] = fBuffer[(fByteCount + 1)];
        data[0] = ((data[0] & 0x0F) << 4);
        int temp = data[1];
        temp = temp >> 4;
        data[0] = (data[0] + temp);
        data[1] = (data[1] & 0xF0);
        fByteCount += 2;
    }

    int result = 0;
    fByteIndex = 0;
    fBitIndex = 8;

    for(int i = 0; i < 12; i++){
        if(data[fByteIndex] & (1 << (fBitIndex - 1))){ //if the MSB is 1, write it to the result
            result += (1 << i);
        }
        fBitIndex--;

        //if at the end of the byte, move on to the next
        if(fBitIndex == 0){
            fByteIndex = 1;
            fBitIndex = 8;
        }
    }

    return result;
}

EDIT:

All fixed. Problem was partly in the masking, and partly in my reading. All I had to do was read directly from fBuffer, because the algorithm was such that fBitIndex would be reduced to 4 after one read (causing the next read to automatically start halfway through a byte). No need to do masking and copying of data into a separate array. Turns out I was just making it more complex for myself.

like image 412
charlemagne Avatar asked Apr 02 '11 07:04

charlemagne


1 Answers

Your code to "decode" the 12-bit values is much too complicated.

For the "even" case, you have the bits like this:

fBuffer[n] fBuffer[n+1] // var
76543210   76543210     // bit offsets
AAAAAAAA   BBBB....     // value

And you need:

result
BA9876543210
AAAAAAAABBBB

Notice that the "A"s have been moved up by 4 positions, the "B"s move down by four. Translate that to C++:

result = (fBuffer[n] << 4) + ((fBuffer[n+1] & 0xF0)>>4);

For the "odd" case:

fBuffer[n] fBuffer[n+1]
76543210   76543210     // bit offsets
....AAAA   BBBBBBBB

And you need:

result
BA9876543210
AAAABBBBBBBB

Notice that the "A"s have been moved up by 8 positions this time, and the "B"s don't need any shifting. Translate that to C++:

result = ((fBuffer[n] & 0x0F) << 8) + fBuffer[n+1];

That's all you need to decode the stream (assuming you're working with unsigned types).

There's something else that's fishy though: I'm not seeing calls reload after the initial load. That is a problem.

like image 53
Mat Avatar answered Oct 23 '22 19:10

Mat