# PLEASE HELP - Strange problem converting from bytes to float

Discussion in 'Java' started by cpptutor2000@yahoo.com, Mar 23, 2008.

1. ### Guest

Could some Java guru please help me ? I am trying to create a simple
application that will capture audio from the PC's default listening
device and do some FFT with the data. The audio bytes are collected in
a byte array, and the main problem I am having right now is how to
convert them to the floating point numbers that would be used in the
computation of the FFT. For prototyping purposes, I am using a
floating point array as :

private final int len = 4096;

float [][] floatArray = new float[len][2];

The reason I am using using the 2-D array is that one dimension would
hold the real and the other the imaginary component of the complex
numbers to be used for the FFT. To convert consecutive chunks of 4
bytes to get a floating point number, I am using the following
function:

public static float arr2float (byte[] arr, int start)
{
int i = 0;
int len = 4;
int cnt = 0;
byte[] tmp = new byte[len];
for (i = start; i < (start + len); i++)
{
tmp[cnt] = arr;
cnt++;
}
int accum = 0;
i = 0;
for ( int shiftBy = 0; shiftBy < 32;
shiftBy += 8 )
{
accum |= ( (long)( tmp & 0xff )
) << shiftBy;
i++;
}
return Float.intBitsToFloat(accum);
}

The actual conversion from the raw bytes to the flaoting point numbers
is done via a loop as:

for (int start = 0; start < 4096; start += 4)
{
floatArray[cnt][0] =
RecordUtility.arr2float(recordedSoundArray,
start);
floatArray[cnt][1] = 0;
System.out.println(cnt + " "
+floatArray[cnt][0]);
cnt++;
}

Unfortunately, the output of the print statement looks like:
0 12690.33
1 1.64703E-40
2 3428.0837
3 2.0703801E-19
4 2.24E-44
5 9.1837E-41
6 1.121E-41
7 2.2421E-41
8 1.469371E-39
9 2.8175146E20
10 1.64653E-40

This is what bothers me that the numbers are huge or very small, and
there are quite a few 'NaN's.

Could someone please kindly provide some hints as what I might be
doing wrong?

, Mar 23, 2008

2. ### Mark SpaceGuest

wrote:
> Could some Java guru please help me ? I am trying to create a simple
> application that will capture audio from the PC's default listening
> device and do some FFT with the data. The audio bytes are collected in

Well for starters, if you're using a Clip, then sample can take a
variable number of bits, not bytes. And they can be either big endian
or little endian.

<http://java.sun.com/javase/6/docs/api/javax/sound/sampled/AudioFormat.html>

You may want to clarify first what your data actually looks like. Then
we can give you a hand with the conversion.

Mark Space, Mar 23, 2008

3. ### Guest

On Mar 22, 7:47 pm, Mark Space <> wrote:
> wrote:
> > Could some Java guru please help me ? I am trying to create a simple
> > application that will capture audio from the PC's default listening
> > device and do some FFT with the data. The audio bytes are collected in

>
> Well for starters, if you're using a Clip, then sample can take a
> variable number of bits, not bytes. And they can be either big endian
> or little endian.
>
> <http://java.sun.com/javase/6/docs/api/javax/sound/sampled/AudioFormat...>
>
> You may want to clarify first what your data actually looks like. Then
> we can give you a hand with the conversion.

I am sorry I did not provide that information. I am using PCM
encoding, with sampling rate = 8000 and channel = 1 (mono)

, Mar 23, 2008
4. ### Logan ShawGuest

wrote:
> On Mar 22, 7:47 pm, Mark Space <> wrote:
>> wrote:
>>> Could some Java guru please help me ? I am trying to create a simple
>>> application that will capture audio from the PC's default listening
>>> device and do some FFT with the data. The audio bytes are collected in

>> Well for starters, if you're using a Clip, then sample can take a
>> variable number of bits, not bytes. And they can be either big endian
>> or little endian.
>>
>> <http://java.sun.com/javase/6/docs/api/javax/sound/sampled/AudioFormat...>
>>
>> You may want to clarify first what your data actually looks like. Then
>> we can give you a hand with the conversion.

>
> I am sorry I did not provide that information. I am using PCM
> encoding, with sampling rate = 8000 and channel = 1 (mono)

Looking at AudioFormat.Encoding, it appears likely that your input
bytes represent plain old simple base-2 integer sample values. But
you're calling Float.intBitsToFloat(), which assumes they are IEEE
floating point values. Instead of all that, once you've converted
your bytes into an integer, you probably just want to use a cast to
convert the integer into a float.

Also, you appear to be assuming that one sample (for one channel)
is 32 bits wide based on this loop:

for ( int shiftBy = 0; shiftBy < 32;
shiftBy += 8 )

It's fairly uncommon (but not impossible, I guess) for anyone
to use 32 bit integers for transferring audio. 24-bit integers
are good enough, and I don't think anyone has ever built an A-to-D
that can give 32 bits worth of integer resolution and not have
the low order 8 bits be anything other than noise. So I would
suspect your incoming samples are either 16-bit integers or
24-bit integers. Or maybe even 8-bit integers if you are using
a sample rate as low as 8000 Hz.

- Logan

Logan Shaw, Mar 23, 2008
5. ### Roedy GreenGuest

On Sat, 22 Mar 2008 17:34:44 -0700 (PDT), ""
<> wrote, quoted or indirectly quoted someone
who said :

>This is what bothers me that the numbers are huge or very small, and
>there are quite a few 'NaN's.

The obvious first. See http://mindprod.com/jgloss/endian.html
--

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Roedy Green, Mar 23, 2008
6. ### LewGuest

Logan Shaw wrote:
> floating point values. Instead of all that, once you've converted
> your bytes into an integer, you probably just want to use a cast to
> convert the integer into a float.

You don't need a cast because it's a widening conversion.

--
Lew

Lew, Mar 23, 2008
7. ### Logan ShawGuest

Lew wrote:
> Logan Shaw wrote:
>> floating point values. Instead of all that, once you've converted
>> your bytes into an integer, you probably just want to use a cast to
>> convert the integer into a float.

>
> You don't need a cast because it's a widening conversion.

Ah, good point. Not being terribly fresh on the kinds of conversions,
I simply assumed that any conversion that could result in loss of
information would require a cast. But as you pointed out, that's not
how Java works: some widening conversions can result in loss of
information; they will not lose information about rough magnitude
of the number, but they can lose precision.

- Logan

Logan Shaw, Mar 23, 2008