mirror of
				https://gitlab.com/ecodis/exhale.git
				synced 2025-06-05 21:59:32 +02:00 
			
		
		
		
	M/S fix and cleanup
This commit is contained in:
		| @@ -11,6 +11,68 @@ | |||||||
| #include "exhaleLibPch.h" | #include "exhaleLibPch.h" | ||||||
| #include "stereoProcessing.h" | #include "stereoProcessing.h" | ||||||
|  |  | ||||||
|  | // static helper functions | ||||||
|  | static inline uint64_t complexAbsMS (const int32_t realPart, const int32_t imagPart) | ||||||
|  | { | ||||||
|  | #if SA_EXACT_COMPLEX_ABS | ||||||
|  |   const double complexSqr = (double) realPart * (double) realPart + (double) imagPart * (double) imagPart; | ||||||
|  |  | ||||||
|  |   return uint64_t (sqrt (complexSqr) + 0.5); | ||||||
|  | #else | ||||||
|  |   const uint64_t absReal  = abs (realPart); // Richard Lyons, 1997; en.wikipedia.org/ | ||||||
|  |   const uint64_t absImag  = abs (imagPart); // wiki/Alpha_max_plus_beta_min_algorithm | ||||||
|  |  | ||||||
|  |   return (absReal > absImag ? absReal + ((absImag * 3) >> 3) : absImag + ((absReal * 3) >> 3)); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int32_t  getMidSample (const int64_t value1, const int64_t value2) | ||||||
|  | { | ||||||
|  |   return int32_t ((value1 + value2 + 1) >> 1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int32_t getSideSample (const int64_t value1, const int64_t value2) | ||||||
|  | { | ||||||
|  |   return int32_t ((value1 - value2 + 1) >> 1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int32_t getResiSample (const int64_t valueR, const int64_t valueD, const int64_t alphaQ) | ||||||
|  | { | ||||||
|  |   return int32_t (valueR - ((valueD * alphaQ - SHRT_MIN) >> 16)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void   setStepSizesMS (const uint32_t* const rmsSfbL, const uint32_t* const rmsSfbR, | ||||||
|  |                                      const uint32_t* const rmsSfbM, const uint32_t* const rmsSfbS, | ||||||
|  |                                      const uint32_t* const grpRms1, const uint32_t* const grpRms2, | ||||||
|  |                                      uint32_t* const grpStepSizes1, uint32_t* const grpStepSizes2, | ||||||
|  |                                      const uint16_t sfb, const uint16_t b, const bool applyPredSte) | ||||||
|  | { | ||||||
|  |   const uint16_t     idx = sfb + b; | ||||||
|  |   const uint32_t sfbRmsL = __max (SP_EPS, rmsSfbL[b]); | ||||||
|  |   const uint32_t sfbRmsR = __max (SP_EPS, rmsSfbR[b]); | ||||||
|  |   const double  sfbFacLR = (sfbRmsL < (grpStepSizes1[idx] >> 1) ? 1.0 : 2.0) * (sfbRmsR < (grpStepSizes2[idx] >> 1) ? 1.0 : 2.0); | ||||||
|  |   const double  sfbMaxMS = (applyPredSte ? __max (rmsSfbM[b], rmsSfbS[b]) : __max (grpRms1[idx], grpRms2[idx])); | ||||||
|  |  | ||||||
|  |   if ((grpStepSizes1[idx] == 0) || (grpStepSizes2[idx] == 0))  // HF noise filled SFB | ||||||
|  |   { | ||||||
|  |     grpStepSizes1[idx] = grpStepSizes2[idx] = 0; | ||||||
|  |   } | ||||||
|  |   else if (sfbFacLR <= 1.0) // simultaneous masking, so no positive SNR in either SFB | ||||||
|  |   { | ||||||
|  |     const double max = __max (sfbRmsL, sfbRmsR); | ||||||
|  |  | ||||||
|  |     grpStepSizes1[idx] = grpStepSizes2[idx] = uint32_t (__max (grpStepSizes1[idx], grpStepSizes2[idx]) * (sfbMaxMS / max) + 0.5); | ||||||
|  |   } | ||||||
|  |   else // partial/no masking, redistribute positive SNR into at least one channel SFB | ||||||
|  |   { | ||||||
|  |     const double min = (applyPredSte ? __min (rmsSfbM[b], rmsSfbS[b]) : __min (grpRms1[idx], grpRms2[idx])); | ||||||
|  |     const double rat = __min (1.0, grpStepSizes1[idx] / (sfbRmsL * 2.0)) * __min (1.0, grpStepSizes2[idx] / (sfbRmsR * 2.0)) * sfbFacLR; | ||||||
|  |  | ||||||
|  |     grpStepSizes1[idx] = grpStepSizes2[idx] = uint32_t (__max (SP_EPS, (min > rat * sfbMaxMS ? sqrt (rat * sfbMaxMS * min) : | ||||||
|  |                                                                         __min (1.0, rat) * sfbMaxMS)) + 0.5); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| // constructor | // constructor | ||||||
| StereoProcessor::StereoProcessor () | StereoProcessor::StereoProcessor () | ||||||
| { | { | ||||||
| @@ -33,7 +95,15 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|   const bool  eightShorts = (grp.numWindowGroups > 1); |   const bool  eightShorts = (grp.numWindowGroups > 1); | ||||||
|   const uint8_t maxSfbSte = (eightShorts ? __min (numSwbFrame, __max (grp.sfbsPerGroup, groupingData2.sfbsPerGroup) + 1) : numSwbFrame); |   const uint8_t maxSfbSte = (eightShorts ? __min (numSwbFrame, __max (grp.sfbsPerGroup, groupingData2.sfbsPerGroup) + 1) : numSwbFrame); | ||||||
|   const bool  perCorrData = (usePerCorrData && !eightShorts); // use perceptual correlation? |   const bool  perCorrData = (usePerCorrData && !eightShorts); // use perceptual correlation? | ||||||
|  |   uint32_t rmsSfbL[2] = {0, 0}, rmsSfbR[2] = {0, 0}; | ||||||
|   uint32_t  numSfbPredSte = 0; // counter |   uint32_t  numSfbPredSte = 0; // counter | ||||||
|  | #if SP_SFB_WISE_STEREO | ||||||
|  |   uint16_t  numSfbNoMsSte = 0, idxSfbNoMsSte = 0; | ||||||
|  |   uint32_t rms1NoMsSte[2] = {0, 0}, rms2NoMsSte[2] = {0, 0}; | ||||||
|  |   uint32_t rmsMNoMsSte[2] = {0, 0}, rmsSNoMsSte[2] = {0, 0}; | ||||||
|  |   uint8_t  dataNoMsSte[2] = {0, 0}; | ||||||
|  |   bool nonZeroPredNoMsSte = false; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   if ((mdctSpectrum1 == nullptr) || (mdctSpectrum2 == nullptr) || (numSwbFrame < maxSfbSte) || (grp.numWindowGroups != groupingData2.numWindowGroups) || |   if ((mdctSpectrum1 == nullptr) || (mdctSpectrum2 == nullptr) || (numSwbFrame < maxSfbSte) || (grp.numWindowGroups != groupingData2.numWindowGroups) || | ||||||
|       (sfbStepSize1  == nullptr) || (sfbStepSize2  == nullptr) || (numSwbFrame < MIN_NUM_SWB_SHORT) || (numSwbFrame > MAX_NUM_SWB_LONG)) |       (sfbStepSize1  == nullptr) || (sfbStepSize2  == nullptr) || (numSwbFrame < MIN_NUM_SWB_SHORT) || (numSwbFrame > MAX_NUM_SWB_LONG)) | ||||||
| @@ -53,22 +123,22 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|  |  | ||||||
|   for (uint16_t gr = 0; gr < grp.numWindowGroups; gr++) |   for (uint16_t gr = 0; gr < grp.numWindowGroups; gr++) | ||||||
|   { |   { | ||||||
|  |     const uint16_t grOffset = numSwbFrame * gr; | ||||||
|     const bool realOnlyCalc = (filterData1.numFilters > 0 && gr == filterData1.filteredWindow) || (mdstSpectrum1 == nullptr) || |     const bool realOnlyCalc = (filterData1.numFilters > 0 && gr == filterData1.filteredWindow) || (mdstSpectrum1 == nullptr) || | ||||||
|                               (filterData2.numFilters > 0 && gr == filterData2.filteredWindow) || (mdstSpectrum2 == nullptr); |                               (filterData2.numFilters > 0 && gr == filterData2.filteredWindow) || (mdstSpectrum2 == nullptr); | ||||||
|     const uint16_t*  grpOff = &grp.sfbOffsets[numSwbFrame * gr]; |     const uint16_t*  grpOff = &grp.sfbOffsets[grOffset]; | ||||||
|     uint32_t* const grpRms1 = &groupingData1.sfbRmsValues[numSwbFrame * gr]; |     uint32_t* const grpRms1 = &groupingData1.sfbRmsValues[grOffset]; | ||||||
|     uint32_t* const grpRms2 = &groupingData2.sfbRmsValues[numSwbFrame * gr]; |     uint32_t* const grpRms2 = &groupingData2.sfbRmsValues[grOffset]; | ||||||
|     uint32_t* grpStepSizes1 = &sfbStepSize1[numSwbFrame * gr]; |     uint32_t* grpStepSizes1 = &sfbStepSize1[grOffset]; | ||||||
|     uint32_t* grpStepSizes2 = &sfbStepSize2[numSwbFrame * gr]; |     uint32_t* grpStepSizes2 = &sfbStepSize2[grOffset]; | ||||||
|     int32_t  b = 0, prevReM = 0, prevReS = 0; |     int32_t  b = 0, prevReM = 0, prevReS = 0; | ||||||
|     uint32_t rmsSfbL[2] = {0, 0}, rmsSfbR[2] = {0, 0}; |  | ||||||
|  |  | ||||||
|     if (realOnlyCalc) // preparation for first magnitude value |     if (realOnlyCalc) // preparation for first magnitude value | ||||||
|     { |     { | ||||||
|       const uint16_t sPlus1 = grpOff[0] + 1; |       const uint16_t sIndex = grpOff[realOnlyOffset] + (grpOff[realOnlyOffset] > 0 ? -1 : 1); | ||||||
|  |  | ||||||
|       prevReM = int32_t (((int64_t) mdctSpectrum1[sPlus1] + (int64_t) mdctSpectrum2[sPlus1] + 1) >> 1); |       prevReM = getMidSample (mdctSpectrum1[sIndex], mdctSpectrum2[sIndex]); | ||||||
|       prevReS = int32_t (((int64_t) mdctSpectrum1[sPlus1] - (int64_t) mdctSpectrum2[sPlus1] + 1) >> 1); |       prevReS = getSideSample(mdctSpectrum1[sIndex], mdctSpectrum2[sIndex]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     for (uint16_t sfb = 0; sfb < maxSfbSte; sfb++) |     for (uint16_t sfb = 0; sfb < maxSfbSte; sfb++) | ||||||
| @@ -78,10 +148,8 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|       const uint16_t sfbWidth = grpOff[sfb + 1] - sfbStart; |       const uint16_t sfbWidth = grpOff[sfb + 1] - sfbStart; | ||||||
|       int32_t* sfbMdct1 = &mdctSpectrum1[sfbStart]; |       int32_t* sfbMdct1 = &mdctSpectrum1[sfbStart]; | ||||||
|       int32_t* sfbMdct2 = &mdctSpectrum2[sfbStart]; |       int32_t* sfbMdct2 = &mdctSpectrum2[sfbStart]; | ||||||
| #if SP_MDST_PRED |  | ||||||
|       int32_t* sfbMdst1 = &mdstSpectrum1[sfbStart]; |       int32_t* sfbMdst1 = &mdstSpectrum1[sfbStart]; | ||||||
|       int32_t* sfbMdst2 = &mdstSpectrum2[sfbStart]; |       int32_t* sfbMdst2 = &mdstSpectrum2[sfbStart]; | ||||||
| #endif |  | ||||||
|       uint64_t sumAbsValM = 0, sumAbsValS = 0; |       uint64_t sumAbsValM = 0, sumAbsValS = 0; | ||||||
|       double   sfbTempVar; |       double   sfbTempVar; | ||||||
|  |  | ||||||
| @@ -96,85 +164,61 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|         memcpy (m_originBandMdst2, sfbMdst2, cpyWidth); |         memcpy (m_originBandMdst2, sfbMdst2, cpyWidth); | ||||||
|       } |       } | ||||||
| #endif | #endif | ||||||
|       if (realOnlyCalc) // real data, only MDCTs are available |       if (realOnlyCalc && (sfb >= realOnlyOffset)) // real-valued data, only MDCTs available | ||||||
|       { |       { | ||||||
|         const int32_t* sfbNext1 = &sfbMdct1[1]; |         const int32_t* sfbNext1 = &sfbMdct1[1]; | ||||||
|         const int32_t* sfbNext2 = &sfbMdct2[1]; |         const int32_t* sfbNext2 = &sfbMdct2[1]; | ||||||
|  |  | ||||||
|         for (uint16_t s = sfbWidth - (sfb + 1 == numSwbFrame ? 1 : 0); s > 0; s--) |         for (uint16_t s = sfbWidth - (sfb + 1 == numSwbFrame ? 1 : 0); s > 0; s--) | ||||||
|         { |         { | ||||||
|           const int32_t dmixReM = int32_t (((int64_t) *sfbMdct1 + (int64_t) *sfbMdct2 + 1) >> 1); |           const int32_t dmixReM = getMidSample (*sfbMdct1, *sfbMdct2); | ||||||
|           const int32_t dmixReS = int32_t (((int64_t) *sfbMdct1 - (int64_t) *sfbMdct2 + 1) >> 1); |           const int32_t dmixReS = getSideSample(*sfbMdct1, *sfbMdct2); | ||||||
|           // TODO: improve the following lines since the calculation is partially redundant! |           // TODO: improve the following lines since the calculation is partially redundant! | ||||||
|           const int32_t dmixImM = int32_t ((((*sfbNext1 + (int64_t) *sfbNext2 + 1) >> 1) - (int64_t) prevReM) >> 1); // estimate, see also |           const int32_t dmixImM = int32_t ((getMidSample (*sfbNext1, *sfbNext2) - (int64_t) prevReM) >> 1); // estimate, see also | ||||||
|           const int32_t dmixImS = int32_t ((((*sfbNext1 - (int64_t) *sfbNext2 + 1) >> 1) - (int64_t) prevReS) >> 1); // getMeanAbsValues() |           const int32_t dmixImS = int32_t ((getSideSample(*sfbNext1, *sfbNext2) - (int64_t) prevReS) >> 1); // getMeanAbsValues() | ||||||
|  |  | ||||||
|           const uint64_t absReM = abs (dmixReM); |           sumAbsValM += complexAbsMS (dmixReM, dmixImM); | ||||||
|           const uint64_t absReS = abs (dmixReS);   // Richard Lyons, 1997; en.wikipedia.org/ |           sumAbsValS += complexAbsMS (dmixReS, dmixImS); | ||||||
|           const uint64_t absImM = abs (dmixImM);   // wiki/Alpha_max_plus_beta_min_algorithm |  | ||||||
|           const uint64_t absImS = abs (dmixImS); |  | ||||||
|  |  | ||||||
|           sumAbsValM += (absReM > absImM ? absReM + ((absImM * 3) >> 3) : absImM + ((absReM * 3) >> 3)); |  | ||||||
|           sumAbsValS += (absReS > absImS ? absReS + ((absImS * 3) >> 3) : absImS + ((absReS * 3) >> 3)); |  | ||||||
|  |  | ||||||
|           *(sfbMdct1++) = dmixReM; |           *(sfbMdct1++) = dmixReM; | ||||||
|           *(sfbMdct2++) = dmixReS; |           *(sfbMdct2++) = dmixReS; | ||||||
| #if SP_MDST_PRED |  | ||||||
|           *(sfbMdst1++) = dmixImM; |           *(sfbMdst1++) = dmixImM; | ||||||
|           *(sfbMdst2++) = dmixImS; |           *(sfbMdst2++) = dmixImS; | ||||||
| #endif |  | ||||||
|           sfbNext1++; prevReM = dmixReM; |           sfbNext1++; prevReM = dmixReM; | ||||||
|           sfbNext2++; prevReS = dmixReS; |           sfbNext2++; prevReS = dmixReS; | ||||||
|         } |         } | ||||||
|         if (sfb + 1 == numSwbFrame) // handle remaining sample |         if (sfb + 1 == numSwbFrame) // process the last sample | ||||||
|         { |         { | ||||||
|           const int32_t dmixReM = int32_t (((int64_t) *sfbMdct1 + (int64_t) *sfbMdct2 + 1) >> 1); |           const int32_t dmixReM = getMidSample (*sfbMdct1, *sfbMdct2); | ||||||
|           const int32_t dmixReS = int32_t (((int64_t) *sfbMdct1 - (int64_t) *sfbMdct2 + 1) >> 1); |           const int32_t dmixReS = getSideSample(*sfbMdct1, *sfbMdct2); | ||||||
|  |  | ||||||
|           sumAbsValM += abs (dmixReM); |           sumAbsValM += abs (dmixReM); | ||||||
|           sumAbsValS += abs (dmixReS); |           sumAbsValS += abs (dmixReS); | ||||||
|  |  | ||||||
|           *sfbMdct1 = dmixReM; |           *sfbMdct1 = dmixReM; | ||||||
|           *sfbMdct2 = dmixReS; |           *sfbMdct2 = dmixReS; | ||||||
| #if SP_MDST_PRED |  | ||||||
|           *sfbMdst1 = 0; |           *sfbMdst1 = 0; | ||||||
|           *sfbMdst2 = 0; |           *sfbMdst2 = 0; | ||||||
| #endif |  | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       else // complex data, both MDCTs and MDSTs are available |       else // complex data, both MDCTs and MDSTs are available | ||||||
|       { |       { | ||||||
| #if !SP_MDST_PRED |  | ||||||
|         int32_t* sfbMdst1 = &mdstSpectrum1[sfbStart]; |  | ||||||
|         int32_t* sfbMdst2 = &mdstSpectrum2[sfbStart]; |  | ||||||
| #endif |  | ||||||
|         for (uint16_t s = sfbWidth; s > 0; s--) |         for (uint16_t s = sfbWidth; s > 0; s--) | ||||||
|         { |         { | ||||||
|           const int32_t dmixReM = int32_t (((int64_t) *sfbMdct1 + (int64_t) *sfbMdct2 + 1) >> 1); |           const int32_t dmixReM = getMidSample (*sfbMdct1, *sfbMdct2); | ||||||
|           const int32_t dmixReS = int32_t (((int64_t) *sfbMdct1 - (int64_t) *sfbMdct2 + 1) >> 1); |           const int32_t dmixReS = getSideSample(*sfbMdct1, *sfbMdct2); | ||||||
|           const int32_t dmixImM = int32_t (((int64_t) *sfbMdst1 + (int64_t) *sfbMdst2 + 1) >> 1); |           const int32_t dmixImM = getMidSample (*sfbMdst1, *sfbMdst2); | ||||||
|           const int32_t dmixImS = int32_t (((int64_t) *sfbMdst1 - (int64_t) *sfbMdst2 + 1) >> 1); |           const int32_t dmixImS = getSideSample(*sfbMdst1, *sfbMdst2); | ||||||
| #if SA_EXACT_COMPLEX_ABS |  | ||||||
|           const double cplxSqrM = (double) dmixReM * (double) dmixReM + (double) dmixImM * (double) dmixImM; |  | ||||||
|           const double cplxSqrS = (double) dmixReS * (double) dmixReS + (double) dmixImS * (double) dmixImS; |  | ||||||
|  |  | ||||||
|           sumAbsValM += uint64_t (sqrt (cplxSqrM) + 0.5); |           sumAbsValM += complexAbsMS (dmixReM, dmixImM); | ||||||
|           sumAbsValS += uint64_t (sqrt (cplxSqrS) + 0.5); |           sumAbsValS += complexAbsMS (dmixReS, dmixImS); | ||||||
| #else |  | ||||||
|           const uint64_t absReM = abs (dmixReM); |  | ||||||
|           const uint64_t absReS = abs (dmixReS);   // Richard Lyons, 1997; en.wikipedia.org/ |  | ||||||
|           const uint64_t absImM = abs (dmixImM);   // wiki/Alpha_max_plus_beta_min_algorithm |  | ||||||
|           const uint64_t absImS = abs (dmixImS); |  | ||||||
|  |  | ||||||
|           sumAbsValM += (absReM > absImM ? absReM + ((absImM * 3) >> 3) : absImM + ((absReM * 3) >> 3)); |  | ||||||
|           sumAbsValS += (absReS > absImS ? absReS + ((absImS * 3) >> 3) : absImS + ((absReS * 3) >> 3)); |  | ||||||
| #endif |  | ||||||
|           *(sfbMdct1++) = dmixReM; |           *(sfbMdct1++) = dmixReM; | ||||||
|           *(sfbMdct2++) = dmixReS; |           *(sfbMdct2++) = dmixReS; | ||||||
|           *(sfbMdst1++) = dmixImM; |           *(sfbMdst1++) = dmixImM; | ||||||
|           *(sfbMdst2++) = dmixImS; |           *(sfbMdst2++) = dmixImS; | ||||||
|         } |         } | ||||||
|       } // realOnlyCalc |       } // realOnlyCalc && sfb >= realOnlyOffset | ||||||
|  |  | ||||||
|       rmsSfbL[sfbIsOdd] = grpRms1[sfb]; |       rmsSfbL[sfbIsOdd] = grpRms1[sfb]; | ||||||
|       rmsSfbR[sfbIsOdd] = grpRms2[sfb]; |       rmsSfbR[sfbIsOdd] = grpRms2[sfb]; | ||||||
| @@ -182,7 +226,7 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|       grpRms1[sfb] = uint32_t ((sumAbsValM + (sfbWidth >> 1)) / sfbWidth); |       grpRms1[sfb] = uint32_t ((sumAbsValM + (sfbWidth >> 1)) / sfbWidth); | ||||||
|       grpRms2[sfb] = uint32_t ((sumAbsValS + (sfbWidth >> 1)) / sfbWidth); |       grpRms2[sfb] = uint32_t ((sumAbsValS + (sfbWidth >> 1)) / sfbWidth); | ||||||
|  |  | ||||||
|       if (applyPredSte) sfbStereoData[sfb + numSwbFrame * gr] = 16; // initialize to alpha=0 |       if (applyPredSte) sfbStereoData[sfb + grOffset] = 16; // initialize to alpha_q to zero | ||||||
|  |  | ||||||
|       if ((sfbIsOdd) || (sfb + 1 == maxSfbSte)) // finish pair |       if ((sfbIsOdd) || (sfb + 1 == maxSfbSte)) // finish pair | ||||||
|       { |       { | ||||||
| @@ -196,15 +240,12 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|           const uint16_t width = grpOff[sfb + 1] - offEv; |           const uint16_t width = grpOff[sfb + 1] - offEv; | ||||||
|           const int32_t* mdctA = (alterPredDir ? &mdctSpectrum2[offEv] : &mdctSpectrum1[offEv]); |           const int32_t* mdctA = (alterPredDir ? &mdctSpectrum2[offEv] : &mdctSpectrum1[offEv]); | ||||||
|           const int32_t* mdctB = (alterPredDir ? &mdctSpectrum1[offEv] : &mdctSpectrum2[offEv]); |           const int32_t* mdctB = (alterPredDir ? &mdctSpectrum1[offEv] : &mdctSpectrum2[offEv]); | ||||||
| #if SP_MDST_PRED |  | ||||||
|           const int32_t* mdstA = (alterPredDir ? &mdstSpectrum2[offEv] : &mdstSpectrum1[offEv]); |           const int32_t* mdstA = (alterPredDir ? &mdstSpectrum2[offEv] : &mdstSpectrum1[offEv]); | ||||||
|           const int32_t* mdstB = (alterPredDir ? &mdstSpectrum1[offEv] : &mdstSpectrum2[offEv]); |           const int32_t* mdstB = (alterPredDir ? &mdstSpectrum1[offEv] : &mdstSpectrum2[offEv]); | ||||||
|           int64_t sumPrdImAReB = 0, sumPrdImAImA = SP_EPS; |  | ||||||
| #endif |  | ||||||
|           int64_t sumPrdReAReB = 0, sumPrdReAReA = SP_EPS;  // stabilizes the division below |           int64_t sumPrdReAReB = 0, sumPrdReAReA = SP_EPS;  // stabilizes the division below | ||||||
|  |           int64_t sumPrdImAReB = 0, sumPrdImAImA = SP_EPS; | ||||||
|           double d, alphaLimit = 1.5; // max alpha_q magnitude |           double d, alphaLimit = 1.5; // max alpha_q magnitude | ||||||
|  |  | ||||||
| #if SP_MDST_PRED |  | ||||||
|           for (uint16_t s = width; s > 0; s--, mdctA++, mdctB++, mdstA++, mdstB++) |           for (uint16_t s = width; s > 0; s--, mdctA++, mdctB++, mdstA++, mdstB++) | ||||||
|           { |           { | ||||||
|             const int64_t prdReAReA = ((int64_t) *mdctA * (int64_t) *mdctA + SA_BW) >> (SA_BW_SHIFT + 1); |             const int64_t prdReAReA = ((int64_t) *mdctA * (int64_t) *mdctA + SA_BW) >> (SA_BW_SHIFT + 1); | ||||||
| @@ -220,57 +261,6 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|             sumPrdImAReB -= ((int64_t) *mdctA * (int64_t) *mdstB + SA_BW) >> (SA_BW_SHIFT + 1); |             sumPrdImAReB -= ((int64_t) *mdctA * (int64_t) *mdstB + SA_BW) >> (SA_BW_SHIFT + 1); | ||||||
|             sumPrdImAImA += prdReAReA; |             sumPrdImAImA += prdReAReA; | ||||||
|           } |           } | ||||||
| #else |  | ||||||
|           for (uint16_t s = width; s > 0; s--, mdctA++, mdctB++) |  | ||||||
|           { |  | ||||||
|             sumPrdReAReB += ((int64_t) *mdctA * (int64_t) *mdctB + SA_BW) >> (SA_BW_SHIFT + 1); |  | ||||||
|             sumPrdReAReA += ((int64_t) *mdctA * (int64_t) *mdctA + SA_BW) >> (SA_BW_SHIFT + 1); |  | ||||||
|           } |  | ||||||
|           if (realOnlyCalc) // real data, only MDCTs available |  | ||||||
|           { |  | ||||||
|             const int32_t* nextA = (alterPredDir ? &mdctSpectrum2[offEv + 1] : &mdctSpectrum1[offEv + 1]); |  | ||||||
|             const int32_t* nextB = (alterPredDir ? &mdctSpectrum1[offEv + 1] : &mdctSpectrum2[offEv + 1]); |  | ||||||
|  |  | ||||||
|             if (sfbEv == 0) // exclude unavailable DC estimate |  | ||||||
|             { |  | ||||||
|               mdctA -= width; nextA++; |  | ||||||
|               mdctB -= width; nextB++; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|               mdctA -= (width + 1); // point to pre- |  | ||||||
|               mdctB -= (width + 1); // vious samples |  | ||||||
|             } |  | ||||||
|             for (uint16_t s = width - (sfbEv == 0 ? 2 : 1); s > 0; s--) // exclude unavailable final estimate |  | ||||||
|             { |  | ||||||
|               const int64_t mdstA = ((int64_t) *(nextA++) - (int64_t) *(mdctA++)) >> 1; // estimate, see also |  | ||||||
|               const int64_t mdstB = ((int64_t) *(nextB++) - (int64_t) *(mdctB++)) >> 1; // getMeanAbsValues() |  | ||||||
|  |  | ||||||
|               sumPrdReAReB += (mdstA * mdstB + SA_BW) >> (SA_BW_SHIFT + 1); |  | ||||||
|               sumPrdReAReA += (mdstA * mdstA + SA_BW) >> (SA_BW_SHIFT + 1); |  | ||||||
|             } |  | ||||||
|             if (sfb + 1 < numSwbFrame) // process final sample |  | ||||||
|             { |  | ||||||
|               const int64_t msSgn = (alterPredDir ? -1 : 1); |  | ||||||
|               const int64_t mdstA = ((((int64_t) *nextB + *nextA * msSgn + 1) >> 1) - (int64_t) *mdctA) >> 1; |  | ||||||
|               const int64_t mdstB = ((((int64_t) *nextA - *nextB * msSgn + 1) >> 1) - (int64_t) *mdctB) >> 1; |  | ||||||
|  |  | ||||||
|               sumPrdReAReB += (mdstA * mdstB + SA_BW) >> (SA_BW_SHIFT + 1); |  | ||||||
|               sumPrdReAReA += (mdstA * mdstA + SA_BW) >> (SA_BW_SHIFT + 1); |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|           else // complex data, both MDCTs and MDSTs available |  | ||||||
|           { |  | ||||||
|             const int32_t* mdstA = (alterPredDir ? &mdstSpectrum2[offEv] : &mdstSpectrum1[offEv]); |  | ||||||
|             const int32_t* mdstB = (alterPredDir ? &mdstSpectrum1[offEv] : &mdstSpectrum2[offEv]); |  | ||||||
|  |  | ||||||
|             for (uint16_t s = width; s > 0; s--, mdstA++, mdstB++) |  | ||||||
|             { |  | ||||||
|               sumPrdReAReB += ((int64_t) *mdstA * (int64_t) *mdstB + SA_BW) >> (SA_BW_SHIFT + 1); |  | ||||||
|               sumPrdReAReA += ((int64_t) *mdstA * (int64_t) *mdstA + SA_BW) >> (SA_BW_SHIFT + 1); |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
| #endif |  | ||||||
|           for (b = sfbIsOdd; b >= 0; b--) // limit alpha_q to prevent residual RMS increases |           for (b = sfbIsOdd; b >= 0; b--) // limit alpha_q to prevent residual RMS increases | ||||||
|           { |           { | ||||||
|             const int idx = sfbEv + b; |             const int idx = sfbEv + b; | ||||||
| @@ -285,7 +275,7 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
| #else | #else | ||||||
|           b = int32_t (10.0 * sfbTempVar + (sfbTempVar < 0 ? -0.5 : 0.5));// nearest integer |           b = int32_t (10.0 * sfbTempVar + (sfbTempVar < 0 ? -0.5 : 0.5));// nearest integer | ||||||
| #endif | #endif | ||||||
|           sfbStereoData[sfbEv + numSwbFrame * gr] = uint8_t (b + 16); // finished alpha_q_re |           sfbStereoData[sfbEv + grOffset] = uint8_t (b + 16); // save SFB's final alpha_q_re | ||||||
| #if SP_MDST_PRED | #if SP_MDST_PRED | ||||||
|           alphaLimit = CLIP_PM ((double) sumPrdImAReB / (double) sumPrdImAImA, alphaLimit); |           alphaLimit = CLIP_PM ((double) sumPrdImAReB / (double) sumPrdImAImA, alphaLimit); | ||||||
| # if SP_OPT_ALPHA_QUANT | # if SP_OPT_ALPHA_QUANT | ||||||
| @@ -295,7 +285,7 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|           b = int32_t (10.0 * alphaLimit + (alphaLimit < 0 ? -0.5 : 0.5));// nearest integer |           b = int32_t (10.0 * alphaLimit + (alphaLimit < 0 ? -0.5 : 0.5));// nearest integer | ||||||
| # endif | # endif | ||||||
|           if (sfbEv + 1 < numSwbFrame) |           if (sfbEv + 1 < numSwbFrame) | ||||||
|           sfbStereoData[sfbEv + 1 + numSwbFrame * gr] = uint8_t (b + 16); // init alpha_q_im |           sfbStereoData[sfbEv + 1 + grOffset] = uint8_t (b + 16); // save initial alpha_q_im | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|           if (perCorrData && ((offEv & (SA_BW - 1)) == 0) && ((width & (SA_BW - 1)) == 0)) |           if (perCorrData && ((offEv & (SA_BW - 1)) == 0) && ((width & (SA_BW - 1)) == 0)) | ||||||
| @@ -307,8 +297,8 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|           } |           } | ||||||
|           else b = UCHAR_MAX; // previous correlation data unavailable, assume maximum value |           else b = UCHAR_MAX; // previous correlation data unavailable, assume maximum value | ||||||
|  |  | ||||||
|           if ((b > SCHAR_MAX && sfbStereoData[sfbEv + numSwbFrame * gr] != 16) ||  // signi- |           if ((b > SCHAR_MAX && sfbStereoData[sfbEv + grOffset] != 16) || // if perceptually | ||||||
|               (2 <= abs ( (int) sfbStereoData[sfbEv + numSwbFrame * gr] - 16)))   // ficant? |               (2 <= abs ( (int) sfbStereoData[sfbEv + grOffset] - 16))) // significant pred. | ||||||
|           { |           { | ||||||
|             nonZeroPredCoef = true; |             nonZeroPredCoef = true; | ||||||
|           } |           } | ||||||
| @@ -350,7 +340,7 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|           const uint64_t bandSumS = (applyPredSte ? (uint64_t) rmsSfbS[0] + (uint64_t) rmsSfbS[1] : bandSum2) >> 1; |           const uint64_t bandSumS = (applyPredSte ? (uint64_t) rmsSfbS[0] + (uint64_t) rmsSfbS[1] : bandSum2) >> 1; | ||||||
|  |  | ||||||
|           if ((__min (bandSumM, bandSumS) * __max (bandSumL, bandSumR) >= __min (bandSumL, bandSumR) * __max (bandSumM, bandSumS)) || |           if ((__min (bandSumM, bandSumS) * __max (bandSumL, bandSumR) >= __min (bandSumL, bandSumR) * __max (bandSumM, bandSumS)) || | ||||||
|               (nonZeroPredCoef && (abs ( (int) sfbStereoData[sfbEv + numSwbFrame * gr] - 16) >= 10))) |               (nonZeroPredCoef && (abs ( (int) sfbStereoData[sfbEv + grOffset] - 16) >= 10))) | ||||||
|           { |           { | ||||||
|             const uint16_t sfbOffEv = grpOff[sfbEv]; |             const uint16_t sfbOffEv = grpOff[sfbEv]; | ||||||
|             const uint16_t cpyWidth = (grpOff[sfb + 1] - sfbOffEv) * sizeof (int32_t); |             const uint16_t cpyWidth = (grpOff[sfb + 1] - sfbOffEv) * sizeof (int32_t); | ||||||
| @@ -364,48 +354,102 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|             { |             { | ||||||
|               const int idx = sfbEv + b; |               const int idx = sfbEv + b; | ||||||
|  |  | ||||||
|               grpRms1[idx] = rmsSfbL[b]; |               if (numSfbNoMsSte == 0) | ||||||
|  |               { | ||||||
|  |                 rms1NoMsSte[b] = grpRms1[idx]; | ||||||
|  |                 rms2NoMsSte[b] = grpRms2[idx]; | ||||||
|  |               } | ||||||
|  |               grpRms1[idx] = rmsSfbL[b]; // recover left/right band energies | ||||||
|               grpRms2[idx] = rmsSfbR[b]; |               grpRms2[idx] = rmsSfbR[b]; | ||||||
|               if (applyPredSte) sfbStereoData[idx + numSwbFrame * gr] = 0; // zeroed ms_used |               if (applyPredSte) | ||||||
|  |               { | ||||||
|  |                 if (numSfbNoMsSte == 0) | ||||||
|  |                 { | ||||||
|  |                   rmsMNoMsSte[b] = rmsSfbM[b]; | ||||||
|  |                   rmsSNoMsSte[b] = rmsSfbS[b]; | ||||||
|  |                   dataNoMsSte[b] = sfbStereoData[idx + grOffset]; | ||||||
|  |                 } | ||||||
|  |                 sfbStereoData[idx + grOffset] = 0;  // set ms_used flag to 0 | ||||||
|  |               } | ||||||
|             } |             } | ||||||
|  |             numSfbNoMsSte++; | ||||||
|  |             idxSfbNoMsSte = sfbEv + grOffset; | ||||||
|  |             nonZeroPredNoMsSte = nonZeroPredCoef; | ||||||
|  |  | ||||||
|             continue; // M/S is not used |             continue; // M/S is not used | ||||||
|           } |           } | ||||||
|         } |         } // if !useFullFrameMS | ||||||
| #endif | #endif | ||||||
|         if (nonZeroPredCoef) numSfbPredSte++;  // a perceptually significant prediction band |         for (b = sfbIsOdd; b >= 0; b--) setStepSizesMS (rmsSfbL, rmsSfbR, rmsSfbM, rmsSfbS, grpRms1, grpRms2, | ||||||
|  |                                                         grpStepSizes1, grpStepSizes2, sfbEv, (uint16_t) b, applyPredSte); | ||||||
|         for (b = sfbIsOdd; b >= 0; b--) |         if (nonZeroPredCoef) numSfbPredSte++; // if perceptually significant prediction band | ||||||
|         { |  | ||||||
|           const int idx = sfbEv + b; |  | ||||||
|           const uint32_t sfbRmsL = __max (SP_EPS, rmsSfbL[b]); |  | ||||||
|           const uint32_t sfbRmsR = __max (SP_EPS, rmsSfbR[b]); |  | ||||||
|           const double  sfbFacLR = (sfbRmsL < (grpStepSizes1[idx] >> 1) ? 1.0 : 2.0) * (sfbRmsR < (grpStepSizes2[idx] >> 1) ? 1.0 : 2.0); |  | ||||||
|  |  | ||||||
|           sfbTempVar = (applyPredSte ? __max (rmsSfbM[b], rmsSfbS[b]) : __max (grpRms1[idx], grpRms2[idx])); |  | ||||||
|  |  | ||||||
|           if ((grpStepSizes1[idx] == 0) || (grpStepSizes2[idx] == 0)) // HF noise filled SFB |  | ||||||
|           { |  | ||||||
|             grpStepSizes1[idx] = grpStepSizes2[idx] = 0; |  | ||||||
|           } |  | ||||||
|           else if (sfbFacLR <= 1.0)  // simultaneous masking - no positive SNR in either SFB |  | ||||||
|           { |  | ||||||
|             const double max = __max (sfbRmsL, sfbRmsR); |  | ||||||
|  |  | ||||||
|             grpStepSizes1[idx] = grpStepSizes2[idx] = uint32_t (__max (grpStepSizes1[idx], grpStepSizes2[idx]) * (sfbTempVar / max) + 0.5); |  | ||||||
|           } |  | ||||||
|           else // partial/no masking - redistribute positive SNR into at least 1 channel SFB |  | ||||||
|           { |  | ||||||
|             const double min = (applyPredSte ? __min (rmsSfbM[b], rmsSfbS[b]) : __min (grpRms1[idx], grpRms2[idx])); |  | ||||||
|             const double rat = __min (1.0, grpStepSizes1[idx] / (sfbRmsL * 2.0)) * __min (1.0, grpStepSizes2[idx] / (sfbRmsR * 2.0)) * sfbFacLR; |  | ||||||
|  |  | ||||||
|             grpStepSizes1[idx] = grpStepSizes2[idx] = uint32_t (__max (SP_EPS, (min > rat * sfbTempVar ? sqrt (rat * sfbTempVar * min) : |  | ||||||
|                                                                                 __min (1.0, rat) * sfbTempVar)) + 0.5); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } // if pair completed |       } // if pair completed | ||||||
|     } |     } | ||||||
|   } // for gr |   } // for gr | ||||||
|  |  | ||||||
|  | #if SP_SFB_WISE_STEREO | ||||||
|  |   if (numSfbNoMsSte == 1) // upgrade single L/R to M/S band to reduce M/S signaling overhead | ||||||
|  |   { | ||||||
|  |     const uint16_t   grNoMS = idxSfbNoMsSte / numSwbFrame; | ||||||
|  |     const uint16_t  offNoMS = numSwbFrame * grNoMS; | ||||||
|  |     const uint16_t  sfbNoMS = idxSfbNoMsSte - offNoMS; | ||||||
|  |     const bool realOnlyCalc = (filterData1.numFilters > 0 && grNoMS == filterData1.filteredWindow) || (mdstSpectrum1 == nullptr) || | ||||||
|  |                               (filterData2.numFilters > 0 && grNoMS == filterData2.filteredWindow) || (mdstSpectrum2 == nullptr); | ||||||
|  |     const uint16_t*  grpOff = &grp.sfbOffsets[offNoMS]; | ||||||
|  |     uint32_t* const grpRms1 = &groupingData1.sfbRmsValues[offNoMS]; | ||||||
|  |     uint32_t* const grpRms2 = &groupingData2.sfbRmsValues[offNoMS]; | ||||||
|  |  | ||||||
|  |     for (int32_t b = (sfbNoMS + 1 < maxSfbSte ? 1 : 0); b >= 0; b--) | ||||||
|  |     { | ||||||
|  |       const int idx = sfbNoMS + b; // sfbNoMS = even SFB index | ||||||
|  |       const uint16_t sfbStart = grpOff[idx]; | ||||||
|  |       const uint16_t sfbWidth = grpOff[idx + 1] - sfbStart; | ||||||
|  |       int32_t* sfbMdct1 = &mdctSpectrum1[sfbStart]; | ||||||
|  |       int32_t* sfbMdct2 = &mdctSpectrum2[sfbStart]; | ||||||
|  |  | ||||||
|  |       rmsSfbL[b] = grpRms1[idx];  // save left/right band RMSs | ||||||
|  |       rmsSfbR[b] = grpRms2[idx]; | ||||||
|  |       grpRms1[idx] = rms1NoMsSte[b];  // recover M/S band RMSs | ||||||
|  |       grpRms2[idx] = rms2NoMsSte[b]; | ||||||
|  |       if (applyPredSte) sfbStereoData[idx + offNoMS] = dataNoMsSte[b]; | ||||||
|  |  | ||||||
|  |       if (realOnlyCalc && (idx >= realOnlyOffset)) // real-valued data, only MDCTs available | ||||||
|  |       { | ||||||
|  |         for (uint16_t s = sfbWidth; s > 0; s--) | ||||||
|  |         { | ||||||
|  |           const int32_t dmixReM = getMidSample (*sfbMdct1, *sfbMdct2); | ||||||
|  |           const int32_t dmixReS = getSideSample(*sfbMdct1, *sfbMdct2); | ||||||
|  |  | ||||||
|  |           *(sfbMdct1++) = dmixReM; | ||||||
|  |           *(sfbMdct2++) = dmixReS; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       else // complex data, both MDCTs and MDSTs are available | ||||||
|  |       { | ||||||
|  |         int32_t* sfbMdst1 = &mdstSpectrum1[sfbStart]; | ||||||
|  |         int32_t* sfbMdst2 = &mdstSpectrum2[sfbStart]; | ||||||
|  |  | ||||||
|  |         for (uint16_t s = sfbWidth; s > 0; s--) | ||||||
|  |         { | ||||||
|  |           const int32_t dmixReM = getMidSample (*sfbMdct1, *sfbMdct2); | ||||||
|  |           const int32_t dmixReS = getSideSample(*sfbMdct1, *sfbMdct2); | ||||||
|  |           const int32_t dmixImM = getMidSample (*sfbMdst1, *sfbMdst2); | ||||||
|  |           const int32_t dmixImS = getSideSample(*sfbMdst1, *sfbMdst2); | ||||||
|  |  | ||||||
|  |           *(sfbMdct1++) = dmixReM; | ||||||
|  |           *(sfbMdct2++) = dmixReS; | ||||||
|  |           *(sfbMdst1++) = dmixImM; | ||||||
|  |           *(sfbMdst2++) = dmixImS; | ||||||
|  |         } | ||||||
|  |       } // realOnlyCalc && idx >= realOnlyOffset | ||||||
|  |  | ||||||
|  |       setStepSizesMS (rmsSfbL, rmsSfbR, rmsMNoMsSte, rmsSNoMsSte, grpRms1, grpRms2, | ||||||
|  |                       &sfbStepSize1[offNoMS], &sfbStepSize2[offNoMS], sfbNoMS, (uint16_t) b, applyPredSte); | ||||||
|  |     } | ||||||
|  |     if (nonZeroPredNoMsSte) numSfbPredSte++; // was perceptually significant prediction band | ||||||
|  |   } // if numSfbNoMsSte == 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   if (numSfbPredSte == 0) // discard prediction coefficients and stay with legacy M/S stereo |   if (numSfbPredSte == 0) // discard prediction coefficients and stay with legacy M/S stereo | ||||||
|   { |   { | ||||||
|     if (applyPredSte) |     if (applyPredSte) | ||||||
| @@ -424,21 +468,22 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|   { |   { | ||||||
|     for (uint16_t gr = 0; gr < grp.numWindowGroups; gr++) |     for (uint16_t gr = 0; gr < grp.numWindowGroups; gr++) | ||||||
|     { |     { | ||||||
|  |       const uint16_t grOffset = numSwbFrame * gr; | ||||||
|       const bool realOnlyCalc = (filterData1.numFilters > 0 && gr == filterData1.filteredWindow) || (mdstSpectrum1 == nullptr) || |       const bool realOnlyCalc = (filterData1.numFilters > 0 && gr == filterData1.filteredWindow) || (mdstSpectrum1 == nullptr) || | ||||||
|                                 (filterData2.numFilters > 0 && gr == filterData2.filteredWindow) || (mdstSpectrum2 == nullptr); |                                 (filterData2.numFilters > 0 && gr == filterData2.filteredWindow) || (mdstSpectrum2 == nullptr); | ||||||
|       const uint16_t*  grpOff = &grp.sfbOffsets[numSwbFrame * gr]; |       const uint16_t*  grpOff = &grp.sfbOffsets[grOffset]; | ||||||
|       uint32_t* const grpRms1 = &groupingData1.sfbRmsValues[numSwbFrame * gr]; |       uint32_t* const grpRms1 = &groupingData1.sfbRmsValues[grOffset]; | ||||||
|       uint32_t* const grpRms2 = &groupingData2.sfbRmsValues[numSwbFrame * gr]; |       uint32_t* const grpRms2 = &groupingData2.sfbRmsValues[grOffset]; | ||||||
|       uint8_t* const grpSData = &sfbStereoData[numSwbFrame * gr]; |       uint8_t* const grpSData = &sfbStereoData[grOffset]; | ||||||
|       int32_t prevResi = 0; |       int32_t prevResi = 0; | ||||||
|  |  | ||||||
|       if (realOnlyCalc) // preparation of res. magnitude value |       if (realOnlyCalc) // preparation of res. magnitude value | ||||||
|       { |       { | ||||||
|         const int64_t alphaRe = (grpSData[0] > 0 ? (int) grpSData[0] - 16 : 0) * SP_0_DOT_1_16BIT; |         const int64_t alphaRe = (grpSData[realOnlyOffset & 0xFE] > 0 ? (int) grpSData[realOnlyOffset & 0xFE] - 16 : 0) * SP_0_DOT_1_16BIT; | ||||||
|         const uint16_t sPlus1 = grpOff[0] + 1; |         const uint16_t sIndex = grpOff[realOnlyOffset] + (grpOff[realOnlyOffset] > 0 ? -1 : 1); | ||||||
|  |  | ||||||
|         prevResi = (alterPredDir ? mdctSpectrum1[sPlus1] - int32_t ((mdctSpectrum2[sPlus1] * alphaRe - SHRT_MIN) >> 16) |         prevResi = (alterPredDir ? getResiSample (mdctSpectrum1[sIndex], mdctSpectrum2[sIndex], alphaRe) | ||||||
|                                  : mdctSpectrum2[sPlus1] - int32_t ((mdctSpectrum1[sPlus1] * alphaRe - SHRT_MIN) >> 16)); |                                  : getResiSample (mdctSpectrum2[sIndex], mdctSpectrum1[sIndex], alphaRe)); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       for (uint16_t sfb = 0; sfb < maxSfbSte; sfb++) |       for (uint16_t sfb = 0; sfb < maxSfbSte; sfb++) | ||||||
| @@ -453,7 +498,7 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|  |  | ||||||
|         if (alphaRe == 0) |         if (alphaRe == 0) | ||||||
|         { |         { | ||||||
|           if (realOnlyCalc) // update previous res. MDCT value |           if (realOnlyCalc && (sfb >= realOnlyOffset)) // update previous residual MDCT data | ||||||
|           { |           { | ||||||
|             sfbMdctR += sfbWidth - 1; |             sfbMdctR += sfbWidth - 1; | ||||||
|             prevResi = (grpSData[sfbEv] > 0 ? *sfbMdctR : int32_t (((int64_t) sfbMdctD[sfbWidth - 1] + |             prevResi = (grpSData[sfbEv] > 0 ? *sfbMdctR : int32_t (((int64_t) sfbMdctD[sfbWidth - 1] + | ||||||
| @@ -462,22 +507,18 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|           continue; // nothing more to do, i.e., no prediction |           continue; // nothing more to do, i.e., no prediction | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (realOnlyCalc) // real data, only MDCT is available |         if (realOnlyCalc && (sfb >= realOnlyOffset))  // real-valued, only MDCT is available | ||||||
|         { |         { | ||||||
|           const int32_t* sfbNextD = &sfbMdctD[1]; |           const int32_t* sfbNextD = &sfbMdctD[1]; | ||||||
|           const int32_t* sfbNextR = &sfbMdctR[1]; |           const int32_t* sfbNextR = &sfbMdctR[1]; | ||||||
|  |  | ||||||
|           for (uint16_t s = sfbWidth - (sfb + 1 == numSwbFrame ? 1 : 0); s > 0; s--) |           for (uint16_t s = sfbWidth - (sfb + 1 == numSwbFrame ? 1 : 0); s > 0; s--) | ||||||
|           { |           { | ||||||
|             const int32_t  resiRe = *sfbMdctR - int32_t ((*sfbMdctD * alphaRe - SHRT_MIN) >> 16); |             const int32_t  resiRe = getResiSample (*sfbMdctR, *sfbMdctD, alphaRe); | ||||||
|             // TODO: improve the following line since the calculation is partially redundant |             // TODO: improve the following line since the calculation is partially redundant | ||||||
|             //       Also, in the final s index of this band, the wrong alphaRe may be used! |             const int32_t  resiIm = int32_t ((getResiSample (*sfbNextR, *sfbNextD, alphaRe) - (int64_t) prevResi) >> 1); | ||||||
|             const int32_t  resiIm = int32_t (((*sfbNextR - ((*sfbNextD * alphaRe - SHRT_MIN) >> 16)) - (int64_t) prevResi) >> 1); |  | ||||||
|  |  | ||||||
|             const uint64_t absReR = abs (resiRe);  // Richard Lyons, 1997; en.wikipedia.org/ |             sumAbsValR += complexAbsMS (resiRe, resiIm); | ||||||
|             const uint64_t absImR = abs (resiIm);  // wiki/Alpha_max_plus_beta_min_algorithm |  | ||||||
|  |  | ||||||
|             sumAbsValR += (absReR > absImR ? absReR + ((absImR * 3) >> 3) : absImR + ((absReR * 3) >> 3)); |  | ||||||
|  |  | ||||||
|             sfbMdctD++; |             sfbMdctD++; | ||||||
|             *(sfbMdctR++) = resiRe; |             *(sfbMdctR++) = resiRe; | ||||||
| @@ -486,7 +527,7 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|           } |           } | ||||||
|           if (sfb + 1 == numSwbFrame)  // process final sample |           if (sfb + 1 == numSwbFrame)  // process final sample | ||||||
|           { |           { | ||||||
|             const int32_t resiRe = *sfbMdctR - int32_t ((*sfbMdctD * alphaRe - SHRT_MIN) >> 16); |             const int32_t  resiRe = getResiSample (*sfbMdctR, *sfbMdctD, alphaRe); | ||||||
|  |  | ||||||
|             sumAbsValR += abs (resiRe); |             sumAbsValR += abs (resiRe); | ||||||
|  |  | ||||||
| @@ -500,24 +541,17 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|  |  | ||||||
|           for (uint16_t s = sfbWidth; s > 0; s--) |           for (uint16_t s = sfbWidth; s > 0; s--) | ||||||
|           { |           { | ||||||
|             const int32_t  resiRe = *sfbMdctR - int32_t ((*sfbMdctD * alphaRe - SHRT_MIN) >> 16); |             const int32_t  resiRe = getResiSample (*sfbMdctR, *sfbMdctD, alphaRe); | ||||||
|             const int32_t  resiIm = *sfbMdstR - int32_t ((*sfbMdstD * alphaRe - SHRT_MIN) >> 16); |             const int32_t  resiIm = getResiSample (*sfbMdstR, *sfbMdstD, alphaRe); | ||||||
| #if SA_EXACT_COMPLEX_ABS |  | ||||||
|             const double cplxSqrR = (double) resiRe * (double) resiRe + (double) resiIm * (double) resiIm; |  | ||||||
|  |  | ||||||
|             sumAbsValR += uint64_t (sqrt (cplxSqrR) + 0.5); |             sumAbsValR += complexAbsMS (resiRe, resiIm); | ||||||
| #else |  | ||||||
|             const uint64_t absReR = abs (resiRe);  // Richard Lyons, 1997; en.wikipedia.org/ |  | ||||||
|             const uint64_t absImR = abs (resiIm);  // wiki/Alpha_max_plus_beta_min_algorithm |  | ||||||
|  |  | ||||||
|             sumAbsValR += (absReR > absImR ? absReR + ((absImR * 3) >> 3) : absImR + ((absReR * 3) >> 3)); |  | ||||||
| #endif |  | ||||||
|             sfbMdctD++; |             sfbMdctD++; | ||||||
|             *(sfbMdctR++) = resiRe; |             *(sfbMdctR++) = resiRe; | ||||||
|             sfbMdstD++; |             sfbMdstD++; | ||||||
|             *(sfbMdstR++) = resiIm; |             *(sfbMdstR++) = resiIm; | ||||||
|           } |           } | ||||||
|         } // realOnlyCalc |         } // realOnlyCalc && sfb >= realOnlyOffset | ||||||
|  |  | ||||||
|         // average spectral res. magnitude across current band |         // average spectral res. magnitude across current band | ||||||
|         sumAbsValR = (sumAbsValR + (sfbWidth >> 1)) / sfbWidth; |         sumAbsValR = (sumAbsValR + (sfbWidth >> 1)) / sfbWidth; | ||||||
| @@ -533,7 +567,7 @@ unsigned StereoProcessor::applyPredJointStereo (int32_t* const mdctSpectrum1, in | |||||||
|           int32_t* sfbMdct1 = &mdctSpectrum1[sfbStart]; |           int32_t* sfbMdct1 = &mdctSpectrum1[sfbStart]; | ||||||
|           int32_t* sfbMdct2 = &mdctSpectrum2[sfbStart]; |           int32_t* sfbMdct2 = &mdctSpectrum2[sfbStart]; | ||||||
|  |  | ||||||
|           if (grpSData[sfb] == 0) continue; // M/S is not used |           if (grpSData[sfb & 0xFFFE] == 0) continue; // no M/S | ||||||
|  |  | ||||||
|           for (uint16_t s = grpOff[sfb + 1] - sfbStart; s > 0; s--) |           for (uint16_t s = grpOff[sfb + 1] - sfbStart; s > 0; s--) | ||||||
|           { |           { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user