void FFTFrame::doInverseFFT(float* data) { Ipp32f* complexP = getUpToDateComplexData(); // Compute inverse transform. ippsDFTInv_PermToR_32f(complexP, reinterpret_cast<Ipp32f*>(data), m_DFTSpec, m_buffer); // Scale so that a forward then inverse FFT yields exactly the original data. const float scale = 1.0 / (2 * m_FFTSize); ippsMulC_32f_I(scale, reinterpret_cast<Ipp32f*>(data), m_FFTSize); }
void FFTFrame::doFFT(const float* data) { Ipp32f* complexP = m_complexData.data(); // Compute Forward transform to perm format. ippsDFTFwd_RToPerm_32f(reinterpret_cast<Ipp32f*>(const_cast<float*>(data)), complexP, m_DFTSpec, m_buffer); const Ipp32f scale = 2.0f; ippsMulC_32f_I(scale, complexP, m_FFTSize); Ipp32f* realP = m_realData.data(); Ipp32f* imagP = m_imagData.data(); ippsCplxToReal_32fc(reinterpret_cast<Ipp32fc*>(complexP), realP, imagP, m_FFTSize >> 1); }
void Quantization(sQuantizationBlock* pBlock, sEnc_individual_channel_stream* pStream, sQuantizationData* qData) { #if !defined(ANDROID) IPP_ALIGNED_ARRAY(32, Ipp32f, mdct_line_abs, N_LONG/2); IPP_ALIGNED_ARRAY(32, Ipp32f, mdct_scaled, N_LONG/2); #else static IPP_ALIGNED_ARRAY(32, Ipp32f, mdct_line_abs, N_LONG/2); static IPP_ALIGNED_ARRAY(32, Ipp32f, mdct_scaled, N_LONG/2); #endif Ipp32f* mdct_line = qData->mdct_line; Ipp32f* bitsToPeCoeff = qData->bitsToPeCoeff; Ipp32f* scalefactorDataBits = qData->scalefactorDataBits; Ipp32s* sfb_offset = pStream->sfb_offset; Ipp32s* sfb_width = pStream->sfb_width; Ipp32s win, sfb; Ipp32s firstNonZeroSfb; Ipp32s bitsForScaleFactorData; ippsAbs_32f(mdct_line, mdct_line_abs, pStream->max_line); ippsPow34_32f(mdct_line_abs, mdct_scaled, pStream->max_line); pBlock->start_common_scalefac = -SF_OFFSET; pBlock->finish_common_scalefac = -SF_OFFSET; if (pBlock->ns_mode) { #if !defined(ANDROID) Ipp32s startSF[MAX_SECTION_NUMBER]; Ipp32s finishSF[MAX_SECTION_NUMBER]; Ipp16s maxXQuant[MAX_SECTION_NUMBER]; #else static Ipp32s startSF[MAX_SECTION_NUMBER]; static Ipp32s finishSF[MAX_SECTION_NUMBER]; static Ipp16s maxXQuant[MAX_SECTION_NUMBER]; #endif Ipp16s* ns_scale_factors = pBlock->ns_scale_factors; Ipp16s* pMaxXQuant = maxXQuant; Ipp32s numSfb = pStream->num_window_groups * pStream->max_sfb; Ipp32s minSf = 100000; Ipp32s maxSf = -100000; for (sfb = 0; sfb < numSfb; sfb++) { aac_LimitSF(mdct_scaled + sfb_offset[sfb], sfb_width[sfb], &startSF[sfb], &finishSF[sfb]); } aac_FindSF(pStream, qData, mdct_scaled, mdct_line_abs, startSF, finishSF, ns_scale_factors, maxXQuant); aac_MinMaxSF(pStream, mdct_scaled, startSF, ns_scale_factors, maxXQuant, &minSf, &maxSf, 60); aac_UpdateSF(pStream, mdct_scaled, mdct_line_abs, startSF, ns_scale_factors, maxXQuant, minSf, *bitsToPeCoeff, 0.2f * pBlock->bits_per_frame); aac_MinMaxSF(pStream, mdct_scaled, startSF, ns_scale_factors, maxXQuant, &minSf, &maxSf, 60); for (sfb = 0; sfb < numSfb; sfb++) { if (maxXQuant[sfb] != 0) { ns_scale_factors[sfb] = (Ipp16s)(maxSf - ns_scale_factors[sfb]); if (ns_scale_factors[sfb] > 0) { Ipp32f mul = (Ipp32f)scalefac_pow[SF_OFFSET - ns_scale_factors[sfb]]; ippsMulC_32f_I(mul, mdct_scaled + sfb_offset[sfb], sfb_width[sfb]); } } } for (win = 0; win < pStream->num_window_groups; win++) { firstNonZeroSfb = -1; for (sfb = 0; sfb < pStream->max_sfb; sfb++) { if (pMaxXQuant[sfb] != 0) { if (firstNonZeroSfb < 0) { firstNonZeroSfb = sfb; } } } if (firstNonZeroSfb < 0) { for (sfb = 0; sfb < pStream->max_sfb; sfb++) { ns_scale_factors[sfb] = 0; } } else { for (sfb = 0; sfb < firstNonZeroSfb; sfb++) { ns_scale_factors[sfb] = ns_scale_factors[firstNonZeroSfb]; } for (sfb = firstNonZeroSfb + 1; sfb < pStream->max_sfb; sfb++) { if (pMaxXQuant[sfb] == 0) { ns_scale_factors[sfb] = ns_scale_factors[sfb - 1]; } } } ns_scale_factors += pStream->max_sfb; pMaxXQuant += pStream->max_sfb; } ns_scale_factors = pBlock->ns_scale_factors; pBlock->last_frame_common_scalefactor[0] = maxSf; pBlock->common_scalefactor_update[0] = 1; } aac_LimitSF(mdct_scaled, pStream->max_line, &pBlock->start_common_scalefac, &pBlock->finish_common_scalefac); main_loop(pBlock, pStream, mdct_line, mdct_scaled, &bitsForScaleFactorData); if (pBlock->ns_mode) { #if !defined(ANDROID) IPP_ALIGNED_ARRAY(32, Ipp32f, mdct_rqnt, N_LONG/2); IPP_ALIGNED_ARRAY(32, Ipp16s, x_quant_unsigned, N_LONG/2); Ipp32f noise[MAX_SECTION_NUMBER]; #else static IPP_ALIGNED_ARRAY(32, Ipp32f, mdct_rqnt, N_LONG/2); static IPP_ALIGNED_ARRAY(32, Ipp16s, x_quant_unsigned, N_LONG/2); static Ipp32f noise[MAX_SECTION_NUMBER]; #endif Ipp32s numSfb = pStream->num_window_groups * pStream->max_sfb; Ipp32f pe = 0, real_sf; *scalefactorDataBits = (*scalefactorDataBits) * 0.9f + bitsForScaleFactorData * 0.1f; for (sfb = 0; sfb < numSfb; sfb++) { Ipp32s scalefactor = pStream->scale_factors[sfb] + pBlock->ns_scale_factors[sfb]; Ipp32f sf = (Ipp32f)scalefac_pow[scalefactor]; Ipp32f temp = (Ipp32f)(MAGIC_NUMBER - 0.5f)/sf; Ipp32s sfb_start = sfb_offset[sfb]; Ipp32f energy = qData->energy[sfb]; #if 0 ippsNoiseCalculation_32f(mdct_scaled + sfb_start, mdct_line_abs + sfb_start, temp, sf, x_quant_unsigned, sfb_width[sfb], pStream->scale_factors[sfb]-SF_OFFSET, &noise[sfb], (Ipp8u*)mdct_rqnt); #else ippsAddC_32f(mdct_scaled + sfb_start, temp, mdct_rqnt, sfb_width[sfb]); ippsMulC_Low_32f16s(mdct_rqnt, sf, (Ipp16s*)x_quant_unsigned, sfb_width[sfb]); ippsPow43_16s32f(x_quant_unsigned, mdct_rqnt, sfb_width[sfb]); ippsCalcSF_16s32f(&pStream->scale_factors[sfb], SF_OFFSET, &real_sf, 1); ippsMulC_32f_I(real_sf, mdct_rqnt, sfb_width[sfb]); ippsSub_32f_I(mdct_line_abs + sfb_start, mdct_rqnt, sfb_width[sfb]); ippsDotProd_32f(mdct_rqnt, mdct_rqnt, sfb_width[sfb], &noise[sfb]); #endif if (energy > noise[sfb]) { pe += (Ipp32f)(sfb_width[sfb] * log10(energy / noise[sfb])); } } qData->outPe = pe; if (pe > 0) { *bitsToPeCoeff = (*bitsToPeCoeff) * 0.9f + (pe/(pBlock->used_bits - bitsForScaleFactorData)) * 0.1f; } } }
void IQSSBDemodulator::process_block(Ipp32f* iq_block, Ipp32f* out_block) { static bool flip=false; // Deinterleave to real and imaginary (I and Q) buffers ippsDeinterleave_32f(iq_block, 2, BLKSIZE, _iq); ippsZero_32f(_in_re+BLKSIZE, NFFT-BLKSIZE); ippsZero_32f(_in_im+BLKSIZE, NFFT-BLKSIZE); // _in_re now contains the real/I part and // _in_im now contains the imaginary/Q part ippsFFTFwd_CToC_32f_I(_in_re, _in_im, _fft_specs, _fft_buf); ippsCartToPolar_32f(_in_re, _in_im, _in_m, _in_p, NFFT); // layout of frequency bins is // NFFT/2 to NFFT-1 and then continues from 0 to NFFT/2-1 // shift desired part to 0Hz int lo = _lo*NFFT; circshift(_in_m, NFFT, lo); circshift(_in_p, NFFT, lo); // zero out undesired sideband if(_sideband == USB) { // zero out LSB, that is NFFT/2 to NFFT-1 ippsZero_32f(_in_m+NFFT/2, NFFT/2); ippsZero_32f(_in_p+NFFT/2, NFFT/2); } else // _sideband must be LSB { // zero out USB, that is 0 to NFFT/2-1 ippsZero_32f(_in_m, NFFT/2); ippsZero_32f(_in_p, NFFT/2); } // filter the passband ippsMul_32f_I(_fir_taps_m, _in_m, NFFT); ippsAdd_32f_I(_fir_taps_p, _in_p, NFFT); // return to time domain ippsPolarToCart_32f(_in_m, _in_p, _in_re, _in_im, NFFT); ippsFFTInv_CToC_32f_I(_in_re, _in_im, _fft_specs, _fft_buf); // do overlap/add // // 1) add the residual from last round ippsAdd_32f_I(_residual_re, _in_re, _residual_length); ippsAdd_32f_I(_residual_im, _in_im, _residual_length); // 2) Store the new residual if(flip) { ippsMulC_32f_I(-1.0, _in_re, NFFT); ippsMulC_32f_I(-1.0, _in_im, NFFT); flip=!flip; } ippsCopy_32f(_in_re+BLKSIZE, _residual_re, _residual_length); ippsCopy_32f(_in_im+BLKSIZE, _residual_im, _residual_length); // agc agc(_in_re, BLKSIZE); // deliver the result ippsCopy_32f(_in_re, out_block, BLKSIZE); }