static SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, const INT channel ) { SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; int elementIndex, elChanIdx=0, numCh=0; for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel); elementIndex++) { SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex]; int c, elChannels; elChanIdx = 0; if (pSbrElement == NULL) break; /* Determine amount of channels for this element */ switch (pSbrElement->elementID) { case ID_CPE: elChannels = 2; break; case ID_LFE: case ID_SCE: elChannels = 1; break; case ID_NONE: default: elChannels = 0; break; } /* Limit with actual allocated element channels */ elChannels = FDKmin(elChannels, pSbrElement->nChannels); for (c = 0; (c < elChannels) && (numCh <= channel); c++) { if (pSbrElement->pSbrChannel[elChanIdx] != NULL) { numCh++; elChanIdx++; } } } elementIndex -= 1; elChanIdx -= 1; if (elChanIdx < 0 || elementIndex < 0) { return NULL; } if ( self->pSbrElement[elementIndex] != NULL ) { if ( self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx] != NULL ) { pSbrDrcChannelData = &self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx]->SbrDec.sbrDrcChannel; } } return (pSbrDrcChannelData); }
/***************************************************************************** functionname: FDKaacEnc_InitTnsConfiguration description: fill TNS_CONFIG structure with sensible content returns: input: bitrate, samplerate, number of channels, blocktype (long or short), TNS Config struct (modified), psy config struct, tns active flag output: *****************************************************************************/ AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate, INT sampleRate, INT channels, INT blockType, INT granuleLength, INT ldSbrPresent, TNS_CONFIG *tC, PSY_CONFIGURATION *pC, INT active, INT useTnsPeak) { int i; //float acfTimeRes = (blockType == SHORT_WINDOW) ? 0.125f : 0.046875f; if (channels <= 0) return (AAC_ENCODER_ERROR)1; /* initialize TNS filter flag, order, and coefficient resolution (in bits per coeff) */ tC->tnsActive = (active) ? TRUE : FALSE; tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */ if (bitRate < 16000) tC->maxOrder -= 2; tC->coefRes = (blockType == SHORT_WINDOW) ? 3 : 4; /* LPC stop line: highest MDCT line to be coded, but do not go beyond TNS_MAX_BANDS! */ tC->lpcStopBand = getTnsMaxBands(sampleRate, granuleLength, (blockType == SHORT_WINDOW) ? 1 : 0); if (tC->lpcStopBand < 0) { return (AAC_ENCODER_ERROR)1; } tC->lpcStopBand = FDKmin(tC->lpcStopBand, pC->sfbActive); tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; switch (granuleLength) { case 1024: /* TNS start line: skip lower MDCT lines to prevent artifacts due to filter mismatch */ tC->lpcStartBand[LOFILT] = (blockType == SHORT_WINDOW) ? 0 : ((sampleRate < 18783) ? 4 : 8); tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; i = tC->lpcStopBand; while (pC->sfbOffset[i] > (tC->lpcStartLine[LOFILT] + (tC->lpcStopLine - tC->lpcStartLine[LOFILT]) / 4)) i--; tC->lpcStartBand[HIFILT] = i; tC->lpcStartLine[HIFILT] = pC->sfbOffset[i]; tC->confTab.threshOn[HIFILT] = 1437; tC->confTab.threshOn[LOFILT] = 1500; tC->confTab.tnsLimitOrder[HIFILT] = tC->maxOrder; tC->confTab.tnsLimitOrder[LOFILT] = tC->maxOrder - 7; tC->confTab.tnsFilterDirection[HIFILT] = FILTER_DIRECTION; tC->confTab.tnsFilterDirection[LOFILT] = FILTER_DIRECTION; tC->confTab.acfSplit[HIFILT] = -1; /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation*/ tC->confTab.acfSplit[LOFILT] = -1; /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation */ tC->confTab.filterEnabled[HIFILT] = 1; tC->confTab.filterEnabled[LOFILT] = 1; tC->confTab.seperateFiltersAllowed = 1; /* compute autocorrelation window based on maximum filter order for given block type */ /* for (i = 0; i <= tC->maxOrder + 3; i++) { float acfWinTemp = acfTimeRes * i; acfWindow[i] = FL2FXCONST_DBL(1.0f - acfWinTemp * acfWinTemp); } */ if (blockType == SHORT_WINDOW) { FDKmemcpy(tC->acfWindow[HIFILT], acfWindowShort, FDKmin(sizeof(acfWindowShort), sizeof(tC->acfWindow[HIFILT]))); FDKmemcpy(tC->acfWindow[LOFILT], acfWindowShort, FDKmin(sizeof(acfWindowShort), sizeof(tC->acfWindow[HIFILT]))); } else { FDKmemcpy(tC->acfWindow[HIFILT], acfWindowLong, FDKmin(sizeof(acfWindowLong), sizeof(tC->acfWindow[HIFILT]))); FDKmemcpy(tC->acfWindow[LOFILT], acfWindowLong, FDKmin(sizeof(acfWindowLong), sizeof(tC->acfWindow[HIFILT]))); } break; case 480: case 512: { const TNS_PARAMETER_TABULATED* pCfg = FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent); if ( pCfg != NULL ) { tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, pC->sfbOffset); tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]]; tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, pC->sfbOffset); tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; tC->confTab.threshOn[HIFILT] = pCfg->threshOn[HIFILT]; tC->confTab.threshOn[LOFILT] = pCfg->threshOn[LOFILT]; tC->confTab.tnsLimitOrder[HIFILT] = pCfg->tnsLimitOrder[HIFILT]; tC->confTab.tnsLimitOrder[LOFILT] = pCfg->tnsLimitOrder[LOFILT]; tC->confTab.tnsFilterDirection[HIFILT] = pCfg->tnsFilterDirection[HIFILT]; tC->confTab.tnsFilterDirection[LOFILT] = pCfg->tnsFilterDirection[LOFILT]; tC->confTab.acfSplit[HIFILT] = pCfg->acfSplit[HIFILT]; tC->confTab.acfSplit[LOFILT] = pCfg->acfSplit[LOFILT]; tC->confTab.filterEnabled[HIFILT] = pCfg->filterEnabled[HIFILT]; tC->confTab.filterEnabled[LOFILT] = pCfg->filterEnabled[LOFILT]; tC->confTab.seperateFiltersAllowed = pCfg->seperateFiltersAllowed; FDKaacEnc_CalcGaussWindow(tC->acfWindow[HIFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE); FDKaacEnc_CalcGaussWindow(tC->acfWindow[LOFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE); } else { tC->tnsActive = FALSE; /* no configuration available, disable tns tool */ } } break; default: tC->tnsActive = FALSE; /* no configuration available, disable tns tool */ } return AAC_ENC_OK; }
TRANSPORTENC_ERROR transportEnc_WriteAccessUnit( HANDLE_TRANSPORTENC hTp, INT frameUsedBits, int bufferFullness, int ncc ) { TRANSPORTENC_ERROR err = TRANSPORTENC_OK; if (!hTp) { return TRANSPORTENC_INVALID_PARAMETER; } HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream; /* In case of writing PCE in raw_data_block frameUsedBits must be adapted. */ if (hTp->pceFrameCounter>=hTp->config.headerPeriod) { frameUsedBits += transportEnc_GetPCEBits(hTp->config.channelMode, hTp->config.matrixMixdownA, 3); /* Consider 3 bits ID signalling in alignment */ } switch (hTp->transportFmt) { case TT_MP4_ADIF: FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, BS_WRITER); adifWrite_EncodeHeader( &hTp->writer.adif, hBs, bufferFullness ); break; case TT_MP4_ADTS: bufferFullness /= ncc; /* Number of Considered Channels */ bufferFullness /= 32; bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */ adtsWrite_EncodeHeader( &hTp->writer.adts, &hTp->bitStream, bufferFullness, frameUsedBits ); break; case TT_DABPLUS: bufferFullness /= ncc; /* Number of Considered Channels */ bufferFullness /= 32; bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */ dabWrite_EncodeHeader( &hTp->writer.dab, &hTp->bitStream, bufferFullness, frameUsedBits ); break; case TT_MP4_LOAS: case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: bufferFullness /= ncc; /* Number of Considered Channels */ bufferFullness /= 32; bufferFullness = FDKmin(0xFF, bufferFullness); /* Signal variable rate */ transportEnc_LatmWrite( &hTp->writer.latm, hBs, frameUsedBits, bufferFullness, &hTp->callbacks ); break; case TT_MP4_RAW: if (hTp->writer.raw.curSubFrame >= hTp->writer.raw.nSubFrames) { hTp->writer.raw.curSubFrame = 0; FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, BS_WRITER); } hTp->writer.raw.prevBits = FDKgetValidBits(hBs); break; default: err = TRANSPORTENC_UNSUPPORTED_FORMAT; break; } /* Write PCE in raw_data_block if required */ if (hTp->pceFrameCounter>=hTp->config.headerPeriod) { INT crcIndex = 0; /* Align inside PCE with repsect to the first bit of the raw_data_block() */ UINT alignAnchor = FDKgetValidBits(&hTp->bitStream); /* Write PCE element ID bits */ FDKwriteBits(&hTp->bitStream, ID_PCE, 3); if ( (hTp->transportFmt==TT_MP4_ADTS) && !hTp->writer.adts.protection_absent) { crcIndex = adtsWrite_CrcStartReg(&hTp->writer.adts, &hTp->bitStream, 0); } /* Write PCE as first raw_data_block element */ transportEnc_writePCE(&hTp->bitStream, hTp->config.channelMode, hTp->config.samplingRate, 0, 1, hTp->config.matrixMixdownA, hTp->config.flags & CC_PSEUDO_SURROUND, alignAnchor); if ( (hTp->transportFmt==TT_MP4_ADTS) && !hTp->writer.adts.protection_absent) { adtsWrite_CrcEndReg(&hTp->writer.adts, &hTp->bitStream, crcIndex); } hTp->pceFrameCounter = 0; /* reset pce frame counter */ } if (hTp->pceFrameCounter!=-1) { hTp->pceFrameCounter++; /* Update pceFrameCounter only if PCE writing is active. */ } return err; }