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;
    }
  }
}
Esempio n. 4
0
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);
}