56

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.

2
  • 2
    is it big-endian or little-endian? I think you need java.nio.ByteBuffer to handle this conversion. Commented Apr 11, 2011 at 18:29
  • Possible duplicate of how to convert short array to byte array Commented May 11, 2016 at 23:05

7 Answers 7

105

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);
Sign up to request clarification or add additional context in comments.

10 Comments

short[] audioData = ByteBuffer.wrap(audioBytes2).order(ByteOrder.BIG_ENDIAN).asShortBuffer().array(); Throws an UnsupportedOperationException.
@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).
@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.
Is this only converting the bytes directly to shorts or is it combining two bytes into a short like I need it to?
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.
|
13
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();
}

1 Comment

It does not convert short array to byte array.
6

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());
}

Comments

6
byte[2] bytes;

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

short s = (short)r;

Comments

2

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.

1 Comment

I'm actually using something similar to that after the reconversion with an audioInputStream.
0

If you are using the Guava Lib, it supports methods such as Shorts.fromBytes(), and for integers Ints.fromBytes() that does this kind of operation for you.

Comments

-1

It looks like you are swapping the byte order between reading the bytes in and writing them back out (unsure if this is intentional or not).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.