void get_dse( Char *DataStreamBytes, BITS *pInputStream) { Int i; Int data_byte_align_flag; UInt count; Int esc_count; Char *pDataStreamBytes; pDataStreamBytes = DataStreamBytes; /* * Get element instance tag ( 4 bits) * ( max of 16 per raw data block) */ get9_n_lessbits(LEN_TAG, pInputStream); /* * get data_byte_align_flag ( 1 bit0 to see if byte alignment is * performed within the DSE */ data_byte_align_flag = get1bits(pInputStream); /* * get count ( 8 bits) */ count = get9_n_lessbits(LEN_D_CNT, pInputStream); /* * if count == 255, its value it is incremented by a * second 8 bit value, esc_count. This final value represents * the number of bytes in the DSE */ if (count == (1 << LEN_D_CNT) - 1) { esc_count = (Int)get9_n_lessbits(LEN_D_ESC, pInputStream); /* 8 bits */ count += esc_count; } /* * Align if flag is set */ if (data_byte_align_flag) { byte_align(pInputStream); } for (i = count; i != 0; i--) { *(pDataStreamBytes++) = (Char) get9_n_lessbits( LEN_BYTE, pInputStream); } return; } /* end get_dse */
/*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ void get_ele_list( EleList *pElementList, BITS *pInputStream, const Bool enableCPE) { Int index; Int *pEleIsCPE; Int *pEleTag; pEleIsCPE = &pElementList->ele_is_cpe[0]; pEleTag = &pElementList->ele_tag[0]; for (index = pElementList->num_ele; index > 0; index--) { if (enableCPE != FALSE) { *pEleIsCPE++ = get1bits(/*LEN_ELE_IS_CPE, */pInputStream); } else { *pEleIsCPE++ = FALSE; } *pEleTag++ = get9_n_lessbits(LEN_TAG, pInputStream); } /* end for (index) */ return; } /* end get_ele_list */
void get_sbr_bitstream(SBRBITSTREAM *sbrBitStream, BITS *pInputStream) { /*---------------------------------------------------------------------------- ; Define all local variables ----------------------------------------------------------------------------*/ Int32 count; Int32 esc_count; Int32 Extention_Type; Int32 i; count = get9_n_lessbits(LEN_F_CNT, pInputStream); if (count == 15) { esc_count = get9_n_lessbits(LEN_F_ESC, pInputStream); count = esc_count + 14; } Extention_Type = get9_n_lessbits(LEN_F_CNT, pInputStream); if (((Extention_Type == SBR_EXTENSION) || (Extention_Type == SBR_EXTENSION_CRC)) && (count < MAXSBRBYTES) && (count) && (sbrBitStream->NrElements < MAXNRELEMENTS)) { sbrBitStream->sbrElement[sbrBitStream->NrElements].ExtensionType = Extention_Type; sbrBitStream->sbrElement[sbrBitStream->NrElements].Payload = count; sbrBitStream->sbrElement[sbrBitStream->NrElements].Data[0] = (UChar) get9_n_lessbits(LEN_F_CNT, pInputStream); for (i = 1 ; i < count ; i++) { sbrBitStream->sbrElement[sbrBitStream->NrElements].Data[i] = (UChar) get9_n_lessbits(8, pInputStream); } sbrBitStream->NrElements += 1; } else { pInputStream->usedBits += (count - 1) * LEN_BYTE; pInputStream->usedBits += 4; /* compenste for LEN_F_CNT (=4) bits read for Extention_Type */ } }
/*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ Int getmask( FrameInfo *pFrameInfo, BITS *pInputStream, Int group[], Int max_sfb, Int mask[]) { Int win; /* window index */ Int sfb; Int mask_present; Int *pMask; Int *pGroup; Int nwin; Int nCall; Int nToDo; UInt32 tempMask; UInt32 bitmask; pMask = mask; pGroup = group; mask_present = get9_n_lessbits( LEN_MASK_PRES, pInputStream); switch (mask_present) { case(MASK_NOT_PRESENT): /* special EXTENDED_MS_MASK cases */ /* no ms at all */ break; case(MASK_ALL_FRAME): /* MS for whole spectrum on, mask bits set to 1 */ nwin = pFrameInfo->num_win; for (win = 0; win < nwin; win = *(pGroup++)) { for (sfb = pFrameInfo->sfb_per_win[win]; sfb > 0; sfb--) { *(pMask++) = 1; /* cannot use memset for Int type */ } } break; case(MASK_FROM_BITSTREAM): /* MS_mask_present==1, get mask information*/ nwin = pFrameInfo->num_win; for (win = 0; win < nwin; win = *(pGroup++)) { /* * the following code is equivalent to * * for(sfb = max_sfb; sfb > 0; sfb--) * { * *(pMask++) = * getbits( * LEN_MASK, * pInputStream); * } * * in order to save the calls to getbits, the above * for-loop is broken into two parts */ nToDo = max_sfb; while (nToDo > 0) { nCall = nToDo; if (nCall > MAX_GETBITS) { nCall = MAX_GETBITS; } tempMask = getbits( nCall, pInputStream); bitmask = (UInt32) 1 << (nCall - 1); for (sfb = nCall; sfb > 0; sfb--) { *(pMask++) = (Int)((tempMask & bitmask) >> (sfb - 1)); bitmask >>= 1; } nToDo -= nCall; } /* * set remaining sfbs to zero * re-use nCall to save one variable on stack */ nCall = pFrameInfo->sfb_per_win[win] - max_sfb; if (nCall >= 0) { pv_memset(pMask, 0, nCall*sizeof(*pMask)); pMask += nCall; } else { mask_present = MASK_ERROR; break; } } /* for (win) */ break; default: /* error */ break; } /* switch (mask_present) */ return mask_present; } /* getmask */
/*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ void lt_decode( const WINDOW_SEQUENCE win_type, BITS *pInputStream, const Int max_sfb, LT_PRED_STATUS *pLt_pred) { Int wnd_num; Int k; Int last_band; Int prev_subblock; Int prev_subblock_nonzero; Int temp_reg; Bool *pWinPredictionUsed = pLt_pred->win_prediction_used; Bool *pSfbPredictionUsed = pLt_pred->sfb_prediction_used; Int *pTempPtr; Int *pDelay = pLt_pred->delay; pDelay[0] = (Int) get17_n_lessbits( LEN_LTP_LAG, /* 11 bits */ pInputStream); pLt_pred->weight_index = (Int) get9_n_lessbits( LEN_LTP_COEF, /* 3 bits */ pInputStream); last_band = max_sfb; if (win_type != EIGHT_SHORT_SEQUENCE) { /* last_band = min(MAX_LT_PRED_LONG_SFB, max_sfb) MAX_SCFAC_BANDS */ if (last_band > MAX_LT_PRED_LONG_SFB) { last_band = MAX_LT_PRED_LONG_SFB; } for (k = last_band; k > 0; k--) { *(pSfbPredictionUsed++) = (Int) get1bits(pInputStream); } /* * This is not a call to memset, because * (max_sfb - last_band) should typically be a small value. */ for (k = (max_sfb - last_band); k > 0; k--) { *(pSfbPredictionUsed++) = FALSE; } } else /* (win_type == EIGHT_SHORT_SEQUENCE) */ { /* last_band = min(MAX_LT_PRED_SHORT_SFB, max_sfb) */ if (last_band > MAX_LT_PRED_SHORT_SFB) { last_band = MAX_LT_PRED_SHORT_SFB; } /* * The following two coding constructs are equivalent... * * first_time == 1 * for (wnd_num=NUM_SHORT_WINDOWS; wnd_num > 0; wnd_num--) * { * if (condition) * { * if (first_time == 1) * { * CODE SECTION A * first_time = 0; * } * else * { * CODE SECTION B * } * } * } * * -----------------------------------EQUIVALENT TO------------ * * wnd_num=NUM_SHORT_WINDOWS; * * do * { * wnd_num--; * if (condition) * { * CODE SECTION A * break; * } * } while( wnd_num > 0) * * while (wnd_num > 0) * { * if (condition) * { * CODE SECTION B * } * wnd_num--; * } * */ prev_subblock = pDelay[0]; pTempPtr = &pSfbPredictionUsed[0]; wnd_num = NUM_SHORT_WINDOWS; prev_subblock_nonzero = prev_subblock; prev_subblock += LTP_LAG_OFFSET; do { /* * Place decrement of wnd_num here, to insure * that the decrement occurs before the * break out of the do-while loop. */ wnd_num--; temp_reg = (Int) get1bits(pInputStream); *(pWinPredictionUsed++) = temp_reg; if (temp_reg != FALSE) { *(pDelay++) = prev_subblock_nonzero; for (k = last_band; k > 0; k--) { *(pTempPtr++) = TRUE; } for (k = (max_sfb - last_band); k > 0; k--) { *(pTempPtr++) = FALSE; } break; } /* if(pWinPredictionUsed) */ else { pDelay++; pTempPtr += max_sfb; } } while (wnd_num > 0); /* * This while loop picks up where the previous one left off. * Notice that the code functions differently inside the loop */ while (wnd_num > 0) { temp_reg = (Int) get1bits(pInputStream); *(pWinPredictionUsed++) = temp_reg; if (temp_reg != FALSE) { temp_reg = (Int) get1bits(pInputStream); if (temp_reg != 0) { temp_reg = (Int) get9_n_lessbits( LEN_LTP_SHORT_LAG, pInputStream); *(pDelay++) = prev_subblock - temp_reg; } else { *(pDelay++) = prev_subblock_nonzero; } for (k = last_band; k > 0; k--) { *(pTempPtr++) = TRUE; } for (k = (max_sfb - last_band); k > 0; k--) { *(pTempPtr++) = FALSE; } } /* if (temp_reg) */ else { pDelay++; pTempPtr += max_sfb; } wnd_num--; } /* while(wnd_num) */ } /* else (win_type == EIGHT_SHORT_SEQUENCE) */ } /* lt_decode */
Int get_adif_header( tDec_Int_File *pVars, ProgConfig *pScratchPCE) { Int i; UInt32 temp; Int numConfigElementsMinus1; Int bitStreamType; UInt32 theIDFromFile; BITS *pInputStream = &pVars->inputStream; ADIF_Header *pHeader = &pVars->scratch.adif_header; Int status = SUCCESS; /* * The ADIF_ID field is 32 bits long, one more than what getbits() can * do, so read the field in two parts. There is no point in saving the * string - it either matches or it does not. If it matches, it must * have been 'ADIF' */ theIDFromFile = get17_n_lessbits((2 * LEN_BYTE), pInputStream); temp = get17_n_lessbits((2 * LEN_BYTE), pInputStream); theIDFromFile = (theIDFromFile << (2 * LEN_BYTE)) | temp; if (theIDFromFile != ADIF_ID) { /* * Rewind the bit stream pointer so a search for ADTS header * can start at the beginning. */ pInputStream->usedBits -= (4 * LEN_BYTE); /* * The constant in the next line needs to be updated when * error handling method is determined. */ status = -1; } else { /* * To save space, the unused fields are read in, but not saved. */ /* copyright string */ temp = get1bits(/* LEN_COPYRT_PRES,*/ pInputStream); if (temp != FALSE) { /* * Read in and ignore the copyright string. If restoring * watch out for count down loop. */ for (i = LEN_COPYRT_ID; i > 0; i--) { get9_n_lessbits(LEN_BYTE, pInputStream); } /* end for */ /* * Make sure to terminate the string with '\0' if restoring * the the copyright string. */ } /* end if */ /* Combine the original/copy and fields into one call */ get9_n_lessbits( LEN_ORIG + LEN_HOME, pInputStream); bitStreamType = get1bits(/* LEN_BS_TYPE,*/ pInputStream); pHeader->bitrate = getbits( LEN_BIT_RATE, pInputStream); /* * Read in all the Program Configuration Elements. * For this library, only one of the up to 16 possible PCE's will be * saved. Since each PCE must be read, a temporary PCE structure is * used, and if that PCE is the one to use, it is copied into the * single PCE. This is done inside of get_prog_config() */ numConfigElementsMinus1 = get9_n_lessbits(LEN_NUM_PCE, pInputStream); for (i = numConfigElementsMinus1; (i >= 0) && (status == SUCCESS); i--) { /* * For ADIF contant bit rate streams, the _encoder_ buffer * fullness is transmitted. This version of an AAC decoder has * no use for this variable; yet it must be read in to move * the bitstream pointers. */ if (bitStreamType == CONSTANT_RATE_BITSTREAM) { getbits( LEN_ADIF_BF, pInputStream); } /* end if */ pVars->adif_test = 1; /* Get one program configuration element */ status = get_prog_config( pVars, pScratchPCE); #ifdef AAC_PLUS /* * For implicit signalling, no hint that sbr or ps is used, so we need to * check the sampling frequency of the aac content, if lesser or equal to * 24 KHz, by defualt upsample, otherwise, do nothing */ if ((pVars->prog_config.sampling_rate_idx >= 6) && (pVars->aacPlusEnabled == true) && pVars->mc_info.audioObjectType == MP4AUDIO_AAC_LC) { pVars->mc_info.upsamplingFactor = 2; pVars->prog_config.sampling_rate_idx -= 3; pVars->mc_info.sbrPresentFlag = 1; pVars->sbrDecoderData.SbrChannel[0].syncState = UPSAMPLING; pVars->sbrDecoderData.SbrChannel[1].syncState = UPSAMPLING; } #endif } /* end for */ } /* end 'else' of --> if (theIDFromFile != ADIF_ID) */ return status; } /* end get_adif_header */
Int get_prog_config( tDec_Int_File *pVars, ProgConfig *pScratchPCE) { Int i; UInt tag; Int numChars; UInt temp; Bool flag; Int status = SUCCESS; BITS *pInputStream = &(pVars->inputStream); /* * The tag is used at the very end to see if this PCE is * the one to be used. Otherwise it does not need to be saved for the * the simple configurations to be used in this version of an AAC * decoder. * * All of the bits of this PCE must be read even if this PCE will not * be used. They are read into a temporary PCE, then later it is decided * whether to keep this PCE. * * To allow quick removal of the fields from the ProgConfig structure * that will probably not be used at a later date, * while still advancing the bitstream pointer,the return value of * getbits is saved into a temporary variable, then transfered to * the structure item. */ tag = get9_n_lessbits(LEN_TAG, pInputStream); pScratchPCE->profile = get9_n_lessbits(LEN_PROFILE, pInputStream); pScratchPCE->sampling_rate_idx = get9_n_lessbits(LEN_SAMP_IDX, pInputStream); if (!pVars->adif_test && (pScratchPCE->sampling_rate_idx != pVars->prog_config.sampling_rate_idx)) { #ifdef AAC_PLUS /* * PCE carries the baseline frequency, if SBR or PS are used, the frequencies will not match * so check for this unique case, and let decoding continue if this is a redundant PCE */ if ((pScratchPCE->sampling_rate_idx != (pVars->prog_config.sampling_rate_idx + 3)) || (pVars->mc_info.upsamplingFactor != 2)) #endif { /* rewind the pointer as implicit channel configuration maybe the case */ pInputStream->usedBits -= (LEN_TAG + LEN_PROFILE + LEN_SAMP_IDX); return (1); /* mismatch cannot happen */ } } /* * Retrieve the number of element lists for each of * front, side, back, lfe, data, and coupling. * * For two-channel stereo or mono, only the data in the front needs * to be saved. However, ALL fields need to be skipped over in some * fashion. Also, the number of elements needs to be temporarily saved * to call get_ele_list(). If that function was changed to pass in * the number of points to be read, the memory set aside inside the * ProgConfig structure could be removed. */ /* * The next six function calls could be combined into one, then use * shifts and masks to retrieve the individual fields. */ temp = get9_n_lessbits(LEN_NUM_ELE, pInputStream); pScratchPCE->front.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_ELE, pInputStream); pScratchPCE->side.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_ELE, pInputStream); pScratchPCE->back.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_LFE, pInputStream); pScratchPCE->lfe.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_DAT, pInputStream); pScratchPCE->data.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_CCE, pInputStream); pScratchPCE->coupling.num_ele = temp; /* * Read in mix down data. * * Whether these fields can be removed and have proper operation * will be determined at a later date. */ /* Read presence of mono_mix */ flag = get1bits(pInputStream);/* LEN_MIX_PRES,*/ pScratchPCE->mono_mix.present = flag; if (flag != FALSE) { temp = get9_n_lessbits(LEN_TAG, pInputStream); pScratchPCE->mono_mix.ele_tag = temp; } /* end if (flag != FALSE) */ /* Read presence of stereo mix */ flag = get1bits(pInputStream); /* LEN_MIX_PRES,*/ pScratchPCE->stereo_mix.present = flag; if (flag != FALSE) { temp = get9_n_lessbits(LEN_TAG, pInputStream); pScratchPCE->stereo_mix.ele_tag = temp; } /* end if (flag != FALSE) */ /* Read presence of matrix mix */ flag = get1bits(pInputStream); /* LEN_MIX_PRES,*/ pScratchPCE->matrix_mix.present = flag; if (flag != FALSE) { temp = get9_n_lessbits(LEN_MMIX_IDX, pInputStream); pScratchPCE->matrix_mix.ele_tag = temp; temp = get1bits(pInputStream); /* LEN_PSUR_ENAB,*/ pScratchPCE->matrix_mix.pseudo_enab = temp; } /* end if (flag != FALSE) */ /* * Get each of the element lists. Only the front information will be * used for the PV decoder, but the usedBits field of pInputStream must * be advanced appropriately. * * This could be optimized by advancing the bit stream for the * elements that do not need to be read. */ get_ele_list(&pScratchPCE->front, pInputStream, TRUE); get_ele_list(&pScratchPCE->side, pInputStream, TRUE); get_ele_list(&pScratchPCE->back, pInputStream, TRUE); get_ele_list(&pScratchPCE->lfe, pInputStream, FALSE); get_ele_list(&pScratchPCE->data, pInputStream, FALSE); get_ele_list(&pScratchPCE->coupling, pInputStream, TRUE); /* * The standard requests a byte alignment before reading in the * comment. This can be done because LEN_COMMENT_BYTES == 8. */ byte_align(pInputStream); numChars = get9_n_lessbits(LEN_COMMENT_BYTES, pInputStream); /* * Ignore the comment - it requires 65 bytes to store (or worse on DSP). * If this field is restored, make sure to append a trailing '\0' */ for (i = numChars; i > 0; i--) { pScratchPCE->comments[i] = (Char) get9_n_lessbits(LEN_BYTE, pInputStream); } /* end for */ if (pVars->current_program < 0) { /* * If this is the first PCE, it becomes the current, regardless of * its tag number. */ pVars->current_program = tag; pVars->mc_info.ch_info[0].tag = 0; } /* end if (pVars->current_program < 0) */ if (tag == (UInt)pVars->current_program) { /* * This branch is reached under two conditions: * 1) This is the first PCE found, it was selected in the above if * block. In all encoders found thus far, the tag value has been * zero. * 2) A PCE has been sent by the encoder with a tag that matches the * the first one sent. It will then be re-read. No encoder found * * Regardless, the temporary PCE will now be copied into the * the one official program configuration. */ /* * Keep adts setting in case of a redundant PCE (only applicable when * using aac-lib own adts parser) */ pScratchPCE->file_is_adts = pVars->prog_config.file_is_adts; pScratchPCE->headerless_frames = pVars->prog_config.headerless_frames; pv_memcpy(&pVars->prog_config, pScratchPCE, sizeof(ProgConfig)); tag = 0; /* * Check that dual-mono does not carry more than 2 tracks, otherwise flag an non-supported error */ if ((pVars->prog_config.front.num_ele > 2) && !(pVars->prog_config.front.ele_is_cpe[tag])) { status = 1; } /* * Check that stereo does not carry more than 1 track, otherwise flag an non-supported error */ if ((pVars->prog_config.front.num_ele > 1) && (pVars->prog_config.front.ele_is_cpe[tag])) { status = 1; } if (!status) { /* enter configuration into MC_Info structure */ status = set_mc_info(&pVars->mc_info, (tMP4AudioObjectType)(pVars->prog_config.profile + 1), pVars->prog_config.sampling_rate_idx, pVars->prog_config.front.ele_tag[tag], pVars->prog_config.front.ele_is_cpe[tag], pVars->winmap, pVars->SFBWidth128); if (pVars->mc_info.upsamplingFactor == 2) { /* * prog_config.sampling_rate_idx corresponds to the aac base layer, * if the upsampling factor is active, then the output frequency needs * to be adjusted accordingly */ pVars->prog_config.sampling_rate_idx -= 3; } } } /* end if (tag == pVars->current_program) */ return (status); }
Int get_ics_info( const tMP4AudioObjectType audioObjectType, BITS *pInputStream, const Bool common_window, WINDOW_SEQUENCE *pWindowSequence, WINDOW_SHAPE *pWindowShape, Int group[], Int *p_max_sfb, FrameInfo *p_winmap[], LT_PRED_STATUS *pFirstLTPStatus, LT_PRED_STATUS *pSecondLTPStatus) { WINDOW_SEQUENCE windowSequence; UInt temp; Bool predictor_data_present; UInt local_max_sfb; UInt allowed_max_sfb; Int status = SUCCESS; Bool first_ltp_data_present = FALSE; Bool second_ltp_data_present = FALSE; /* * The following three calls to getbits have been replaced with one * call for speed: * * getbits(LEN_ICS_RESERV, pInputStream); * windowSequence = getbits(LEN_WIN_SEQ, pInputStream); * *pWindowShape = getbits(LEN_WIN_SH, pInputStream); * */ temp = get9_n_lessbits( LEN_ICS_RESERV + LEN_WIN_SEQ + LEN_WIN_SH, pInputStream); windowSequence = (WINDOW_SEQUENCE)((temp >> LEN_WIN_SH) & ((0x1 << LEN_WIN_SEQ) - 1)); *pWindowShape = (WINDOW_SHAPE)((temp) & ((0x1 << LEN_WIN_SH) - 1)); /* * This pointer should not be NULL as long as the initialization code * has been run, so the test for NULL has been removed. */ allowed_max_sfb = p_winmap[windowSequence]->sfb_per_win[0]; if (windowSequence == EIGHT_SHORT_SEQUENCE) { local_max_sfb = get9_n_lessbits(LEN_MAX_SFBS, pInputStream); getgroup( group, pInputStream); if (local_max_sfb > allowed_max_sfb) { status = 1; /* ERROR CODE - needs to be updated */ } } /* end of TRUE of if (windowSequence == EIGHT_SHORT_SEQUENCE) */ else { /* There is only one group for long windows. */ group[0] = 1; /* * The window is long, get the maximum scale factor bands, * and get long term prediction info. * * Reference [1] states that the audioObjectType is first tested, * then the predictor_data_present is read on either branch of the * if (audioObjectType == MP4AUDIO_LTP). Instead, this code combines * the two calls on both branches into one before the * if, and then in turn combines with another call to getbits, all * in the name of speed. * * This would be the individual calls, without checking the number * of scale factor bands: * * local_max_sfb = * (Int) getbits( * LEN_MAX_SFBL, * pInputStream); * * if (audioObjectType == MP4AUDIO_LTP) * { * predictor_data_present = * (Bool) getbits( * LEN_PREDICTOR_DATA_PRESENT, * pInputStream); * * ..... (read LTP data) * * } * else * { * * predictor_data_present = * (Bool) getbits( * LEN_PREDICTOR_DATA_PRESENT, * pInputStream); * * ..... (its an error for this library) * } */ temp = get9_n_lessbits( LEN_MAX_SFBL + LEN_PREDICTOR_DATA_PRESENT, pInputStream); local_max_sfb = (Int)(temp >> LEN_PREDICTOR_DATA_PRESENT); predictor_data_present = (Bool)(temp & ((0x1 << LEN_PREDICTOR_DATA_PRESENT) - 1)); if (local_max_sfb > allowed_max_sfb) { status = 1; /* ERROR CODE - needs to be updated */ } else if (audioObjectType == MP4AUDIO_LTP) { /* * Note that the predictor data bit has already been * read. */ /* * If the object type is LTP, the predictor data is * LTP. If the object type is not LTP, the predictor data * is so called "frequency predictor data", which is not * supported by this implementation. Refer to (1) */ if (predictor_data_present != FALSE) { first_ltp_data_present = (Bool) get1bits(/* LEN_LTP_DATA_PRESENT,*/ pInputStream); if (first_ltp_data_present != FALSE) { lt_decode( windowSequence, pInputStream, local_max_sfb, pFirstLTPStatus); } if (common_window != FALSE) { second_ltp_data_present = (Bool) get1bits(/* LEN_LTP_DATA_PRESENT,*/ pInputStream); if (second_ltp_data_present != FALSE) { lt_decode( windowSequence, pInputStream, local_max_sfb, pSecondLTPStatus); } } /* if (common_window != FALSE) */ } /* if (predictor_data_present != FALSE) */ } /* else if (audioObjectType == MP4AUDIO_LTP) */ else { /* * Note that the predictor data bit has already been * read. */ /* * The object type is not LTP. If there is data, its * frequency predictor data, not supported by this * implementation. */ if (predictor_data_present != FALSE) { status = 1; /* ERROR CODE UPDATE LATER */ } /* if (predictor_data_present != FALSE) */ } /* end of "else" clause of if (audioObjectType == MP4AUDIO_LTP) */ } /* if (windowSequence == EIGHT_SHORT_SEQUENCE) [FALSE branch] */ /* * Save all local copies. */ pFirstLTPStatus->ltp_data_present = first_ltp_data_present; if (common_window != FALSE) { pSecondLTPStatus->ltp_data_present = second_ltp_data_present; } *p_max_sfb = local_max_sfb; *pWindowSequence = windowSequence; return (status); } /* get_ics_info */
/*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ Int huffdecode( Int id_syn_ele, BITS *pInputStream, tDec_Int_File *pVars, tDec_Int_Chan *pChVars[]) { /*---------------------------------------------------------------------------- ; Define all local variables ----------------------------------------------------------------------------*/ Int ch; Int common_window; Int hasmask; Int status = SUCCESS; Int num_channels = 0; MC_Info *pMcInfo; per_chan_share_w_fxpCoef *pChLeftShare; /* Helper pointer */ per_chan_share_w_fxpCoef *pChRightShare; /* Helper pointer */ /*---------------------------------------------------------------------------- ; Function body here ----------------------------------------------------------------------------*/ get9_n_lessbits( LEN_TAG, pInputStream); /* suppose an un-supported id_syn_ele will never be passed */ common_window = 0; if (id_syn_ele == ID_CPE) { common_window = get1bits(pInputStream); } pMcInfo = &pVars->mc_info; /* * check if provided info (num of channels) on audio config, * matches read bitstream data, if not, allow update only once. * In almost all cases it should match. */ #if 0 if ((pMcInfo->ch_info[0].cpe != id_syn_ele)) { if (pVars->mc_info.implicit_channeling) /* check done only once */ { pMcInfo->ch_info[0].cpe = id_syn_ele & 1; /* collect info from bitstream * implicit_channeling flag is locked * after 1st frame, to avoid toggling * parameter in the middle of the clip */ pMcInfo->nch = (id_syn_ele & 1) + 1; /* update number of channels */ } else { status = 1; /* ERROR break if syntax error persist */ } } #endif if (status == SUCCESS) { if (id_syn_ele == ID_SCE) { num_channels = 1; pVars->hasmask = 0; } else if (id_syn_ele == ID_CPE) { pChLeftShare = pChVars[LEFT]->pShareWfxpCoef; pChRightShare = pChVars[RIGHT]->pShareWfxpCoef; num_channels = 2; if (common_window != FALSE) { status = get_ics_info( (tMP4AudioObjectType) pVars->mc_info.audioObjectType, pInputStream, (Bool)common_window, (WINDOW_SEQUENCE *) & pChVars[LEFT]->wnd, (WINDOW_SHAPE *) & pChVars[LEFT]->wnd_shape_this_bk, pChLeftShare->group, (Int *) & pChLeftShare->max_sfb, pVars->winmap, (LT_PRED_STATUS *) & pChLeftShare->lt_status, (LT_PRED_STATUS *) & pChRightShare->lt_status); if (status == SUCCESS) { /* copy left channel info to right channel */ pChVars[RIGHT]->wnd = pChVars[LEFT]->wnd; pChVars[RIGHT]->wnd_shape_this_bk = pChVars[LEFT]->wnd_shape_this_bk; pChRightShare->max_sfb = pChLeftShare->max_sfb; pv_memcpy( pChRightShare->group, pChLeftShare->group, NSHORT*sizeof(pChLeftShare->group[0])); hasmask = getmask( pVars->winmap[pChVars[LEFT]->wnd], pInputStream, pChLeftShare->group, pChLeftShare->max_sfb, pVars->mask); if (hasmask == MASK_ERROR) { status = 1; /* ERROR code */ } pVars->hasmask = hasmask; } /* if (status == 0) */ } else { pVars->hasmask = 0; } /* if (common_window) */ } /* if (id_syn_ele) */ else if (id_syn_ele == ID_LFE) { num_channels = 1; pVars->hasmask = 0; } /* if (id_syn_ele) == ID_LFE */ } /* if (status) */ ch = 0; while ((ch < num_channels) && (status == SUCCESS)) { pChLeftShare = pChVars[ch]->pShareWfxpCoef; status = getics( pInputStream, common_window, pVars, pChVars[ch], pChLeftShare->group, &pChLeftShare->max_sfb, pChLeftShare->cb_map, &pChLeftShare->tns, pVars->winmap, &pVars->share.a.pulseInfo, pVars->share.a.sect); ch++; } /* while (ch) */ /*---------------------------------------------------------------------------- ; Return status ----------------------------------------------------------------------------*/ return status; } /* huffdecode */
/*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ Int get_audio_specific_config(tDec_Int_File * const pVars) { UInt temp; tMP4AudioObjectType audioObjectType; //UInt32 sampling_rate; UInt channel_config; UInt syncExtensionType; UInt extensionAudioObjectType = 0; UInt extensionSamplingFrequencyIndex = 0; BITS *pInputStream; Int status; status = SUCCESS; pInputStream = &(pVars->inputStream); pVars->mc_info.upsamplingFactor = 1; /* default to regular AAC */ temp = get9_n_lessbits(LEN_OBJ_TYPE + LEN_SAMP_RATE_IDX, pInputStream); /* * The following code can directly set the values of elements in * MC_Info, rather than first setting the values in pVars->prog_config * and then copy these values to MC_Info by calling set_mc_info. * In order to keep consistent with get_prog_config (ADIF) and * get_adts_header (ADTS), the code here is still copying * the info, and set the pVars->current_program = 0 */ /* AudioObjectType */ audioObjectType = (tMP4AudioObjectType)((temp & 0x1f0) >> 4); pVars->mc_info.ExtendedAudioObjectType = audioObjectType; /* default */ /* saving an audioObjectType into a profile field */ /* pVars->prog_config.profile = audioObjectType; */ /* sampling rate index */ pVars->prog_config.sampling_rate_idx = temp & 0xf; if (pVars->prog_config.sampling_rate_idx > 0xb) { /* * Only support 12 sampling frequencies from array samp_rate_info ( see sfb.cpp) * 7350 Hz (index 0xc) is not supported, the other indexes are reserved or escape */ if (pVars->prog_config.sampling_rate_idx == 0xf) /* escape sequence */ { /* * sampling rate not listed in Table 1.6.2, * this release does not support this */ /*sampling_rate = getbits( LEN_SAMP_RATE, pInputStream);*/ getbits(LEN_SAMP_RATE, pInputStream); /* future use */ } status = 1; } channel_config = get9_n_lessbits(LEN_CHAN_CONFIG, pInputStream); if ((channel_config > 2) && (!pVars->aacConfigUtilityEnabled)) { /* * AAC lib does not support more than two channels * signal error when in decoder mode * do not test when in utility mode */ status = 1; } if (audioObjectType == MP4AUDIO_SBR || audioObjectType == MP4AUDIO_PS) { /* to disable explicit backward compatiblity check */ pVars->mc_info.ExtendedAudioObjectType = MP4AUDIO_SBR; pVars->mc_info.sbrPresentFlag = 1; if (audioObjectType == MP4AUDIO_PS) { pVars->mc_info.psPresentFlag = 1; pVars->mc_info.ExtendedAudioObjectType = MP4AUDIO_PS; } extensionSamplingFrequencyIndex = /* extensionSamplingFrequencyIndex */ get9_n_lessbits(LEN_SAMP_RATE_IDX, pInputStream); if (extensionSamplingFrequencyIndex == 0x0f) { /* * sampling rate not listed in Table 1.6.2, * this release does not support this */ /*sampling_rate = getbits( LEN_SAMP_RATE, pInputStream);*/ getbits(LEN_SAMP_RATE, pInputStream); } audioObjectType = (tMP4AudioObjectType) get9_n_lessbits(LEN_OBJ_TYPE , pInputStream); } if ((/*(audioObjectType == MP4AUDIO_AAC_MAIN) ||*/ (audioObjectType == MP4AUDIO_AAC_LC) || /*(audioObjectType == MP4AUDIO_AAC_SSR) ||*/ (audioObjectType == MP4AUDIO_LTP) /*||*/ /*(audioObjectType == MP4AUDIO_AAC_SCALABLE) ||*/ /*(audioObjectType == MP4AUDIO_TWINVQ)*/) && (status == SUCCESS)) { status = get_GA_specific_config(pVars, pInputStream, channel_config, audioObjectType); /* * verify that Program config returned a supported audio object type */ if ((pVars->mc_info.audioObjectType != MP4AUDIO_AAC_LC) && (pVars->mc_info.audioObjectType != MP4AUDIO_LTP)) { return 1; /* status != SUCCESS invalid aot */ } } else { return 1; /* status != SUCCESS invalid aot or invalid parameter */ } /* * SBR tool explicit signaling ( backward compatible ) */ if (extensionAudioObjectType != MP4AUDIO_SBR) { syncExtensionType = (UInt)get17_n_lessbits(LEN_SYNC_EXTENSION_TYPE, pInputStream); printf("%s(): syncExtensionType:%d\n", __FUNCTION__, syncExtensionType); if (syncExtensionType == 0x2b7) { extensionAudioObjectType = get9_n_lessbits( /* extensionAudioObjectType */ LEN_OBJ_TYPE, pInputStream); if (extensionAudioObjectType == MP4AUDIO_SBR) { printf("%s(): extensionAudioObjectType is MP4AUDIO_SBR\n", __FUNCTION__); pVars->mc_info.sbrPresentFlag = get1bits(pInputStream); /* sbrPresentFlag */ if (pVars->mc_info.sbrPresentFlag == 1) { printf("%s(): sbrPresent\n", __FUNCTION__); extensionSamplingFrequencyIndex = get9_n_lessbits( /* extensionSamplingFrequencyIndex */ LEN_SAMP_RATE_IDX, pInputStream); if (pVars->aacPlusEnabled == true) { #ifdef AAC_PLUS if (extensionSamplingFrequencyIndex < 3) { /* * Disable SBR/PS for any sampling freq. > 48 KHz * 3GPP request support up to Level 2, == max AAC/SBR present * 24/48 KHz */ pVars->aacPlusEnabled = false; printf("%s(): diasable\n", __FUNCTION__); } else { pVars->mc_info.upsamplingFactor = (samp_rate_info[extensionSamplingFrequencyIndex].samp_rate >> 1) == samp_rate_info[pVars->prog_config.sampling_rate_idx].samp_rate ? 2 : 1; printf("%s(): upsamplingFactor : %d\n", __FUNCTION__, pVars->mc_info.upsamplingFactor); if ((Int)extensionSamplingFrequencyIndex == pVars->prog_config.sampling_rate_idx) { /* * Disable SBR decoding for any sbr-downsampled file whose SF is >= 24 KHz */ if (pVars->prog_config.sampling_rate_idx < 6) { pVars->aacPlusEnabled = false; printf("%s(): diasable\n", __FUNCTION__); } pVars->mc_info.bDownSampledSbr = true; } pVars->prog_config.sampling_rate_idx = extensionSamplingFrequencyIndex; } #endif } else printf("pVars->aacPlusEnabled is false\n");
/*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ Int huffcb( SectInfo *pSect, BITS *pInputStream, Int sectbits[], Int tot_sfb, Int sfb_per_win, Int max_sfb) { /*---------------------------------------------------------------------------- ; Define all local variables ----------------------------------------------------------------------------*/ Int base; /* section boundary */ Int sect_len_incr; Int esc_val; /* ESC of section length = 31(long), =7 (short) */ Int bits; /* # of bits used to express esc_val */ Int num_sect; Int active_sfb; Int group_base; /*---------------------------------------------------------------------------- ; Function body here ----------------------------------------------------------------------------*/ bits = sectbits[0]; /* 3 for SHORT_WIN, 5 for LONG_WIN */ esc_val = (1 << bits) - 1; /* ESC_value for section length */ num_sect = 0; base = 0; group_base = 0; /* read until the end of one frame */ while ((base < tot_sfb) && (num_sect < tot_sfb)) { pSect->sect_cb = get9_n_lessbits( LEN_CB, pInputStream); /* section codebook */ sect_len_incr = get9_n_lessbits( bits, pInputStream); /* length_incr */ /* read until non-ESC value, see p55 reference 2 */ while ((sect_len_incr == esc_val) && (base < tot_sfb)) { base += esc_val; sect_len_incr = get9_n_lessbits( bits, pInputStream); } base += sect_len_incr; pSect->sect_end = base; /* total # of sfb until current section */ pSect++; num_sect++; /* active_sfb = base % sfb_per_win; */ active_sfb = base - group_base; /* * insert a zero section for regions above max_sfb for each group * Make sure that active_sfb is also lesser than tot_sfb */ if ((active_sfb == max_sfb) && (active_sfb < tot_sfb)) { base += (sfb_per_win - max_sfb); pSect->sect_cb = 0; /* huffman codebook 0 */ pSect->sect_end = base; num_sect++; pSect++; group_base = base; } else if (active_sfb > max_sfb) { /* within each group, the sections must delineate the sfb * from zero to max_sfb so that the 1st section within each * group starts at sfb0 and the last section ends at max_sfb * see p55 reference 2 */ break; } } /* while (base=0) */ if (base != tot_sfb || num_sect > tot_sfb) { num_sect = 0; /* error */ } return num_sect; } /* huffcb */
/*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ Int getics( Int id_syn_ele, BITS *pInputStream, Int common_window, tDec_Int_File *pVars, tDec_Int_Chan *pChVars, Int group[], Int *pMax_sfb, Int *pCodebookMap, TNS_frame_info *pTnsFrameInfo, FrameInfo **pWinMap, PulseInfo *pPulseInfo, SectInfo sect[]) { /*---------------------------------------------------------------------------- ; Define all local variables ----------------------------------------------------------------------------*/ Int status = SUCCESS; Int nsect = 0; Int i; Int cb; Int sectWidth; Int sectStart; Int totSfb; Int *pGroup; FrameInfo *pFrameInfo; Int global_gain; /* originally passed in from huffdecode */ Bool present; /*---------------------------------------------------------------------------- ; Function body here ----------------------------------------------------------------------------*/ pGroup = group; /* read global gain from Input bitstream */ global_gain = get9_n_lessbits(LEN_SCL_PCM, pInputStream); if (common_window == FALSE) { status = get_ics_info(pVars->mc_info.audioObjectType, pInputStream, common_window, &pChVars->wnd, &pChVars->wnd_shape_this_bk, group, pMax_sfb, pWinMap, &pChVars->pShareWfxpCoef->lt_status, NULL); } pFrameInfo = pWinMap[pChVars->wnd]; /* at least, number of window should be 1 or 8 */ if ((pFrameInfo->num_win != 1) && (pFrameInfo->num_win != 8)) { status = 1; } /* First, calculate total number of scalefactor bands * for this grouping. Then, decode section data */ if (*pMax_sfb > 0) { /* calculate total number of sfb */ i = 0; totSfb = 0; do { totSfb++; } while (*pGroup++ < pFrameInfo->num_win); totSfb *= pFrameInfo->sfb_per_win[0]; /* decode section data */ nsect = huffcb(sect, pInputStream, pFrameInfo->sectbits, totSfb, pFrameInfo->sfb_per_win[0], *pMax_sfb); if (nsect == 0) { status = 1; /* decode section data error */ }/* if (nsect) */ /* generate "linear" description from section info * stored as codebook for each scalefactor band and group * when nsect == 0, for-loop does not execute */ sectStart = 0; for (i = 0; i < nsect; i++) { cb = sect[i].sect_cb; sectWidth = sect[i].sect_end - sectStart; sectStart += sectWidth; while (sectWidth > 0) { *pCodebookMap++ = cb; /* cannot use memset for Int */ sectWidth--; } } /* for (i) */ } else { /* set all sections with ZERO_HCB */ pv_memset(pCodebookMap, ZERO_HCB, MAXBANDS*sizeof(*pCodebookMap)); /* for (i=MAXBANDS; i>0; i--) { *(pCodebookMap++) = ZERO_HCB; } */ } /* if (*pMax_sfb) */ /* calculate band offsets * (because of grouping and interleaving this cannot be * a constant: store it in pFrameInfo->frame_sfb_top) */ if (pFrameInfo->islong == FALSE) { calc_gsfb_table(pFrameInfo, group); } /* decode scale factor data */ if (status == SUCCESS) { status = hufffac(pFrameInfo, pInputStream, group, nsect, sect, global_gain, pChVars->pShareWfxpCoef->factors, pVars->scratch.a.huffbook_used); } /* if (status) */ /* noiseless coding */ if (status == SUCCESS) { present = get1bits(pInputStream); pPulseInfo->pulse_data_present = present; if (present != FALSE) { if (pFrameInfo->islong == 1) { status = get_pulse_data(pPulseInfo, pInputStream); } else { /* CommonExit(1,"Pulse data not allowed for short blocks"); */ status = 1; } /* if (pFrameInfo) */ } /* if (present) */ } /* if (status) */ /* decode tns data */ if (status == SUCCESS) { present = get1bits(pInputStream); pTnsFrameInfo->tns_data_present = present; if (present != FALSE) { get_tns(pChVars->pShareWfxpCoef->max_sfb, pInputStream, pChVars->wnd, pFrameInfo, &pVars->mc_info, pTnsFrameInfo, pVars->scratch.a.tns_decode_coef); } else { for (i = pFrameInfo->num_win - 1; i >= 0 ; i--) { pTnsFrameInfo->n_filt[i] = 0; } } /* if(present) */ } /* if (status) */ /* gain control */ if (status == SUCCESS) { present = get1bits(pInputStream); if (present != FALSE) { /* CommonExit(1, "Gain control not implemented"); */ status = 1; } } /* if (status) */ if (status == SUCCESS) { /* Support Mono, Dual-Mono, or Stereo */ if ((id_syn_ele == ID_SCE) || (id_syn_ele == ID_CPE)) { status = huffspec_fxp(pFrameInfo, pInputStream, nsect, sect, pChVars->pShareWfxpCoef->factors, pChVars->fxpCoef, pVars->share.a.quantSpec, pVars->scratch.tmp_spec, pWinMap[ONLY_LONG_WINDOW], pPulseInfo, pChVars->pShareWfxpCoef->qFormat); } } /*---------------------------------------------------------------------------- ; Return status ----------------------------------------------------------------------------*/ return status; } /* getics */