Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 349
  • Last Modified:

ArrayIndexOutOfBoundsException

I am getting an ArrayIndexOutOfBoundsException.

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 22051
        at FlashFFT.handleAudioBytes(FlashFFT.java:174)
        at FlashFFT.generateFFT(FlashFFT.java:93)
        at CommandLine.main(CommandLine.java:26)
Java Result: 1

Here is the handleAudioBytes method:
private void handleAudioBytes() {
		left = new float[sampleSize];
		right = new float[sampleSize];

		int c = (int) ((long) (framesRead * frameSize) - (long) (audioDataBuffer.length * offset));

		if (c > 0) {
			for (int a = 0; a < sampleSize; a++, c += 4) {
				if (c >= audioDataBuffer.length) {
					c = (c - audioDataBuffer.length);
					offset++;
				}
				// channelMode == CHANNEL_MODE_STEREO && sampleType ==
				// SAMPLE_TYPE_SIXTEEN_BIT
				left[a] = ((audioDataBuffer[c + 1] << 8) + audioDataBuffer[c]) / 32767.0f;
				right[a] = ((audioDataBuffer[c + 3] << 8) + audioDataBuffer[c + 2]) / 32767.0f;
			}
		}
	}

Open in new window


line 174 is right[a] = ((audioDataBuffer[c + 3] << 8) + audioDataBuffer[c + 2]) / 32767.0f;

Anybody knwos what could be wrong?
0
chudyksg
Asked:
chudyksg
  • 6
  • 5
  • 5
2 Solutions
 
for_yanCommented:
well, how do you create audoDataBuffer and can it be that c+3 would be at some point > that its dimension ?
0
 
for_yanCommented:
can you print out a and c right before that line:
System.out.println("a: " + a + " c: " + c + " length:  " +  audioDataBuffer.length );
0
 
mccarlIT Business Systems Analyst / Software DeveloperCommented:
I think that you are probably assuming the audioBuffer.length will always be a multiple of 4, but somehow it is not the case. It a bit hard to work out the logic, but this change should at least resolve the error. Whether it is correct for what you are trying to do, is another matter.

