byte array to short array and back again in java

52,801

Solution 1

I also suggest you try ByteBuffer.

byte[] bytes = {};
short[] shorts = new short[bytes.length/2];
// to turn bytes to shorts as either big endian or little endian. 
ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);

// to turn shorts back to bytes.
byte[] bytes2 = new byte[shortsA.length * 2];
ByteBuffer.wrap(bytes2).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(shortsA);

Solution 2

public short bytesToShort(byte[] bytes) {
     return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
}
public byte[] shortToBytes(short value) {
    return ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort(value).array();
}

Solution 3

How about some ByteBuffers?

byte[] payload = new byte[]{0x7F,0x1B,0x10,0x11};
ByteBuffer bb = ByteBuffer.wrap(payload).order(ByteOrder.BIG_ENDIAN);
ShortBuffer sb = bb.asShortBuffer();
while(sb.hasRemaining()){
  System.out.println(sb.get());
}

Solution 4

byte[2] bytes;

int r = bytes[1] & 0xFF;
r = (r << 8) | (bytes[0] & 0xFF);

short s = (short)r;

Solution 5

Your code is doing little-endian shorts, not big. You've the indexing for MSB and LSB swapped.

Since you are using big-endian shorts, you could be using a DataInputStream wrapped around a ByteArrayInputStream (and DataOutputStream/ByteArrayOutputStream) on the other end, rather than doing your own decoding.

If you're getting every other decode working, I'd guess you've got an odd number of bytes, or an off-by-one error elsewhere which is causing your mistake to get fixed on every other pass.

Finally, I'd step through the array with i+=2 and use MSB= arr[i] and LSB=arr[i+1] rather than multiplying by 2, but that's just me.

Share:
52,801
Aaron
Author by

Aaron

Updated on July 24, 2021

Comments

  • Aaron
    Aaron almost 3 years

    I'm having some issues taking audio data stored in a byte array, converting it to a big-endian short array, encoding it, then changing it back into a byte array. Here is what I have. The original audio data is stored in audioBytes2. I am using the same format for decode with a minus on the cos function instead. Unfortunately, changing the byte and short data types is non-negotiable.

        short[] audioData = null;
        int nlengthInSamples = audioBytes2.length / 2;
        audioData = new short[nlengthInSamples];
    
        for (int i = 0; i < nlengthInSamples; i++) {
           short MSB = (short) audioBytes2[2*i+1];
           short LSB = (short) audioBytes2[2*i];
           audioData[i] = (short) (MSB << 8 | (255 & LSB));
        }
    
        int i = 0;
        while (i < audioData.length) {
            audioData[i] = (short)(audioData[i] + (short)5*Math.cos(2*Math.PI*i/(((Number)EncodeBox.getValue()).intValue())));
            i++;
        }
    
        short x = 0;
        i = 0;
        while (i < audioData.length) {
            x = audioData[i];
            audioBytes2[2*i+1] = (byte)(x >>> 0);
            audioBytes2[2*i] = (byte)(x >>> 8);
            i++;
        }
    

    I have done everything that I can think of to make this work, but the closest I've come is getting it to work every other encode/decode and I have no idea why. Thanks for any help.

  • Aaron
    Aaron about 13 years
    I'm actually using something similar to that after the reconversion with an audioInputStream.
  • Aaron
    Aaron about 13 years
    short[] audioData = ByteBuffer.wrap(audioBytes2).order(ByteOrder.BIG_ENDIAN).asS‌​hortBuffer().array()‌​; Throws an UnsupportedOperationException.
  • kdgregory
    kdgregory about 13 years
    @Aaron - yes, but what throws that exception? (hint: a ShortBuffer acts as a view on an underlying ByteBuffer, and its get() method should do exactly what you want).
  • Vishy
    Vishy about 13 years
    @kdgregory, It wasn't until you suggested the fix. I forgot array() only works if the underlying store is an short[] or similar primitive array to match the XxxxxBuffer.
  • Aaron
    Aaron about 13 years
    Is this only converting the bytes directly to shorts or is it combining two bytes into a short like I need it to?
  • Vishy
    Vishy about 13 years
    As you can see it create half as many shorts as bytes and twice as many bytes are shorts. If it didn't do the conversion you needed the ByteOrder would be pointless. as just casting byte to short and back again doesn't require a ByteOrder. If you have doubts, I suggest you try it and see if it suits your needed.
  • Collin Bell
    Collin Bell over 7 years
    Is byte[] bytes = {}; pseudocode for set bytes to something? Is this standard in Java stackoverflow?
  • Vishy
    Vishy over 7 years
    @CollinBell it's short hand for byte[] bytes = new byte[0];
  • Collin Bell
    Collin Bell over 7 years
    @PeterLawrey Is that standard/common notion?...just to know if I should use it when communicating with others.
  • Vishy
    Vishy over 7 years
    @CollinBell I use it all the time, I expect that's what is generally used in the JDK code.
  • Nikolay Shmyrev
    Nikolay Shmyrev over 4 years
    It does not convert short array to byte array.
  • Uriel Frankel
    Uriel Frankel over 2 years
    I suggest to use in android ByteOrder.nativeOrder()