数组在此代码中的位置超出范围?

时间:2017-08-01 18:50:43

标签: java arrays indexoutofboundsexception lang

我是Java的新手,我收到这个错误,我可以设法了解它的来源。我正在进行FFT分析,我收到了错误:

java.lang.ArrayIndexOutOfBoundsException: 66,
at DrawingFunction.main(DrawingFunction.java:66)
at AnimationGen.begin(AnimationGen.java:54)
at FFTclass.main2(FFTclass.java:213)
at fftTry.main(fftTry.java:34)

代码是fft的代码:

public static void main(String[] args) {


    final String NEWLINE = "\n";

    String inputFile = "C:/Users/USER/Downloads/DD.wav"; // Place the wav file in the top level directory, ie S:/input.wav


    File fileLocation = new File(inputFile);

    System.out.println("START");
    try {

        double[] complexNumber = readFully(fileLocation);
        System.out.println(NEWLINE + "Read file");

        double[] realPart = complexNumber;
        double[] imagPart = new double[realPart.length];
        System.out.println("Length = " + realPart.length);

        FFTclass FFT = new FFTclass(1024);
        FFT.main2(realPart,imagPart,1024);

        //for (int i = 0; i < complexNumber.length; ++i) {
        //    System.out.println(complexNumber[i]);
        //}

    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

static double[] readFully(File file) throws UnsupportedAudioFileException, IOException {
    AudioInputStream in = AudioSystem.getAudioInputStream(file);
    AudioFormat fmt = in.getFormat();
    double sampleRate = fmt.getSampleRate();
    double frameSize = fmt.getFrameSize();
    double auidioDuration = fmt.getFrameRate();
    double channels = fmt.getChannels();
    System.out.println("File length = " + file.length() + " ");
    System.out.println("Sample Rate = " + sampleRate + " per second");
    System.out.println("Frame size = " + frameSize + " per second");
    System.out.println("Frame rate = " + auidioDuration + " per second");
    System.out.println("Channels = " + channels);
    System.out.println("Length in time = " + (file.length()/frameSize * auidioDuration) + " seconds");
    System.out.println("Length in time in minutes = " + (int)(file.length()/(frameSize* auidioDuration *60)) + " minutes and " + ( (file.length()/(frameSize* auidioDuration *60))- (int)(file.length()/(frameSize* auidioDuration *60)) )* 60 + " seconds");

    byte[] bytes;
    try {
        if (fmt.getEncoding() != Encoding.PCM_SIGNED) {
            throw new UnsupportedAudioFileException();
        }

        // read the data fully
        bytes = new byte[in.available()];
        in.read(bytes);
    } finally {
        in.close();
    }

    int bits = fmt.getSampleSizeInBits();
    double max = Math.pow(2, bits - 1);

    ByteBuffer bb = ByteBuffer.wrap(bytes);
    bb.order(fmt.isBigEndian() ?
            ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);

    double[] samples = new double[bytes.length * 8 / bits];
    // convert sample-by-sample to a scale of
    // -1.0 <= samples[i] < 1.0
    for (int i = 0; i < samples.length; ++i) {
        switch (bits) {
            case 8:
                samples[i] = (bb.get() / max);
                break;
            case 16:
                samples[i] = (bb.getShort() / max);
                break;
            case 32:
                samples[i] = (bb.getInt() / max);
                break;
            case 64:
                samples[i] = (bb.getLong() / max);
                break;
            default:
                throw new UnsupportedAudioFileException();
        }
    }

    return samples;


}

对于FFT类:

int n, m;

// Lookup tables.  Only need to recompute when size of FFT changes.
double[] cos;
double[] sin;



double[] window;

public FFTclass(int n) {
    this.n = n;
    this.m = (int)(Math.log(n) / Math.log(2));

    // Make sure n is a power of 2
    if(n != (1<<m))
        throw new RuntimeException("FFT length must be power of 2");

    // precompute tables
    cos = new double[n/2];
    sin = new double[n/2];

    //     for(int i=0; i<n/4; i++) {
    //       cos[i] = Math.cos(-2*Math.PI*i/n);
    //       sin[n/4-i] = cos[i];
    //       cos[n/2-i] = -cos[i];
    //       sin[n/4+i] = cos[i];
    //       cos[n/2+i] = -cos[i];
    //       sin[n*3/4-i] = -cos[i];
    //       cos[n-i]   = cos[i];
    //       sin[n*3/4+i] = -cos[i];
    //     }

    for(int i=0; i<n/2; i++) {
        cos[i] = Math.cos(-2*Math.PI*i/n);
        sin[i] = Math.sin(-2*Math.PI*i/n);
    }

    makeWindow();
}

protected void makeWindow() {
    // Make a blackman window:
    // w(n)=0.42-0.5cos{(2*PI*n)/(N-1)}+0.08cos{(4*PI*n)/(N-1)};
    window = new double[n];
    for(int i = 0; i < window.length; i++)
        window[i] = 0.42 - 0.5 * Math.cos(2*Math.PI*i/(n-1))
                + 0.08 * Math.cos(4*Math.PI*i/(n-1));
}

public double[] getWindow() {
    return window;
}


/***************************************************************
 00089   * fft.c
 00090   * Douglas L. Jones
 00091   * University of Illinois at Urbana-Champaign
 00092   * January 19, 1992
 00093   * http://cnx.rice.edu/content/m12016/latest/
 00094   *
 00095   *   fft: in-place radix-2 DIT DFT of a complex input
 00096   *
 00097   *   input:
 00098   * n: length of FFT: must be a power of two
 00099   * m: n = 2**m
 00100   *   input/output
 00101   * x: double array of length n with real part of data
 00102   * y: double array of length n with imag part of data
 00103   *
 00104   *   Permission to copy and use this program is granted
 00105   *   as long as this header is included.
 00106   ****************************************************************/
public void fft(double[] x, double[] y)
{
    int i,j,k,n1,n2,a;
    double c,s,e,t1,t2;


    // Bit-reverse
    j = 0;
    n2 = n/2;
    for (i=1; i < n - 1; i++) {
        n1 = n2;
        while ( j >= n1 ) {
            j = j - n1;
            n1 = n1/2;
        }
        j = j + n1;

        if (i < j) {
            t1 = x[i];
            x[i] = x[j];
            x[j] = t1;
            t1 = y[i];
            y[i] = y[j];
            y[j] = t1;
        }
    }

    // FFT
    n1 = 0;
    n2 = 1;

    for (i=0; i < m; i++) {
        n1 = n2;
        n2 = n2 + n2;
        a = 0;

        for (j=0; j < n1; j++) {
            c = cos[a];
            s = sin[a];
            a +=  1 << (m-i-1);

            for (k=j; k < n; k=k+n2) {
                t1 = c*x[k+n1] - s*y[k+n1];
                t2 = s*x[k+n1] + c*y[k+n1];
                x[k+n1] = x[k] - t1;
                y[k+n1] = y[k] - t2;
                x[k] = x[k] + t1;
                y[k] = y[k] + t2;
            }
        }
    }
}




// Test the FFT to make sure it's working
public static void main2(double[] re, double[] im, int N) {


    FFTclass fft = new FFTclass(N);

    double[] window = fft.getWindow();

    double[] ang;
    double[] amplitude;

    // Impulse
    re[0] = 1; im[0] = 0;
    for(int i=1; i<N; i++)
        re[i] = im[i] = 0;
    System.out.println("Impulse");
    beforeAfter(fft, re, im);

    // Nyquist
    for(int i=0; i<N; i++) {
        re[i] = Math.pow(-1, i);
        im[i] = 0;
    }
    System.out.println("Nyquist");
    beforeAfter(fft, re, im);

    // Single sin
    for(int i=0; i<N; i++) {
        re[i] = Math.cos(2*Math.PI*i / N);
        im[i] = 0;
    }
    System.out.println("Single sin");
    beforeAfter(fft, re, im);

    // Ramp
    for(int i=0; i<N; i++) {
        re[i] = i;
        im[i] = 0;
    }
    System.out.println("Ramp");
    beforeAfter(fft, re, im);

    amplitude = new double[re.length];
    ang = new double[re.length];
    for(int i=0; i<re.length;i++)
    {
        amplitude[i] = Math.sqrt( (re[i]*re[i])+ (im[i]*im[i]) );

    //Calculate and return the phase
    // angle in degrees.
    if(im[i] == 0.0 && re[i] == 0.0){ang[i] = 0.0;}
    else{ang[i] = Math.atan(im[i]/re[i])*180.0/Math.PI;}

    if(re[i] < 0.0 && im[i] == 0.0){ang[i] = 180.0;}
    else if(re[i] < 0.0 && im[i] == -0.0){
        ang[i] = -180.0;}
    else if(re[i] < 0.0 && im[i] > 0.0){
        ang[i] += 180.0;}
    else if(re[i] < 0.0 && im[i] < 0.0){
        ang[i] += -180.0;}

    }

    for(int i = 100500; i<100600; i++)
    {
        System.out.print( '\n' + "Magnitude["+i+"] = " +amplitude[i]+ ", ");
        System.out.print( '\n' + "Angle phase["+i+"] = " +ang[i]+ ", ");
    }



    long time = System.currentTimeMillis();
    double iter = 30000;
    for(int i=0; i<iter; i++)
        fft.fft(re,im);
    time = System.currentTimeMillis() - time;
    System.out.println("\n" + "Averaged " + (time/iter) + "ms per iteration");
    System.out.println("Time: " + (time) + "ms");

    AnimationGen animation = new AnimationGen();
    animation.begin(amplitude);

}

protected static void beforeAfter(FFTclass fft, double[] re, double[] im) {
    System.out.println("Before: ");
    printReIm(re, im);
    fft.fft(re, im);
    System.out.println("After: ");
    printReIm(re, im);
}

protected static void printReIm(double[] re, double[] im) {
    System.out.print("Re: [");
    //for(int i=0; i<re.length; i++)
    System.out.println("i = " + re.length);
        for(int i=100550; i<100650; i++)
        System.out.print(((int)(re[i]*1000)/1000.0) + " ");

    System.out.print("]\nIm: [");
    //for(int i=0; i<im.length; i++)
        for(int i=100550; i<100650; i++)
        System.out.print(((int)(im[i]*1000)/1000.0) + " ");

    System.out.println("]");
}

动画源:

public int frameWidth = 1920;
public int frameHeigth = 1080;
public int fps = 30;




public void begin(double[] magnitude)
{



    int magnitudeLength = magnitude.length;
    int value = (int)magnitudeLength/44100;

    double [][][] magnitudesPerSecond = new double[value][fps][(int)44100/fps];
    for(int i = 0; i < value;i++) {
        for(int j = 0; j < fps;j++) {
            for (int k = 0; k < (int)44100/fps; k++) {
                int arraynumber = k + (j*fps) +(i * (int)44100/fps);
                    magnitudesPerSecond[i][j][k] = magnitude[arraynumber];
            }
        }
    }



    System.out.println("i = " + magnitudesPerSecond.length);
    System.out.println("j = " + magnitudesPerSecond[0].length);
    System.out.println("k = " + magnitudesPerSecond[0][0].length);


    DrawingFunction DF = new DrawingFunction();
    DF.main(value, fps, magnitudesPerSecond);

}

最后的DrawingFunction

public int second = 0;
Timer t = new Timer();
TimerTask timeTask = new TimerTask() {
    @Override
    public void run() {
        second++;
    }
};

public double addingAngle = 0;

public int frameWidth = 1920;
public int frameHeigth = 1080;

public int value;
public int fps;

public double[][][] magnitude;


double xPoint[][][];
double yPoint[][][];


public void main(int value, int fps, double[][][] magnitude) {


    this.value = value;
    this.fps = fps;
    this.magnitude = magnitude;




    ///////////////////////////////////////////////////////////////////////////////////////////////////
    double xPoint[][][] = new double[value][fps][64];
    double yPoint[][][] = new double[value][fps][64];
    for (int counter = 0; counter < value; counter++) {



        for (int i = 0; i < fps; i++) {
            for (int j = 0; j < (44100 / fps); j += ((44100 / fps) / 64)) {

                xPoint[counter][i][j] = magnitude[counter][i][j];

                for (int t = 0; t < ((44100 / fps) / 65); t++) { //64 is the number of bands taken into and only 55 from them are used
                    if(j+t < magnitude[0][0].length) {
                        xPoint[counter][i][j] += magnitude[counter][i][j + t];
                    }
                    System.out.println("Here xPoint[" +i+"]["+j+"]" + (j + t));

                }

                xPoint[counter][i][j] /= (int) ((44100 / fps) / 64);
            }

            int t = 0;
            for (double angle = addingAngle; angle < 2 * Math.PI + addingAngle; angle += 2 * Math.PI / 55) {

                xPoint[counter][i][t] *= Math.cos(angle); //All X points [second][frame][band]
                yPoint[counter][i][t] *= Math.sin(angle); //All Y points [second][frame][band]
                t++;
            }
            addingAngle += Math.PI / 110; //110 = 55 points * 2 so rotation is slower
        }

        this.xPoint = xPoint;
        this.yPoint = yPoint;

        // Up to here we have 64 xPoints and 64 yPoints, but only the first 55 of each are multiplied by the angle


        // jl.setIcon(new ImageIcon("/images/T.png"));



    }
    for (int i = 0; i < 55; i++) {
        System.out.println("Point[" + i + "] is: " + xPoint[0][0][i]);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////



    JFrame window = new JFrame();
    window.add(new DrawingFunction());
    window.pack();
    window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    window.setLocationRelativeTo(null);
    window.setSize(frameWidth, frameHeigth);
    window.setBackground(Color.blue);
    window.setVisible(true);
    repaint();
}

@Override
protected void paintComponent(Graphics g) {
    g.setColor(Color.black);
    g.fillRect(800, 500, 300, 300);        //g.translate(frameWidth/2, frameHeigth/2);


    Polygon p = new Polygon();
    for (int i = 0; i < 55; i++)
        p.addPoint(15 * (int) xPoint[0][0][i], 15 * (int) yPoint[0][0][i]);

    g.setColor(Color.black);
    g.drawPolygon(p);
    g.fillRect(800, 800, 400, 400);
    validate(); // So image appears even if screen is small

我知道代码很长,希望它不难阅读,这是我第一次在这里提出问题

2 个答案:

答案 0 :(得分:2)

我会在这里查看以下几行:

double xPoint[][][] = new double[value][fps][64];

//...

for (int j = 0; j < (44100 / fps); j += ((44100 / fps) / 64)) {
    xPoint[counter][i][j] = magnitude[counter][i][j];

请注意,输入的fps为30,因此((44100/30)/ 64))= 22.96875(或22为int)。所以当这个循环迭代时,j将如下:

  • j = 0

  • j = 22

  • j = 44

  • j = 66(数组越界)

答案 1 :(得分:1)

fps的值是30(如果我没有遗漏任何东西)。 44100 / fps = 1,470。所以,j从0到1,469。但是,你的数组的第三个维度只有64 ......

double xPoint[][][] = new double[value][fps][64];
double yPoint[][][] = new double[value][fps][64];
for (int counter = 0; counter < value; counter++) {



        for (int i = 0; i < fps; i++) {
            for (int j = 0; j < (44100 / fps); j += ((44100 / fps) / 64)) {

            xPoint[counter][i][j] = magnitude[counter][i][j];