public virtual void initImdct(FFT mdctCtx) { SineWin.initFfSineWindows(); // Initialize the MDCT transform mdctCtx.mdctInit(8, true, -1.0); }
public virtual void ipqf(FFT dctCtx, IPQFChannelContext hist, float[] @in, float[] @out) { float[] idctIn = new float[ATRAC3P_SUBBANDS]; float[] idctOut = new float[ATRAC3P_SUBBANDS]; Arrays.Fill(@out, 0, ATRAC3P_FRAME_SAMPLES, 0f); for (int s = 0; s < ATRAC3P_SUBBAND_SAMPLES; s++) { // pack up one sample from each subband for (int sb = 0; sb < ATRAC3P_SUBBANDS; sb++) { idctIn[sb] = @in[sb * ATRAC3P_SUBBAND_SAMPLES + s]; } // Calculate the sine and cosine part of the PQF using IDCT-IV dctCtx.imdctHalf(idctOut, 0, idctIn, 0); // append the result to the history for (int i = 0; i < 8; i++) { hist.buf1[hist.pos][i] = idctOut[i + 8]; hist.buf2[hist.pos][i] = idctOut[7 - i]; } int posNow = hist.pos; int posNext = mod23_lut[posNow + 2]; // posNext = (posNow + 1) % 23 for (int t = 0; t < ATRAC3P_PQF_FIR_LEN; t++) { for (int i = 0; i < 8; i++) { @out[s * 16 + i + 0] += hist.buf1[posNow][i] * ipqf_coeffs1[t][i] + hist.buf2[posNext][i] * ipqf_coeffs2[t][i]; @out[s * 16 + i + 8] += hist.buf1[posNow][7 - i] * ipqf_coeffs1[t][i + 8] + hist.buf2[posNext][7 - i] * ipqf_coeffs2[t][i + 8]; } posNow = mod23_lut[posNext + 2]; // posNow = (posNow + 2) % 23; posNext = mod23_lut[posNow + 2]; // posNext = (posNext + 2) % 23; } hist.pos = mod23_lut[hist.pos]; // hist.pos = (hist.pos - 1) % 23; } }
public virtual void imdct(FFT mdctCtx, float[] @in, int inOffset, float[] @out, int outOffset, int windId, int sb) { if ((sb & 1) != 0) { for (int i = 0; i < ATRAC3P_SUBBAND_SAMPLES / 2; i++) { float tmp = @in[inOffset + i]; @in[inOffset + i] = @in[inOffset + ATRAC3P_SUBBAND_SAMPLES - 1 - i]; @in[inOffset + ATRAC3P_SUBBAND_SAMPLES - 1 - i] = tmp; } } mdctCtx.imdctCalc(@out, outOffset, @in, inOffset); /* Perform windowing on the output. * ATRAC3+ uses two different MDCT windows: * - The first one is just the plain sine window of size 256 * - The 2nd one is the plain sine window of size 128 * wrapped into zero (at the start) and one (at the end) regions. * Both regions are 32 samples long. */ if ((windId & 2) != 0) { // 1st half: steep window Arrays.Fill(@out, outOffset, outOffset + 32, 0f); vectorFmul(@out, outOffset + 32, @out, outOffset + 32, ff_sine_64, 0, 64); } else { // 1st halt: simple sine window vectorFmul(@out, outOffset, @out, outOffset, ff_sine_128, 0, ATRAC3P_MDCT_SIZE / 2); } if ((windId & 1) != 0) { // 2nd half: steep window vectorFmulReverse(@out, outOffset + 160, @out, outOffset + 160, ff_sine_64, 0, 64); Arrays.Fill(@out, outOffset + 224, outOffset + 224 + 32, 0f); } else { // 2nd half: simple sine window vectorFmulReverse(@out, outOffset + 128, @out, outOffset + 128, ff_sine_128, 0, ATRAC3P_MDCT_SIZE / 2); } }