简体   繁体   中英

Separate bits from short[] in order of most to least significant C#

I want to separate the bits of a short[] contained in a byte[] so the most significant bit of each short are arranged in one contiguous block(array? line?) followed by the next bit from each short and so on. This is a condensed sample of how the layout of the bits would change:

0101010101010101 0101010101010101
would become
0011001100110011 0011001100110011
or with 3 it would look like
0101010101010101 0101010101010101 0101010101010101
which would become
0001110001110001 1100011100011100 0111000111000111

I put that in a code block to preserve the line breaks.

This would be easy If I could address each bit individually but I have to use bitwise operators which makes it extremely difficult.

Ignoring the possibility that the number of elements in the array wouldn't be a multiple of the base type bit length which in this case is 16 I came up with this:

fixed(byte* inptr = sourcearray){ //the shorts in a byte[]
    fixed(byte* outptr = destination){//the output byte[]
        var insamples = (short*)inptr;
        var outsamples = (ushort*)outptr;
        var mask = (ushort)0b1000000000000000;
        for(int i = 0, j = 0; i < numsamples; ++i, j += 16){
            if(j >= numsamples){
                j = 0;
                mask >>= 1;
            }
            outsamples[i] = (ushort)((insamples[j] & mask) | ((insamples[j + 1] & mask) >> 1) | ((insamples[j + 2] & mask) >> 2) | ((insamples[j + 3] & mask) >> 3) |
                                    ((insamples[j + 4] & mask) >> 4) | ((insamples[j + 5] & mask) >> 5) | ((insamples[j + 6] & mask) >> 6) | ((insamples[j + 7] & mask) >> 7) |
                                    ((insamples[j + 8] & mask) >> 8) | ((insamples[j + 9] & mask) >> 9) | ((insamples[j + 10] & mask) >> 10) | ((insamples[j + 11] & mask) >> 11) |
                                    ((insamples[j + 12] & mask) >> 12) | ((insamples[j + 13] & mask) >> 13) | ((insamples[j + 14] & mask) >> 14) | ((insamples[j + 15] & mask) >> 15));
        }
    }
}

The array I'm working with is 480 shorts (960 bytes) long, I'm pretty sure it does what I want but I'm having trouble writing the function that does the opposite to restore the the array to its original state, so far I have nothing that makes sense, I need it to be reasonably optimal to minimize the processing required but its hurting my brain.

I would probably be better off doing this in C++ but I want to keep the program entirely managed.

I hate to answer my own question but I have just discovered the System.Collections.BitArray class which allows me to address bits individually and within minutes I replaced the code in the op with this:

for(int i = 0, j = 0, k = 0; i < inbits.Length; ++i, j += 16){
    if(j >= inbits.Length) j = ++k;
    _outbitsout[i] = inbits[j];
}

and to reverse that operation:

var stride = inbits.Length/16;
for(int i = 0, j = 0, k = 0; i < inbits.Length; ++i, j += stride){
    if(j >= inbits.Length) j = ++k;
    _outbitsin[i] = inbits[j];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM