summaryrefslogtreecommitdiffstats
path: root/libSBRenc/src/ps_main.cpp
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/src/ps_main.cpp
parent9bf37cc9712506b2483650c82d3c41152337ef7e (diff)
downloadfdk-aac-698b536f3b34a7cfc41a80e1034cc359456bdd66.tar.gz
fdk-aac-698b536f3b34a7cfc41a80e1034cc359456bdd66.tar.bz2
fdk-aac-698b536f3b34a7cfc41a80e1034cc359456bdd66.zip
Update to 2012_05_11 version.
Fixes: - Don't throw error for invalid bitrate but limit to functional value - More robust ASC parsing - More robust handling of corrupt bitstreams - Handle multiple raw access units Change-Id: Ib49fe2545ff4185fe924126da702fe84ac5c2d87
Diffstat (limited to 'libSBRenc/src/ps_main.cpp')
-rw-r--r--libSBRenc/src/ps_main.cpp1143
1 files changed, 310 insertions, 833 deletions
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;