diff options
author | Andreas Huber <andih@google.com> | 2009-12-07 09:56:32 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2009-12-07 11:02:28 -0800 |
commit | f44de515d3b6098a0b585865c1a0c7b20d3075a6 (patch) | |
tree | 028b1d81643bbb332464b42b50a0f79ba5359142 /media/libstagefright/codecs/aacdec/imdct_fxp.cpp | |
parent | bf697e37550d9e8376089b0b5e498613bede798c (diff) | |
download | frameworks_av-f44de515d3b6098a0b585865c1a0c7b20d3075a6.zip frameworks_av-f44de515d3b6098a0b585865c1a0c7b20d3075a6.tar.gz frameworks_av-f44de515d3b6098a0b585865c1a0c7b20d3075a6.tar.bz2 |
Initial check in of stagefright software AAC decoder based on PV source code.
Diffstat (limited to 'media/libstagefright/codecs/aacdec/imdct_fxp.cpp')
-rw-r--r-- | media/libstagefright/codecs/aacdec/imdct_fxp.cpp | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/aacdec/imdct_fxp.cpp b/media/libstagefright/codecs/aacdec/imdct_fxp.cpp new file mode 100644 index 0000000..ad67f20 --- /dev/null +++ b/media/libstagefright/codecs/aacdec/imdct_fxp.cpp @@ -0,0 +1,476 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +/* + + Pathname: imdct_fxp.c + Funtions: imdct_fxp + +------------------------------------------------------------------------------ + INPUT AND OUTPUT DEFINITIONS + + Inputs: + + data_quant = Input vector, with quantized spectral lines: + type Int32 + + freq_2_time_buffer = Scratch memory used for in-place FFT calculation, + min size required 1024, + type Int32 + + n = Length of input vector "data_quant". Currently 256 or 2048 + type const Int + + Q_format = Q_format of the input vector "data_quant" + type Int + + max = Maximum value inside input vector "data_quant" + type Int32 + + Local Stores/Buffers/Pointers Needed: + None + + Global Stores/Buffers/Pointers Needed: + None + + Outputs: + shift = shift factor to reflect scaling introduced by IFFT and imdct_fxp, + + Pointers and Buffers Modified: + Results are return in "Data_Int_precision" + + Local Stores Modified: + None + + Global Stores Modified: + None + +------------------------------------------------------------------------------ + FUNCTION DESCRIPTION + + The IMDCT is a linear orthogonal lapped transform, based on the idea of + time domain aliasing cancellation (TDAC). + IMDCT is critically sampled, which means that though it is 50% overlapped, + a sequence data after IMDCT has the same number of coefficients as samples + before the transform (after overlap-and-add). This means, that a single + block of IMDCT data does not correspond to the original block on which the + IMDCT was performed. When subsequent blocks of inverse transformed data + are added (still using 50% overlap), the errors introduced by the + transform cancels out.Thanks to the overlapping feature, the IMDCT is very + useful for quantization. It effectively removes the otherwise easily + detectable blocking artifact between transform blocks. + + N = twice the length of input vector X + y = vector of length N, will hold fixed point IDCT + p = 0:1:N-1 + + 2 N/2-1 + y(p) = --- SUM X(m)*cos(pi/(2*N)*(2*p+1+N/2)*(2*m+1)) + N m=0 + + The window that completes the TDAC is applied before calling this function. + The IMDCT can be calculated using an IFFT, for this, the IMDCT need be + rewritten as an odd-time odd-frequency discrete Fourier transform. Thus, + the IMDCT can be calculated using only one n/4 point FFT and some pre and + post-rotation of the sample points. + + + where X(k) is the input with N frequency lines + + X(k) ---------------------------- + | + | + Pre-rotation by exp(j(2pi/N)(k+1/8)) + | + | + N/4- point IFFT + | + | + Post-rotation by exp(j(2pi/N)(n+1/8)) + | + | + ------------- x(n) In the time domain + + +------------------------------------------------------------------------------ + REQUIREMENTS + + This function should provide a fixed point IMDCT with an average + quantization error less than 1 % (variance and mean). + +------------------------------------------------------------------------------ + REFERENCES + + [1] Analysis/Synthesis Filter Bank design based on time domain + aliasing cancellation + Jhon Princen, et. al. + IEEE Transactions on ASSP, vol ASSP-34, No. 5 October 1986 + Pg 1153 - 1161 + + [2] Regular FFT-related transform kernels for DCT/DST based + polyphase filterbanks + Rolf Gluth + Proc. ICASSP 1991, pg. 2205 - 2208 + +------------------------------------------------------------------------------ + PSEUDO-CODE + + Cx, Cy are complex number + + + exp = log2(n)-1 + + FOR ( k=0; k< n/2; k +=2) + + Cx = - data_quant[k] + j data_quant[n/2-1 - k] + + freq_2_time_buffer = Cx * exp(j(2pi/n)(k+1/8)) + + ENDFOR + + CALL IFFT( freq_2_time_buffer, n/4) + + MODIFYING( freq_2_time_buffer ) + + RETURNING( shift ) + + FOR ( k=0; k< n/4; k +=2) + + Cx = freq_2_time_buffer[ k] + j freq_2_time_buffer[ k+1] + + Cy = Cx * exp(j(2pi/n)(k+1/8)) + + data_quant[3n/4-1 - k ] = Real(Cy) + data_quant[ n/4-1 - k ] = - Imag(Cy) + data_quant[3n/4 + k ] = Real(Cy) + data_quant[ n/4 + k ] = Imag(Cy) + + ENDFOR + + FOR ( k=n/4; k< n/2; k +=2) + + Cx = freq_2_time_buffer[ k] + j freq_2_time_buffer[ k+1] + + Cy = Cx * exp(j(2pi/n)(k+1/8)) + + data_quant[3n/4-1 - k ] = Real(Cy) + data_quant[ n/4 + k ] = - Real(Cy) + data_quant[5n/4 - k ] = Imag(Cy) + data_quant[ n/4 + k ] = Imag(Cy) + + ENDFOR + + MODIFIED data_quant[] + + RETURN (exp - shift) + +------------------------------------------------------------------------------ + RESOURCES USED + When the code is written for a specific target processor the + the resources used should be documented below. + + STACK USAGE: [stack count for this module] + [variable to represent + stack usage for each subroutine called] + + where: [stack usage variable] = stack usage for [subroutine + name] (see [filename].ext) + + DATA MEMORY USED: x words + + PROGRAM MEMORY USED: x words + + CLOCK CYCLES: [cycle count equation for this module] + [variable + used to represent cycle count for each subroutine + called] + + where: [cycle count variable] = cycle count for [subroutine + name] (see [filename].ext) + +------------------------------------------------------------------------------ +*/ + + +/*---------------------------------------------------------------------------- +; INCLUDES +----------------------------------------------------------------------------*/ + +#include "pv_audio_type_defs.h" +#include "imdct_fxp.h" + + +#include "mix_radix_fft.h" +#include "digit_reversal_tables.h" +#include "fft_rx4.h" +#include "inv_short_complex_rot.h" +#include "inv_long_complex_rot.h" +#include "pv_normalize.h" +#include "fxp_mul32.h" +#include "aac_mem_funcs.h" + +#include "window_block_fxp.h" + +/*---------------------------------------------------------------------------- +; MACROS +; Define module specific macros here +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; DEFINES +; Include all pre-processor statements here. Include conditional +; compile variables also. +----------------------------------------------------------------------------*/ +#define ERROR_IN_FRAME_SIZE 10 + +/*---------------------------------------------------------------------------- +; LOCAL FUNCTION DEFINITIONS +; Function Prototype declaration +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; LOCAL VARIABLE DEFINITIONS +; Variable declaration - defined here and used outside this module +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; EXTERNAL FUNCTION REFERENCES +; Declare functions defined elsewhere and referenced in this module +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; EXTERNAL VARIABLES REFERENCES +; Declare variables used in this module but defined elsewhere +----------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------- +; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES +; Declare variables used in this module but defined elsewhere +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + + +Int imdct_fxp(Int32 data_quant[], + Int32 freq_2_time_buffer[], + const Int n, + Int Q_format, + Int32 max) +{ + + Int32 exp_jw; + Int shift = 0; + + const Int32 *p_rotate; + const Int32 *p_rotate_2; + + Int32 *p_data_1; + Int32 *p_data_2; + + Int32 temp_re32; + Int32 temp_im32; + + Int shift1 = 0; + Int32 temp1; + Int32 temp2; + + Int k; + Int n_2 = n >> 1; + Int n_4 = n >> 2; + + + + if (max != 0) + { + + switch (n) + { + case SHORT_WINDOW_TYPE: + p_rotate = exp_rotation_N_256; + shift = 21; /* log2(n)-1 + 14 acomodates 2/N factor */ + break; + + case LONG_WINDOW_TYPE: + p_rotate = exp_rotation_N_2048; + shift = 24; /* log2(n)-1 +14 acomodates 2/N factor */ + break; + + default: + /* + * There is no defined behavior for a non supported frame + * size. By returning a fixed scaling factor, the input will + * scaled down and the will be heard as a low level noise + */ + return(ERROR_IN_FRAME_SIZE); + + } + + /* + * p_data_1 p_data_2 + * | | + * RIRIRIRIRIRIRIRIRIRIRIRIRIRIRI....RIRIRIRIRIRI + * | | + * + */ + + p_data_1 = data_quant; /* uses first half of buffer */ + p_data_2 = &data_quant[n_2 - 1]; /* uses second half of buffer */ + + p_rotate_2 = &p_rotate[n_4-1]; + + shift1 = pv_normalize(max) - 1; /* -1 to leave room for addition */ + Q_format -= (16 - shift1); + max = 0; + + + if (shift1 >= 0) + { + temp_re32 = *(p_data_1++) << shift1; + temp_im32 = *(p_data_2--) << shift1; + + for (k = n_4 >> 1; k != 0; k--) + { + /* + * Real and Imag parts have been swaped to use FFT as IFFT + */ + /* + * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8)) + */ + exp_jw = *p_rotate++; + + temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw); + temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw); + + temp_im32 = *(p_data_1--) << shift1; + temp_re32 = *(p_data_2--) << shift1; + *(p_data_1++) = temp1; + *(p_data_1++) = temp2; + max |= (temp1 >> 31) ^ temp1; + max |= (temp2 >> 31) ^ temp2; + + + /* + * Real and Imag parts have been swaped to use FFT as IFFT + */ + + /* + * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8)) + */ + + exp_jw = *p_rotate_2--; + + temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw); + temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw); + + + temp_re32 = *(p_data_1++) << shift1; + temp_im32 = *(p_data_2--) << shift1; + + *(p_data_2 + 2) = temp1; + *(p_data_2 + 3) = temp2; + max |= (temp1 >> 31) ^ temp1; + max |= (temp2 >> 31) ^ temp2; + + } + } + else + { + temp_re32 = *(p_data_1++) >> 1; + temp_im32 = *(p_data_2--) >> 1; + + for (k = n_4 >> 1; k != 0; k--) + { + /* + * Real and Imag parts have been swaped to use FFT as IFFT + */ + /* + * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8)) + */ + exp_jw = *p_rotate++; + + temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw); + temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw); + + temp_im32 = *(p_data_1--) >> 1; + temp_re32 = *(p_data_2--) >> 1; + *(p_data_1++) = temp1; + *(p_data_1++) = temp2; + + max |= (temp1 >> 31) ^ temp1; + max |= (temp2 >> 31) ^ temp2; + + + /* + * Real and Imag parts have been swaped to use FFT as IFFT + */ + + /* + * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8)) + */ + exp_jw = *p_rotate_2--; + + temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw); + temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw); + + temp_re32 = *(p_data_1++) >> 1; + temp_im32 = *(p_data_2--) >> 1; + + *(p_data_2 + 3) = temp2; + *(p_data_2 + 2) = temp1; + + max |= (temp1 >> 31) ^ temp1; + max |= (temp2 >> 31) ^ temp2; + + } + } + + + if (n != SHORT_WINDOW_TYPE) + { + + shift -= mix_radix_fft(data_quant, + &max); + + shift -= inv_long_complex_rot(data_quant, + max); + + } + else /* n_4 is 64 */ + { + + shift -= fft_rx4_short(data_quant, &max); + + + shift -= inv_short_complex_rot(data_quant, + freq_2_time_buffer, + max); + + pv_memcpy(data_quant, + freq_2_time_buffer, + SHORT_WINDOW*sizeof(*data_quant)); + } + + } + else + { + Q_format = ALL_ZEROS_BUFFER; + } + + return(shift + Q_format); + +} /* imdct_fxp */ |