Change the line

 if (c >= audioDataBuffer.length) {

to

 if (c > (audioDataBuffer.length - 4)) {
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
chudyksgAuthor Commented:
for_yan: for the print out see attached file
mccarl: that didn't help errorPrintout.txt
0
 
for_yanCommented:
Noit helped c = 22048, so c+3 is out ofbounds
0
 
for_yanCommented:
so check it right before executing line 174  line and skip this line , or catch
this exception and ignore it - if it is only possible
0
 
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Ah, yes, I see.. My suggestion should have changed the exception though from... java.lang.ArrayIndexOutOfBoundsException: 22051    to... java.lang.ArrayIndexOutOfBoundsException: -2

As I said, you are assuming that the audioBuffer's length is a multiple of 4 (but it isn't) and so trying to process the buffer's bytes in groups of 4 just isn't going to work.


For us to help you much more, you will need to provide more details.. What is the purpose of this method, what determine the length of audioBuffer, how is audioBuffer declared, where does sampleSize, frameSize and framesRead come from?
0
 
chudyksgAuthor Commented:
Well it is not actually my code. I downloaded the source code from here http://javaflash-fft.sourceforge.net/ . It looks on the web page it is working. I want to analyse the code how it is done because I have to do something similar but when I try to run from net beans I get that error. I get the error if I run it from the command line as well
0
 
for_yanCommented:
Well, it looks like it happens at the last point - not knowing anything about the details,  one option is - is just say a<(samplSize-1)
within the loop - hopefully it would not spoil too much
0
 
chudyksgAuthor Commented:
Here is the whole code
public class FlashFFT {

	private float[] left;

	private float[] right;

	private int sampleSize = 2048;

	private byte[] audioDataBuffer = null;

	private KJFFT fft = new KJFFT(512);

	private float[] old_FFT = new float[512];

	private int desiredBands = 12;

	private int framesRead = 0;

	private int position = 0;

	private AudioFormat baseFormat;

	private int offset = 0;

	private int frameSize;

	private FlashFFTDataConsumer consumer;

	public FlashFFT() {
	}

	/**
	 * @param inputFile
	 * @throws IOException
	 * @throws UnsupportedAudioFileException
	 */
	public void generateFFT(File inputFile, FlashFFTDataConsumer consumer, int desiredFPS,
			int desiredBands) {
		this.consumer = consumer;
		AudioInputStream din = null;
		AudioInputStream in = null;
		FileOutputStream fos = null;
		try {
			long time = new Date().getTime();
			this.desiredBands = desiredBands;
			AudioFileFormat baseFileFormat = null;
			baseFormat = null;
			baseFileFormat = AudioSystem.getAudioFileFormat(inputFile);
			baseFormat = baseFileFormat.getFormat();
			in = AudioSystem.getAudioInputStream(inputFile);
			AudioFormat decodedFormat = new AudioFormat(
					AudioFormat.Encoding.PCM_SIGNED,
					baseFormat.getSampleRate(), 16, baseFormat.getChannels(),
					baseFormat.getChannels() * 2, baseFormat.getSampleRate(),
					false);
			din = AudioSystem.getAudioInputStream(decodedFormat, in);

			frameSize = decodedFormat.getFrameSize();
			byte[] data = new byte[4096];
			System.out.println("Input sample rate: "
					+ baseFormat.getSampleRate() + "Hz");
			audioDataBuffer = new byte[(int) baseFormat.getSampleRate() << 1];

			int nBytesRead = 0;
			float passCount = 0;
			int sampleCount = 0;
			System.out.println("Processing input at " + desiredFPS
					+ "fps... (one mark for 100 frames)");

                        while (nBytesRead != -1) {
				nBytesRead = din.read(data, 0, data.length);
				if (nBytesRead != -1) {
					framesRead += (nBytesRead / decodedFormat.getFrameSize());
					storeAudioData(data, 0, nBytesRead);
					handleAudioBytes();
					passCount += 1000 / (baseFormat.getSampleRate() / 1000);

					if (passCount >= (1000 / desiredFPS) * sampleCount) {
						computeFFT(mergeStereo(left, right));
						sampleCount++;
						if (sampleCount % 100 == 0) {
							System.out.print("#");
							if (sampleCount % 5000 == 0)
								System.out.print("\n");
						}
					}

				}
			}
			consumer.processFinished();
			long duration = new Date().getTime() - time;
			System.out.println("\nFinished!");
			System.out.println("Processed " + (int) sampleCount / desiredFPS
					+ "s of samples in " + (int) duration / 1000 + "s ("
					+ (int) (sampleCount / desiredFPS)
					/ (int) (duration / 1000) + "x real time)");
		} catch (IOException e) {
			throw new FFTException(e);
		} catch (UnsupportedAudioFileException e) {
			throw new FFTException(e);
		} finally {
			try {
				if (din != null)
					din.close();
				if (in != null)
					in.close();
				if (fos != null) {
					fos.flush();
					fos.close();
				}
			} catch (IOException e1) {
				throw new FFTException(e1);
			}

		}
	}

	private void storeAudioData(byte[] pAudioData, int pOffset, int pLength) {

		int wOverrun = 0;

		if (position + pLength > audioDataBuffer.length - 1) {
			wOverrun = (position + pLength) - audioDataBuffer.length;
			pLength = audioDataBuffer.length - position;
		}

		System.arraycopy(pAudioData, pOffset, audioDataBuffer, position,
				pLength);
		if (wOverrun > 0) {

			System.arraycopy(pAudioData, pOffset + pLength, audioDataBuffer, 0,
					wOverrun);
			position = wOverrun;

		} else {
			position += pLength;
		}

	}

	private void handleAudioBytes() {
		left = new float[sampleSize];
		right = new float[sampleSize];

		int c = (int) ((long) (framesRead * frameSize) - (long) (audioDataBuffer.length * offset));

		if (c > 0) {
			for (int a = 0; a < sampleSize; a++, c += 4) {
				if (c > (audioDataBuffer.length - 4)) {
					c = (c - audioDataBuffer.length);
					offset++;
				}
				// channelMode == CHANNEL_MODE_STEREO && sampleType ==
				// SAMPLE_TYPE_SIXTEEN_BIT
				left[a] = ((audioDataBuffer[c + 1] << 8) + audioDataBuffer[c]) / 32767.0f;
                            //    System.out.println("a: " + a + " c: " + c + " length:  " +  audioDataBuffer.length );
				right[a] = ((audioDataBuffer[c + 3] << 8) + audioDataBuffer[c + 2]) / 32767.0f;
			}
		}
	}

	private float[] mergeStereo(float[] pLeft, float[] pRight) {

		for (int a = 0; a < pLeft.length; a++) {
			pLeft[a] = (pLeft[a] + pRight[a]) / 2.0f;
		}
		return pLeft;

	}

	private void computeFFT(float[] pSample) {
		int saMultiplier = (512 / 2) / desiredBands;

		float c = 0;
		float[] wFFT = fft.calculate(pSample);

		float wSadfrr = (0.03f);
		
		float result[] = new float[desiredBands];

		for (int a = 0, bd = 0; bd < desiredBands; a += saMultiplier, bd++) {
			float wFs = 0;

			// -- Average out nearest bands.
			for (int b = 0; b < saMultiplier; b++) {
				wFs += wFFT[a + b];
			}

			// -- Log filter.
			wFs = (wFs * (float) Math.log(bd + 2));

			if (wFs > 1.0f) {
				wFs = 1.0f;
			}

			// -- Compute SA decay...
			if (wFs >= (old_FFT[a] /* - wSadfrr */)) {

				old_FFT[a] = wFs;

			} else {

				old_FFT[a] -= wSadfrr;

				if (old_FFT[a] < 0) {
					old_FFT[a] = 0;
				}

				wFs = old_FFT[a];

			}
			
			result[bd] = wFs;	
		}
		consumer.handleFFT(result);
	}

}

Open in new window

0
 
chudyksgAuthor Commented:
After adding:  if (c > (audioDataBuffer.length - 4)) {
I am getting Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at line : left[a] = ((audioDataBuffer[c + 1] << 8) + audioDataBuffer[c]) / 32767.0f;
0
 
mccarlIT Business Systems Analyst / Software DeveloperCommented:
It is just bad code from the looks of it. I am guessing that you might be passing in a audio file that is mono?

It seems that the code around lines 51 to 55 (in the post just above) is expecting to handle audio files of either mono or stereo, as it is not hardcoding the number of channels but it is using the number of channels from baseFormat, which is the format of the input file. However, the code in handleAudioBytes and on line 95 above is making a huge assumption that the input is in stereo.

File a bug report with the code's author!
0
 
chudyksgAuthor Commented:
Well I just downloaded a stereo file and still the same problem.
0
 
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Can you post the full output for that stereo file (including the extra output statement that for_yan asked to include)?
0
 
chudyksgAuthor Commented:
I forgot to change the code to the previous one. Once I have done it, it is working. Thanks for that. Any idea how to make it accept mono files?
0
 
mccarlIT Business Systems Analyst / Software DeveloperCommented:
This might work, it is the easiest I can see to change it. Change handleAudioBytes to this...

 
private void handleAudioBytes(int numChannels) {
		left = new float[sampleSize];
		right = new float[sampleSize];

		int c = (int) ((long) (framesRead * frameSize) - (long) (audioDataBuffer.length * offset));

		if (c > 0) {
			for (int a = 0; a < sampleSize; a++, c += 4) {
				if (c >= audioDataBuffer.length) {
					c = (c - audioDataBuffer.length);
					offset++;
				}
				if(numChannels == 2)
				{
				    // channelMode == CHANNEL_MODE_STEREO && sampleType ==
				    // SAMPLE_TYPE_SIXTEEN_BIT
				    left[a] = ((audioDataBuffer[c + 1] << 8) + audioDataBuffer[c]) / 32767.0f;
				    right[a] = ((audioDataBuffer[c + 3] << 8) + audioDataBuffer[c + 2]) / 32767.0f;
				}
				if(numChannels == 1)
				{
				    // channelMode == CHANNEL_MODE_MONO && sampleType ==
				    // SAMPLE_TYPE_SIXTEEN_BIT
				    left[a] = ((audioDataBuffer[c + 1] << 8) + audioDataBuffer[c]) / 32767.0f;
				    right[a] = left[a];
				}
			}
		}
	}

Open in new window


And then change line 75 from the above to...

 
handleAudioBytes(baseFormat.getChannels());

Open in new window


Note, that this is not by any means the best way to do this change, but it should be a quick hack to get it working. To do a better job handling both mono/stereo would require more extensive work.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 6
  • 5
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now