0

1. Confusion on byte declaration

I have successfully read raw data from the microphone using AudioRecord class in Android. In my code, the raw data is saved as: byte data[] = new byte[bufferSize];

Here bufferSize is a constant number (I guess) 7680. My first question is: what's the difference between

byte data[] = new byte[bufferSize]; and byte[] data = new byte[bufferSize];? My code seems to be not different in both cases.

2. byte to float

My next step is to do some calculation with the raw data. For better precision, I want to convert byte type data to float. Here's the code:

private void writeAudioDataToFile() {
    byte data[] = new byte[bufferSize];
    String filename = getTempFilename();
    FileOutputStream os = null;

    try {
        os = new FileOutputStream(filename);
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    int read = 0;

    if(null != os) {
        while(isRecording) {
            // First print: raw data from microphone
            Log.v("print1", "data");
            read = recorder.read(data, 0, bufferSize);
            System.out.println(Arrays.toString(data)); 

            // Second print: byte[] to float[]
            Log.v("print2", "buff");
            float[] inBufferMain = new float[bufferSize];
            for (int i = 0; i < bufferSize; i++) {
                inBufferMain[i] = (float) data[i];
            }   
            System.out.println(Arrays.toString(inBufferMain)); 

            // Calculating inBufferMain here
            // ...

            // Third print: float[] to byte[]
            Log.v("print3", "data");
            for (int i = 0; i < bufferSize; i++) {
                data[i] = (byte) inBufferMain[i];
            }
            System.out.println(Arrays.toString(data)); 

            if(AudioRecord.ERROR_INVALID_OPERATION != read) {
                try {
                    os.write(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        try {
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

In the code above, after reading data from the microphone, I print it in logcat. The results are around 1000 integer numbers. Why 1000? Because the buffer read 7680 bits in all and saved as byte, that is 7680 / 8 ≈ 1000. Please correct me if my analysis is wrong. But after byte-to-float conversion, the results are only around 600 float numbers. The first 600 value in the float array is same as the one in the byte array, but the remaining numbers are missing. Is there anything wrong with my method of printing?

3. float to byte

Assumed that I've processed the float array and now is time for float-to-byte conversion. But the results of the third print are all 0. How to convert float[] to byte[]?

Thanks

WangYudong
  • 4,335
  • 4
  • 32
  • 54
  • 1
    for some reason java still supports the `byte data[]` syntax. `data` however will be an instance of `byte[]`. For consistency, I recommend to always use `byte[] data` as it follows the `Type name` declaration structure. – njzk2 Sep 26 '14 at 18:52
  • @StefanFreitag what's wrong with float to byte conversion in my case then? – WangYudong Sep 26 '14 at 18:57
  • I think the cast from float to byte does not perform conversion, but only takes the first byte, which is probably the exponent, which here is 0. Don't cast floats to bytes. At best you'll loose a lot of precision, at worse your float values will be completely out of the byte range. – njzk2 Sep 26 '14 at 18:59
  • From my understanding a conversion from bytes to floats results in 1) grouping the bytes into groups of four and then 2) calculating the float value based on such a group. Typically you will find two ways for the calculation: using shift operators or bytebuffers. – Stefan Freitag Sep 26 '14 at 19:10

2 Answers2

1
System.out.println(Arrays.toString(data));

will print exactly data.length bytes, which is bufferSize.

The size of a logcat entry is limited, however to 4076 chars. Between the joining ", " and the size of the String representation of the byte, 1000 is a good estimate.

The same goes for floats, except they are usually bigger to print.

The conclusion is that what you are seeing is just a limitation of the logcat payload. see What is the size limit for Logcat and how to change its capacity?

Community
  • 1
  • 1
njzk2
  • 38,969
  • 7
  • 69
  • 107
  • Thanks for your explanation. Do you have any suggestion on printing large groups of data? Because I always check my code in that way. – WangYudong Sep 26 '14 at 19:04
  • you'll have to cut your string in substrings. However, I don't know that a 7000 bytes list is a good way of checking data. You can log the length of the array, for example, and may be a few values at the beginning. – njzk2 Sep 26 '14 at 19:13
  • To your comment: the reason why I cast floats to bytes is that I need to write `data` to file using [OutputStream.write](http://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#write%28int%29). – WangYudong Sep 26 '14 at 19:14
  • If you need to transmit your float array into an outputstream, you cannot simply cast to byte. you probably need a `DataOutputStream` and the `writeFloat` method. On the other side of the stream, you need to use `readFloat` on a DataInputStream. (for each element in the array. You probably want to write the size of the array at some point.) – njzk2 Sep 26 '14 at 19:14
  • (Also, you don't need the whole array, since only `read` bytes are actually read from the audio recorder.) – njzk2 Sep 26 '14 at 19:16
  • Yes, I am recording audio. Do you mean some of `read` bytes are not from recorder? But how do I know which bytes are from the recorder? – WangYudong Sep 26 '14 at 19:19
  • when you call `read = recorder.read(data, 0, bufferSize);`, if you look at the doc, `read` is number of actually read bytes. The rest are not overwritten and can be 0s, or previously inserted data. – njzk2 Sep 26 '14 at 19:25
  • @WangYudong consider to accept the answer given by njzk2 and give him credit :). With regard to the array declaration and initialisation the second is the convention used by all the programmers I come to know. – Alboz Sep 26 '14 at 19:27
1

With regard to your question number 3. You can make use of ByteBuffer to convert from float[] to byte[]. Read the Oracle documentation: ByteBuffer.java

This class has utilities methods like putFloat() and many others, it becomes trivial to do these type of conversions :)

Alboz
  • 1,833
  • 20
  • 29