PLEASE HELP - Strange problem converting from bytes to float

C

cpptutor2000

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?

Thanks in advance for your help.
 
M

Mark Space

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.
 
C

cpptutor2000

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)
 
L

Logan Shaw

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
 
L

Lew

Logan said:
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.
 
L

Logan Shaw

Lew said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top