how to convert short array to byte array
Asked Answered
D

3

20

I have found converting a short to byte array, and byte array to short array, but not short array to byte array.

Here is the code leading up to the conversion

while(!stopped)
        { 
            Log.i("Map", "Writing new data to buffer");
            short[] buffer = buffers[ix++ % buffers.length];

            N = recorder.read(buffer,0,buffer.length);
            track.write(buffer, 0, buffer.length);

            byte[] bytes2 = new byte[N];

I have tried

              int i = 0;
              ByteBuffer byteBuf = ByteBuffer.allocate(N);
              while (buffer.length >= i) {
                  byteBuf.putShort(buffer[i]);
                  i++;
        }

bytes2 = byteBuf.array();

and

    ByteBuffer.wrap(bytes2).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(buffer);

However I receive this error on both (the error if not exactly the same but very similar for both):

05-29 13:41:12.021: W/AudioTrack(9758): obtainBuffer() track 0x30efa0 disabled, restarting

05-29 13:41:12.857: W/AudioWorker(9758): Error reading voice AudioWorker

05-29 13:41:12.857: W/AudioWorker(9758): java.nio.BufferOverflowException

05-29 13:41:12.857: W/AudioWorker(9758): at java.nio.ShortBuffer.put(ShortBuffer.java:422)

05-29 13:41:12.857: W/AudioWorker(9758): at java.nio.ShortToByteBufferAdapter.put(ShortToByteBufferAdapter.java:210)

05-29 13:41:12.857: W/AudioWorker(9758): at java.nio.ShortBuffer.put(ShortBuffer.java:391)

05-29 13:41:12.857: W/AudioWorker(9758): at com.avispl.nicu.audio.AudioWorker.run(AudioWorker.java:126)

And just to be give as much info as possible here is the code after that uses the byte array

Log.i("Map", "test");
                //convert to ulaw
                read(bytes2, 0, N);

                //send to server
                os.write(bytes2,0,bytes2.length);

                System.out.println("bytesRead "+buffer.length);
                System.out.println("data "+Arrays.toString(buffer));
            }
Dilks answered 29/5, 2012 at 18:44 Comment(3)
not sure what im suppose to get from this. the link you post is in spanish and idk what its about, maybe a joke about relevance? I just wanted to show what N is and avoid questions.Dilks
Oh dear. I think @Bohemian meant sscce.org, not ssccee.orgWesterly
Possible duplicate of byte array to short array and back again in javaSuperego
M
17

Java short is a 16-bit type, and byte is an 8-bit type. You have a loop that tries to insert N shorts into a buffer that's N-bytes long; it needs to be 2*N bytes long to fit all your data.

ByteBuffer byteBuf = ByteBuffer.allocate(2*N);
while (N >= i) {
    byteBuf.putShort(buffer[i]);
    i++;
}
Marleen answered 29/5, 2012 at 18:50 Comment(1)
A foreach loop is almost always faster in Java: for (short s : buffer) byteBuf.put(s);Specify
H
46

I found ByteBuffer to be the slowest conversion method out of three that I've profiled. See below...

Platform: Nexus S, Android 4.1.1, No SIM card

Method #1: Use a ByteBuffer

byte [] ShortToByte_ByteBuffer_Method(short [] input)
{
  int index;
  int iterations = input.length;

  ByteBuffer bb = ByteBuffer.allocate(input.length * 2);

  for(index = 0; index != iterations; ++index)
  {
    bb.putShort(input[index]);    
  }

  return bb.array();       
}

Method #2: Twiddle bits directly

byte [] ShortToByte_Twiddle_Method(short [] input)
{
  int short_index, byte_index;
  int iterations = input.length;

  byte [] buffer = new byte[input.length * 2];

  short_index = byte_index = 0;

  for(/*NOP*/; short_index != iterations; /*NOP*/)
  {
    buffer[byte_index]     = (byte) (input[short_index] & 0x00FF); 
    buffer[byte_index + 1] = (byte) ((input[short_index] & 0xFF00) >> 8);

    ++short_index; byte_index += 2;
  }

  return buffer;
}

Method #3: Use C via JNI

TypeCast.java

package mynamespace.util;

public class TypeCast
{
  public static native byte [] shortToByte(short [] input);

  static
  {
    System.loadLibrary("type_conversion");
  }
}

native.c

#include <jni.h>
#include <string.h>

jbyteArray Java_mynamespace_util_TypeCast_shortToByte(JNIEnv *env, jobject obj, jshortArray input)
{
  jshort     *input_array_elements;
  int         input_length;

  jbyte      *output_array_elements;
  jbyteArray  output;

  input_array_elements = (*env)->GetShortArrayElements(env, input, 0);
  input_length         = (*env)->GetArrayLength(env, input);

  output                = (jbyteArray) ((*env)->NewByteArray(env, input_length * 2));
  output_array_elements = (*env)->GetByteArrayElements(env, output, 0);

  memcpy(output_array_elements, input_array_elements, input_length * 2);

  (*env)->ReleaseShortArrayElements(env, input, input_array_elements, JNI_ABORT);
  (*env)->ReleaseByteArrayElements(env, output, output_array_elements, 0);

  return output;
}

Results:

For a one million element input array, the time of execution is as follows:

Method #1 ByteBuffer: 865 ms

Method #2 Twiddle: 299 ms

Method #3 C: 39 ms

Hekking answered 10/9, 2012 at 7:37 Comment(1)
pls can you upload and provide a link to the .SO file of the C method. it would be realy helpfull. I dont want to download the ndk just for this. thanks.Typewrite
M
17

Java short is a 16-bit type, and byte is an 8-bit type. You have a loop that tries to insert N shorts into a buffer that's N-bytes long; it needs to be 2*N bytes long to fit all your data.

ByteBuffer byteBuf = ByteBuffer.allocate(2*N);
while (N >= i) {
    byteBuf.putShort(buffer[i]);
    i++;
}
Marleen answered 29/5, 2012 at 18:50 Comment(1)
A foreach loop is almost always faster in Java: for (short s : buffer) byteBuf.put(s);Specify
P
0

Here is how converted from short array to byte array.

Note: to change endianness, swap those resultData[c++] lines. Currently Little Endian.

  public byte[] getBytes(short[] data) {
       byte[] resultData = new byte[data.length * 2];
       int c = 0;
       for (int i = 0; i < data.length; i++) {
           resultData[c++] = (byte) (((data[i])) & 0xFF);
           resultData[c++] = (byte) (((data[i]) >>> 8) & 0xFF);
       }
       return resultData;
   }
Pneumo answered 23/8, 2022 at 8:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.