synchronized void backward(float[] in, float[] out){
    if(_x.length<n/2){
      _x=new float[n/2];
    }
    if(_w.length<n/2){
      _w=new float[n/2];
    }
    float[] x=_x;
    float[] w=_w;
    int n2=n>>>1;
    int n4=n>>>2;
    int n8=n>>>3;

    // rotate + step 1
    {
      int inO=1;
      int xO=0;
      int A=n2;

      int i;
      for(i=0; i<n8; i++){
        A-=2;
        x[xO++]=-in[inO+2]*trig[A+1]-in[inO]*trig[A];
        x[xO++]=in[inO]*trig[A+1]-in[inO+2]*trig[A];
        inO+=4;
      }

      inO=n2-4;

      for(i=0; i<n8; i++){
        A-=2;
        x[xO++]=in[inO]*trig[A+1]+in[inO+2]*trig[A];
        x[xO++]=in[inO]*trig[A]-in[inO+2]*trig[A+1];
        inO-=4;
      }
    }

    float[] xxx=mdct_kernel(x, w, n, n2, n4, n8);
    int xx=0;

    // step 8

    {
      int B=n2;
      int o1=n4, o2=o1-1;
      int o3=n4+n2, o4=o3-1;

      for(int i=0; i<n4; i++){
        float temp1=(xxx[xx]*trig[B+1]-xxx[xx+1]*trig[B]);
        float temp2=-(xxx[xx]*trig[B]+xxx[xx+1]*trig[B+1]);

        out[o1]=-temp1;
        out[o2]=temp1;
        out[o3]=temp2;
        out[o4]=temp2;

        o1++;
        o2--;
        o3++;
        o4--;
        xx+=2;
        B+=2;
      }
    }
  }