summaryrefslogtreecommitdiffstats
path: root/libSBRenc
diff options
context:
space:
mode:
authorDave Burke <daveburke@google.com>2012-05-12 13:17:25 -0700
committerDave Burke <daveburke@google.com>2012-05-12 13:47:46 -0700
commit698b536f3b34a7cfc41a80e1034cc359456bdd66 (patch)
treefa3dfa75d535b188725f1b84316cb4b06db79771 /libSBRenc
parent9bf37cc9712506b2483650c82d3c41152337ef7e (diff)
downloadODR-AudioEnc-698b536f3b34a7cfc41a80e1034cc359456bdd66.tar.gz
ODR-AudioEnc-698b536f3b34a7cfc41a80e1034cc359456bdd66.tar.bz2
ODR-AudioEnc-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')
-rw-r--r--libSBRenc/include/sbr_encoder.h10
-rw-r--r--libSBRenc/src/Android.mk1
-rw-r--r--libSBRenc/src/env_est.cpp34
-rw-r--r--libSBRenc/src/env_est.h3
-rw-r--r--libSBRenc/src/ps_bitenc.cpp3
-rw-r--r--libSBRenc/src/ps_const.h24
-rw-r--r--libSBRenc/src/ps_encode.cpp228
-rw-r--r--libSBRenc/src/ps_encode.h44
-rw-r--r--libSBRenc/src/ps_main.cpp1143
-rw-r--r--libSBRenc/src/ps_main.h220
-rw-r--r--libSBRenc/src/psenc_hybrid.cpp836
-rw-r--r--libSBRenc/src/psenc_hybrid.h182
-rw-r--r--libSBRenc/src/sbr.h3
-rw-r--r--libSBRenc/src/sbr_encoder.cpp189
-rw-r--r--libSBRenc/src/sbr_ram.cpp62
-rw-r--r--libSBRenc/src/sbr_ram.h72
-rw-r--r--libSBRenc/src/sbr_rom.cpp14
-rw-r--r--libSBRenc/src/sbr_rom.h8
18 files changed, 753 insertions, 2323 deletions
diff --git a/libSBRenc/include/sbr_encoder.h b/libSBRenc/include/sbr_encoder.h
index d54582d..88d0569 100644
--- a/libSBRenc/include/sbr_encoder.h
+++ b/libSBRenc/include/sbr_encoder.h
@@ -213,6 +213,16 @@ INT sbrEncoder_Open(
);
/**
+ * \brief get closest working bit rate to specified desired bit rate for a single SBR element
+ * \param bitRate the desired target bit rate
+ * \param numChannels the amount of audio channels
+ * \param coreSampleRate the sample rate of the core coder
+ * \param the current Audio Object Type
+ * \return closest working bit rate to bitRate value
+ */
+UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, UINT coreSampleRate, AUDIO_OBJECT_TYPE aot);
+
+/**
* \brief Initialize SBR Encoder instance.
* \param phSbrEncoder Pointer to a SBR Encoder instance.
* \param elInfo Structure that describes the element/channel arrangement.
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];