diff options
author | Dave Burke <daveburke@google.com> | 2012-05-12 13:17:25 -0700 |
---|---|---|
committer | Dave Burke <daveburke@google.com> | 2012-05-12 13:47:46 -0700 |
commit | 698b536f3b34a7cfc41a80e1034cc359456bdd66 (patch) | |
tree | fa3dfa75d535b188725f1b84316cb4b06db79771 /libSBRenc/src | |
parent | 9bf37cc9712506b2483650c82d3c41152337ef7e (diff) | |
download | fdk-aac-698b536f3b34a7cfc41a80e1034cc359456bdd66.tar.gz fdk-aac-698b536f3b34a7cfc41a80e1034cc359456bdd66.tar.bz2 fdk-aac-698b536f3b34a7cfc41a80e1034cc359456bdd66.zip |
Update to 2012_05_11 version.
Fixes:
- Don't throw error for invalid bitrate but limit to functional value
- More robust ASC parsing
- More robust handling of corrupt bitstreams
- Handle multiple raw access units
Change-Id: Ib49fe2545ff4185fe924126da702fe84ac5c2d87
Diffstat (limited to 'libSBRenc/src')
-rw-r--r-- | libSBRenc/src/Android.mk | 1 | ||||
-rw-r--r-- | libSBRenc/src/env_est.cpp | 34 | ||||
-rw-r--r-- | libSBRenc/src/env_est.h | 3 | ||||
-rw-r--r-- | libSBRenc/src/ps_bitenc.cpp | 3 | ||||
-rw-r--r-- | libSBRenc/src/ps_const.h | 24 | ||||
-rw-r--r-- | libSBRenc/src/ps_encode.cpp | 228 | ||||
-rw-r--r-- | libSBRenc/src/ps_encode.h | 44 | ||||
-rw-r--r-- | libSBRenc/src/ps_main.cpp | 1143 | ||||
-rw-r--r-- | libSBRenc/src/ps_main.h | 220 | ||||
-rw-r--r-- | libSBRenc/src/psenc_hybrid.cpp | 836 | ||||
-rw-r--r-- | libSBRenc/src/psenc_hybrid.h | 182 | ||||
-rw-r--r-- | libSBRenc/src/sbr.h | 3 | ||||
-rw-r--r-- | libSBRenc/src/sbr_encoder.cpp | 189 | ||||
-rw-r--r-- | libSBRenc/src/sbr_ram.cpp | 62 | ||||
-rw-r--r-- | libSBRenc/src/sbr_ram.h | 72 | ||||
-rw-r--r-- | libSBRenc/src/sbr_rom.cpp | 14 | ||||
-rw-r--r-- | libSBRenc/src/sbr_rom.h | 8 |
17 files changed, 743 insertions, 2323 deletions
diff --git a/libSBRenc/src/Android.mk b/libSBRenc/src/Android.mk index 55d5d4e..0a3a9d8 100644 --- a/libSBRenc/src/Android.mk +++ b/libSBRenc/src/Android.mk @@ -16,7 +16,6 @@ LOCAL_SRC_FILES := \ env_est.cpp \ invf_est.cpp \ nf_est.cpp \ - psenc_hybrid.cpp \ ps_main.cpp \ sbrenc_freq_sca.cpp \ sbr_misc.cpp \ diff --git a/libSBRenc/src/env_est.cpp b/libSBRenc/src/env_est.cpp index 0b7f7b0..8e8e190 100644 --- a/libSBRenc/src/env_est.cpp +++ b/libSBRenc/src/env_est.cpp @@ -799,27 +799,6 @@ calculateSbrEnvelope (FIXP_DBL **RESTRICT YBufferLeft, /*! energy buffer left * } /* i*/ } -/* - * Update QMF buffers - */ -static void FDKsbrEnc_updateRIBuffers(HANDLE_ENV_CHANNEL h_envChan) -{ - int i; - - /* rBufferWriteOffset ist always 0, do we need this ? */ - for (i = 0; i < h_envChan->sbrExtractEnvelope.rBufferWriteOffset; i++) { - FIXP_DBL *temp; - - temp = h_envChan->sbrExtractEnvelope.rBuffer[i]; - h_envChan->sbrExtractEnvelope.rBuffer[i] = h_envChan->sbrExtractEnvelope.rBuffer[i + h_envChan->sbrExtractEnvelope.no_cols]; - h_envChan->sbrExtractEnvelope.rBuffer[i + h_envChan->sbrExtractEnvelope.no_cols] = temp; - - temp = h_envChan->sbrExtractEnvelope.iBuffer[i]; - h_envChan->sbrExtractEnvelope.iBuffer[i] = h_envChan->sbrExtractEnvelope.iBuffer[i + h_envChan->sbrExtractEnvelope.no_cols]; - h_envChan->sbrExtractEnvelope.iBuffer[i + h_envChan->sbrExtractEnvelope.no_cols] = temp; - } -} - /***************************************************************************/ /*! @@ -873,8 +852,8 @@ FDKsbrEnc_extractSbrEnvelope1 ( Precalculation of Tonality Quotas COEFF Transform OK */ FDKsbrEnc_CalculateTonalityQuotas(&hEnvChan->TonCorr, - sbrExtrEnv->rBuffer+ sbrExtrEnv->rBufferWriteOffset, - sbrExtrEnv->iBuffer+ sbrExtrEnv->rBufferWriteOffset, + sbrExtrEnv->rBuffer, + sbrExtrEnv->iBuffer, h_con->freqBandTable[HI][h_con->nSfb[HI]], hEnvChan->qmfScale); @@ -914,8 +893,6 @@ FDKsbrEnc_extractSbrEnvelope1 ( sbrExtrEnv->no_cols); - - FDKsbrEnc_updateRIBuffers(hEnvChan); } /***************************************************************************/ @@ -1741,12 +1718,11 @@ FDKsbrEnc_InitExtractSbrEnvelope (HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, { hSbrCut->YBufferWriteOffset = tran_off*time_step; } - hSbrCut->rBufferWriteOffset = 0; hSbrCut->rBufferReadOffset = 0; YBufferLength = hSbrCut->YBufferWriteOffset + no_cols; - rBufferLength = hSbrCut->rBufferWriteOffset + no_cols; + rBufferLength = no_cols; hSbrCut->pre_transient_info[0] = 0; hSbrCut->pre_transient_info[1] = 0; @@ -1824,8 +1800,8 @@ FDKsbrEnc_deleteExtractSbrEnvelope (HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut) INT FDKsbrEnc_GetEnvEstDelay(HANDLE_SBR_EXTRACT_ENVELOPE hSbr) { - return hSbr->no_rows*((hSbr->YBufferWriteOffset)*2 + /* mult 2 because nrg's are grouped half */ - hSbr->rBufferWriteOffset - hSbr->rBufferReadOffset ); /* in reference hold half spec and calc nrg's on overlapped spec */ + return hSbr->no_rows*((hSbr->YBufferWriteOffset)*2 /* mult 2 because nrg's are grouped half */ + - hSbr->rBufferReadOffset ); /* in reference hold half spec and calc nrg's on overlapped spec */ } diff --git a/libSBRenc/src/env_est.h b/libSBRenc/src/env_est.h index 5aa66ee..be74976 100644 --- a/libSBRenc/src/env_est.h +++ b/libSBRenc/src/env_est.h @@ -25,7 +25,7 @@ ****************************************************************************/ /*! \file - \brief Envelope estimation structs and prototypes $Revision: 36847 $ + \brief Envelope estimation structs and prototypes $Revision: 37142 $ */ #ifndef __ENV_EST_H #define __ENV_EST_H @@ -56,7 +56,6 @@ typedef struct int YBufferWriteOffset; int YBufferSzShift; int rBufferReadOffset; - int rBufferWriteOffset; int no_cols; int no_rows; diff --git a/libSBRenc/src/ps_bitenc.cpp b/libSBRenc/src/ps_bitenc.cpp index 960229b..82fec24 100644 --- a/libSBRenc/src/ps_bitenc.cpp +++ b/libSBRenc/src/ps_bitenc.cpp @@ -202,8 +202,7 @@ static const UINT opdDeltaTime_Code[] = static const INT psBands[] = { PS_BANDS_COARSE, - PS_BANDS_MID, - PS_BANDS_FINE + PS_BANDS_MID }; static INT getNoBands(PS_RESOLUTION mode) diff --git a/libSBRenc/src/ps_const.h b/libSBRenc/src/ps_const.h index 20fcc88..376528b 100644 --- a/libSBRenc/src/ps_const.h +++ b/libSBRenc/src/ps_const.h @@ -28,6 +28,17 @@ #ifndef PS_CONST_H #define PS_CONST_H +#define MAX_PS_CHANNELS ( 2 ) +#define HYBRID_MAX_QMF_BANDS ( 3 ) +#define HYBRID_FILTER_LENGTH ( 13 ) +#define HYBRID_FILTER_DELAY ( (HYBRID_FILTER_LENGTH-1)/2 ) + +#define HYBRID_FRAMESIZE ( QMF_MAX_TIME_SLOTS ) +#define HYBRID_READ_OFFSET ( 10 ) + +#define MAX_HYBRID_BANDS ( (QMF_CHANNELS-HYBRID_MAX_QMF_BANDS+10) ) + + typedef enum { PS_RES_COARSE = 0, PS_RES_MID = 1, @@ -37,8 +48,7 @@ typedef enum { typedef enum { PS_BANDS_COARSE = 10, PS_BANDS_MID = 20, - PS_BANDS_FINE = 34, - PS_MAX_BANDS = PS_BANDS_FINE + PS_MAX_BANDS = PS_BANDS_MID } PS_BANDS; typedef enum { @@ -62,4 +72,14 @@ typedef enum { } PS_CONSTS; +typedef enum { + PSENC_OK = 0x0000, /*!< No error happened. All fine. */ + PSENC_INVALID_HANDLE = 0x0020, /*!< Handle passed to function call was invalid. */ + PSENC_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + PSENC_INIT_ERROR = 0x0040, /*!< General initialization error. */ + PSENC_ENCODE_ERROR = 0x0060 /*!< The encoding process was interrupted by an unexpected error. */ + +} FDK_PSENC_ERROR; + + #endif diff --git a/libSBRenc/src/ps_encode.cpp b/libSBRenc/src/ps_encode.cpp index 1f78d66..6f098aa 100644 --- a/libSBRenc/src/ps_encode.cpp +++ b/libSBRenc/src/ps_encode.cpp @@ -27,7 +27,7 @@ ******************************************************************************/ /*! \file - \brief PS parameter extraction, encoding functions $Revision: 36847 $ + \brief PS parameter extraction, encoding functions $Revision: 37142 $ */ #include "ps_main.h" @@ -43,7 +43,6 @@ #include "genericStds.h" - inline void FDKsbrEnc_addFIXP_DBL(const FIXP_DBL *X, const FIXP_DBL *Y, FIXP_DBL *Z, INT n) { for (INT i=0; i<n; i++) @@ -78,7 +77,6 @@ static const INT subband2parameter20[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] = }; - typedef enum { MAX_TIME_DIFF_FRAMES = 20, MAX_PS_NOHEADER_CNT = 10, @@ -106,54 +104,17 @@ static const FIXP_DBL iccQuant[8] = { 0x7fffffff, 0x77ef9d7f, 0x6babc97f, 0x4ceaf27f, 0x2f0ed3c0, 0x00000000, 0xb49ba601, 0x80000000 }; - - - -/* - name: static HANDLE_ERROR_INFO CreatePSData() - description: Creates struct (buffer) to store ps data - returns: error code of type HANDLE_ERROR_INFO - input: none - output: - HANDLE_PS_DATA *hPsData: according handle -*/ -static HANDLE_ERROR_INFO CreatePSData(HANDLE_PS_DATA *hPsData) +static FDK_PSENC_ERROR InitPSData( + HANDLE_PS_DATA hPsData + ) { - HANDLE_ERROR_INFO error = noError; + FDK_PSENC_ERROR error = PSENC_OK; - *hPsData = GetRam_PsData(); - if (*hPsData==NULL) { - error = 1; - goto bail; + if(hPsData == NULL) { + error = PSENC_INVALID_HANDLE; } - FDKmemclear(*hPsData,sizeof(PS_DATA)); - -bail: - return error; -} - - -/* - name: static HANDLE_ERROR_INFO DestroyPSData() - description: frees according data handle - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PS_DATA *hPsData - output: none -*/ -static HANDLE_ERROR_INFO DestroyPSData(HANDLE_PS_DATA *phPsData) -{ - FreeRam_PsData(phPsData); - - return noError; -} - - -static HANDLE_ERROR_INFO InitPSData(HANDLE_PS_DATA hPsData) -{ - INT i, env; - HANDLE_ERROR_INFO error = noError; - - if(hPsData != NULL){ - + else { + int i, env; FDKmemclear(hPsData,sizeof(PS_DATA)); for (i=0; i<PS_MAX_BANDS; i++) { @@ -182,8 +143,6 @@ static HANDLE_ERROR_INFO InitPSData(HANDLE_PS_DATA hPsData) hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; hPsData->noEnvCnt = MAX_NOENV_CNT; - } else { - error = ERROR(CDI, "Unable to write to hPsData."); } return error; @@ -226,9 +185,6 @@ static INT getICCMode(const INT nBands, case PS_BANDS_MID: mode = PS_RES_MID; break; - case PS_BANDS_FINE: - mode = PS_RES_FINE; - break; default: mode = 0; } @@ -252,9 +208,6 @@ static INT getIIDMode(const INT nBands, case PS_BANDS_MID: mode = PS_RES_MID; break; - case PS_BANDS_FINE: - mode = PS_RES_FINE; - break; default: mode = 0; break; @@ -339,7 +292,6 @@ static void processIidData(PS_DATA *psData, INT loudnDiff = 0; INT iidTransmit = 0; - bitsIidFreq = bitsIidTime = 0; /* Quantize IID coefficients */ @@ -348,7 +300,6 @@ static void processIidData(PS_DATA *psData, errIIDFine += quantizeCoef(iid[env], psBands, iidQuantFine_fx, 15, 31, iidIdxFine[env]); } - /* normalize error to number of envelopes, ps bands errIID /= psBands*nEnvelopes; errIIDFine /= psBands*nEnvelopes; */ @@ -638,8 +589,8 @@ static void calculateIID(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], */ FIXP_DBL IID = fMultDiv2( FL2FXCONST_DBL(LOG10_2_10/IID_SCALE_FT), (ldPwrL[env][i]-ldPwrR[env][i]) ); - IID = fixMin( IID, (FIXP_DBL)(FL2FXCONST_DBL( 1.f)>>(LD_DATA_SHIFT+1)) ); - IID = fixMax( IID, (FIXP_DBL)(FL2FXCONST_DBL(-1.f)>>(LD_DATA_SHIFT+1)) ); + IID = fixMin( IID, (FIXP_DBL)(MAXVAL_DBL>>(LD_DATA_SHIFT+1)) ); + IID = fixMax( IID, (FIXP_DBL)(MINVAL_DBL>>(LD_DATA_SHIFT+1)) ); iid[env][i] = IID << (LD_DATA_SHIFT+1); } } @@ -664,9 +615,6 @@ static void calculateICC(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], case PS_BANDS_MID: border = 11; break; - case PS_BANDS_FINE: - border = 16; - break; default: break; } @@ -748,70 +696,74 @@ void FDKsbrEnc_initPsBandNrgScale(HANDLE_PS_ENCODE hPsEncode) } } -HANDLE_ERROR_INFO FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE *phPsEncode){ - - HANDLE_ERROR_INFO error = noError; - - HANDLE_PS_ENCODE hPsEncode = GetRam_PsEncode(); - FDKmemclear(hPsEncode,sizeof(PS_ENCODE)); +FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode( + HANDLE_PS_ENCODE *phPsEncode + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; - if(error == noError){ - if(noError != (error = CreatePSData(&hPsEncode->hPsData))){ - error = handBack(error); + if (phPsEncode==NULL) { + error = PSENC_INVALID_HANDLE; + } + else { + HANDLE_PS_ENCODE hPsEncode = NULL; + if (NULL==(hPsEncode = GetRam_PsEncode())) { + error = PSENC_MEMORY_ERROR; + goto bail; } + FDKmemclear(hPsEncode,sizeof(PS_ENCODE)); + *phPsEncode = hPsEncode; /* return allocated handle */ } - - *phPsEncode = hPsEncode; - +bail: return error; } -HANDLE_ERROR_INFO FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, const PS_BANDS psEncMode, const FIXP_DBL iidQuantErrorThreshold){ - - HANDLE_ERROR_INFO error = noError; +FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode( + HANDLE_PS_ENCODE hPsEncode, + const PS_BANDS psEncMode, + const FIXP_DBL iidQuantErrorThreshold + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; - if(error == noError){ - if(noError != (InitPSData(hPsEncode->hPsData))){ - error = handBack(error); - } + if (NULL==hPsEncode) { + error = PSENC_INVALID_HANDLE; } + else { + if (PSENC_OK != (InitPSData(&hPsEncode->psData))) { + goto bail; + } - if(error == noError){ switch(psEncMode){ - case PS_BANDS_COARSE: - case PS_BANDS_MID: - hPsEncode->nQmfIidGroups = QMF_GROUPS_LO_RES; - hPsEncode->nSubQmfIidGroups = SUBQMF_GROUPS_LO_RES; - FDKmemcpy(hPsEncode->iidGroupBorders, iidGroupBordersLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups + 1)*sizeof(INT)); - FDKmemcpy(hPsEncode->subband2parameterIndex, subband2parameter20, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(INT)); - FDKmemcpy(hPsEncode->iidGroupWidthLd, iidGroupWidthLdLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(UCHAR)); - break; - case PS_BANDS_FINE: - FDK_ASSERT(0); /* we don't support this mode! */ - - break; - default: - error = ERROR(CDI, "Invalid stereo band configuration."); - break; + case PS_BANDS_COARSE: + case PS_BANDS_MID: + hPsEncode->nQmfIidGroups = QMF_GROUPS_LO_RES; + hPsEncode->nSubQmfIidGroups = SUBQMF_GROUPS_LO_RES; + FDKmemcpy(hPsEncode->iidGroupBorders, iidGroupBordersLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups + 1)*sizeof(INT)); + FDKmemcpy(hPsEncode->subband2parameterIndex, subband2parameter20, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(INT)); + FDKmemcpy(hPsEncode->iidGroupWidthLd, iidGroupWidthLdLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(UCHAR)); + break; + default: + error = PSENC_INIT_ERROR; + goto bail; } - } - if(error == noError){ hPsEncode->psEncMode = psEncMode; hPsEncode->iidQuantErrorThreshold = iidQuantErrorThreshold; FDKsbrEnc_initPsBandNrgScale(hPsEncode); } - +bail: return error; } -HANDLE_ERROR_INFO FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode){ - - HANDLE_ERROR_INFO error = noError; +FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode( + HANDLE_PS_ENCODE *phPsEncode + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; - if(error == noError){ - DestroyPSData(&(*phPsEncode)->hPsData); + if (NULL !=phPsEncode) { FreeRam_PsEncode(phPsEncode); } @@ -825,44 +777,42 @@ typedef struct { FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS]; FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS]; FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + } PS_PWR_DATA; -HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode, - HANDLE_PS_OUT RESTRICT hPsOut, - HANDLE_PS_CHANNEL_DATA RESTRICT hChanDatal, - HANDLE_PS_CHANNEL_DATA RESTRICT hChanDatar, - UCHAR *RESTRICT dynBandScale, - UINT maxEnvelopes, - const int sendHeader) + +FDK_PSENC_ERROR FDKsbrEnc_PSEncode( + HANDLE_PS_ENCODE hPsEncode, + HANDLE_PS_OUT hPsOut, + UCHAR *dynBandScale, + UINT maxEnvelopes, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT frameSize, + const INT sendHeader + ) { - HANDLE_ERROR_INFO error = noError; - HANDLE_PS_DATA hPsData = hPsEncode->hPsData; - HANDLE_PS_HYBRID_DATA hHybDatal = hChanDatal->hHybData; - HANDLE_PS_HYBRID_DATA hHybDatar = hChanDatar->hHybData; - FIXP_QMF **RESTRICT lr = NULL, **RESTRICT li = NULL, **RESTRICT rr = NULL, **RESTRICT ri = NULL; + FDK_PSENC_ERROR error = PSENC_OK; + + HANDLE_PS_DATA hPsData = &hPsEncode->psData; FIXP_DBL iid [PS_MAX_ENVELOPES][PS_MAX_BANDS]; FIXP_DBL icc [PS_MAX_ENVELOPES][PS_MAX_BANDS]; int envBorder[PS_MAX_ENVELOPES+1]; - int group, bin, border, col, subband, band; + int group, bin, col, subband, band; int i = 0; int env = 0; int psBands = (int) hPsEncode->psEncMode; - int frameSize = FDKsbrEnc_GetHybridFrameSize(hHybDatal); /* same as FDKsbrEnc_GetHybridFrameSize(hHybDatar) */ int nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; int nEnvelopes = fixMin(maxEnvelopes, (UINT)PS_MAX_ENVELOPES); C_ALLOC_SCRATCH_START(pwrData, PS_PWR_DATA, 1); - for(env=0; env<nEnvelopes+1;env++) { envBorder[env] = fMultI(GetInvInt(nEnvelopes),frameSize*env); } for(env=0; env<nEnvelopes;env++) { - INT nHybridQmfOffset = 0; - int descale = 0; /* clear energy array */ for (band=0; band<psBands; band++) { @@ -872,10 +822,6 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode, /**** calculate energies and correlation ****/ /* start with hybrid data */ - lr = hHybDatal->rHybData; li = hHybDatal->iHybData; - rr = hHybDatar->rHybData; ri = hHybDatar->iHybData; - UCHAR switched = 0; - for (group=0; group < nIidGroups; group++) { /* Translate group to bin */ bin = hPsEncode->subband2parameterIndex[group]; @@ -885,30 +831,21 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode, bin >>= 1; } - if (!switched && group == hPsEncode->nSubQmfIidGroups) { - /* switch to qmf data */ - lr = hChanDatal->hPsQmfData->rQmfData; li = hChanDatal->hPsQmfData->iQmfData; - rr = hChanDatar->hPsQmfData->rQmfData; ri = hChanDatar->hPsQmfData->iQmfData; - /* calc offset between hybrid subsubbands and qmf bands */ - nHybridQmfOffset = FDKsbrEnc_GetNumberHybridQmfBands(hHybDatal) - FDKsbrEnc_GetNumberHybridBands(hHybDatal); - switched = 1; - } - /* determine group border */ - int bScale = 2*descale + hPsEncode->psBandNrgScale[bin]; - border = hPsEncode->iidGroupBorders[group+1]; + int bScale = hPsEncode->psBandNrgScale[bin]; FIXP_DBL pwrL_env_bin = pwrData->pwrL[env][bin]; FIXP_DBL pwrR_env_bin = pwrData->pwrR[env][bin]; FIXP_DBL pwrCr_env_bin = pwrData->pwrCr[env][bin]; FIXP_DBL pwrCi_env_bin = pwrData->pwrCi[env][bin]; + int scale = (int)dynBandScale[bin]; for (col=envBorder[env]; col<envBorder[env+1]; col++) { - for (subband = hPsEncode->iidGroupBorders[group]; subband < border; subband++) { - FIXP_QMF l_real = (lr[col][subband + nHybridQmfOffset]) << scale; - FIXP_QMF l_imag = (li[col][subband + nHybridQmfOffset]) << scale; - FIXP_QMF r_real = (rr[col][subband + nHybridQmfOffset]) << scale; - FIXP_QMF r_imag = (ri[col][subband + nHybridQmfOffset]) << scale; + for (subband = hPsEncode->iidGroupBorders[group]; subband < hPsEncode->iidGroupBorders[group+1]; subband++) { + FIXP_QMF l_real = (hybridData[col][0][0][subband]) << scale; + FIXP_QMF l_imag = (hybridData[col][0][1][subband]) << scale; + FIXP_QMF r_real = (hybridData[col][1][0][subband]) << scale; + FIXP_QMF r_imag = (hybridData[col][1][1][subband]) << scale; pwrL_env_bin += (fPow2Div2(l_real) + fPow2Div2(l_imag)) >> bScale; pwrR_env_bin += (fPow2Div2(r_real) + fPow2Div2(r_imag)) >> bScale; @@ -931,13 +868,10 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode, } /* nEnvelopes */ - /* calculate iid and icc */ calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands); calculateICC(pwrData->ldPwrL, pwrData->ldPwrR, pwrData->pwrCr, pwrData->pwrCi, icc, nEnvelopes, psBands); - - /*** Envelope Reduction ***/ while (envelopeReducible(iid,icc,psBands,nEnvelopes)) { int e=0; @@ -1001,7 +935,6 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode, } - if (nEnvelopes>0) { hPsOut->enableIID = hPsData->iidEnable; @@ -1060,7 +993,6 @@ HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE RESTRICT hPsEncode, } } /* Envelope > 0 */ - C_ALLOC_SCRATCH_END(pwrData, PS_PWR_DATA, 1) return error; diff --git a/libSBRenc/src/ps_encode.h b/libSBRenc/src/ps_encode.h index 6ce9d1f..be8ba9a 100644 --- a/libSBRenc/src/ps_encode.h +++ b/libSBRenc/src/ps_encode.h @@ -27,7 +27,7 @@ ******************************************************************************/ /*! \file - \brief PS parameter extraction, encoding functions $Revision: 36847 $ + \brief PS parameter extraction, encoding functions $Revision: 37142 $ */ #ifndef __INCLUDED_PS_ENCODE_H @@ -35,7 +35,7 @@ #include "ps_const.h" #include "ps_bitenc.h" -#include "psenc_hybrid.h" + #define IID_SCALE_FT (64.f) /* maxVal in Quant tab is +/- 50 */ #define IID_SCALE 6 /* maxVal in Quant tab is +/- 50 */ @@ -81,7 +81,7 @@ typedef struct T_PS_DATA { typedef struct T_PS_ENCODE{ - HANDLE_PS_DATA hPsData; + PS_DATA psData; PS_BANDS psEncMode; INT nQmfIidGroups; @@ -97,21 +97,29 @@ typedef struct T_PS_ENCODE{ typedef struct T_PS_ENCODE *HANDLE_PS_ENCODE; -typedef struct T_PS_CHANNEL_DATA *HANDLE_PS_CHANNEL_DATA; - -HANDLE_ERROR_INFO FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE *phPsEncode); - -HANDLE_ERROR_INFO FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, const PS_BANDS psEncMode, const FIXP_DBL iidQuantErrorThreshold); - -HANDLE_ERROR_INFO FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode); - -HANDLE_ERROR_INFO FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE hPsEncode, - HANDLE_PS_OUT hPsOut, - HANDLE_PS_CHANNEL_DATA hChanDatal, - HANDLE_PS_CHANNEL_DATA hChanDatar, - UCHAR *dynBandScale, - UINT maxEnvelopes, - const int sendHeader); +FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode( + HANDLE_PS_ENCODE *phPsEncode + ); + +FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode( + HANDLE_PS_ENCODE hPsEncode, + const PS_BANDS psEncMode, + const FIXP_DBL iidQuantErrorThreshold + ); + +FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode( + HANDLE_PS_ENCODE *phPsEncode + ); + +FDK_PSENC_ERROR FDKsbrEnc_PSEncode( + HANDLE_PS_ENCODE hPsEncode, + HANDLE_PS_OUT hPsOut, + UCHAR *dynBandScale, + UINT maxEnvelopes, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT frameSize, + const INT sendHeader + ); #endif diff --git a/libSBRenc/src/ps_main.cpp b/libSBRenc/src/ps_main.cpp index c2b19d8..be954c9 100644 --- a/libSBRenc/src/ps_main.cpp +++ b/libSBRenc/src/ps_main.cpp @@ -36,673 +36,247 @@ #include "sbr_ram.h" - - -/* Function declarations ****************************************************/ -static void psFindBestScaling(HANDLE_PARAMETRIC_STEREO hParametricStereo, - UCHAR *dynBandScale, - FIXP_QMF *maxBandValue, - SCHAR *dmxScale); - -/* - name: static HANDLE_ERROR_INFO CreatePSQmf() - description: Creates struct (buffer) to store qmf data - returns: error code of type HANDLE_ERROR_INFO - input: - INT nCols: number of qmf samples stored in regular qmf buffer - - INT nRows: number qmf channels - - INT hybridFilterDelay: delay in qmf samples of hybrid filter - output: - HANDLE_PS_QMF_DATA *hPsQmfData: according handle -*/ -static HANDLE_ERROR_INFO CreatePSQmf(HANDLE_PS_QMF_DATA *phPsQmfData, INT ch) -{ - HANDLE_ERROR_INFO error = noError; - HANDLE_PS_QMF_DATA hPsQmfData = GetRam_PsQmfData(ch); - if (hPsQmfData==NULL) { - error = 1; - goto bail; - } - FDKmemclear(hPsQmfData, sizeof(PS_QMF_DATA)); - - hPsQmfData->rQmfData[0] = GetRam_PsRqmf(ch); - hPsQmfData->iQmfData[0] = GetRam_PsIqmf(ch); - - if ( (hPsQmfData->rQmfData[0]==NULL) || (hPsQmfData->iQmfData[0]==NULL) ) { - error = 1; - goto bail; - } - - -bail: - *phPsQmfData = hPsQmfData; - return error; -} - -static HANDLE_ERROR_INFO InitPSQmf(HANDLE_PS_QMF_DATA hPsQmfData, INT nCols, INT nRows, INT hybridFilterDelay, INT ch, UCHAR *dynamic_RAM) -{ - INT i, bufferLength = 0; - - hPsQmfData->nCols = nCols; - hPsQmfData->nRows = nRows; - hPsQmfData->bufferReadOffset = QMF_READ_OFFSET; - hPsQmfData->bufferReadOffsetHybrid = HYBRID_READ_OFFSET; /* calc read offset for hybrid analysis in qmf samples */ - hPsQmfData->bufferWriteOffset = hPsQmfData->bufferReadOffsetHybrid + hybridFilterDelay; - hPsQmfData->bufferLength = bufferLength = hPsQmfData->bufferWriteOffset + nCols; - - FDK_ASSERT(PSENC_QMF_BUFFER_LENGTH>=bufferLength); - - for(i=0; i<bufferLength; i++) { - hPsQmfData->rQmfData[i] = FDKsbrEnc_SliceRam_PsRqmf(hPsQmfData->rQmfData[0], dynamic_RAM, ch, i, nCols); - hPsQmfData->iQmfData[i] = FDKsbrEnc_SliceRam_PsIqmf(hPsQmfData->iQmfData[0], dynamic_RAM, ch, i, nCols); - } - - for(i=0; i<bufferLength; i++){ - FDKmemclear(hPsQmfData->rQmfData[i], (sizeof(FIXP_QMF)*QMF_CHANNELS)); - FDKmemclear(hPsQmfData->iQmfData[i], (sizeof(FIXP_QMF)*QMF_CHANNELS)); - } - - return noError; -} - - -/* - name: static HANDLE_ERROR_INFO CreatePSChannel() - description: Creates PS channel struct - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PS_HYBRID_CONFIG hHybConfig: config structure for hybrid filter bank - output: - HANDLE_PS_CHANNEL_DATA *hPsChannelData -*/ -static HANDLE_ERROR_INFO CreatePSChannel(HANDLE_PS_CHANNEL_DATA *hPsChannelData, - INT ch - ) +/*--------------- function declarations --------------------*/ +static void psFindBestScaling( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + UCHAR *dynBandScale, + FIXP_QMF *maxBandValue, + SCHAR *dmxScale + ); + +/*------------- function definitions ----------------*/ +FDK_PSENC_ERROR PSEnc_Create( + HANDLE_PARAMETRIC_STEREO *phParametricStereo + ) { - HANDLE_ERROR_INFO error = noError; + FDK_PSENC_ERROR error = PSENC_OK; - (*hPsChannelData) = GetRam_PsChData(ch); - - if (*hPsChannelData==NULL) { - error = 1; - goto bail; + if (phParametricStereo==NULL) { + error = PSENC_INVALID_HANDLE; } - FDKmemclear(*hPsChannelData, sizeof(PS_CHANNEL_DATA)); + else { + int i; + HANDLE_PARAMETRIC_STEREO hParametricStereo = NULL; - - if (error == noError) { - if (noError != (error = FDKsbrEnc_CreateHybridFilterBank(&(*hPsChannelData)->hHybAna, - ch ))) - { + if (NULL==(hParametricStereo = GetRam_ParamStereo())) { + error = PSENC_MEMORY_ERROR; goto bail; } - } - if (error == noError) { - if (noError != (error = FDKsbrEnc_CreateHybridData( &((*hPsChannelData)->hHybData), - ch))) { - goto bail; - } - } - if(error == noError){ - if(noError != (error = CreatePSQmf(&((*hPsChannelData)->hPsQmfData), ch))) - { - goto bail; - } - } -bail: - return error; -} - -static HANDLE_ERROR_INFO InitPSChannel(HANDLE_PS_CHANNEL_DATA hPsChannelData, - HANDLE_PS_HYBRID_CONFIG hHybConfig, - INT noQmfSlots, - INT noQmfBands - ,INT ch, - UCHAR *dynamic_RAM - ) -{ - HANDLE_ERROR_INFO error = noError; - INT hybridFilterDelay = 0; - - if (error == noError) { - if (noError != (error = FDKsbrEnc_InitHybridFilterBank(hPsChannelData->hHybAna, - hHybConfig, - noQmfSlots ))) - { - error = handBack(error); - } - } + FDKmemclear(hParametricStereo, sizeof(PARAMETRIC_STEREO)); - if(error == noError){ - hybridFilterDelay = FDKsbrEnc_GetHybridFilterDelay(hPsChannelData->hHybAna); - hPsChannelData->psChannelDelay = hybridFilterDelay * noQmfBands; - } - - if (error == noError) { - if (noError != (error = FDKsbrEnc_InitHybridData( hPsChannelData->hHybData, - hHybConfig, - noQmfSlots))) - { - error = handBack(error); - } - } - - if(error == noError){ - if(noError != (error = InitPSQmf(hPsChannelData->hPsQmfData, - noQmfSlots, - noQmfBands, - hybridFilterDelay - ,ch, - dynamic_RAM - ))) - { - error = handBack(error); - } - } - - return error; -} - - -/* - name: static HANDLE_ERROR_INFO PSEnc_Create() - description: Creates PS struct - returns: error code of type HANDLE_ERROR_INFO - input: HANDLE_PSENC_CONFIG hPsEncConfig: configuration - output: HANDLE_PARAMETRIC_STEREO *hParametricStereo - -*/ -HANDLE_ERROR_INFO -PSEnc_Create(HANDLE_PARAMETRIC_STEREO *phParametricStereo) -{ - HANDLE_ERROR_INFO error = noError; - INT i; - HANDLE_PARAMETRIC_STEREO hParametricStereo = GetRam_ParamStereo(); - - if (hParametricStereo==NULL) { - error = 1; - goto bail; - } - - FDKmemclear(hParametricStereo,sizeof(PARAMETRIC_STEREO)); - - hParametricStereo->qmfDelayRealRef = GetRam_PsEnvRBuffer(0); - hParametricStereo->qmfDelayImagRef = GetRam_PsEnvIBuffer(0); - - if ( (hParametricStereo->qmfDelayRealRef==NULL) || (hParametricStereo->qmfDelayImagRef==NULL) ) { - error = 1; - goto bail; - } - - for (i = 0; i < (QMF_MAX_TIME_SLOTS>>1); i++) { - hParametricStereo->qmfDelayReal[i] = hParametricStereo->qmfDelayRealRef + (i*QMF_CHANNELS); - hParametricStereo->qmfDelayImag[i] = hParametricStereo->qmfDelayImagRef + (i*QMF_CHANNELS); - } - - for(i=0; i<MAX_PS_CHANNELS; i++){ - if(noError != (error = CreatePSChannel(&hParametricStereo->hPsChannelData[i], - i - ))) - { + if (PSENC_OK != (error = FDKsbrEnc_CreatePSEncode(&hParametricStereo->hPsEncode))) { goto bail; } - } - - if(noError != (error = FDKsbrEnc_CreatePSEncode(&hParametricStereo->hPsEncode))) { - error = 1; - goto bail; - } - - hParametricStereo->hHybridConfig = GetRam_PsHybConfig(); /* allocate memory */ + for (i=0; i<MAX_PS_CHANNELS; i++) { + if (FDKhybridAnalysisOpen( + &hParametricStereo->fdkHybAnaFilter[i], + hParametricStereo->__staticHybAnaStatesLF[i], + sizeof(hParametricStereo->__staticHybAnaStatesLF[i]), + hParametricStereo->__staticHybAnaStatesHF[i], + sizeof(hParametricStereo->__staticHybAnaStatesHF[i]) + ) !=0 ) + { + error = PSENC_MEMORY_ERROR; + goto bail; + } + } - /* calc PS_OUT values and delay one frame ! */ - hParametricStereo->hPsOut[0] = GetRam_PsOut(0); - hParametricStereo->hPsOut[1] = GetRam_PsOut(1); - if ( (hParametricStereo->hHybridConfig==NULL) || (hParametricStereo->hPsOut[0]==NULL) || (hParametricStereo->hPsOut[1]==NULL) ) { - error = 1; - goto bail; + *phParametricStereo = hParametricStereo; /* return allocated handle */ } - bail: - *phParametricStereo = hParametricStereo; return error; } -HANDLE_ERROR_INFO -PSEnc_Init(HANDLE_PARAMETRIC_STEREO hParametricStereo, - HANDLE_PSENC_CONFIG hPsEncConfig, - INT noQmfSlots, - INT noQmfBands - ,UCHAR *dynamic_RAM - ) +FDK_PSENC_ERROR PSEnc_Init( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + const HANDLE_PSENC_CONFIG hPsEncConfig, + INT noQmfSlots, + INT noQmfBands + ,UCHAR *dynamic_RAM + ) { - HANDLE_ERROR_INFO error = noError; - INT i; - INT tmpDelay = 0; + FDK_PSENC_ERROR error = PSENC_OK; - if(error == noError){ - if(hPsEncConfig == NULL){ - error = ERROR(CDI, "Invalid configuration handle."); - } + if ( (NULL==hParametricStereo) || (NULL==hPsEncConfig) ) { + error = PSENC_INVALID_HANDLE; } + else { + int ch, i; - hParametricStereo->initPS = 1; - hParametricStereo->noQmfSlots = noQmfSlots; - hParametricStereo->noQmfBands = noQmfBands; + hParametricStereo->initPS = 1; + hParametricStereo->noQmfSlots = noQmfSlots; + hParametricStereo->noQmfBands = noQmfBands; - for (i = 0; i < hParametricStereo->noQmfSlots>>1; i++) { - FDKmemclear( hParametricStereo->qmfDelayReal[i],QMF_CHANNELS*sizeof(FIXP_DBL)); - FDKmemclear( hParametricStereo->qmfDelayImag[i],QMF_CHANNELS*sizeof(FIXP_DBL)); - } - hParametricStereo->qmfDelayScale = FRACT_BITS-1; - - if(error == noError) { - PS_BANDS nHybridSubbands = (PS_BANDS)0; - - switch(hPsEncConfig->nStereoBands){ - case PSENC_STEREO_BANDS_10: - nHybridSubbands = PS_BANDS_COARSE; - break; - case PSENC_STEREO_BANDS_20: - nHybridSubbands = PS_BANDS_MID; - break; - case PSENC_STEREO_BANDS_34: - /* nHybridSubbands = PS_BANDS_FINE; */ - FDK_ASSERT(0); /* we don't support this mode! */ - break; - default: - nHybridSubbands = (PS_BANDS)0; - break; - } - /* create configuration for hybrid filter bank */ - FDKmemclear(hParametricStereo->hHybridConfig,sizeof(PS_HYBRID_CONFIG)); - if(noError != (error = FDKsbrEnc_CreateHybridConfig(&hParametricStereo->hHybridConfig, nHybridSubbands))) { - error = handBack(error); - } - } + /* clear delay lines */ + FDKmemclear(hParametricStereo->qmfDelayLines, sizeof(hParametricStereo->qmfDelayLines)); + hParametricStereo->qmfDelayScale = FRACT_BITS-1; - tmpDelay = 0; - for(i=0; i<MAX_PS_CHANNELS; i++) { - - if(error == noError){ - if(noError != (error = InitPSChannel( hParametricStereo->hPsChannelData[i], - hParametricStereo->hHybridConfig, - hParametricStereo->noQmfSlots, - hParametricStereo->noQmfBands - ,i, - dynamic_RAM - ))) - { - error = handBack(error); - } - } - - if(error == noError){ - /* sum up delay in samples for all channels (should be the same for all channels) */ - tmpDelay += hParametricStereo->hPsChannelData[i]->psChannelDelay; - } - } + /* create configuration for hybrid filter bank */ + for (ch=0; ch<MAX_PS_CHANNELS; ch++) { + FDKhybridAnalysisInit( + &hParametricStereo->fdkHybAnaFilter[ch], + THREE_TO_TEN, + QMF_CHANNELS, + QMF_CHANNELS, + 1 + ); + } /* ch */ + + FDKhybridSynthesisInit( + &hParametricStereo->fdkHybSynFilter, + THREE_TO_TEN, + QMF_CHANNELS, + QMF_CHANNELS + ); - if(error == noError){ /* determine average delay */ - hParametricStereo->psDelay = tmpDelay/MAX_PS_CHANNELS; - } + hParametricStereo->psDelay = (HYBRID_FILTER_DELAY*hParametricStereo->noQmfBands); - if(error == noError){ - if ( (hPsEncConfig->maxEnvelopes < PSENC_NENV_1) - || (hPsEncConfig->maxEnvelopes > PSENC_NENV_MAX) ) { + if ( (hPsEncConfig->maxEnvelopes < PSENC_NENV_1) || (hPsEncConfig->maxEnvelopes > PSENC_NENV_MAX) ) { hPsEncConfig->maxEnvelopes = PSENC_NENV_DEFAULT; } hParametricStereo->maxEnvelopes = hPsEncConfig->maxEnvelopes; - } - if(error == noError){ - if(noError != (error = FDKsbrEnc_InitPSEncode(hParametricStereo->hPsEncode, (PS_BANDS) hPsEncConfig->nStereoBands, hPsEncConfig->iidQuantErrorThreshold))){ - error = handBack(error); + if (PSENC_OK != (error = FDKsbrEnc_InitPSEncode(hParametricStereo->hPsEncode, (PS_BANDS) hPsEncConfig->nStereoBands, hPsEncConfig->iidQuantErrorThreshold))){ + goto bail; } - } - - /* clear buffer */ - FDKmemclear(hParametricStereo->hPsOut[0], sizeof(PS_OUT)); - FDKmemclear(hParametricStereo->hPsOut[1], sizeof(PS_OUT)); - - /* clear scaling buffer */ - FDKmemclear(hParametricStereo->dynBandScale, sizeof(UCHAR)*PS_MAX_BANDS); - FDKmemclear(hParametricStereo->maxBandValue, sizeof(FIXP_QMF)*PS_MAX_BANDS); - - return error; -} - - - -/* - name: static HANDLE_ERROR_INFO DestroyPSQmf - description: destroy PS qmf buffers - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PS_QMF_DATA *hPsQmfData - output: none -*/ - -static HANDLE_ERROR_INFO DestroyPSQmf(HANDLE_PS_QMF_DATA* phPsQmfData) -{ - HANDLE_PS_QMF_DATA hPsQmfData = *phPsQmfData; - - if(hPsQmfData) { - FreeRam_PsRqmf(hPsQmfData->rQmfData); - FreeRam_PsIqmf(hPsQmfData->iQmfData); - FreeRam_PsQmfData(phPsQmfData); - } - - return noError; -} - - - -/* - name: static HANDLE_ERROR_INFO DestroyPSChannel - description: destroy PS channel data - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PS_CHANNEL_DATA *hPsChannelDAta - output: none -*/ - - -static HANDLE_ERROR_INFO DestroyPSChannel(HANDLE_PS_CHANNEL_DATA *phPsChannelData){ - - HANDLE_ERROR_INFO error = noError; - HANDLE_PS_CHANNEL_DATA hPsChannelData = *phPsChannelData; - - if(hPsChannelData != NULL){ - - DestroyPSQmf(&hPsChannelData->hPsQmfData); - FDKsbrEnc_DeleteHybridFilterBank(&hPsChannelData->hHybAna); + for (ch = 0; ch<MAX_PS_CHANNELS; ch ++) { + FIXP_DBL *pDynReal = GetRam_Sbr_envRBuffer (ch, dynamic_RAM); + FIXP_DBL *pDynImag = GetRam_Sbr_envIBuffer (ch, dynamic_RAM); - FDKsbrEnc_DestroyHybridData(&hPsChannelData->hHybData); - - FreeRam_PsChData(phPsChannelData); - } - - return error; -} - - -/* - name: static HANDLE_ERROR_INFO PSEnc_Destroy - description: destroy PS encoder handle - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PARAMETRIC_STEREO *hParametricStereo - output: none -*/ - -HANDLE_ERROR_INFO -PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO *phParametricStereo){ - - HANDLE_ERROR_INFO error = noError; - HANDLE_PARAMETRIC_STEREO hParametricStereo = *phParametricStereo; - INT i; + for (i=0; i<HYBRID_FRAMESIZE; i++) { + hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][ch][0] = &pDynReal[i*MAX_HYBRID_BANDS]; + hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][ch][1] = &pDynImag[i*MAX_HYBRID_BANDS];; + } - if(hParametricStereo != NULL){ - for(i=0; i<MAX_PS_CHANNELS; i++){ - DestroyPSChannel(&(hParametricStereo->hPsChannelData[i])); - } - FreeRam_PsEnvRBuffer(&hParametricStereo->qmfDelayRealRef); - FreeRam_PsEnvIBuffer(&hParametricStereo->qmfDelayImagRef); + for (i=0; i<HYBRID_READ_OFFSET; i++) { + hParametricStereo->pHybridData[i][ch][0] = hParametricStereo->__staticHybridData[i][ch][0]; + hParametricStereo->pHybridData[i][ch][1] = hParametricStereo->__staticHybridData[i][ch][1]; + } + } /* ch */ - FDKsbrEnc_DestroyPSEncode(&hParametricStereo->hPsEncode); + /* clear static hybrid buffer */ + FDKmemclear(hParametricStereo->__staticHybridData, sizeof(hParametricStereo->__staticHybridData)); - FreeRam_PsOut(&hParametricStereo->hPsOut[0]); - FreeRam_PsOut(&hParametricStereo->hPsOut[1]); + /* clear bs buffer */ + FDKmemclear(hParametricStereo->psOut, sizeof(hParametricStereo->psOut)); - FreeRam_PsHybConfig(&hParametricStereo->hHybridConfig); - FreeRam_ParamStereo(phParametricStereo); - } + /* clear scaling buffer */ + FDKmemclear(hParametricStereo->dynBandScale, sizeof(UCHAR)*PS_MAX_BANDS); + FDKmemclear(hParametricStereo->maxBandValue, sizeof(FIXP_QMF)*PS_MAX_BANDS); + } /* valid handle */ +bail: return error; } -/* - name: static HANDLE_ERROR_INFO UpdatePSQmfData - description: updates buffer containing qmf data first/second halve - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PARAMETRIC_STEREO hParametricStereo - output: - HANDLE_PARAMETRIC_STEREO hParametricStereo with updated qmf data -*/ -static HANDLE_ERROR_INFO -UpdatePSQmfData_first(HANDLE_PARAMETRIC_STEREO hParametricStereo) +FDK_PSENC_ERROR PSEnc_Destroy( + HANDLE_PARAMETRIC_STEREO *phParametricStereo + ) { - HANDLE_ERROR_INFO error = noError; - int i, ch; - for (ch=0; ch<MAX_PS_CHANNELS; ch++) { - /* get qmf buffers */ - FIXP_QMF **RESTRICT realQmfData = hParametricStereo->hPsChannelData[ch]->hPsQmfData->rQmfData + QMF_READ_OFFSET; - FIXP_QMF **RESTRICT imagQmfData = hParametricStereo->hPsChannelData[ch]->hPsQmfData->iQmfData + QMF_READ_OFFSET; - - /* get needed parameters */ - INT nCols = hParametricStereo->hPsChannelData[ch]->hPsQmfData->nCols; - INT nRows = hParametricStereo->hPsChannelData[ch]->hPsQmfData->nRows; - - /* move processed buffer data nCols qmf samples forward */ - for(i=0; i<HYBRID_READ_OFFSET; i++){ - FDKmemcpy (realQmfData[i], realQmfData[i + nCols], sizeof(FIXP_QMF)*nRows ); - FDKmemcpy (imagQmfData[i], imagQmfData[i + nCols], sizeof(FIXP_QMF)*nRows ); - } - } + FDK_PSENC_ERROR error = PSENC_OK; - return error; -} - -HANDLE_ERROR_INFO -UpdatePSQmfData_second(HANDLE_PARAMETRIC_STEREO hParametricStereo) -{ - HANDLE_ERROR_INFO error = noError; - int i, ch; - for (ch=0; ch<MAX_PS_CHANNELS; ch++) { - /* get qmf buffers */ - FIXP_QMF **RESTRICT realQmfData = hParametricStereo->hPsChannelData[ch]->hPsQmfData->rQmfData + QMF_READ_OFFSET; - FIXP_QMF **RESTRICT imagQmfData = hParametricStereo->hPsChannelData[ch]->hPsQmfData->iQmfData + QMF_READ_OFFSET; - - /* get needed parameters */ - INT writeOffset = hParametricStereo->hPsChannelData[ch]->hPsQmfData->bufferWriteOffset; - INT nCols = hParametricStereo->hPsChannelData[ch]->hPsQmfData->nCols; - INT nRows = hParametricStereo->hPsChannelData[ch]->hPsQmfData->nRows; - - /* move processed buffer data nCols qmf samples forward */ - for(i=HYBRID_READ_OFFSET; i<writeOffset; i++){ - FDKmemcpy (realQmfData[i], realQmfData[i + nCols], sizeof(FIXP_QMF)*nRows ); - FDKmemcpy (imagQmfData[i], imagQmfData[i + nCols], sizeof(FIXP_QMF)*nRows ); + if (NULL!=phParametricStereo) { + HANDLE_PARAMETRIC_STEREO hParametricStereo = *phParametricStereo; + if(hParametricStereo != NULL){ + FDKsbrEnc_DestroyPSEncode(&hParametricStereo->hPsEncode); + FreeRam_ParamStereo(phParametricStereo); } } return error; } - - -/* - name: static HANDLE_ERROR_INFO UpdatePSHybridData - description: updates buffer containg PS hybrid data - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PARAMETRIC_STEREO hParametricStereo - output: - HANDLE_PARAMETRIC_STEREO hParametricStereo with updated hybrid data -*/ - -static HANDLE_ERROR_INFO UpdatePSHybridData(HANDLE_PARAMETRIC_STEREO hParametricStereo) +static FDK_PSENC_ERROR ExtractPSParameters( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + const int sendHeader, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2] + ) { - INT i, ch; - - for (ch=0; ch<MAX_PS_CHANNELS; ch++) { - HANDLE_PS_HYBRID_DATA hHybData = hParametricStereo->hPsChannelData[ch]->hHybData; - FIXP_QMF **realHybridData = hHybData->rHybData + HYBRID_DATA_READ_OFFSET; - FIXP_QMF **imagHybridData = hHybData->iHybData + HYBRID_DATA_READ_OFFSET; - INT writeOffset = hHybData->hybDataWriteOffset; - INT frameSize = hHybData->frameSize; - - for(i=0; i<writeOffset; i++){ - FDKmemcpy (realHybridData[i], realHybridData[i + frameSize], sizeof(FIXP_QMF)*HYBRID_NUM_BANDS ); - FDKmemcpy (imagHybridData[i], imagHybridData[i + frameSize], sizeof(FIXP_QMF)*HYBRID_NUM_BANDS ); - } - } - - return noError; -} - - -/* - name: static HANDLE_ERROR_INFO ExtractPSParameters - description: PS parameter extraction - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PARAMETRIC_STEREO hParametricStereo - output: - HANDLE_PARAMETRIC_STEREO hParametricStereo PS parameter -*/ - -static HANDLE_ERROR_INFO -ExtractPSParameters(HANDLE_PARAMETRIC_STEREO hParametricStereo, const int sendHeader){ - - HANDLE_ERROR_INFO error = noError; - - if(error == noError){ - if(hParametricStereo == NULL){ - error = ERROR(CDI, "Invalid handle hParametricStereo."); + FDK_PSENC_ERROR error = PSENC_OK; + + if (hParametricStereo == NULL) { + error = PSENC_INVALID_HANDLE; + } + else { + /* call ps encode function */ + if (hParametricStereo->initPS){ + hParametricStereo->psOut[1] = hParametricStereo->psOut[0]; + } + hParametricStereo->psOut[0] = hParametricStereo->psOut[1]; + + if (PSENC_OK != (error = FDKsbrEnc_PSEncode( + hParametricStereo->hPsEncode, + &hParametricStereo->psOut[1], + hParametricStereo->dynBandScale, + hParametricStereo->maxEnvelopes, + hybridData, + hParametricStereo->noQmfSlots, + sendHeader))) + { + goto bail; } - } - /* call ps encode function */ - if(error == noError){ - if (hParametricStereo->initPS){ - *hParametricStereo->hPsOut[1] = *hParametricStereo->hPsOut[0]; - } - *hParametricStereo->hPsOut[0] = *hParametricStereo->hPsOut[1]; - - if(noError != (error = FDKsbrEnc_PSEncode(hParametricStereo->hPsEncode, - hParametricStereo->hPsOut[1], - hParametricStereo->hPsChannelData[0], - hParametricStereo->hPsChannelData[1], - hParametricStereo->dynBandScale, - hParametricStereo->maxEnvelopes, - sendHeader))){ - error = handBack(error); + if (hParametricStereo->initPS) { + hParametricStereo->psOut[0] = hParametricStereo->psOut[1]; + hParametricStereo->initPS = 0; } - if (hParametricStereo->initPS){ - *hParametricStereo->hPsOut[0] = *hParametricStereo->hPsOut[1]; - hParametricStereo->initPS = 0; - } } - +bail: return error; } -/* - name: static HANDLE_ERROR_INFO DownmixPSQmfData - description: energy weighted downmix and hybrid synthesis - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PARAMETRIC_STEREO hParametricStereo containing left and right channel qmf data - output: - HANDLE_PARAMETRIC_STEREO with updated qmf data buffer, hybrid data buffer - - FIXP_QMF **mixRealQmfData: pointer to buffer containing downmixed (real) qmf data - - FIXP_QMF **mixImagQmfData: pointer to buffer containing downmixed (imag) qmf data -*/ - -static HANDLE_ERROR_INFO -DownmixPSQmfData(HANDLE_PARAMETRIC_STEREO hParametricStereo, FIXP_QMF **RESTRICT mixRealQmfData, - FIXP_QMF **RESTRICT mixImagQmfData, SCHAR *downmixScale) +static FDK_PSENC_ERROR DownmixPSQmfData( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, + FIXP_QMF **RESTRICT mixRealQmfData, + FIXP_QMF **RESTRICT mixImagQmfData, + INT_PCM *downsampledOutSignal, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT noQmfSlots, + const INT psQmfScale[MAX_PS_CHANNELS], + SCHAR *qmfScale + ) { - HANDLE_ERROR_INFO error = noError; - int n, k; - int dynQmfScale, adjQmfScale; - int nQmfSamples=0, nQmfBands=0, nHybridQmfBands=0; - FIXP_QMF **RESTRICT leftRealQmfData = NULL; - FIXP_QMF **RESTRICT leftImagQmfData = NULL; - FIXP_QMF **RESTRICT rightRealQmfData = NULL; - FIXP_QMF **RESTRICT rightImagQmfData = NULL; - FIXP_QMF **RESTRICT leftRealHybridQmfData = NULL; - FIXP_QMF **RESTRICT leftImagHybridQmfData = NULL; - FIXP_QMF **RESTRICT rightRealHybridQmfData = NULL; - FIXP_QMF **RESTRICT rightImagHybridQmfData = NULL; + FDK_PSENC_ERROR error = PSENC_OK; if(hParametricStereo == NULL){ - error = ERROR(CDI, "Invalid handle hParametricStereo."); - } - - if(error == noError){ - /* Update first part of qmf buffers... - no whole buffer update possible; downmix is inplace */ - if(noError != (error = UpdatePSQmfData_first(hParametricStereo))){ - error = handBack(error); - } + error = PSENC_INVALID_HANDLE; } - - if(error == noError){ - /* get buffers: synchronize QMF buffers and hybrid buffers to compensate hybrid filter delay */ - /* hybrid filter bank looks nHybridFilterDelay qmf samples forward */ - leftRealQmfData = hParametricStereo->hPsChannelData[0]->hPsQmfData->rQmfData + HYBRID_READ_OFFSET; - leftImagQmfData = hParametricStereo->hPsChannelData[0]->hPsQmfData->iQmfData + HYBRID_READ_OFFSET; - rightRealQmfData = hParametricStereo->hPsChannelData[1]->hPsQmfData->rQmfData + HYBRID_READ_OFFSET; - rightImagQmfData = hParametricStereo->hPsChannelData[1]->hPsQmfData->iQmfData + HYBRID_READ_OFFSET; - - leftRealHybridQmfData = hParametricStereo->hPsChannelData[0]->hHybData->rHybData + HYBRID_WRITE_OFFSET; - leftImagHybridQmfData = hParametricStereo->hPsChannelData[0]->hHybData->iHybData + HYBRID_WRITE_OFFSET; - rightRealHybridQmfData = hParametricStereo->hPsChannelData[1]->hHybData->rHybData + HYBRID_WRITE_OFFSET; - rightImagHybridQmfData = hParametricStereo->hPsChannelData[1]->hHybData->iHybData + HYBRID_WRITE_OFFSET; - - /* get number of needed parameters */ - nQmfSamples = hParametricStereo->hPsChannelData[0]->hPsQmfData->nCols; - nQmfBands = hParametricStereo->hPsChannelData[0]->hPsQmfData->nRows; - nHybridQmfBands = FDKsbrEnc_GetNumberHybridQmfBands(hParametricStereo->hPsChannelData[0]->hHybData); + else { + int n, k; + C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_QMF, QMF_CHANNELS*2); /* define scalings */ - adjQmfScale = hParametricStereo->hPsChannelData[0]->hHybData->sf_fixpHybrid - - hParametricStereo->hPsChannelData[0]->psQmfScale; - - dynQmfScale = fixMax(0, hParametricStereo->dmxScale-1); /* scale one bit more for addition of left and right */ - - *downmixScale = hParametricStereo->hPsChannelData[0]->hHybData->sf_fixpHybrid - dynQmfScale + 1; - - const FIXP_DBL maxStereoScaleFactor = FL2FXCONST_DBL(2.0f/2.f); + int dynQmfScale = fixMax(0, hParametricStereo->dmxScale-1); /* scale one bit more for addition of left and right */ + int downmixScale = psQmfScale[0] - dynQmfScale; + const FIXP_DBL maxStereoScaleFactor = MAXVAL_DBL; /* 2.f/2.f */ - for(n = 0; n<nQmfSamples; n++){ - INT hybridDataOffset = 0; + for (n = 0; n<noQmfSlots; n++) { - for(k = 0; k<nQmfBands; k++){ - INT l, nHybridSubBands; - FIXP_DBL tmpMixReal, tmpMixImag; + FIXP_DBL tmpHybrid[2][MAX_HYBRID_BANDS]; - if(k < nHybridQmfBands){ - /* process sub-subbands from hybrid qmf */ - nHybridSubBands = FDKsbrEnc_GetHybridResolution(hParametricStereo->hPsChannelData[0]->hHybData, k); - } else { - /* process qmf data */ - nHybridSubBands = 1; - } - - tmpMixReal = FL2FXCONST_DBL(0.f); - tmpMixImag = FL2FXCONST_DBL(0.f); - - for(l=0; l<nHybridSubBands; l++) { + for(k = 0; k<71; k++){ int dynScale, sc; /* scaling */ FIXP_QMF tmpLeftReal, tmpRightReal, tmpLeftImag, tmpRightImag; FIXP_DBL tmpScaleFactor, stereoScaleFactor; - if(k < nHybridQmfBands){ - /* process sub-subbands from hybrid qmf */ - tmpLeftReal = (leftRealHybridQmfData[n][hybridDataOffset + l]); - tmpLeftImag = (leftImagHybridQmfData[n][hybridDataOffset + l]); - tmpRightReal = (rightRealHybridQmfData[n][hybridDataOffset + l]); - tmpRightImag = (rightImagHybridQmfData[n][hybridDataOffset + l]); - dynScale = dynQmfScale; - } else { - /* process qmf data */ - tmpLeftReal = leftRealQmfData[n][k]; - tmpLeftImag = leftImagQmfData[n][k]; - tmpRightReal = rightRealQmfData[n][k]; - tmpRightImag = rightImagQmfData[n][k]; - dynScale = dynQmfScale-adjQmfScale; - } + tmpLeftReal = hybridData[n][0][0][k]; + tmpLeftImag = hybridData[n][0][1][k]; + tmpRightReal = hybridData[n][1][0][k]; + tmpRightImag = hybridData[n][1][1][k]; sc = fixMax(0,CntLeadingZeros( fixMax(fixMax(fixp_abs(tmpLeftReal),fixp_abs(tmpLeftImag)),fixMax(fixp_abs(tmpRightReal),fixp_abs(tmpRightImag))) )-2); tmpLeftReal <<= sc; tmpLeftImag <<= sc; tmpRightReal <<= sc; tmpRightImag <<= sc; - dynScale = fixMin(sc-dynScale,DFRACT_BITS-1); + dynScale = fixMin(sc-dynQmfScale,DFRACT_BITS-1); /* calc stereo scale factor to avoid loss of energy in bands */ /* stereo scale factor = min(2.0f, sqrt( (abs(l(k, n)^2 + abs(r(k, n)^2 )))/(0.5f*abs(l(k, n) + r(k, n))) )) */ @@ -735,268 +309,192 @@ DownmixPSQmfData(HANDLE_PARAMETRIC_STEREO hParametricStereo, FIXP_QMF **RESTRICT stereoScaleFactor = maxStereoScaleFactor; } - /* write data to output */ - tmpMixReal += fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftReal + tmpRightReal))>>dynScale; - tmpMixImag += fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftImag + tmpRightImag))>>dynScale; - } + /* write data to hybrid output */ + tmpHybrid[0][k] = fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftReal + tmpRightReal))>>dynScale; + tmpHybrid[1][k] = fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftImag + tmpRightImag))>>dynScale; - mixRealQmfData[n][k] = tmpMixReal; - mixImagQmfData[n][k] = tmpMixImag; + } /* hybrid bands - k */ - hybridDataOffset += nHybridSubBands; - } - } - } /* if(error == noError) */ + FDKhybridSynthesisApply( + &hParametricStereo->fdkHybSynFilter, + tmpHybrid[0], + tmpHybrid[1], + mixRealQmfData[n], + mixImagQmfData[n]); + qmfSynthesisFilteringSlot( + sbrSynthQmf, + mixRealQmfData[n], + mixImagQmfData[n], + downmixScale-7, + downmixScale-7, + downsampledOutSignal+(n*sbrSynthQmf->no_channels), + 1, + pWorkBuffer); - if(error == noError){ - /* ... and update the hybrid data */ - if(noError != (error = UpdatePSHybridData(hParametricStereo))){ - error = handBack(error); - } - } + } /* slots */ - return error; -} + *qmfScale = -downmixScale + 7; + C_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_QMF, QMF_CHANNELS*2); -/* - name: INT FDKsbrEnc_PSEnc_WritePSData() - description: writes ps_data() element to bitstream (hBitstream), returns number of written bits; - returns number of written bits only, if hBitstream == NULL - returns: number of bits in ps_data() - input: - HANDLE_PARAMETRIC_STEREO hParametricStereo containing extracted ps parameters - output: - HANDLE_FDK_BITSTREAM containing ps_data() element -*/ -INT -FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo, HANDLE_FDK_BITSTREAM hBitstream) -{ - - INT nBitsWritten = 0; + { + const INT noQmfSlots2 = hParametricStereo->noQmfSlots>>1; + const int noQmfBands = hParametricStereo->noQmfBands; - if(hParametricStereo != NULL){ - nBitsWritten = FDKsbrEnc_WritePSBitstream(hParametricStereo->hPsOut[0], hBitstream); - } + INT scale, i, j, slotOffset; - return nBitsWritten; -} + FIXP_QMF tmp[2][QMF_CHANNELS]; + for (i=0; i<noQmfSlots2; i++) { + FDKmemcpy(tmp[0], hParametricStereo->qmfDelayLines[0][i], noQmfBands*sizeof(FIXP_QMF)); + FDKmemcpy(tmp[1], hParametricStereo->qmfDelayLines[1][i], noQmfBands*sizeof(FIXP_QMF)); -/* - name: static HANDLE_ERROR_INFO PSHybridAnalysis() - description: hybrid analysis filter bank of lowest qmf banks - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PARAMETRIC_STEREO hParametricStereo containing qmf samples - output: - HANDLE_PARAMETRIC STEREO hParametricStereo also containing hybrid data -*/ + FDKmemcpy(hParametricStereo->qmfDelayLines[0][i], mixRealQmfData[i+noQmfSlots2], noQmfBands*sizeof(FIXP_QMF)); + FDKmemcpy(hParametricStereo->qmfDelayLines[1][i], mixImagQmfData[i+noQmfSlots2], noQmfBands*sizeof(FIXP_QMF)); -static HANDLE_ERROR_INFO -PSHybridAnalysis(HANDLE_PARAMETRIC_STEREO hParametricStereo){ + FDKmemcpy(mixRealQmfData[i+noQmfSlots2], mixRealQmfData[i], noQmfBands*sizeof(FIXP_QMF)); + FDKmemcpy(mixImagQmfData[i+noQmfSlots2], mixImagQmfData[i], noQmfBands*sizeof(FIXP_QMF)); - HANDLE_ERROR_INFO error = noError; - int ch; + FDKmemcpy(mixRealQmfData[i], tmp[0], noQmfBands*sizeof(FIXP_QMF)); + FDKmemcpy(mixImagQmfData[i], tmp[1], noQmfBands*sizeof(FIXP_QMF)); + } - if(hParametricStereo == NULL){ - error = ERROR(CDI, "Invalid handle hParametricStereo."); - } + if (hParametricStereo->qmfDelayScale > *qmfScale) { + scale = hParametricStereo->qmfDelayScale - *qmfScale; + slotOffset = 0; + } + else { + scale = *qmfScale - hParametricStereo->qmfDelayScale; + slotOffset = noQmfSlots2; + } - for (ch=0; ch<MAX_PS_CHANNELS; ch++) { - if(error == noError){ - if(noError != (error = HybridAnalysis(hParametricStereo->hPsChannelData[ch]->hHybAna, - hParametricStereo->hPsChannelData[ch]->hPsQmfData->rQmfData + HYBRID_READ_OFFSET, - hParametricStereo->hPsChannelData[ch]->hPsQmfData->iQmfData + HYBRID_READ_OFFSET, - hParametricStereo->hPsChannelData[ch]->psQmfScale, - hParametricStereo->hPsChannelData[ch]->hHybData->rHybData + HYBRID_WRITE_OFFSET, - hParametricStereo->hPsChannelData[ch]->hHybData->iHybData + HYBRID_WRITE_OFFSET, - &hParametricStereo->hPsChannelData[ch]->hHybData->sf_fixpHybrid))){ - error = handBack(error); + for (i=0; i<noQmfSlots2; i++) { + for (j=0; j<noQmfBands; j++) { + mixRealQmfData[i+slotOffset][j] >>= scale; + mixImagQmfData[i+slotOffset][j] >>= scale; } } + + scale = *qmfScale; + *qmfScale = FDKmin(*qmfScale, hParametricStereo->qmfDelayScale); + hParametricStereo->qmfDelayScale = scale; } + } /* valid handle */ + return error; } -/* - name: HANDLE_ERROR_INFO FDKsbrEnc_PSEnc_ParametricStereoProcessing - description: Complete PS Processing: - qmf + hybrid analysis of time domain data (left and right channel), - PS parameter extraction - downmix of qmf data - returns: error code of type HANDLE_ERROR_INFO - input: - HANDLE_PARAMETRIC_STEREO hParametricStereo - output: - HANDLE_PARAMETRIC STEREO hParametricStereo containing extracted PS parameters - - FIXP_DBL **qmfDataReal: Pointer to buffer containing downmixed, real qmf data - - FIXP_DBL **qmfDataImag: Pointer to buffer containing downmixed, imag qmf data - - INT_PCM **downsampledOutSignal: Pointer to buffer containing downmixed time signal - - SCHAR *qmfScale: Updated scale value for the QMF downmix data - -*/ - -HANDLE_ERROR_INFO -FDKsbrEnc_PSEnc_ParametricStereoProcessing(HANDLE_PARAMETRIC_STEREO hParametricStereo, - FIXP_QMF **RESTRICT qmfDataReal, - FIXP_QMF **RESTRICT qmfDataImag, - INT qmfOffset, - INT_PCM *downsampledOutSignal, - HANDLE_QMF_FILTER_BANK sbrSynthQmf, - SCHAR *qmfScale, - const int sendHeader) + +INT FDKsbrEnc_PSEnc_WritePSData( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitstream + ) { - HANDLE_ERROR_INFO error = noError; - FIXP_QMF **downmixedRealQmfData = qmfDataReal+qmfOffset; - FIXP_QMF **downmixedImagQmfData = qmfDataImag+qmfOffset; - SCHAR dmScale = 0; - INT noQmfBands = hParametricStereo->noQmfBands; + return ( (hParametricStereo!=NULL) ? FDKsbrEnc_WritePSBitstream(&hParametricStereo->psOut[0], hBitstream) : 0 ); +} - if (error == noError) { - /* do ps hybrid analysis */ - if(noError != (error = PSHybridAnalysis(hParametricStereo))){ - error = handBack(error); - } - } - - /* find best scaling in new QMF and Hybrid data */ - psFindBestScaling( hParametricStereo, - hParametricStereo->dynBandScale, - hParametricStereo->maxBandValue, - &hParametricStereo->dmxScale ) ; +FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + INT_PCM *samples[2], + UINT timeInStride, + QMF_FILTER_BANK **hQmfAnalysis, + FIXP_QMF **RESTRICT downmixedRealQmfData, + FIXP_QMF **RESTRICT downmixedImagQmfData, + INT_PCM *downsampledOutSignal, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, + SCHAR *qmfScale, + const int sendHeader + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + INT noQmfBands = hParametricStereo->noQmfBands; + INT psQmfScale[MAX_PS_CHANNELS] = {0}; + int psCh, i; + C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, QMF_CHANNELS*4); + for (psCh = 0; psCh<MAX_PS_CHANNELS; psCh ++) { - if(error == noError){ - /* extract the ps parameters */ - if(noError != (error = ExtractPSParameters(hParametricStereo, sendHeader))){ - error = handBack(error); - } - } + for (i = 0; i < hQmfAnalysis[psCh]->no_col; i++) { - if(error == noError){ - /* downmix and hybrid synthesis */ - if(noError != (error = DownmixPSQmfData(hParametricStereo, downmixedRealQmfData, downmixedImagQmfData, &dmScale))){ - error = handBack(error); - } - } + qmfAnalysisFilteringSlot( + hQmfAnalysis[psCh], + &pWorkBuffer[2*QMF_CHANNELS], /* qmfReal[QMF_CHANNELS] */ + &pWorkBuffer[3*QMF_CHANNELS], /* qmfImag[QMF_CHANNELS] */ + samples[psCh]+i*(hQmfAnalysis[psCh]->no_channels*timeInStride), + timeInStride, + &pWorkBuffer[0*QMF_CHANNELS] /* qmf workbuffer 2*QMF_CHANNELS */ + ); + FDKhybridAnalysisApply( + &hParametricStereo->fdkHybAnaFilter[psCh], + &pWorkBuffer[2*QMF_CHANNELS], /* qmfReal[QMF_CHANNELS] */ + &pWorkBuffer[3*QMF_CHANNELS], /* qmfImag[QMF_CHANNELS] */ + hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][psCh][0], + hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][psCh][1] + ); - if (error == noError) - { - C_ALLOC_SCRATCH_START(qmfWorkBuffer, FIXP_DBL, QMF_CHANNELS*2); - /* + } /* no_col loop i */ - QMF synthesis including downsampling + psQmfScale[psCh] = hQmfAnalysis[psCh]->outScalefactor; - */ - QMF_SCALE_FACTOR tmpScale; - int scale = -dmScale; - tmpScale.lb_scale = scale; - tmpScale.ov_lb_scale = scale; - tmpScale.hb_scale = scale; - tmpScale.ov_hb_scale = 0; + } /* for psCh */ - qmfSynthesisFiltering( sbrSynthQmf, - downmixedRealQmfData, - downmixedImagQmfData, - &tmpScale, - 0, - downsampledOutSignal, - 1, - qmfWorkBuffer ); + C_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, QMF_CHANNELS*4); - C_ALLOC_SCRATCH_END(qmfWorkBuffer, FIXP_DBL, QMF_CHANNELS*2); + /* find best scaling in new QMF and Hybrid data */ + psFindBestScaling( hParametricStereo, + &hParametricStereo->pHybridData[HYBRID_READ_OFFSET], + hParametricStereo->dynBandScale, + hParametricStereo->maxBandValue, + &hParametricStereo->dmxScale ) ; + /* extract the ps parameters */ + if(PSENC_OK != (error = ExtractPSParameters(hParametricStereo, sendHeader, &hParametricStereo->pHybridData[0]))){ + goto bail; } - /* scaling in sbr module differs -> scaling update */ - *qmfScale = -dmScale + 7; - - - /* - * Do PS to SBR QMF data transfer/scaling buffer shifting, delay lines etc. - */ - { - INT noQmfSlots2 = hParametricStereo->noQmfSlots>>1; - - FIXP_QMF r_tmp1; - FIXP_QMF i_tmp1; - FIXP_QMF **delayQmfReal = hParametricStereo->qmfDelayReal; - FIXP_QMF **delayQmfImag = hParametricStereo->qmfDelayImag; - INT scale, i, j; - - if (hParametricStereo->qmfDelayScale > *qmfScale) { - scale = hParametricStereo->qmfDelayScale - *qmfScale; + /* save hybrid date for next frame */ + for (i=0; i<HYBRID_READ_OFFSET; i++) { + FDKmemcpy(hParametricStereo->pHybridData[i][0][0], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][0][0], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* left, real */ + FDKmemcpy(hParametricStereo->pHybridData[i][0][1], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][0][1], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* left, imag */ + FDKmemcpy(hParametricStereo->pHybridData[i][1][0], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][1][0], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* right, real */ + FDKmemcpy(hParametricStereo->pHybridData[i][1][1], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][1][1], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* right, imag */ + } - for (i=0; i<noQmfSlots2; i++) { - for (j=0; j<noQmfBands; j++) { - r_tmp1 = qmfDataReal[i][j]; - i_tmp1 = qmfDataImag[i][j]; - - qmfDataReal[i][j] = delayQmfReal[i][j] >> scale; - qmfDataImag[i][j] = delayQmfImag[i][j] >> scale; - delayQmfReal[i][j] = qmfDataReal[i+noQmfSlots2][j]; - delayQmfImag[i][j] = qmfDataImag[i+noQmfSlots2][j]; - qmfDataReal[i+noQmfSlots2][j] = r_tmp1; - qmfDataImag[i+noQmfSlots2][j] = i_tmp1; - } - } - hParametricStereo->qmfDelayScale = *qmfScale; - } - else { - scale = *qmfScale - hParametricStereo->qmfDelayScale; - for (i=0; i<noQmfSlots2; i++) { - for (j=0; j<noQmfBands; j++) { - r_tmp1 = qmfDataReal[i][j]; - i_tmp1 = qmfDataImag[i][j]; - - qmfDataReal[i][j] = delayQmfReal[i][j]; - qmfDataImag[i][j] = delayQmfImag[i][j]; - delayQmfReal[i][j] = qmfDataReal[i+noQmfSlots2][j]; - delayQmfImag[i][j] = qmfDataImag[i+noQmfSlots2][j]; - qmfDataReal[i+noQmfSlots2][j] = r_tmp1 >> scale; - qmfDataImag[i+noQmfSlots2][j] = i_tmp1 >> scale; - } - } - scale = *qmfScale; - *qmfScale = hParametricStereo->qmfDelayScale; - hParametricStereo->qmfDelayScale = scale; - } + /* downmix and hybrid synthesis */ + if (PSENC_OK != (error = DownmixPSQmfData(hParametricStereo, sbrSynthQmf, downmixedRealQmfData, downmixedImagQmfData, downsampledOutSignal, &hParametricStereo->pHybridData[HYBRID_READ_OFFSET], hParametricStereo->noQmfSlots, psQmfScale, qmfScale))) { + goto bail; } +bail: + return error; } -static void psFindBestScaling(HANDLE_PARAMETRIC_STEREO hParametricStereo, - UCHAR *RESTRICT dynBandScale, - FIXP_QMF *RESTRICT maxBandValue, - SCHAR *RESTRICT dmxScale) +static void psFindBestScaling( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + UCHAR *dynBandScale, + FIXP_QMF *maxBandValue, + SCHAR *dmxScale + ) { HANDLE_PS_ENCODE hPsEncode = hParametricStereo->hPsEncode; - HANDLE_PS_HYBRID_DATA hHybDatal = hParametricStereo->hPsChannelData[0]->hHybData; - - INT group, bin, border, col, band; - INT frameSize = FDKsbrEnc_GetHybridFrameSize(hHybDatal); /* same as FDKsbrEnc_GetHybridFrameSize(hHybDatar) */ - INT psBands = (INT) hPsEncode->psEncMode; - INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; - - FIXP_QMF **lr = hParametricStereo->hPsChannelData[0]->hHybData->rHybData; - FIXP_QMF **li = hParametricStereo->hPsChannelData[0]->hHybData->iHybData; - FIXP_QMF **rr = hParametricStereo->hPsChannelData[1]->hHybData->rHybData; - FIXP_QMF **ri = hParametricStereo->hPsChannelData[1]->hHybData->iHybData; - FIXP_QMF **lrBuffer = hParametricStereo->hPsChannelData[0]->hPsQmfData->rQmfData; - FIXP_QMF **liBuffer = hParametricStereo->hPsChannelData[0]->hPsQmfData->iQmfData; - FIXP_QMF **rrBuffer = hParametricStereo->hPsChannelData[1]->hPsQmfData->rQmfData; - FIXP_QMF **riBuffer = hParametricStereo->hPsChannelData[1]->hPsQmfData->iQmfData; + + INT group, bin, col, band; + const INT frameSize = hParametricStereo->noQmfSlots; + const INT psBands = (INT) hPsEncode->psEncMode; + const INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; /* group wise scaling */ FIXP_QMF maxVal [2][PS_MAX_BANDS]; FIXP_QMF maxValue = FL2FXCONST_DBL(0.f); - INT nHybridQmfOffset = 0; - - UCHAR switched = 0; - FDKmemclear(maxVal, sizeof(maxVal)); /* start with hybrid data */ @@ -1004,53 +502,32 @@ static void psFindBestScaling(HANDLE_PARAMETRIC_STEREO hParametricStereo, /* Translate group to bin */ bin = hPsEncode->subband2parameterIndex[group]; - if (!switched && group == hPsEncode->nSubQmfIidGroups) { - /* switch to qmf data */ - lr = lrBuffer; li = liBuffer; - rr = rrBuffer; ri = riBuffer; - - /* calc offset between hybrid subsubbands and qmf bands */ - nHybridQmfOffset = FDKsbrEnc_GetNumberHybridQmfBands(hHybDatal) - FDKsbrEnc_GetNumberHybridBands(hHybDatal); - switched = 1; - } - /* Translate from 20 bins to 10 bins */ if (hPsEncode->psEncMode == PS_BANDS_COARSE) { bin >>= 1; } - /* determine group border */ - border = hPsEncode->iidGroupBorders[group+1]; - /* QMF downmix scaling */ { FIXP_QMF tmp = maxVal[0][bin]; int i; - for (col=HYBRID_READ_OFFSET; col<frameSize; col++) { - FIXP_QMF *pLR = &lr[col][hPsEncode->iidGroupBorders[group] + nHybridQmfOffset]; - FIXP_QMF *pLI = &li[col][hPsEncode->iidGroupBorders[group] + nHybridQmfOffset]; - FIXP_QMF *pRR = &rr[col][hPsEncode->iidGroupBorders[group] + nHybridQmfOffset]; - FIXP_QMF *pRI = &ri[col][hPsEncode->iidGroupBorders[group] + nHybridQmfOffset]; - for (i = 0; i<border-hPsEncode->iidGroupBorders[group]; i++) { - tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(*pLR++)); - tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(*pLI++)); - tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(*pRR++)); - tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(*pRI++)); + for (col=0; col<frameSize-HYBRID_READ_OFFSET; col++) { + for (i = hPsEncode->iidGroupBorders[group]; i < hPsEncode->iidGroupBorders[group+1]; i++) { + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][0][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][1][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][0][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][1][i])); } } maxVal[0][bin] = tmp; tmp = maxVal[1][bin]; - for (col=frameSize; col<HYBRID_READ_OFFSET+frameSize; col++) { - FIXP_QMF *pLR = &lr[col][hPsEncode->iidGroupBorders[group] + nHybridQmfOffset]; - FIXP_QMF *pLI = &li[col][hPsEncode->iidGroupBorders[group] + nHybridQmfOffset]; - FIXP_QMF *pRR = &rr[col][hPsEncode->iidGroupBorders[group] + nHybridQmfOffset]; - FIXP_QMF *pRI = &ri[col][hPsEncode->iidGroupBorders[group] + nHybridQmfOffset]; - for (i = 0; i<border-hPsEncode->iidGroupBorders[group]; i++) { - tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(*pLR++)); - tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(*pLI++)); - tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(*pRR++)); - tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(*pRI++)); + for (col=frameSize-HYBRID_READ_OFFSET; col<frameSize; col++) { + for (i = hPsEncode->iidGroupBorders[group]; i < hPsEncode->iidGroupBorders[group+1]; i++) { + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][0][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][1][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][0][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][1][i])); } } maxVal[1][bin] = tmp; diff --git a/libSBRenc/src/ps_main.h b/libSBRenc/src/ps_main.h index b2fac92..4833fe0 100644 --- a/libSBRenc/src/ps_main.h +++ b/libSBRenc/src/ps_main.h @@ -30,74 +30,49 @@ /* Includes ******************************************************************/ #include "sbr_def.h" -#include "psenc_hybrid.h" +#include "qmf.h" #include "ps_encode.h" #include "FDK_bitstream.h" +#include "FDK_hybrid.h" + /* Data Types ****************************************************************/ typedef enum { PSENC_STEREO_BANDS_INVALID = 0, - PSENC_STEREO_BANDS_10 = 10, - PSENC_STEREO_BANDS_20 = 20, - PSENC_STEREO_BANDS_34 = 34 + PSENC_STEREO_BANDS_10 = 10, + PSENC_STEREO_BANDS_20 = 20 + } PSENC_STEREO_BANDS_CONFIG; typedef enum { - PSENC_NENV_1 = 1, - PSENC_NENV_2 = 2, - PSENC_NENV_4 = 4, - PSENC_NENV_DEFAULT = PSENC_NENV_2, - PSENC_NENV_MAX = PSENC_NENV_4 -} PSENC_NENV_CONFIG; + PSENC_NENV_1 = 1, + PSENC_NENV_2 = 2, + PSENC_NENV_4 = 4, + PSENC_NENV_DEFAULT = PSENC_NENV_2, + PSENC_NENV_MAX = PSENC_NENV_4 -#define MAX_PS_CHANNELS ( 2 ) -#define PSENC_QMF_BUFFER_LENGTH ( 48 ) +} PSENC_NENV_CONFIG; typedef struct { - - UINT bitrateFrom; /* inclusive */ - UINT bitrateTo; /* exclusive */ - PSENC_STEREO_BANDS_CONFIG nStereoBands; - PSENC_NENV_CONFIG nEnvelopes; - LONG iidQuantErrorThreshold; /* quantization threshold to switch between coarse and fine iid quantization */ + UINT bitrateFrom; /* inclusive */ + UINT bitrateTo; /* exclusive */ + PSENC_STEREO_BANDS_CONFIG nStereoBands; + PSENC_NENV_CONFIG nEnvelopes; + LONG iidQuantErrorThreshold; /* quantization threshold to switch between coarse and fine iid quantization */ } psTuningTable_t; /* Function / Class Declarations *********************************************/ -typedef struct T_PS_QMF_DATA -{ - FIXP_QMF *rQmfData[PSENC_QMF_BUFFER_LENGTH]; - FIXP_QMF *iQmfData[PSENC_QMF_BUFFER_LENGTH]; - INT nCols; - INT nRows; - INT bufferReadOffset; - INT bufferReadOffsetHybrid; - INT bufferWriteOffset; - INT bufferLength; -} PS_QMF_DATA, *HANDLE_PS_QMF_DATA; - -typedef struct T_PS_CHANNEL_DATA { - HANDLE_PS_QMF_DATA hPsQmfData; - - int psQmfScale; - HANDLE_PS_HYBRID_DATA hHybData; - HANDLE_PS_HYBRID hHybAna; - INT psChannelDelay; /* delay in samples */ -} PS_CHANNEL_DATA, *HANDLE_PS_CHANNEL_DATA; - typedef struct T_PARAMETRIC_STEREO { - - HANDLE_PS_HYBRID_CONFIG hHybridConfig; - HANDLE_PS_CHANNEL_DATA hPsChannelData[MAX_PS_CHANNELS]; HANDLE_PS_ENCODE hPsEncode; - HANDLE_PS_OUT hPsOut[2]; + PS_OUT psOut[2]; - FIXP_QMF *qmfDelayReal[QMF_MAX_TIME_SLOTS>>1]; - FIXP_QMF *qmfDelayImag[QMF_MAX_TIME_SLOTS>>1]; - FIXP_QMF *qmfDelayRealRef; - FIXP_QMF *qmfDelayImagRef; - int qmfDelayScale; + FIXP_DBL __staticHybridData[HYBRID_READ_OFFSET][MAX_PS_CHANNELS][2][MAX_HYBRID_BANDS]; + FIXP_DBL *pHybridData[HYBRID_READ_OFFSET+HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2]; + + FIXP_QMF qmfDelayLines[2][QMF_MAX_TIME_SLOTS>>1][QMF_CHANNELS]; + int qmfDelayScale; INT psDelay; UINT maxEnvelopes; @@ -108,53 +83,126 @@ typedef struct T_PARAMETRIC_STEREO { INT noQmfSlots; INT noQmfBands; -} PARAMETRIC_STEREO; + FIXP_DBL __staticHybAnaStatesLF[MAX_PS_CHANNELS][2*HYBRID_FILTER_LENGTH*HYBRID_MAX_QMF_BANDS]; + FIXP_DBL __staticHybAnaStatesHF[MAX_PS_CHANNELS][2*HYBRID_FILTER_DELAY*(QMF_CHANNELS-HYBRID_MAX_QMF_BANDS)]; + FDK_ANA_HYB_FILTER fdkHybAnaFilter[MAX_PS_CHANNELS]; + FDK_SYN_HYB_FILTER fdkHybSynFilter; +} PARAMETRIC_STEREO; typedef struct T_PSENC_CONFIG { - - INT frameSize; - INT qmfFilterMode; - INT sbrPsDelay; - PSENC_STEREO_BANDS_CONFIG nStereoBands; - PSENC_NENV_CONFIG maxEnvelopes; - FIXP_DBL iidQuantErrorThreshold; + INT frameSize; + INT qmfFilterMode; + INT sbrPsDelay; + PSENC_STEREO_BANDS_CONFIG nStereoBands; + PSENC_NENV_CONFIG maxEnvelopes; + FIXP_DBL iidQuantErrorThreshold; } PSENC_CONFIG, *HANDLE_PSENC_CONFIG; typedef struct T_PARAMETRIC_STEREO *HANDLE_PARAMETRIC_STEREO; -HANDLE_ERROR_INFO -PSEnc_Create(HANDLE_PARAMETRIC_STEREO *phParametricStereo); - -HANDLE_ERROR_INFO -PSEnc_Init(HANDLE_PARAMETRIC_STEREO hParametricStereo, - HANDLE_PSENC_CONFIG hPsEncConfig, - INT noQmfSlots, - INT noQmfBands - ,UCHAR *dynamic_RAM - ); - -HANDLE_ERROR_INFO -UpdatePSQmfData_second(HANDLE_PARAMETRIC_STEREO hParametricStereo); - -HANDLE_ERROR_INFO -PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO *hParametricStereo); - - -HANDLE_ERROR_INFO -FDKsbrEnc_PSEnc_ParametricStereoProcessing(HANDLE_PARAMETRIC_STEREO hParametricStereo, - FIXP_QMF **RESTRICT qmfRealData, - FIXP_QMF **RESTRICT qmfImagData, - INT qmfOffset, - INT_PCM *downsampledOutSignal, - HANDLE_QMF_FILTER_BANK sbrSynthQmf, - SCHAR *qmfScale, - const int sendHeader); - -INT -FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo, HANDLE_FDK_BITSTREAM hBitstream); +/** + * \brief Create a parametric stereo encoder instance. + * + * \param phParametricStereo A pointer to a parametric stereo handle to be allocated. Initialized on return. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_MEMORY_ERROR, on failure. + */ +FDK_PSENC_ERROR PSEnc_Create( + HANDLE_PARAMETRIC_STEREO *phParametricStereo + ); + + +/** + * \brief Initialize a parametric stereo encoder instance. + * + * \param hParametricStereo Meta Data handle. + * \param hPsEncConfig Filled parametric stereo configuration structure. + * \param noQmfSlots Number of slots within one audio frame. + * \param noQmfBands Number of QMF bands. + * \param dynamic_RAM Pointer to preallocated workbuffer. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_INIT_ERROR, on failure. + */ +FDK_PSENC_ERROR PSEnc_Init( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + const HANDLE_PSENC_CONFIG hPsEncConfig, + INT noQmfSlots, + INT noQmfBands + ,UCHAR *dynamic_RAM + ); + + +/** + * \brief Destroy parametric stereo encoder instance. + * + * Deallocate instance and free whole memory. + * + * \param phParametricStereo Pointer to the parametric stereo handle to be deallocated. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, on failure. + */ +FDK_PSENC_ERROR PSEnc_Destroy( + HANDLE_PARAMETRIC_STEREO *phParametricStereo + ); + + +/** + * \brief Apply parametric stereo processing. + * + * \param hParametricStereo Meta Data handle. + * \param samples Pointer to 2 channel audio input signal. + * \param timeInStride, Stride factor of input buffer. + * \param hQmfAnalysis, Pointer to QMF analysis filterbanks. + * \param downmixedRealQmfData Pointer to real QMF buffer to be written to. + * \param downmixedImagQmfData Pointer to imag QMF buffer to be written to. + * \param downsampledOutSignal Pointer to buffer where to write downmixed timesignal. + * \param sbrSynthQmf Pointer to QMF synthesis filterbank. + * \param qmfScale Return scaling factor of the qmf data. + * \param sendHeader Signal whether to write header data. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_ENCODE_ERROR, on failure. + */ +FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + INT_PCM *samples[2], + UINT timeInStride, + QMF_FILTER_BANK **hQmfAnalysis, + FIXP_QMF **RESTRICT downmixedRealQmfData, + FIXP_QMF **RESTRICT downmixedImagQmfData, + INT_PCM *downsampledOutSignal, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, + SCHAR *qmfScale, + const int sendHeader + ); + + +/** + * \brief Write parametric stereo bitstream. + * + * Write ps_data() element to bitstream and return number of written bits. + * Returns number of written bits only, if hBitstream == NULL. + * + * \param hParametricStereo Meta Data handle. + * \param hBitstream Bitstream buffer handle. + * + * \return + * - number of written bits. + */ +INT FDKsbrEnc_PSEnc_WritePSData( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitstream + ); #endif /* __INCLUDED_PS_MAIN_H */ diff --git a/libSBRenc/src/psenc_hybrid.cpp b/libSBRenc/src/psenc_hybrid.cpp deleted file mode 100644 index a314678..0000000 --- a/libSBRenc/src/psenc_hybrid.cpp +++ /dev/null @@ -1,836 +0,0 @@ -/***************************** MPEG Audio Encoder *************************** - - (C) Copyright Fraunhofer IIS (2004-2005) - All Rights Reserved - - Please be advised that this software and/or program delivery is - Confidential Information of Fraunhofer and subject to and covered by the - - Fraunhofer IIS Software Evaluation Agreement - between Google Inc. and Fraunhofer - effective and in full force since March 1, 2012. - - You may use this software and/or program only under the terms and - conditions described in the above mentioned Fraunhofer IIS Software - Evaluation Agreement. Any other and/or further use requires a separate agreement. - - - $Id$ - Initial author: M. Neuendorf, M. Multrus - contents/description: hybrid analysis filter bank - - This software and/or program is protected by copyright law and international - treaties. Any reproduction or distribution of this software and/or program, - or any portion of it, may result in severe civil and criminal penalties, and - will be prosecuted to the maximum extent possible under law. - -******************************************************************************/ - -#include "psenc_hybrid.h" - - -/* Includes ******************************************************************/ - -#include "psenc_hybrid.h" -#include "sbr_ram.h" - -#include "fft.h" - -#include "genericStds.h" - -/* Defines *******************************************************************/ - -#define HYBRID_SCALE 4 - -/*//#define FAST_FILTER2 -#define FAST_FILTER4 -#define FAST_FILTER8 -#define FAST_FILTER12 -*/ -#define HYBRID_INVERSE_ORDER ( 0x0F000000 ) -#define HYBRID_INVERSE_MASK ( ~HYBRID_INVERSE_ORDER ) - -//#define REAL ( 0 ) -//#define CPLX ( 1 ) - -#define cos0Pi FL2FXCONST_DBL( 1.f) -#define sin0Pi FL2FXCONST_DBL( 0.f) -#define cos1Pi FL2FXCONST_DBL(-1.f) -#define sin1Pi FL2FXCONST_DBL( 0.f) -#define cos1Pi_2 FL2FXCONST_DBL( 0.f) -#define sin1Pi_2 FL2FXCONST_DBL( 1.f) -#define cos1Pi_3 FL2FXCONST_DBL( 0.5f) -#define sin1Pi_3 FL2FXCONST_DBL( 0.86602540378444f) - -#define cos0Pi_4 cos0Pi -#define cos1Pi_4 FL2FXCONST_DBL(0.70710678118655f) -#define cos2Pi_4 cos1Pi_2 -#define cos3Pi_4 (-cos1Pi_4) -#define cos4Pi_4 (-cos0Pi_4) -#define cos5Pi_4 cos3Pi_4 -#define cos6Pi_4 cos2Pi_4 - -#define sin0Pi_4 sin0Pi -#define sin1Pi_4 FL2FXCONST_DBL(0.70710678118655f) -#define sin2Pi_4 sin1Pi_2 -#define sin3Pi_4 sin1Pi_4 -#define sin4Pi_4 sin0Pi_4 -#define sin5Pi_4 (-sin3Pi_4) -#define sin6Pi_4 (-sin2Pi_4) - -#define cos0Pi_8 cos0Pi -#define cos1Pi_8 FL2FXCONST_DBL(0.92387953251129f) -#define cos2Pi_8 cos1Pi_4 -#define cos3Pi_8 FL2FXCONST_DBL(0.38268343236509f) -#define cos4Pi_8 cos2Pi_4 -#define cos5Pi_8 (-cos3Pi_8) -#define cos6Pi_8 (-cos2Pi_8) - -#define sin0Pi_8 sin0Pi -#define sin1Pi_8 cos3Pi_8 -#define sin2Pi_8 sin1Pi_4 -#define sin3Pi_8 cos1Pi_8 -#define sin4Pi_8 sin2Pi_4 -#define sin5Pi_8 sin3Pi_8 -#define sin6Pi_8 sin1Pi_4 - -#define cos0Pi_12 cos0Pi -#define cos1Pi_12 FL2FXCONST_DBL(0.96592582628906f) -#define cos2Pi_12 FL2FXCONST_DBL(0.86602540378444f) -#define cos3Pi_12 cos1Pi_4 -#define cos4Pi_12 cos1Pi_3 -#define cos5Pi_12 FL2FXCONST_DBL(0.25881904510252f) -#define cos6Pi_12 cos1Pi_2 - -#define sin0Pi_12 sin0Pi -#define sin1Pi_12 cos5Pi_12 -#define sin2Pi_12 cos4Pi_12 -#define sin3Pi_12 sin1Pi_4 -#define sin4Pi_12 sin1Pi_3 -#define sin5Pi_12 cos1Pi_12 -#define sin6Pi_12 sin1Pi_2 - -#define FFT_IDX_R(a) (2*a) -#define FFT_IDX_I(a) (2*a+1) - - -/* Constants *****************************************************************/ - -/* static const UINT noQmfBandsInHybrid34 = 5; */ - -static const INT aHybridResolution10[] = { HYBRID_6_CPLX, - HYBRID_2_REAL | HYBRID_INVERSE_ORDER, - HYBRID_2_REAL }; - -static const INT aHybridResolution20[] = { HYBRID_6_CPLX, - HYBRID_2_REAL | HYBRID_INVERSE_ORDER, - HYBRID_2_REAL }; - -/*static const INT aHybridResolution34[] = { HYBRID_12_CPLX, - HYBRID_8_CPLX, - HYBRID_4_CPLX, - HYBRID_4_CPLX, - HYBRID_4_CPLX };*/ - -static const FIXP_DBL p8_13_20[HYBRID_FILTER_LENGTH] = -{ - FL2FXCONST_DBL(0.00746082949812f), FL2FXCONST_DBL(0.02270420949825f), FL2FXCONST_DBL(0.04546865930473f), FL2FXCONST_DBL(0.07266113929591f), - FL2FXCONST_DBL(0.09885108575264f), FL2FXCONST_DBL(0.11793710567217f), FL2FXCONST_DBL(0.125f ), FL2FXCONST_DBL(0.11793710567217f), - FL2FXCONST_DBL(0.09885108575264f), FL2FXCONST_DBL(0.07266113929591f), FL2FXCONST_DBL(0.04546865930473f), FL2FXCONST_DBL(0.02270420949825f), - FL2FXCONST_DBL(0.00746082949812f) -}; - -static const FIXP_DBL p2_13_20[HYBRID_FILTER_LENGTH] = -{ - FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL( 0.01899487526049f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(-0.07293139167538f), - FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL( 0.30596630545168f), FL2FXCONST_DBL(0.5f), FL2FXCONST_DBL( 0.30596630545168f), - FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(-0.07293139167538f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL( 0.01899487526049f), - FL2FXCONST_DBL(0.0f) -}; - - -/*static const float p12_13_34[HYBRID_FILTER_LENGTH] = -{ - 0.04081179924692, 0.03812810994926, 0.05144908135699, 0.06399831151592, - 0.07428313801106, 0.08100347892914, 0.08333333333333, 0.08100347892914, - 0.07428313801106, 0.06399831151592, 0.05144908135699, 0.03812810994926, - 0.04081179924692 -}; - -static const float p8_13_34[HYBRID_FILTER_LENGTH] = -{ - 0.01565675600122, 0.03752716391991, 0.05417891378782, 0.08417044116767, - 0.10307344158036, 0.12222452249753, 0.12500000000000, 0.12222452249753, - 0.10307344158036, 0.08417044116767, 0.05417891378782, 0.03752716391991, - 0.01565675600122 -}; - -static const float p4_13_34[HYBRID_FILTER_LENGTH] = -{ - -0.05908211155639, -0.04871498374946, 0.0, 0.07778723915851, - 0.16486303567403, 0.23279856662996, 0.25, 0.23279856662996, - 0.16486303567403, 0.07778723915851, 0.0, -0.04871498374946, - -0.05908211155639 -};*/ - - -/* Function / Class Implementation *******************************************/ - - - -/*****************************************************************************/ -/* **** FILTERBANK CONFIG **** */ - -HANDLE_ERROR_INFO FDKsbrEnc_CreateHybridConfig(HANDLE_PS_HYBRID_CONFIG *phHybConfig, - PS_BANDS mode) -{ - HANDLE_ERROR_INFO error = noError; - HANDLE_PS_HYBRID_CONFIG h = NULL; - UINT k = 0; - - if (error == noError) { - h = *phHybConfig; /* Simplify your life */ - h->mode = mode; - - switch (mode) { - case PS_BANDS_MID: - h->noQmfBandsInHybrid = NO_QMF_BANDS_HYBRID_20; - for (k=0; k<h->noQmfBandsInHybrid; k++) { - h->aHybridResolution[k] = aHybridResolution20[k]; - } - break; - - case PS_BANDS_FINE: - /*h->noQmfBandsInHybrid = noQmfBandsInHybrid34; - for (k=0; k<h->noQmfBandsInHybrid; k++) { - h->aHybridResolution[k] = aHybridResolution34[k]; - }*/ - FDK_ASSERT(0); /* we don't support! */ - break; - - case PS_BANDS_COARSE: - h->noQmfBandsInHybrid = NO_QMF_BANDS_HYBRID_10; - for (k=0; k<h->noQmfBandsInHybrid; k++) { - h->aHybridResolution[k] = aHybridResolution10[k]; - } - break; - - default: - error = ERROR(CDI, "Invalid hybrid filter bank configuration."); - break; - } - } - - return error; -} - -/*****************************************************************************/ -/* **** FILTERBANK DATA **** */ - -HANDLE_ERROR_INFO FDKsbrEnc_CreateHybridData(HANDLE_PS_HYBRID_DATA *phHybData, - INT ch) -{ - HANDLE_ERROR_INFO error = noError; - int k; - - HANDLE_PS_HYBRID_DATA hHybData = GetRam_HybData(ch); - if (hHybData==NULL) { - error = 1; - goto bail; - } - - FDKmemclear(hHybData, sizeof(PS_HYBRID_DATA)); - - hHybData->rHybData[0] = GetRam_PsRhyb(ch); - hHybData->iHybData[0] = GetRam_PsIhyb(ch); - if ( (hHybData->rHybData[0]==NULL) || (hHybData->iHybData[0]==NULL) ) { - error = 1; - goto bail; - } - - - - for (k=1; k<(HYBRID_FRAMESIZE+HYBRID_WRITEOFFSET); k++) { - hHybData->rHybData[k] = hHybData->rHybData[0] + (k*HYBRID_NUM_BANDS); - hHybData->iHybData[k] = hHybData->iHybData[0] + (k*HYBRID_NUM_BANDS); - } - -bail: - *phHybData = hHybData; - return error; -} - - -HANDLE_ERROR_INFO FDKsbrEnc_InitHybridData(HANDLE_PS_HYBRID_DATA hHybData, - HANDLE_PS_HYBRID_CONFIG hHybConfig, - INT frameSize) -{ - HANDLE_ERROR_INFO error = noError; - INT nHybridBands = 0; - INT k = 0; - INT noBands = 0; - const INT *hybridRes = NULL; - - if (hHybConfig != NULL) { - noBands = hHybConfig->noQmfBandsInHybrid; - hybridRes = hHybConfig->aHybridResolution; - } - - for (k=0; k<noBands; k++) { - nHybridBands += (hybridRes[k] & HYBRID_INVERSE_MASK); - } - FDK_ASSERT (HYBRID_NUM_BANDS>=nHybridBands); - - hHybData->hybDataReadOffset = HYBRID_DATA_READ_OFFSET; - hHybData->hybDataWriteOffset = HYBRID_WRITEOFFSET; - - for (k=0; k<(HYBRID_FRAMESIZE+HYBRID_WRITEOFFSET); k++) { - FDKmemclear(hHybData->rHybData[k], sizeof(FIXP_QMF)*HYBRID_NUM_BANDS); - FDKmemclear(hHybData->iHybData[k], sizeof(FIXP_QMF)*HYBRID_NUM_BANDS); - } - - hHybData->frameSize = frameSize; - hHybData->nHybridBands = nHybridBands; - hHybData->nHybridQmfBands = noBands; - - /* store hybrid resoltion in hybrid data handle */ - FDK_ASSERT (HYBRID_MAX_QMF_BANDS>=hHybData->nHybridQmfBands); - for(k = 0; k<hHybData->nHybridQmfBands; k++){ - hHybData->nHybridResolution[k] = (hybridRes[k] & HYBRID_INVERSE_MASK); - } - - return error; -} - -HANDLE_ERROR_INFO FDKsbrEnc_DestroyHybridData(HANDLE_PS_HYBRID_DATA* phHybData) -{ - HANDLE_PS_HYBRID_DATA hHybData = *phHybData; - - if (hHybData!=NULL) { - FreeRam_PsRhyb(&hHybData->rHybData[0]); - FreeRam_PsIhyb(&hHybData->iHybData[0]); - FreeRam_HybData(phHybData); - } - - return noError; -} - -/*** Access functions ***/ - -/* return hybrid band resolution of qmf band 'qmfBand' */ -INT FDKsbrEnc_GetHybridResolution(HANDLE_PS_HYBRID_DATA h, INT qmfBand){ - - INT nHybridResolution = 0; - - if(h->nHybridResolution){ - nHybridResolution = h->nHybridResolution[qmfBand]; - } - - return nHybridResolution; -} - -/*****************************************************************************/ -/* **** FILTERBANK **** */ - -/* - 2 channel filter - Filter Coefs: - 0.0, - 0.01899487526049, - 0.0, - -0.07293139167538, - 0.0, - 0.30596630545168, - 0.5, - 0.30596630545168, - 0.0, - -0.07293139167538, - 0.0, - 0.01899487526049, - 0.0 - - - Filter design: - h[q,n] = g[n] * cos(2pi/2 * q * (n-6) ); n = 0..12, q = 0,1; - - -> h[0,n] = g[n] * 1; - -> h[1,n] = g[n] * pow(-1,n); - -*/ - -static void dualChannelFiltering(const FIXP_QMF *RESTRICT pQmfReal, - const FIXP_QMF *RESTRICT pQmfImag, - FIXP_QMF **RESTRICT mHybridReal, - FIXP_QMF **RESTRICT mHybridImag, - INT nSamples) -{ - INT i; - - for(i = 0; i < nSamples; i++) { - FIXP_DBL r1, r3, r5, r6; - FIXP_DBL i1, i3, i5, i6; - - /* symmetric filter coefficients - scaleValue same as used in eightChannelFiltering (HYBRID_SCALE = 4) - */ - r1 = fMultDiv2(p2_13_20[1], (FIXP_QMF)((pQmfReal[1+i]>>1) + (pQmfReal[11+i]>>1)) ) >> 2; - r3 = fMultDiv2(p2_13_20[3], (FIXP_QMF)((pQmfReal[3+i]>>1) + (pQmfReal[ 9+i]>>1)) ) >> 2; - r5 = fMultDiv2(p2_13_20[5], (FIXP_QMF)((pQmfReal[5+i]>>1) + (pQmfReal[ 7+i]>>1)) ) >> 2; - r6 = fMultDiv2(p2_13_20[6], (FIXP_QMF) (pQmfReal[6+i]>>1) ) >> 2; - - i1 = fMultDiv2(p2_13_20[1], (FIXP_QMF)((pQmfImag[1+i]>>1) + (pQmfImag[11+i]>>1)) ) >> 2; - i3 = fMultDiv2(p2_13_20[3], (FIXP_QMF)((pQmfImag[3+i]>>1) + (pQmfImag[ 9+i]>>1)) ) >> 2; - i5 = fMultDiv2(p2_13_20[5], (FIXP_QMF)((pQmfImag[5+i]>>1) + (pQmfImag[ 7+i]>>1)) ) >> 2; - i6 = fMultDiv2(p2_13_20[6], (FIXP_QMF) (pQmfImag[6+i]>>1) ) >> 2; - - mHybridReal[i][0] = FX_DBL2FX_QMF(r1 + r3 + r5 + r6); - mHybridImag[i][0] = FX_DBL2FX_QMF(i1 + i3 + i5 + i6); - - mHybridReal[i][1] = FX_DBL2FX_QMF(- r1 - r3 - r5 + r6); - mHybridImag[i][1] = FX_DBL2FX_QMF(- i1 - i3 - i5 + i6); - } -} - -/* - 8 channel filter - - Implementation using a FFT of length 8 - - prototype filter coefficients: - 0.00746082949812 0.02270420949825 0.04546865930473 0.07266113929591 0.09885108575264 0.11793710567217 - 0.125 - 0.11793710567217 0.09885108575264 0.07266113929591 0.04546865930473 0.02270420949825 0.00746082949812 - - Filter design: - N = 13; Q = 8; - h[q,n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (n - 6)); n = 0..(N-1), q = 0..(Q-1); - - Time Signal: x[t]; - Filter Bank Output - y[q,t] = conv(x[t],h[q,t]) = conv(h[q,t],x[t]) = sum(x[k] * h[q, t - k] ) = sum(h[q, k] * x[t - k] ); k = 0..(N-1); - - y[q,t] = x[t - 12]*h[q, 12] + x[t - 11]*h[q, 11] + x[t - 10]*h[q, 10] + x[t - 9]*h[q, 9] - + x[t - 8]*h[q, 8] + x[t - 7]*h[q, 7] - + x[t - 6]*h[q, 6] - + x[t - 5]*h[q, 5] + x[t - 4]*h[q, 4] - + x[t - 3]*h[q, 3] + x[t - 2]*h[q, 2] + x[t - 1]*h[q, 1] + x[t - 0]*h[q, 0]; - - h'[q, n] = h[q,(N-1)-n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (6 - n)); n = 0..(N-1), q = 0..(Q-1); - - y[q,t] = x[t - 12]*h'[q, 0] + x[t - 11]*h'[q, 1] + x[t - 10]*h'[q, 2] + x[t - 9]*h'[q, 3] - + x[t - 8]*h'[q, 4] + x[t - 7]*h'[q, 5] - + x[t - 6]*h'[q, 6] - + x[t - 5]*h'[q, 7] + x[t - 4]*h'[q, 8] - + x[t - 3]*h'[q, 9] + x[t - 2]*h'[q, 10] + x[t - 1]*h'[q, 11] + x[t - 0]*h'[q, 12]; - - Try to split off FFT Modulation Term: - FFT(x[t], q) = sum(x[t+k]*exp(-j*2*pi/N *q * k)) - c m - Step 1: h'[q,n] = g[n] * ( exp(j * 2 * pi / 8 * .5 * (6 - n)) ) * ( exp (j * 2 * pi / 8 * q * (6 - n)) ); - - h'[q,n] = g[n] *c[n] * m[q,n]; (see above) - c[n] = exp( j * 2 * pi / 8 * .5 * (6 - n) ); - m[q,n] = exp( j * 2 * pi / 8 * q * (6 - n) ); - - y[q,t] = x[t - 0]*g[0]*c[0]*m[q,0] + x[t - 1]*g[1]*c[ 1]*m[q, 1] + ... - ... + x[t - 12]*g[2]*c[12]*m[q,12]; - - | - n m *exp(-j*2*pi) | n' fft -------------------------------------------------------------------------------------------------------------------------- - 0 exp( j * 2 * pi / 8 * q * 6) -> exp(-j * 2 * pi / 8 * q * 2) | 2 exp(-j * 2 * pi / 8 * q * 0) - 1 exp( j * 2 * pi / 8 * q * 5) -> exp(-j * 2 * pi / 8 * q * 3) | 3 exp(-j * 2 * pi / 8 * q * 1) - 2 exp( j * 2 * pi / 8 * q * 4) -> exp(-j * 2 * pi / 8 * q * 4) | 4 exp(-j * 2 * pi / 8 * q * 2) - 3 exp( j * 2 * pi / 8 * q * 3) -> exp(-j * 2 * pi / 8 * q * 5) | 5 exp(-j * 2 * pi / 8 * q * 3) - 4 exp( j * 2 * pi / 8 * q * 2) -> exp(-j * 2 * pi / 8 * q * 6) | 6 exp(-j * 2 * pi / 8 * q * 4) - 5 exp( j * 2 * pi / 8 * q * 1) -> exp(-j * 2 * pi / 8 * q * 7) | 7 exp(-j * 2 * pi / 8 * q * 5) - 6 exp( j * 2 * pi / 8 * q * 0) | 0 exp(-j * 2 * pi / 8 * q * 6) - 7 exp(-j * 2 * pi / 8 * q * 1) | 1 exp(-j * 2 * pi / 8 * q * 7) - 8 exp(-j * 2 * pi / 8 * q * 2) | 2 - 9 exp(-j * 2 * pi / 8 * q * 3) | 3 - 10 exp(-j * 2 * pi / 8 * q * 4) | 4 - 11 exp(-j * 2 * pi / 8 * q * 5) | 5 - 12 exp(-j * 2 * pi / 8 * q * 6) | 6 - - - now use fft modulation coefficients - m[6] = = fft[0] - m[7] = = fft[1] - m[8] = m[ 0] = fft[2] - m[9] = m[ 1] = fft[3] - m[10] = m[ 2] = fft[4] - m[11] = m[ 3] = fft[5] - m[12] = m[ 4] = fft[6] - m[ 5] = fft[7] - - y[q,t] = ( x[t- 6]*g[ 6]*c[ 6] ) * fft[q,0] + - ( x[t- 7]*g[ 7]*c[ 7] ) * fft[q,1] + - ( x[t- 0]*g[ 0]*c[ 0] + x[t- 8]*g[ 8]*c[ 8] ) * fft[q,2] + - ( x[t- 1]*g[ 1]*c[ 1] + x[t- 9]*g[ 9]*c[ 9] ) * fft[q,3] + - ( x[t- 2]*g[ 2]*c[ 2] + x[t-10]*g[10]*c[10] ) * fft[q,4] + - ( x[t- 3]*g[ 3]*c[ 3] + x[t-11]*g[11]*c[11] ) * fft[q,5] + - ( x[t- 4]*g[ 4]*c[ 4] + x[t-12]*g[12]*c[12] ) * fft[q,6] + - ( x[t- 5]*g[ 5]*c[ 5] ) * fft[q,7]; - - pre twiddle factors c[n] = exp(j * 2 * pi / 8 * .5 * (6 - n)); - n c] | n c[n] | n c[n] ---------------------------------------------------------------------------------------------------- - 0 exp( j * 6 * pi / 8) | 1 exp( j * 5 * pi / 8) | 2 exp( j * 4 * pi / 8) - 3 exp( j * 3 * pi / 8) | 4 exp( j * 2 * pi / 8) | 5 exp( j * 1 * pi / 8) - 6 exp( j * 0 * pi / 8) | 7 exp(-j * 1 * pi / 8) | 8 exp(-j * 2 * pi / 8) - 9 exp(-j * 3 * pi / 8) | 10 exp(-j * 4 * pi / 8) | 11 exp(-j * 5 * pi / 8) - 12 exp(-j * 6 * pi / 8) | | - -*/ - -static const FIXP_DBL cr[13] = -{ cos6Pi_8, cos5Pi_8, cos4Pi_8, - cos3Pi_8, cos2Pi_8, cos1Pi_8, - cos0Pi_8, - cos1Pi_8, cos2Pi_8, cos3Pi_8, - cos4Pi_8, cos5Pi_8, cos6Pi_8 -}; - -static const FIXP_DBL ci[13] = -{ - sin6Pi_8, sin5Pi_8, sin4Pi_8, - sin3Pi_8, sin2Pi_8, sin1Pi_8, - sin0Pi_8, - -sin1Pi_8, -sin2Pi_8, -sin3Pi_8, - -sin4Pi_8, -sin5Pi_8, -sin6Pi_8 -}; - - -static void eightChannelFiltering(const FIXP_QMF *pQmfReal, - const FIXP_QMF *pQmfImag, - FIXP_DBL *fft, - FIXP_QMF **mHybridReal, - FIXP_QMF **mHybridImag, - INT nSamples, - const FIXP_DBL *p) -{ - INT i, bin; - for(i = 0; i < nSamples; i++) { - /* pre twiddeling - scaling 4 = 2 (fMultDiv2) + 2 (dit_fft) scaling (HYBRID_SCALE = 4) - */ - fft[FFT_IDX_R(0)] = fMultDiv2(p[6], fMultSubDiv2(fMultDiv2(cr[6], pQmfReal[6+i]), ci[6], pQmfImag[6+i])); - fft[FFT_IDX_I(0)] = fMultDiv2(p[6], fMultAddDiv2(fMultDiv2(ci[6], pQmfReal[6+i]), cr[6], pQmfImag[6+i])); - - fft[FFT_IDX_R(1)] = fMultDiv2(p[7], fMultSubDiv2(fMultDiv2(cr[7], pQmfReal[7+i]), ci[7], pQmfImag[7+i])); - fft[FFT_IDX_I(1)] = fMultDiv2(p[7], fMultAddDiv2(fMultDiv2(ci[7], pQmfReal[7+i]), cr[7], pQmfImag[7+i])); - - fft[FFT_IDX_R(2)] = ( fMultDiv2(p[ 0], fMultSubDiv2(fMultDiv2(cr[0], pQmfReal[ 0+i]), ci[0], pQmfImag[ 0+i]))+ - fMultDiv2(p[ 8], fMultSubDiv2(fMultDiv2(cr[8], pQmfReal[ 8+i]), ci[8], pQmfImag[ 8+i])) ); - fft[FFT_IDX_I(2)] = ( fMultDiv2(p[ 0], fMultAddDiv2(fMultDiv2(ci[0], pQmfReal[ 0+i]), cr[0], pQmfImag[ 0+i]))+ - fMultDiv2(p[ 8], fMultAddDiv2(fMultDiv2(ci[8], pQmfReal[ 8+i]), cr[8], pQmfImag[ 8+i])) ); - - fft[FFT_IDX_R(3)] = ( fMultDiv2(p[ 1], fMultSubDiv2(fMultDiv2(cr[1], pQmfReal[ 1+i]), ci[1], pQmfImag[ 1+i]))+ - fMultDiv2(p[ 9], fMultSubDiv2(fMultDiv2(cr[9], pQmfReal[ 9+i]), ci[9], pQmfImag[ 9+i])) ); - fft[FFT_IDX_I(3)] = ( fMultDiv2(p[ 1], fMultAddDiv2(fMultDiv2(ci[1], pQmfReal[ 1+i]), cr[1], pQmfImag[ 1+i]))+ - fMultDiv2(p[ 9], fMultAddDiv2(fMultDiv2(ci[9], pQmfReal[ 9+i]), cr[9], pQmfImag[ 9+i])) ); - - fft[FFT_IDX_R(4)] = ( fMultDiv2(p[ 2], fMultSubDiv2( fMultDiv2(cr[2], pQmfReal[ 2+i]), ci[2], pQmfImag[ 2+i]))+ - fMultDiv2(p[10], fMultSubDiv2(fMultDiv2(cr[10], pQmfReal[10+i]), ci[10], pQmfImag[10+i])) ); - fft[FFT_IDX_I(4)] = ( fMultDiv2(p[ 2], fMultAddDiv2( fMultDiv2(ci[2], pQmfReal[ 2+i]), cr[2], pQmfImag[ 2+i]))+ - fMultDiv2(p[10], fMultAddDiv2(fMultDiv2(ci[10], pQmfReal[10+i]), cr[10], pQmfImag[10+i])) ); - - fft[FFT_IDX_R(5)] = ( fMultDiv2(p[ 3], fMultSubDiv2( fMultDiv2(cr[3], pQmfReal[ 3+i]), ci[3], pQmfImag[ 3+i]))+ - fMultDiv2(p[11], fMultSubDiv2(fMultDiv2(cr[11], pQmfReal[11+i]), ci[11], pQmfImag[11+i])) ); - fft[FFT_IDX_I(5)] = ( fMultDiv2(p[ 3], fMultAddDiv2( fMultDiv2(ci[3], pQmfReal[ 3+i]), cr[3], pQmfImag[ 3+i]))+ - fMultDiv2(p[11], fMultAddDiv2(fMultDiv2(ci[11], pQmfReal[11+i]), cr[11], pQmfImag[11+i])) ); - - fft[FFT_IDX_R(6)] = ( fMultDiv2(p[ 4], fMultSubDiv2( fMultDiv2(cr[4], pQmfReal[ 4+i]), ci[4], pQmfImag[ 4+i]))+ - fMultDiv2(p[12], fMultSubDiv2(fMultDiv2(cr[12], pQmfReal[12+i]), ci[12], pQmfImag[12+i])) ); - fft[FFT_IDX_I(6)] = ( fMultDiv2(p[ 4], fMultAddDiv2( fMultDiv2(ci[4], pQmfReal[ 4+i]), cr[4], pQmfImag[ 4+i]))+ - fMultDiv2(p[12], fMultAddDiv2(fMultDiv2(ci[12], pQmfReal[12+i]), cr[12], pQmfImag[12+i])) ); - - fft[FFT_IDX_R(7)] = fMultDiv2(p[5], fMultSubDiv2(fMultDiv2(cr[5], pQmfReal[5+i]), ci[5], pQmfImag[5+i])); - fft[FFT_IDX_I(7)] = fMultDiv2(p[5], fMultAddDiv2(fMultDiv2(ci[5], pQmfReal[5+i]), cr[5], pQmfImag[5+i])); - - /* fft modulation */ - fft_8(fft); - - /* resort fft data INTo output array*/ - for(bin=0; bin<8;bin++ ) { - mHybridReal[i][bin] = FX_DBL2FX_QMF(fft[FFT_IDX_R(bin)]); - mHybridImag[i][bin] = FX_DBL2FX_QMF(fft[FFT_IDX_I(bin)]); - } - } -} - -/**************************************************************************//** -HybridAnalysis -******************************************************************************/ - -HANDLE_ERROR_INFO -HybridAnalysis ( HANDLE_PS_HYBRID hHybrid, /*!< Handle to HYBRID struct. */ - FIXP_QMF *const *const mQmfReal, /*!< The real part of the QMF-matrix. */ - FIXP_QMF *const *const mQmfImag, /*!< The imaginary part of the QMF-matrix. */ - SCHAR sf_fixpQmf, /*!< Qmf scale factor */ - FIXP_QMF **mHybridReal, /*!< The real part of the hybrid-matrix. */ - FIXP_QMF **mHybridImag, /*!< The imaginary part of the hybrid-matrix. */ - SCHAR *sf_fixpHybrid) /*!< Hybrid scale factor */ -{ - HANDLE_ERROR_INFO error = noError; - INT n, band; - INT hybridRes; - INT chOffset = 0; - /* INT usedStereoBands = hHybrid->mode; */ /*!< indicates which 8 band filter to use */ - INT frameSize = hHybrid->frameSize; - INT hybridFilterDelay = hHybrid->hybridFilterDelay; - - for(band = 0; band < hHybrid->nQmfBands; band++) { /* loop all qmf bands */ - - if(error == noError){ - hybridRes = hHybrid->pResolution[band]; - - /* Create working buffer. */ - /* Copy stored samples to working buffer. */ - FDKmemcpy(hHybrid->pWorkReal, hHybrid->mQmfBufferReal[band], - hHybrid->qmfBufferMove * sizeof(FIXP_QMF)); - FDKmemcpy(hHybrid->pWorkImag, hHybrid->mQmfBufferImag[band], - hHybrid->qmfBufferMove * sizeof(FIXP_QMF)); - - /* Append new samples to working buffer. */ - for(n = 0; n < frameSize; n++) { - hHybrid->pWorkReal [hHybrid->qmfBufferMove + n] = mQmfReal [n + hybridFilterDelay] [band]; - hHybrid->pWorkImag [hHybrid->qmfBufferMove + n] = mQmfImag [n + hybridFilterDelay] [band]; - } - - /* Store samples for next frame. */ - FDKmemcpy(hHybrid->mQmfBufferReal[band], hHybrid->pWorkReal + frameSize, - hHybrid->qmfBufferMove * sizeof(FIXP_QMF)); - FDKmemcpy(hHybrid->mQmfBufferImag[band], hHybrid->pWorkImag + frameSize, - hHybrid->qmfBufferMove * sizeof(FIXP_QMF)); - - - switch(hybridRes) { - case HYBRID_2_REAL: - dualChannelFiltering( hHybrid->pWorkReal, - hHybrid->pWorkImag, - hHybrid->mTempReal, - hHybrid->mTempImag, - frameSize); - - /* copy data to output buffer */ - for(n = 0; n < frameSize; n++) { - FDKmemcpy(&mHybridReal[n][chOffset], hHybrid->mTempReal[n], - (INT)(hybridRes & HYBRID_INVERSE_MASK)*sizeof(FIXP_QMF)); - FDKmemcpy(&mHybridImag[n][chOffset], hHybrid->mTempImag[n], - (INT)(hybridRes & HYBRID_INVERSE_MASK)*sizeof(FIXP_QMF)); - } - break; - - case HYBRID_2_REAL | HYBRID_INVERSE_ORDER: - dualChannelFiltering( hHybrid->pWorkReal, - hHybrid->pWorkImag, - hHybrid->mTempReal, - hHybrid->mTempImag, - frameSize); - - /* copy and resort data */ - for ( n = 0; n < frameSize; n++ ) - { - mHybridReal[n][chOffset + 0] = hHybrid->mTempReal[n][1] ; - mHybridReal[n][chOffset + 1] = hHybrid->mTempReal[n][0] ; - mHybridImag[n][chOffset + 0] = hHybrid->mTempImag[n][1] ; - mHybridImag[n][chOffset + 1] = hHybrid->mTempImag[n][0] ; - } - break; - - case HYBRID_6_CPLX: - eightChannelFiltering( hHybrid->pWorkReal, - hHybrid->pWorkImag, - hHybrid->fft, - hHybrid->mTempReal, - hHybrid->mTempImag, - frameSize, - /*(usedStereoBands==PS_BANDS_FINE)?p8_13_34:*/p8_13_20); - - /* do the shuffle */ - for ( n = 0; n < frameSize; n++ ) - { - /* add data ... */ - hHybrid->mTempReal[n][2] += hHybrid->mTempReal[n][5]; - hHybrid->mTempImag[n][2] += hHybrid->mTempImag[n][5]; - hHybrid->mTempReal[n][3] += hHybrid->mTempReal[n][4]; - hHybrid->mTempImag[n][3] += hHybrid->mTempImag[n][4]; - - /* shuffle and copy to output buffer */ - mHybridReal[n][chOffset + 0] = hHybrid->mTempReal[n][6] ; - mHybridReal[n][chOffset + 1] = hHybrid->mTempReal[n][7] ; - mHybridReal[n][chOffset + 2] = hHybrid->mTempReal[n][0] ; - mHybridReal[n][chOffset + 3] = hHybrid->mTempReal[n][1] ; - mHybridReal[n][chOffset + 4] = hHybrid->mTempReal[n][2] ; - mHybridReal[n][chOffset + 5] = hHybrid->mTempReal[n][3] ; - - mHybridImag[n][chOffset + 0] = hHybrid->mTempImag[n][6] ; - mHybridImag[n][chOffset + 1] = hHybrid->mTempImag[n][7] ; - mHybridImag[n][chOffset + 2] = hHybrid->mTempImag[n][0] ; - mHybridImag[n][chOffset + 3] = hHybrid->mTempImag[n][1] ; - mHybridImag[n][chOffset + 4] = hHybrid->mTempImag[n][2] ; - mHybridImag[n][chOffset + 5] = hHybrid->mTempImag[n][3] ; - } - break; - - case HYBRID_8_CPLX: - eightChannelFiltering( hHybrid->pWorkReal, - hHybrid->pWorkImag, - hHybrid->fft, - hHybrid->mTempReal, - hHybrid->mTempImag, - frameSize, - /*(usedStereoBands==PS_BANDS_FINE)?p8_13_34:*/p8_13_20); - - /* copy data to output buffer */ - for(n = 0; n < frameSize; n++) { - FDKmemcpy(&mHybridReal[n][chOffset], hHybrid->mTempReal[n], - (INT)(hybridRes & HYBRID_INVERSE_MASK)*sizeof(FIXP_QMF)); - FDKmemcpy(&mHybridImag[n][chOffset], hHybrid->mTempImag[n], - (INT)(hybridRes & HYBRID_INVERSE_MASK)*sizeof(FIXP_QMF)); - } - break; - - default: - error = ERROR(CDI, "Invalid filter bank configuration."); - break; - } - /* prepare next run by incresing chOffset */ - chOffset += hybridRes & HYBRID_INVERSE_MASK; - } - } - - *sf_fixpHybrid = sf_fixpQmf + HYBRID_SCALE; - - return error; -} - -/**************************************************************************//** - FDKsbrEnc_CreateHybridFilterBank -******************************************************************************/ -HANDLE_ERROR_INFO -FDKsbrEnc_CreateHybridFilterBank ( HANDLE_PS_HYBRID *phHybrid, /*!< Pointer to handle to HYBRID struct. */ - INT ch) /*!< Current channel */ -{ - HANDLE_ERROR_INFO error = noError; - INT i; - HANDLE_PS_HYBRID hs = GetRam_PsHybrid(ch); /* allocate memory */ - if (hs==NULL) { - error = 1; - goto bail; - } - - hs->fft = GetRam_PsHybFFT(); - - /* alloc working memory */ - hs->pWorkReal = GetRam_PsHybWkReal(); - hs->pWorkImag = GetRam_PsHybWkImag(); - - if ( (hs->fft==NULL) || (hs->pWorkReal==NULL) || (hs->pWorkImag==NULL) ) { - error = 1; - goto bail; - } - - /* Allocate buffers */ - for (i = 0; i < HYBRID_FRAMESIZE; i++) { - hs->mTempReal[i] = GetRam_PsMtmpReal(i); - hs->mTempImag[i] = GetRam_PsMtmpImag(i); - if ( (hs->mTempReal[i]==NULL) || (hs->mTempImag[i]==NULL) ) { - error = 1; - goto bail; - } - } - -bail: - *phHybrid = hs; - return error; -} - -HANDLE_ERROR_INFO -FDKsbrEnc_InitHybridFilterBank ( HANDLE_PS_HYBRID hs, /*!< Handle to HYBRID struct. */ - HANDLE_PS_HYBRID_CONFIG hHybConfig, /*!< Configuration hanlde for filter bank */ - INT frameSize) /*!< Number of QMF slots */ -{ - HANDLE_ERROR_INFO error = noError; - INT i; - INT maxNoChannels = HYBRID_12_CPLX, noBands; - PS_BANDS mode; - const INT *RESTRICT pResolution; - - /* filter bank configuration */ - mode = hHybConfig->mode; - noBands = hHybConfig->noQmfBandsInHybrid; - pResolution = hHybConfig->aHybridResolution; - - /* assign resolution, check for valid values */ - for (i = 0; i < noBands; i++) { - if(error == noError){ - if( pResolution[i] != HYBRID_12_CPLX && - pResolution[i] != HYBRID_8_CPLX && - pResolution[i] != HYBRID_6_CPLX && - pResolution[i] != HYBRID_2_REAL && - pResolution[i] != (HYBRID_2_REAL | HYBRID_INVERSE_ORDER) && - pResolution[i] != HYBRID_4_CPLX ){ - error = ERROR(CDI, "Invalid filter bank resolution"); - } - } - hs->pResolution[i] = pResolution[i]; - if((pResolution[i] & HYBRID_INVERSE_MASK) > maxNoChannels){ - maxNoChannels = pResolution[i] & HYBRID_INVERSE_MASK; - } - } - FDK_ASSERT (MAX_HYBRID_RES>=maxNoChannels); /* check size of mTempReal/Imag */ - - /* assign parameters */ - hs->mode = mode; - hs->nQmfBands = noBands; - hs->frameSize = frameSize; - hs->frameSizeInit = frameSize; - hs->qmfBufferMove = HYBRID_FILTER_LENGTH - 1; - hs->hybridFilterDelay = HYBRID_FILTER_LENGTH/2; - - FDK_ASSERT (HYBRID_FRAMESIZE>=hs->frameSize); - FDK_ASSERT (QMF_BUFFER_MOVE>=hs->qmfBufferMove); - - return error; -} - - -/**************************************************************************//** - FDKsbrEnc_DeleteHybridFilterBank -******************************************************************************/ - -HANDLE_ERROR_INFO -FDKsbrEnc_DeleteHybridFilterBank ( HANDLE_PS_HYBRID* phHybrid ) /*!< Pointer to handle to HYBRID struct. */ -{ - int i; - HANDLE_PS_HYBRID hHybrid = *phHybrid; - - if (hHybrid!=NULL) { - if (hHybrid->fft) - FreeRam_PsHybFFT(&hHybrid->fft); - if (hHybrid->pWorkReal) - FreeRam_PsHybWkReal(&hHybrid->pWorkReal); - if (hHybrid->pWorkImag) - FreeRam_PsHybWkImag(&hHybrid->pWorkImag); - - for (i = 0; i < HYBRID_FRAMESIZE; i++) { - if (hHybrid->mTempReal[i]) - FreeRam_PsMtmpReal(&hHybrid->mTempReal[i]); - if (hHybrid->mTempImag[i]) - FreeRam_PsMtmpImag(&hHybrid->mTempImag[i]); - } - - FreeRam_PsHybrid(phHybrid); - } - - return noError; -} - -/*** Access functions ***/ -INT FDKsbrEnc_GetHybridFilterDelay(HANDLE_PS_HYBRID hHybrid){ - - return hHybrid->hybridFilterDelay; -} - diff --git a/libSBRenc/src/psenc_hybrid.h b/libSBRenc/src/psenc_hybrid.h deleted file mode 100644 index 79e600d..0000000 --- a/libSBRenc/src/psenc_hybrid.h +++ /dev/null @@ -1,182 +0,0 @@ -/***************************** MPEG Audio Encoder *************************** - - (C) Copyright Fraunhofer IIS (2004-2005) - All Rights Reserved - - Please be advised that this software and/or program delivery is - Confidential Information of Fraunhofer and subject to and covered by the - - Fraunhofer IIS Software Evaluation Agreement - between Google Inc. and Fraunhofer - effective and in full force since March 1, 2012. - - You may use this software and/or program only under the terms and - conditions described in the above mentioned Fraunhofer IIS Software - Evaluation Agreement. Any other and/or further use requires a separate agreement. - - - $Id$ - Initial author: M. Neuendorf, M. Multrus - contents/description: hypbrid filter bank (prototypes) - - This software and/or program is protected by copyright law and international - treaties. Any reproduction or distribution of this software and/or program, - or any portion of it, may result in severe civil and criminal penalties, and - will be prosecuted to the maximum extent possible under law. - -******************************************************************************/ -#ifndef __hybrid_h -#define __hybrid_h - -/* Includes ******************************************************************/ -#include "sbr_def.h" -#include "ps_const.h" - -#include "qmf.h" - -/* Data Types ****************************************************************/ - -typedef enum { - HYBRID_2_REAL = 2, - HYBRID_4_CPLX = 4, - HYBRID_6_CPLX = 6, - HYBRID_8_CPLX = 8, - HYBRID_12_CPLX = 12 -} HYBRID_RES; - -#define MAX_HYBRID_RES (HYBRID_12_CPLX) - -/* Defines *******************************************************************/ -#define MAX_QMF_BANDS_IN_HYBRID (5) -#define MAX_IID_GROUPS (50) /* NO_IID_GROUPS_HI_RES */ - -#define HYBRID_FILTER_LENGTH ( 13 ) - -#define HYBRID_FRAMESIZE ( QMF_MAX_TIME_SLOTS ) -#define HYBRID_WRITEOFFSET ( 10 ) -#define HYBRID_NUM_BANDS ( 10 ) - -#define NO_QMF_BANDS_HYBRID_10 ( 3 ) -#define NO_QMF_BANDS_HYBRID_20 ( 3 ) -#define HYBRID_MAX_QMF_BANDS ( NO_QMF_BANDS_HYBRID_20 ) - -#define QMF_BUFFER_MOVE ( HYBRID_FILTER_LENGTH - 1 ) - - -/* Data Types ****************************************************************/ -typedef struct PS_HYBRID_CONFIG_tag { - PS_BANDS mode; - - UINT noQmfBandsInHybrid; - INT aHybridResolution[MAX_QMF_BANDS_IN_HYBRID]; /* valid entries from 0 to noQmfBandsInHybrid */ - -} PS_HYBRID_CONFIG, *HANDLE_PS_HYBRID_CONFIG; - -typedef struct PS_HYBRID_tag -{ - PS_BANDS mode; - INT nQmfBands; - INT frameSizeInit; - INT frameSize; - INT pResolution[HYBRID_MAX_QMF_BANDS]; - INT qmfBufferMove; - INT hybridFilterDelay; - - FIXP_DBL *fft; - - FIXP_QMF *pWorkReal; /**< Working arrays for Qmf samples. */ - FIXP_QMF *pWorkImag; - - FIXP_QMF mQmfBufferReal[HYBRID_MAX_QMF_BANDS][QMF_BUFFER_MOVE]; /**< Stores old Qmf samples. */ - FIXP_QMF mQmfBufferImag[HYBRID_MAX_QMF_BANDS][QMF_BUFFER_MOVE]; - FIXP_QMF *mTempReal[HYBRID_FRAMESIZE]; /**< Temporary matrices for filter bank output. */ - FIXP_QMF *mTempImag[HYBRID_FRAMESIZE]; - -} PS_HYBRID; - -typedef struct PS_HYBRID_DATA_tag { - INT frameSize; - INT nHybridBands; - INT nHybridQmfBands; - INT nHybridResolution [HYBRID_MAX_QMF_BANDS]; - - FIXP_QMF* rHybData [(HYBRID_FRAMESIZE + HYBRID_WRITEOFFSET)]; - FIXP_QMF* iHybData [(HYBRID_FRAMESIZE + HYBRID_WRITEOFFSET)]; - SCHAR sf_fixpHybrid; - - INT hybDataReadOffset; - INT hybDataWriteOffset; - -} PS_HYBRID_DATA; - - -typedef struct PS_HYBRID_DATA_tag *HANDLE_PS_HYBRID_DATA; -typedef struct PS_HYBRID_tag *HANDLE_PS_HYBRID; - - - -/* Function Declarations *********************************************/ - -/*****************************************************************************/ -/* **** FILTERBANK CONFIG **** */ - -HANDLE_ERROR_INFO FDKsbrEnc_CreateHybridConfig(HANDLE_PS_HYBRID_CONFIG *phHybConfig, - PS_BANDS mode); - -/*****************************************************************************/ -/* **** FILTERBANK DATA **** */ - -HANDLE_ERROR_INFO FDKsbrEnc_CreateHybridData(HANDLE_PS_HYBRID_DATA *phHybData, - INT ch); - -HANDLE_ERROR_INFO FDKsbrEnc_InitHybridData(HANDLE_PS_HYBRID_DATA hHybData, - HANDLE_PS_HYBRID_CONFIG hHybConfig, - INT frameSize); - -HANDLE_ERROR_INFO FDKsbrEnc_DestroyHybridData(HANDLE_PS_HYBRID_DATA* phHybData); - -inline INT FDKsbrEnc_GetHybridFrameSize(HANDLE_PS_HYBRID_DATA h) { - return h->frameSize; -} - -inline INT FDKsbrEnc_GetNumberHybridBands(HANDLE_PS_HYBRID_DATA h) { - return h->nHybridBands; -} - -inline INT FDKsbrEnc_GetNumberHybridQmfBands(HANDLE_PS_HYBRID_DATA h) { - return h->nHybridQmfBands; -} - -INT FDKsbrEnc_GetHybridResolution(HANDLE_PS_HYBRID_DATA h, INT qmfBand); - - - -/*****************************************************************************/ -/* **** FILTERBANK **** */ - -HANDLE_ERROR_INFO -FDKsbrEnc_CreateHybridFilterBank ( HANDLE_PS_HYBRID *phHybrid, - INT ch ); - -HANDLE_ERROR_INFO -FDKsbrEnc_InitHybridFilterBank ( HANDLE_PS_HYBRID hHybrid, - HANDLE_PS_HYBRID_CONFIG hHybConfig, - INT frameSize ); - -HANDLE_ERROR_INFO -FDKsbrEnc_DeleteHybridFilterBank ( HANDLE_PS_HYBRID* phHybrid ); - -HANDLE_ERROR_INFO -HybridAnalysis ( HANDLE_PS_HYBRID hHybrid, - FIXP_QMF *const * const mQmfReal, - FIXP_QMF *const * const mQmfImag, - SCHAR sf_fixpQmf, - FIXP_QMF **mHybridReal, - FIXP_QMF **mHybridImag, - SCHAR *sf_fixpHybrid); - - -INT -FDKsbrEnc_GetHybridFilterDelay(HANDLE_PS_HYBRID hHybrid); - -#endif /*__hybrid_h*/ diff --git a/libSBRenc/src/sbr.h b/libSBRenc/src/sbr.h index 40a3953..c833db5 100644 --- a/libSBRenc/src/sbr.h +++ b/libSBRenc/src/sbr.h @@ -25,7 +25,7 @@ *******************************************************************************/ /*! \file - \brief Main SBR structs definitions $Revision: 36847 $ + \brief Main SBR structs definitions $Revision: 37142 $ */ #ifndef __SBR_H @@ -92,7 +92,6 @@ struct SBR_ENCODER UCHAR* dynamicRam; UCHAR* pSBRdynamic_RAM; - HANDLE_PSENC_CONFIG hPsEncConfig; HANDLE_PARAMETRIC_STEREO hParametricStereo; QMF_FILTER_BANK qmfSynthesisPS; diff --git a/libSBRenc/src/sbr_encoder.cpp b/libSBRenc/src/sbr_encoder.cpp index 9c3cf37..31dea4e 100644 --- a/libSBRenc/src/sbr_encoder.cpp +++ b/libSBRenc/src/sbr_encoder.cpp @@ -37,7 +37,6 @@ #include "qmf.h" #include "ps_main.h" -#include "psenc_hybrid.h" #define SBRENCODER_LIB_VL0 3 #define SBRENCODER_LIB_VL1 2 @@ -101,30 +100,76 @@ \return Index to the appropriate table ****************************************************************************/ +#define DISTANCE_CEIL_VALUE 5000000 static INT getSbrTuningTableIndex(UINT bitrate, /*! the total bitrate in bits/sec */ UINT numChannels,/*! the number of channels for the core coder */ UINT sampleRate, /*! the sampling rate of the core coder */ - AUDIO_OBJECT_TYPE core + AUDIO_OBJECT_TYPE core, + UINT *pBitRateClosest ) { - int i, paramSetTop; + int i, paramSetTop, bitRateClosestLowerIndex=-1, bitRateClosestUpperIndex=-1, found = 0; + UINT bitRateClosestUpper = 0, bitRateClosestLower=DISTANCE_CEIL_VALUE; + + FDK_ASSERT(SBRENC_TUNING_SIZE == sizeof(sbrTuningTable)/sizeof(sbrTuningTable[0])); if (core == AOT_ER_AAC_ELD) { paramSetTop = SBRENC_TUNING_SIZE; - i = 126; + i = SBRENC_AACLC_TUNING_SIZE; } else { - paramSetTop = 126; + paramSetTop = SBRENC_AACLC_TUNING_SIZE; i = 0; } for (; i < paramSetTop ; i++) { - if (numChannels == sbrTuningTable [i].numChannels) { - if ((sampleRate == sbrTuningTable [i].sampleRate) && - (bitrate >= sbrTuningTable [i].bitrateFrom) && + if ( numChannels == sbrTuningTable [i].numChannels + && sampleRate == sbrTuningTable [i].sampleRate ) + { + found = 1; + if ((bitrate >= sbrTuningTable [i].bitrateFrom) && (bitrate < sbrTuningTable [i].bitrateTo)) { + bitRateClosestLower = bitrate; + bitRateClosestUpper = bitrate; + //FDKprintf("entry %d\n", i); return i ; + } else { + if ( sbrTuningTable [i].bitrateFrom > bitrate ) { + if (sbrTuningTable [i].bitrateFrom < bitRateClosestLower) { + bitRateClosestLower = sbrTuningTable [i].bitrateFrom; + bitRateClosestLowerIndex = i; + } + } + if ( sbrTuningTable [i].bitrateTo <= bitrate ) { + if (sbrTuningTable [i].bitrateTo > bitRateClosestUpper) { + bitRateClosestUpper = sbrTuningTable [i].bitrateTo-1; + bitRateClosestUpperIndex = i; + } + } + } + } + } + + if (pBitRateClosest != NULL) + { + /* Is there was at least one matching tuning entry found then pick the least distance bit rate */ + if (found) + { + int distanceUpper=DISTANCE_CEIL_VALUE, distanceLower=DISTANCE_CEIL_VALUE; + if (bitRateClosestLowerIndex >= 0) { + distanceLower = sbrTuningTable [bitRateClosestLowerIndex].bitrateFrom - bitrate; } + if (bitRateClosestUpperIndex >= 0) { + distanceUpper = bitrate - sbrTuningTable [bitRateClosestUpperIndex].bitrateTo; + } + if ( distanceUpper < distanceLower ) + { + *pBitRateClosest = bitRateClosestUpper; + } else { + *pBitRateClosest = bitRateClosestLower; + } + } else { + *pBitRateClosest = 0; } } @@ -141,14 +186,46 @@ getSbrTuningTableIndex(UINT bitrate, /*! the total bitrate in bits/sec */ ****************************************************************************/ static INT -getPsTuningTableIndex(UINT bitrate){ +getPsTuningTableIndex(UINT bitrate, UINT *pBitRateClosest){ INT i, paramSets = sizeof (psTuningTable) / sizeof (psTuningTable [0]); + int bitRateClosestLowerIndex=-1, bitRateClosestUpperIndex=-1; + UINT bitRateClosestUpper = 0, bitRateClosestLower=DISTANCE_CEIL_VALUE; for (i = 0 ; i < paramSets ; i++) { if ((bitrate >= psTuningTable [i].bitrateFrom) && (bitrate < psTuningTable [i].bitrateTo)) { return i ; + } else { + if ( psTuningTable [i].bitrateFrom > bitrate ) { + if (psTuningTable [i].bitrateFrom < bitRateClosestLower) { + bitRateClosestLower = psTuningTable [i].bitrateFrom; + bitRateClosestLowerIndex = i; + } + } + if ( psTuningTable [i].bitrateTo <= bitrate ) { + if (psTuningTable [i].bitrateTo > bitRateClosestUpper) { + bitRateClosestUpper = psTuningTable [i].bitrateTo-1; + bitRateClosestUpperIndex = i; + } + } + } + } + + if (pBitRateClosest != NULL) + { + int distanceUpper=DISTANCE_CEIL_VALUE, distanceLower=DISTANCE_CEIL_VALUE; + if (bitRateClosestLowerIndex >= 0) { + distanceLower = sbrTuningTable [bitRateClosestLowerIndex].bitrateFrom - bitrate; + } + if (bitRateClosestUpperIndex >= 0) { + distanceUpper = bitrate - sbrTuningTable [bitRateClosestUpperIndex].bitrateTo; + } + if ( distanceUpper < distanceLower ) + { + *pBitRateClosest = bitRateClosestUpper; + } else { + *pBitRateClosest = bitRateClosestLower; } } @@ -197,7 +274,7 @@ FDKsbrEnc_IsSbrSettingAvail (UINT bitrate, /*! the total bitrate in bit /* try DOWN_SMPL_FAC of the input sampling rate */ sampleRateCore = sampleRateInput/DOWN_SMPL_FAC; - idx = getSbrTuningTableIndex(bitrate, numOutputChannels, sampleRateCore, core); + idx = getSbrTuningTableIndex(bitrate, numOutputChannels, sampleRateCore, core, NULL); return (idx == INVALID_TABLE_IDX ? 0 : 1); } @@ -257,7 +334,7 @@ FDKsbrEnc_AdjustSbrSettings (const sbrConfigurationPtr config, /*! output, modif } } - idx = getSbrTuningTableIndex(bitRate,numChannels,fsCore, core); + idx = getSbrTuningTableIndex(bitRate,numChannels,fsCore, core, NULL); if (idx != INVALID_TABLE_IDX) { config->startFreq = sbrTuningTable[idx].startFreq ; @@ -492,8 +569,6 @@ void sbrEncoder_Close (HANDLE_SBR_ENCODER *phSbrEncoder) } - if (hSbrEncoder->hPsEncConfig) - FreeRam_PsEncConf(&hSbrEncoder->hPsEncConfig); if (hSbrEncoder->hParametricStereo) PSEnc_Destroy(&hSbrEncoder->hParametricStereo); if (hSbrEncoder->qmfSynthesisPS.FilterStates) @@ -801,8 +876,8 @@ FDKsbrEnc_EnvEncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder, /* Obtain pointers to QMF buffers. */ - pQmfReal = sbrExtrEnv->rBuffer+sbrExtrEnv->rBufferWriteOffset; - pQmfImag = sbrExtrEnv->iBuffer+sbrExtrEnv->rBufferWriteOffset; + pQmfReal = sbrExtrEnv->rBuffer; + pQmfImag = sbrExtrEnv->iBuffer; qmfAnalysisFiltering( hSbrElement->hQmfAnalysis[ch], pQmfReal, @@ -822,33 +897,8 @@ FDKsbrEnc_EnvEncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder, /* Parametric Stereo processing */ - if(hSbrElement->elInfo.fParametricStereo) + if (hSbrElement->elInfo.fParametricStereo) { - int psCh; - - /* Parametric Stereo QMF buffer preprocessing: copy previous qmf data down */ - UpdatePSQmfData_second(hEnvEncoder->hParametricStereo); - - for (psCh = 0; psCh<2; psCh ++) - { - C_ALLOC_SCRATCH_START(qmfWorkBuffer, FIXP_DBL, QMF_CHANNELS*2); - HANDLE_PS_QMF_DATA hPsQmfData = hEnvEncoder->hParametricStereo->hPsChannelData[psCh]->hPsQmfData; - QMF_SCALE_FACTOR tmpScale; - - - qmfAnalysisFiltering( hSbrElement->hQmfAnalysis[psCh], - hPsQmfData->rQmfData + hPsQmfData->bufferWriteOffset, - hPsQmfData->iQmfData + hPsQmfData->bufferWriteOffset, - &tmpScale, - samples + hSbrElement->elInfo.ChannelIndex[psCh], - timeInStride, - qmfWorkBuffer ); - - C_ALLOC_SCRATCH_END(qmfWorkBuffer, FIXP_DBL, QMF_CHANNELS*2); - - hEnvEncoder->hParametricStereo->hPsChannelData[psCh]->psQmfScale = -tmpScale.lb_scale; - } - /* Limit Parametric Stereo to one instance */ FDK_ASSERT(ch == 0); @@ -867,10 +917,13 @@ FDKsbrEnc_EnvEncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder, o downmixed qmf data is written to sbrExtrEnv->rBuffer and sbrExtrEnv->iBuffer */ SCHAR qmfScale; + INT_PCM* pSamples[2] = {samples + hSbrElement->elInfo.ChannelIndex[0],samples + hSbrElement->elInfo.ChannelIndex[1]}; error = FDKsbrEnc_PSEnc_ParametricStereoProcessing( hEnvEncoder->hParametricStereo, + pSamples, + timeInStride, + hSbrElement->hQmfAnalysis, sbrExtrEnv->rBuffer, sbrExtrEnv->iBuffer, - sbrExtrEnv->rBufferWriteOffset, samples + hSbrElement->elInfo.ChannelIndex[ch], &hEnvEncoder->qmfSynthesisPS, &qmfScale, @@ -1266,11 +1319,6 @@ INT sbrEncoder_Open( } if (supportPS) { - hSbrEncoder->hPsEncConfig = GetRam_PsEncConf(); - if (hSbrEncoder->hPsEncConfig==NULL) { - goto bail; - } - if (PSEnc_Create(&hSbrEncoder->hParametricStereo)) { goto bail; @@ -1582,6 +1630,32 @@ INT FDKsbrEnc_DelayCompensation ( return 0; } +UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, UINT coreSampleRate, AUDIO_OBJECT_TYPE aot) +{ + UINT newBitRate; + INT index; + + FDK_ASSERT(numChannels > 0 && numChannels <= 2); + if (aot == AOT_PS) { + if (numChannels == 2) { + index = getPsTuningTableIndex(bitRate, &newBitRate); + if (index == INVALID_TABLE_IDX) { + bitRate = newBitRate; + } + /* Set numChannels to 1 because for PS we need a SBR SCE (mono) element. */ + numChannels = 1; + } else { + return 0; + } + } + index = getSbrTuningTableIndex(bitRate, numChannels, coreSampleRate, aot, &newBitRate); + if (index != INVALID_TABLE_IDX) { + newBitRate = bitRate; + } + + return newBitRate; +} + INT sbrEncoder_Init( HANDLE_SBR_ENCODER hSbrEncoder, @@ -1894,22 +1968,23 @@ INT sbrEncoder_Init( /* initialize parametric stereo */ if (usePs) { + PSENC_CONFIG psEncConfig; FDK_ASSERT(hSbrEncoder->noElements == 1); - INT psTuningTableIdx = getPsTuningTableIndex(elInfo[0].bitRate); //sbrConfig.codecSettings.bitRate); + INT psTuningTableIdx = getPsTuningTableIndex(elInfo[0].bitRate, NULL); - hSbrEncoder->hPsEncConfig->frameSize = *frameLength; //sbrConfig.sbrFrameSize; - hSbrEncoder->hPsEncConfig->qmfFilterMode = 0; - hSbrEncoder->hPsEncConfig->sbrPsDelay = 0; + psEncConfig.frameSize = *frameLength; //sbrConfig.sbrFrameSize; + psEncConfig.qmfFilterMode = 0; + psEncConfig.sbrPsDelay = 0; /* tuning parameters */ if (psTuningTableIdx != INVALID_TABLE_IDX) { - hSbrEncoder->hPsEncConfig->nStereoBands = psTuningTable[psTuningTableIdx].nStereoBands; - hSbrEncoder->hPsEncConfig->maxEnvelopes = psTuningTable[psTuningTableIdx].nEnvelopes; - hSbrEncoder->hPsEncConfig->iidQuantErrorThreshold = (FIXP_DBL)psTuningTable[psTuningTableIdx].iidQuantErrorThreshold; + psEncConfig.nStereoBands = psTuningTable[psTuningTableIdx].nStereoBands; + psEncConfig.maxEnvelopes = psTuningTable[psTuningTableIdx].nEnvelopes; + psEncConfig.iidQuantErrorThreshold = (FIXP_DBL)psTuningTable[psTuningTableIdx].iidQuantErrorThreshold; /* calculation is not quite linear, increased number of envelopes causes more bits */ /* assume avg. 50 bits per frame for 10 stereo bands / 1 envelope configuration */ - hSbrEncoder->estimateBitrate += ( (((*sampleRate) * 5 * hSbrEncoder->hPsEncConfig->nStereoBands * hSbrEncoder->hPsEncConfig->maxEnvelopes) / hSbrEncoder->frameSize)); + hSbrEncoder->estimateBitrate += ( (((*sampleRate) * 5 * psEncConfig.nStereoBands * psEncConfig.maxEnvelopes) / hSbrEncoder->frameSize)); } else { error = ERROR(CDI, "Invalid ps tuning table index."); @@ -1926,10 +2001,10 @@ INT sbrEncoder_Init( if(errorInfo == noError){ /* update delay */ - hSbrEncoder->hPsEncConfig->sbrPsDelay = FDKsbrEnc_GetEnvEstDelay(&hSbrEncoder->sbrElement[0]->sbrChannel[0]->hEnvChannel.sbrExtractEnvelope); + psEncConfig.sbrPsDelay = FDKsbrEnc_GetEnvEstDelay(&hSbrEncoder->sbrElement[0]->sbrChannel[0]->hEnvChannel.sbrExtractEnvelope); if(noError != (errorInfo = PSEnc_Init( hSbrEncoder->hParametricStereo, - hSbrEncoder->hPsEncConfig, + &psEncConfig, hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots, hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands ,hSbrEncoder->dynamicRam diff --git a/libSBRenc/src/sbr_ram.cpp b/libSBRenc/src/sbr_ram.cpp index 289270c..2413059 100644 --- a/libSBRenc/src/sbr_ram.cpp +++ b/libSBRenc/src/sbr_ram.cpp @@ -26,7 +26,7 @@ /*! \file \brief Memory layout - $Revision: 36847 $ + $Revision: 37142 $ This module declares all static and dynamic memory spaces */ @@ -114,39 +114,10 @@ C_ALLOC_MEM2 (Ram_Sbr_guideVectorOrig, FIXP_DBL, (MAX_NO_OF_ESTIMATES*MAX_FREQ_C */ C_AALLOC_MEM_L(Ram_PsQmfStatesSynthesis, FIXP_DBL, QMF_FILTER_LENGTH/2, SECT_DATA_L1) -C_ALLOC_MEM (Ram_PsEnvRBuffer, FIXP_DBL, QMF_MAX_TIME_SLOTS*QMF_CHANNELS/2) -C_ALLOC_MEM (Ram_PsEnvIBuffer, FIXP_DBL, QMF_MAX_TIME_SLOTS*QMF_CHANNELS/2) -C_ALLOC_MEM2 (Ram_PsChData, PS_CHANNEL_DATA, 1, MAX_PS_CHANNELS) -C_ALLOC_MEM (Ram_PsEncConf, PSENC_CONFIG, 1) C_ALLOC_MEM_L (Ram_PsEncode, PS_ENCODE, 1, SECT_DATA_L1) -C_ALLOC_MEM (Ram_PsData, PS_DATA, 1) C_ALLOC_MEM (Ram_ParamStereo, PARAMETRIC_STEREO, 1) -C_ALLOC_MEM2 (Ram_PsOut, PS_OUT, 1, 2) -/* QMF data - */ -C_ALLOC_MEM (Ram_PsQmfNewSamples, FIXP_DBL, QMF_CHANNELS) - -C_ALLOC_MEM2 (Ram_PsQmfData, PS_QMF_DATA, 1, MAX_PS_CHANNELS) - -/* HYBRID data - */ -C_AALLOC_MEM (Ram_PsHybFFT, FIXP_DBL, 16) - -C_ALLOC_MEM2(Ram_HybData, PS_HYBRID_DATA, 1, MAX_PS_CHANNELS) -C_ALLOC_MEM2(Ram_PsHybrid, PS_HYBRID, 1, MAX_PS_CHANNELS) -C_ALLOC_MEM (Ram_PsHybConfig, PS_HYBRID_CONFIG, 1) - -C_ALLOC_MEM2(Ram_PsRhyb, FIXP_QMF, ((HYBRID_FRAMESIZE+HYBRID_WRITEOFFSET)*HYBRID_NUM_BANDS), MAX_PS_CHANNELS) -C_ALLOC_MEM2(Ram_PsIhyb, FIXP_QMF, ((HYBRID_FRAMESIZE+HYBRID_WRITEOFFSET)*HYBRID_NUM_BANDS), MAX_PS_CHANNELS) - -C_ALLOC_MEM (Ram_PsHybWkReal, FIXP_QMF, (HYBRID_FRAMESIZE + QMF_BUFFER_MOVE)) -C_ALLOC_MEM (Ram_PsHybWkImag, FIXP_QMF, (HYBRID_FRAMESIZE + QMF_BUFFER_MOVE)) - -C_ALLOC_MEM2(Ram_PsMtmpReal, FIXP_QMF, (MAX_HYBRID_RES), HYBRID_FRAMESIZE) -C_ALLOC_MEM2(Ram_PsMtmpImag, FIXP_QMF, (MAX_HYBRID_RES), HYBRID_FRAMESIZE) - /* @} */ @@ -175,38 +146,11 @@ C_ALLOC_MEM2(Ram_PsMtmpImag, FIXP_QMF, (MAX_HYBRID_RES), HYBRID_FRAMESIZE) /* The SBR encoder uses a single channel overlapping buffer set (always n=0), but PS does not. */ FIXP_DBL* GetRam_Sbr_envRBuffer (int n, UCHAR* dynamic_RAM) { FDK_ASSERT(dynamic_RAM!=0); - return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (n*ENV_R_BUFF_BYTE*2) )); + return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE)) )); } FIXP_DBL* GetRam_Sbr_envIBuffer (int n, UCHAR* dynamic_RAM) { FDK_ASSERT(dynamic_RAM!=0); - //return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (MAX_NUM_CHANNELS*ENV_R_BUFF_BYTE) + n*ENV_I_BUFF_BYTE)); - return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (ENV_R_BUFF_BYTE) + (n*ENV_I_BUFF_BYTE*2))); - } - - /* reuse QMF buffer in PS module. We Require space to hold 2 channels. */ - C_ALLOC_MEM2(Ram_PsRqmf, FIXP_QMF, ((PSENC_QMF_BUFFER_LENGTH-QMF_MAX_TIME_SLOTS)*(QMF_CHANNELS)), MAX_PS_CHANNELS) - C_ALLOC_MEM2(Ram_PsIqmf, FIXP_QMF, ((PSENC_QMF_BUFFER_LENGTH-QMF_MAX_TIME_SLOTS)*(QMF_CHANNELS)), MAX_PS_CHANNELS) - - FIXP_QMF* FDKsbrEnc_SliceRam_PsRqmf(FIXP_DBL* rQmfData, UCHAR* dynamic_RAM, int ch, int i, int qmfSlots) - { - FDK_ASSERT(dynamic_RAM!=0); - if (i<HYBRID_READ_OFFSET) - return rQmfData + (i*(QMF_CHANNELS)); - else if ((i<(HYBRID_READ_OFFSET+qmfSlots))) - return GetRam_Sbr_envRBuffer(ch, dynamic_RAM) + ( (i-(HYBRID_READ_OFFSET))*(QMF_CHANNELS) ); - else - return rQmfData + ((i-qmfSlots)*(QMF_CHANNELS)); - } - - FIXP_QMF* FDKsbrEnc_SliceRam_PsIqmf(FIXP_DBL* iQmfData, UCHAR* dynamic_RAM, int ch, int i, int qmfSlots) - { - FDK_ASSERT(dynamic_RAM!=0); - if (i<HYBRID_READ_OFFSET) - return iQmfData + (i*(QMF_CHANNELS)); - else if ((i<(HYBRID_READ_OFFSET+qmfSlots))) - return GetRam_Sbr_envIBuffer(ch, dynamic_RAM) + ( (i-(HYBRID_READ_OFFSET))*(QMF_CHANNELS) ); - else - return iQmfData + ((i-qmfSlots)*(QMF_CHANNELS)); + return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (ENV_R_BUFF_BYTE) + (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE)))); } diff --git a/libSBRenc/src/sbr_ram.h b/libSBRenc/src/sbr_ram.h index 23eca20..3377c2a 100644 --- a/libSBRenc/src/sbr_ram.h +++ b/libSBRenc/src/sbr_ram.h @@ -26,7 +26,7 @@ /*! \file \brief Memory layout -$Revision: 36847 $ +$Revision: 37142 $ */ #ifndef __SBR_RAM_H #define __SBR_RAM_H @@ -44,10 +44,10 @@ $Revision: 36847 $ #define ENV_TRANSIENTS_BYTE ( (sizeof(FIXP_DBL)*(MAX_NUM_CHANNELS*3*QMF_MAX_TIME_SLOTS)) ) -#define ENV_R_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * QMF_CHANNELS)) ) -#define ENV_I_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * QMF_CHANNELS)) ) + #define ENV_R_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * MAX_HYBRID_BANDS)) ) + #define ENV_I_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * MAX_HYBRID_BANDS)) ) + #define Y_BUF_CH_BYTE ( (2*sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * MAX_HYBRID_BANDS)) ) -#define Y_BUF_CH_BYTE ( (sizeof(FIXP_DBL)*QMF_MAX_TIME_SLOTS * QMF_CHANNELS) ) #define ENV_R_BUF_PS_BYTE ( (sizeof(FIXP_DBL)*QMF_MAX_TIME_SLOTS * QMF_CHANNELS / 2) ) #define ENV_I_BUF_PS_BYTE ( (sizeof(FIXP_DBL)*QMF_MAX_TIME_SLOTS * QMF_CHANNELS / 2) ) @@ -60,27 +60,24 @@ $Revision: 36847 $ /* Workbuffer RAM - Allocation */ /* ++++++++++++++++++++++++++++++++++++++++++++++++++++ - | OFFSET_NRG | OFFSET_QMF | + | OFFSET_QMF | OFFSET_NRG | ++++++++++++++++++++++++++++++++++++++++++++++++++++ - -------------------------------------------------- - | 0.5 * | | - | sbr_envYBuffer_size | sbr_envRBuffer | - | | sbr_envIBuffer | - -------------------------------------------------- + ------------------------- ------------------------- + | | 0.5 * | + | sbr_envRBuffer | sbr_envYBuffer_size | + | sbr_envIBuffer | | + ------------------------- ------------------------- */ #define BUF_NRG_SIZE ( (MAX_NUM_CHANNELS * Y_2_BUF_BYTE) ) + #define BUF_QMF_SIZE (ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE) - #define OFFSET_NRG ( 0 ) - #define OFFSET_QMF ( OFFSET_NRG + BUF_NRG_SIZE ) + /* Size of the shareable memory region than can be reused */ + #define SBR_ENC_DYN_RAM_SIZE ( BUF_QMF_SIZE + BUF_NRG_SIZE ) - /* if common dynamic memory used in AAC-core and SBR, find out maximal size of - SCR buffer (see XX in figure above) */ - /* Only PS required holding 2 channel QMF data. AAC_WK_BUF_SIZE_0 must fit into this buffer. */ - #define BUF_QMF_SIZE ( 2*(ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE) ) + #define OFFSET_QMF ( 0 ) + #define OFFSET_NRG ( OFFSET_QMF + BUF_QMF_SIZE ) - /* Size of the shareable memory region than can be reused */ - #define SBR_ENC_DYN_RAM_SIZE ( BUF_NRG_SIZE + BUF_QMF_SIZE ) /* ***************************************************************************************************** @@ -117,53 +114,14 @@ $Revision: 36847 $ H_ALLOC_MEM(Ram_Sbr_guideVectorOrig, FIXP_DBL) - H_ALLOC_MEM(Ram_PsEnvRBuffer, FIXP_QMF) - H_ALLOC_MEM(Ram_PsEnvIBuffer, FIXP_QMF) - H_ALLOC_MEM(Ram_PsQmfStatesSynthesis, FIXP_DBL) - H_ALLOC_MEM(Ram_PsQmfNewSamples, FIXP_DBL) - H_ALLOC_MEM(Ram_PsEncConf, PSENC_CONFIG) H_ALLOC_MEM(Ram_PsEncode, PS_ENCODE) - H_ALLOC_MEM(Ram_PsData, PS_DATA) - -#define HYBRID_READ_OFFSET ( 10 ) -#define HYBRID_WRITE_OFFSET ( ((32)>>1)-6 ) -#define HYBRID_DATA_READ_OFFSET ( 0 ) -#define QMF_READ_OFFSET ( 0 ) - - H_ALLOC_MEM(Ram_PsRqmf, FIXP_DBL) - H_ALLOC_MEM(Ram_PsIqmf, FIXP_DBL) FIXP_DBL* FDKsbrEnc_SliceRam_PsRqmf (FIXP_DBL* rQmfData, UCHAR* dynamic_RAM, int n, int i, int qmfSlots); FIXP_DBL* FDKsbrEnc_SliceRam_PsIqmf (FIXP_DBL* iQmfData, UCHAR* dynamic_RAM, int n, int i, int qmfSlots); - H_ALLOC_MEM(Ram_PsQmfData, PS_QMF_DATA) - H_ALLOC_MEM(Ram_PsChData, PS_CHANNEL_DATA) - H_ALLOC_MEM(Ram_ParamStereo, PARAMETRIC_STEREO) - H_ALLOC_MEM(Ram_PsOut, PS_OUT) - - /* HYBRID */ - H_ALLOC_MEM(Ram_PsHybFFT, FIXP_DBL) - - H_ALLOC_MEM(Ram_HybData, PS_HYBRID_DATA) - H_ALLOC_MEM(Ram_PsRhyb, FIXP_DBL) - H_ALLOC_MEM(Ram_PsIhyb, FIXP_DBL) - - H_ALLOC_MEM(Ram_PsHybConfig, PS_HYBRID_CONFIG) - H_ALLOC_MEM(Ram_PsHybrid, PS_HYBRID) - - FIXP_DBL* psMqmfBufferRealInit (INT ch, INT i); - FIXP_DBL* psMqmfBufferImagInit (INT ch, INT i); - - - /* working buffer */ - H_ALLOC_MEM(Ram_PsHybWkReal, FIXP_DBL) - H_ALLOC_MEM(Ram_PsHybWkImag, FIXP_DBL) - - H_ALLOC_MEM(Ram_PsMtmpReal, FIXP_DBL) - H_ALLOC_MEM(Ram_PsMtmpImag, FIXP_DBL) diff --git a/libSBRenc/src/sbr_rom.cpp b/libSBRenc/src/sbr_rom.cpp index e83a519..77cef12 100644 --- a/libSBRenc/src/sbr_rom.cpp +++ b/libSBRenc/src/sbr_rom.cpp @@ -25,7 +25,7 @@ /*! \file \brief Definition of constant tables - $Revision: 36914 $ + $Revision: 37577 $ This module contains most of the constant data that can be stored in ROM. */ @@ -623,8 +623,8 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] = /* 22.05/44.1 kHz dual rate */ { 8000, 11369, 22050, 1, 1, 1, 1, 1, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 8 kbit/s */ /**changed (not changed !!)*/ { 11369, 16000, 22050, 1, 1, 0, 3, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 12 kbit/s */ - { 16000, 18000, 22050, 1, 1, 0, 4, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */ - { 18000, 22000, 22050, 1, 1, 2, 5, 4, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ + { 16000, 18000, 22050, 1, 2, 4, 4, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */ + { 18000, 22000, 22050, 1, 4, 4, 5, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ { 22000, 28000, 22050, 1, 4, 4, 6, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 24 kbit/s */ { 28000, 36000, 22050, 1, 7, 8, 8, 8, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */ { 36000, 44000, 22050, 1, 9, 9, 9, 9, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ @@ -634,8 +634,8 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] = /* 24/48 kHz dual rate */ { 8000, 12000, 24000, 1, 1, 1, 1, 1, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 8 kbit/s */ /**changed (not changed !!)*/ { 12000, 16000, 24000, 1, 1, 0, 3, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 12 kbit/s */ - { 16000, 18000, 24000, 1, 1, 0, 4, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */ - { 18000, 22000, 24000, 1, 1, 1, 4, 4, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ + { 16000, 18000, 24000, 1, 2, 4, 4, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */ + { 18000, 22000, 24000, 1, 4, 4, 5, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ { 22000, 28000, 24000, 1, 4, 4, 6, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 24 kbit/s */ { 28000, 36000, 24000, 1, 6, 8, 8, 8, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */ { 36000, 44000, 24000, 1, 8, 9, 9, 9, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ @@ -643,7 +643,6 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] = { 52000, 64001, 24000, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 48 kbit/s */ /* 22.05/44.1 kHz dual rate */ - { 16000, 24000, 22050, 2, 0, 0, 0, 0, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */ { 24000, 28000, 22050, 2, 3, 2, 5, 4, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */ { 28000, 32000, 22050, 2, 3, 2, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 28 kbit/s */ { 32000, 36000, 22050, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ @@ -655,7 +654,6 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] = { 82000,128001, 22050, 2, 13,12,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ /* 24/48 kHz dual rate */ - { 16000, 24000, 24000, 2, 0, 0, 0, 0, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */ { 24000, 28000, 24000, 2, 3, 3, 5, 5, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */ { 28000, 36000, 24000, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ { 36000, 44000, 24000, 2, 4, 8, 8, 8, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ @@ -664,6 +662,8 @@ const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE] = { 60000, 76000, 24000, 2, 11,12,10,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ { 76000, 88000, 24000, 2, 12,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ { 88000,128001, 24000, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 92 kbit/s */ + + }; const psTuningTable_t psTuningTable[4] = diff --git a/libSBRenc/src/sbr_rom.h b/libSBRenc/src/sbr_rom.h index 696a54c..68135cb 100644 --- a/libSBRenc/src/sbr_rom.h +++ b/libSBRenc/src/sbr_rom.h @@ -26,7 +26,7 @@ /*! \file \brief Declaration of constant tables -$Revision: 36847 $ +$Revision: 37577 $ */ #ifndef __SBR_ROM_H #define __SBR_ROM_H @@ -60,7 +60,11 @@ extern const UCHAR v_Huff_NoiseLevelL11T[63]; extern const INT bookSbrNoiseBalanceC11T[25]; extern const UCHAR bookSbrNoiseBalanceL11T[25]; -#define SBRENC_TUNING_SIZE (126 + 37) +#define SBRENC_AACLC_TUNING_SIZE 124 +#define SBRENC_AACELD_TUNING_SIZE 35 +#define SBRENC_AACELD2_TUNING_SIZE 31 + +#define SBRENC_TUNING_SIZE (SBRENC_AACLC_TUNING_SIZE + SBRENC_AACELD_TUNING_SIZE) extern const sbrTuningTable_t sbrTuningTable[SBRENC_TUNING_SIZE]; |