Loading lib_dec/jbm_pcmdsp_apa.c +206 −0 Original line number Diff line number Diff line Loading @@ -1078,6 +1078,211 @@ UWord8 apa_exec_fx( return 3; } /* get target length */ test(); test(); IF( EQ_16( ps->l_frm, 480 ) || EQ_16( ps->l_frm, 960 ) || EQ_16( ps->l_frm, 1920 ) ) { /* decomposite ps->l_frm into 15<<i, e.g. 480=15<<5 */ i = sub( 15 - 4, norm_s( ps->l_frm ) ); /* this only works for 20ms framing */ assert( ps->l_frm == shl( shr( ps->l_frm, i ), i ) ); // assert( i_mult2( sub( ps->scale, 100 ), add( ps->nFramesSinceSetScale, 1 ) ) == ( ps->scale - 100 ) * ( ps->nFramesSinceSetScale + 1 ) ); expScaling = L_shr_r( L_mult0( i_mult2( sub( ps->scale, 100 ), add( (Word16) ps->nFramesSinceSetScale, 1 ) ), 19661 /*15*(1<<2)/100.0 Q15*/ ), sub( 15 + 2, i ) ); } ELSE { /* decomposite ps->l_frm into 5<<i, e.g. 320=5<<6 */ i = sub( 15 - 3, norm_s( ps->l_frm ) ); /* this only works for 20ms framing */ assert( ps->l_frm == shl( shr( ps->l_frm, i ), i ) ); // assert( i_mult2( sub( ps->scale, 100 ), add( ps->nFramesSinceSetScale, 1 ) ) == ( ps->scale - 100 ) * ( ps->nFramesSinceSetScale + 1 ) ); expScaling = L_shr_r( L_mult0( i_mult2( sub( ps->scale, 100 ), add( (Word16) ps->nFramesSinceSetScale, 1 ) ), 13107 /*5*(1<<3)/100.0 Q15*/ ), sub( 15 + 3, i ) ); } actScaling = L_sub( ps->diffSinceSetScale, ps->l_frm ); l_frm_out_target = L_sub( expScaling, actScaling ); /* Wait until we have l_frm outputs samples */ /* (required to search for correlation in the past). */ /* If we don't have enough samples, simply copy input to output */ IF( LT_32( ps->l_buf_out, ps->l_frm ) ) { FOR( i = 0; i < ps->l_frm; i++ ) { a_out[i] = a_in[i]; move16(); } l_frm_out = ps->l_frm; move16(); } ELSE { Word16 *buf_out_ptr = &( ps->buf_out_fx[ps->l_buf_out - ps->l_frm] ); Word16 *frm_in_ptr = &( frm_in[ps->l_frm] ); /* fill input frame */ /* 1st input frame: previous output samples */ FOR( i = 0; i < ps->l_frm; i++ ) { frm_in[i] = buf_out_ptr[i]; move16(); } /* 2nd input frame: new input samples */ FOR( i = 0; i < ps->l_frm; i++ ) { frm_in_ptr[i] = a_in[i]; move16(); } /* no scaling */ IF( EQ_32( ps->scale, 100 ) ) { copy_frm_fx( ps, frm_in, a_out, &l_frm_out ); } /* shrink */ ELSE IF( LT_32( ps->scale, 100 ) ) { shrink_frm_fx( ps, frm_in, maxScaling, a_out, &l_frm_out ); } /* extend */ ELSE { extend_frm_fx( ps, frm_in, a_out, &l_frm_out ); } /* control the amount/frequency of scaling */ IF( NE_32( l_frm_out, ps->l_frm ) ) { test(); IF( NE_32( maxScaling, 0 ) && GT_32( abs_s( extract_l( L_sub( ps->l_frm, l_frm_out ) ) ), maxScaling ) ) { /* maxScaling exceeded -> discard scaled frame */ copy_frm_fx( ps, frm_in, a_out, &l_frm_out ); } ELSE IF( GT_32( L_abs( l_frm_out_target ), ps->l_frm ) ) /* ignore small difference */ { dl_copied = L_sub( l_frm_out_target, ps->l_frm ); dl_scaled = L_sub( l_frm_out_target, l_frm_out ); /* discard scaled frame if copied frame is closer to target length */ IF( LT_32( L_abs( dl_copied ), L_abs( dl_scaled ) ) ) { copy_frm_fx( ps, frm_in, a_out, &l_frm_out ); } } } } /* copy output to internal buffer */ /* avoid buffer overflow: */ /* discard old samples; always keep at least most recent l_frm samples */ IF( GT_32( L_add( ps->l_buf_out, l_frm_out ), ps->buf_out_capacity ) ) { Word16 *buf_out_ptr1 = ps->buf_out_fx; Word16 *buf_out_ptr2; l_rem = extract_l( L_sub( ps->l_frm, l_frm_out ) ); if ( l_rem < 0 ) { l_rem = 0; move16(); } buf_out_ptr2 = &( ps->buf_out_fx[ps->l_buf_out - l_rem] ); FOR( i = 0; i < l_rem; i++ ) { buf_out_ptr1[i] = buf_out_ptr2[i]; move16(); } ps->l_buf_out = l_rem; move16(); } /* append new output samples */ IF( GT_32( L_add( ps->l_buf_out, l_frm_out ), ps->buf_out_capacity ) ) { return 5; } { Word16 *buf_out_ptr = &( ps->buf_out_fx[ps->l_buf_out] ); FOR( i = 0; i < l_frm_out; i++ ) { buf_out_ptr[i] = a_out[i]; move16(); } } ps->l_buf_out = (UWord16) L_add( ps->l_buf_out, l_frm_out ); move16(); *l_out = l_frm_out; move16(); /* update time */ ps->l_in_total = UL_addNsD( ps->l_in_total, ps->l_frm ); move32(); test(); IF( LT_32( L_abs( ps->diffSinceSetScale ), L_sub( 0x7FFFFF, L_sub( l_frm_out, ps->l_frm ) ) ) && LT_64( ps->nFramesSinceSetScale, statsResetThreshold ) ) { ps->diffSinceSetScale = L_add( ps->diffSinceSetScale, L_sub( l_frm_out, ps->l_frm ) ); move32(); ps->nFramesSinceSetScale = UL_addNsD( ps->nFramesSinceSetScale, 1 ); move32(); } ELSE /* scale statistics down to avoid overflow */ { ps->diffSinceSetScale = L_shr( ps->diffSinceSetScale, (Word16) statsResetShift ); move32(); ps->nFramesSinceSetScale = UL_lshr( ps->nFramesSinceSetScale, (Word16) statsResetShift ); move32(); } return 0; } UWord8 apa_exec_ivas_fx( apa_state_t *ps, /* i/o: state struct */ const Word16 a_in[], /* i : input samples */ UWord16 l_in, /* i : number of input samples */ UWord16 maxScaling, /* i : allowed number of inserted/removed samples */ Word16 a_out[], /* o : output samples */ UWord16 *l_out /* o : number of output samples */ ) { UWord16 i; Word16 frm_in[APA_BUF]; /* TODO(mcjbm): this buffer could be smaller - always allocates space for 16 channels */ UWord16 l_frm_out; Word16 l_rem; Word32 dl_scaled, dl_copied, l_frm_out_target; Word32 expScaling, actScaling; UWord32 statsResetThreshold, statsResetShift; statsResetThreshold = 1637; move32(); statsResetShift = 2; move32(); /* Convert max_scaling from "per channel" to total */ maxScaling = (UWord16) imult3216( maxScaling, ps->num_channels ); /* make sure no invalid output is used */ *l_out = 0; move16(); l_frm_out = 0; move16(); /* make sure pointer is valid */ IF( ps == NULL ) { return 1; } /* check available rate */ IF( ps->rate == 0 ) { return 2; } /* check size of input */ IF( NE_32( l_in, ps->l_frm ) ) { return 3; } /* get target length */ test(); test(); Loading Loading @@ -1231,6 +1436,7 @@ UWord8 apa_exec_fx( return 0; } #else uint8_t apa_exec( apa_state_t *ps, /* i/o: state struct */ Loading lib_dec/jbm_pcmdsp_apa.h +1 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,7 @@ bool apa_set_quality( apa_state_t *s, float quality, uint16_t qualityred, uint16 bool apa_exit( apa_state_t **s ); uint8_t apa_exec( apa_state_t *s, const float a_in[], uint16_t l_in, uint16_t maxScaling, float a_out[], uint16_t *l_out ); uint8_t apa_exec_ivas_fx( apa_state_t *s, const Word16 a_in[], uint16_t l_in, uint16_t maxScaling, Word16 a_out[], uint16_t *l_out ); uint8_t apa_exec_fx( apa_state_t *s, const Word16 a_in[], uint16_t l_in, uint16_t maxScaling, Word16 a_out[], uint16_t *l_out ); #endif /* JBM_PCMDSP_APA_H */ lib_dec/lib_dec_fx.c +26 −10 Original line number Diff line number Diff line Loading @@ -1088,21 +1088,37 @@ ivas_error IVAS_DEC_GetSamples( // tmp apaExecBuffer Word16 tmp_apaExecBuffer[APA_BUF]; IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) ) { for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q12 ) ); tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q11 ) ); } IF( apa_exec_fx( hIvasDec->hTimeScaler, tmp_apaExecBuffer, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, tmp_apaExecBuffer, &nTimeScalerOutSamples ) != 0 ) { return IVAS_ERR_UNKNOWN; } for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { hIvasDec->apaExecBuffer_fx[i] = L_shl( tmp_apaExecBuffer[i], Q11 ); } } ELSE { for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q12 ) ); } IF( apa_exec_ivas_fx( hIvasDec->hTimeScaler, tmp_apaExecBuffer, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, tmp_apaExecBuffer, &nTimeScalerOutSamples ) != 0 ) { return IVAS_ERR_UNKNOWN; } for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { hIvasDec->apaExecBuffer_fx[i] = L_shl( tmp_apaExecBuffer[i], Q12 ); } } assert( LE_32( (Word32) nTimeScalerOutSamples, APA_BUF ) ); nSamplesTcsScaled = idiv1616( extract_l( nTimeScalerOutSamples ), nTransportChannels ); } Loading Loading
lib_dec/jbm_pcmdsp_apa.c +206 −0 Original line number Diff line number Diff line Loading @@ -1078,6 +1078,211 @@ UWord8 apa_exec_fx( return 3; } /* get target length */ test(); test(); IF( EQ_16( ps->l_frm, 480 ) || EQ_16( ps->l_frm, 960 ) || EQ_16( ps->l_frm, 1920 ) ) { /* decomposite ps->l_frm into 15<<i, e.g. 480=15<<5 */ i = sub( 15 - 4, norm_s( ps->l_frm ) ); /* this only works for 20ms framing */ assert( ps->l_frm == shl( shr( ps->l_frm, i ), i ) ); // assert( i_mult2( sub( ps->scale, 100 ), add( ps->nFramesSinceSetScale, 1 ) ) == ( ps->scale - 100 ) * ( ps->nFramesSinceSetScale + 1 ) ); expScaling = L_shr_r( L_mult0( i_mult2( sub( ps->scale, 100 ), add( (Word16) ps->nFramesSinceSetScale, 1 ) ), 19661 /*15*(1<<2)/100.0 Q15*/ ), sub( 15 + 2, i ) ); } ELSE { /* decomposite ps->l_frm into 5<<i, e.g. 320=5<<6 */ i = sub( 15 - 3, norm_s( ps->l_frm ) ); /* this only works for 20ms framing */ assert( ps->l_frm == shl( shr( ps->l_frm, i ), i ) ); // assert( i_mult2( sub( ps->scale, 100 ), add( ps->nFramesSinceSetScale, 1 ) ) == ( ps->scale - 100 ) * ( ps->nFramesSinceSetScale + 1 ) ); expScaling = L_shr_r( L_mult0( i_mult2( sub( ps->scale, 100 ), add( (Word16) ps->nFramesSinceSetScale, 1 ) ), 13107 /*5*(1<<3)/100.0 Q15*/ ), sub( 15 + 3, i ) ); } actScaling = L_sub( ps->diffSinceSetScale, ps->l_frm ); l_frm_out_target = L_sub( expScaling, actScaling ); /* Wait until we have l_frm outputs samples */ /* (required to search for correlation in the past). */ /* If we don't have enough samples, simply copy input to output */ IF( LT_32( ps->l_buf_out, ps->l_frm ) ) { FOR( i = 0; i < ps->l_frm; i++ ) { a_out[i] = a_in[i]; move16(); } l_frm_out = ps->l_frm; move16(); } ELSE { Word16 *buf_out_ptr = &( ps->buf_out_fx[ps->l_buf_out - ps->l_frm] ); Word16 *frm_in_ptr = &( frm_in[ps->l_frm] ); /* fill input frame */ /* 1st input frame: previous output samples */ FOR( i = 0; i < ps->l_frm; i++ ) { frm_in[i] = buf_out_ptr[i]; move16(); } /* 2nd input frame: new input samples */ FOR( i = 0; i < ps->l_frm; i++ ) { frm_in_ptr[i] = a_in[i]; move16(); } /* no scaling */ IF( EQ_32( ps->scale, 100 ) ) { copy_frm_fx( ps, frm_in, a_out, &l_frm_out ); } /* shrink */ ELSE IF( LT_32( ps->scale, 100 ) ) { shrink_frm_fx( ps, frm_in, maxScaling, a_out, &l_frm_out ); } /* extend */ ELSE { extend_frm_fx( ps, frm_in, a_out, &l_frm_out ); } /* control the amount/frequency of scaling */ IF( NE_32( l_frm_out, ps->l_frm ) ) { test(); IF( NE_32( maxScaling, 0 ) && GT_32( abs_s( extract_l( L_sub( ps->l_frm, l_frm_out ) ) ), maxScaling ) ) { /* maxScaling exceeded -> discard scaled frame */ copy_frm_fx( ps, frm_in, a_out, &l_frm_out ); } ELSE IF( GT_32( L_abs( l_frm_out_target ), ps->l_frm ) ) /* ignore small difference */ { dl_copied = L_sub( l_frm_out_target, ps->l_frm ); dl_scaled = L_sub( l_frm_out_target, l_frm_out ); /* discard scaled frame if copied frame is closer to target length */ IF( LT_32( L_abs( dl_copied ), L_abs( dl_scaled ) ) ) { copy_frm_fx( ps, frm_in, a_out, &l_frm_out ); } } } } /* copy output to internal buffer */ /* avoid buffer overflow: */ /* discard old samples; always keep at least most recent l_frm samples */ IF( GT_32( L_add( ps->l_buf_out, l_frm_out ), ps->buf_out_capacity ) ) { Word16 *buf_out_ptr1 = ps->buf_out_fx; Word16 *buf_out_ptr2; l_rem = extract_l( L_sub( ps->l_frm, l_frm_out ) ); if ( l_rem < 0 ) { l_rem = 0; move16(); } buf_out_ptr2 = &( ps->buf_out_fx[ps->l_buf_out - l_rem] ); FOR( i = 0; i < l_rem; i++ ) { buf_out_ptr1[i] = buf_out_ptr2[i]; move16(); } ps->l_buf_out = l_rem; move16(); } /* append new output samples */ IF( GT_32( L_add( ps->l_buf_out, l_frm_out ), ps->buf_out_capacity ) ) { return 5; } { Word16 *buf_out_ptr = &( ps->buf_out_fx[ps->l_buf_out] ); FOR( i = 0; i < l_frm_out; i++ ) { buf_out_ptr[i] = a_out[i]; move16(); } } ps->l_buf_out = (UWord16) L_add( ps->l_buf_out, l_frm_out ); move16(); *l_out = l_frm_out; move16(); /* update time */ ps->l_in_total = UL_addNsD( ps->l_in_total, ps->l_frm ); move32(); test(); IF( LT_32( L_abs( ps->diffSinceSetScale ), L_sub( 0x7FFFFF, L_sub( l_frm_out, ps->l_frm ) ) ) && LT_64( ps->nFramesSinceSetScale, statsResetThreshold ) ) { ps->diffSinceSetScale = L_add( ps->diffSinceSetScale, L_sub( l_frm_out, ps->l_frm ) ); move32(); ps->nFramesSinceSetScale = UL_addNsD( ps->nFramesSinceSetScale, 1 ); move32(); } ELSE /* scale statistics down to avoid overflow */ { ps->diffSinceSetScale = L_shr( ps->diffSinceSetScale, (Word16) statsResetShift ); move32(); ps->nFramesSinceSetScale = UL_lshr( ps->nFramesSinceSetScale, (Word16) statsResetShift ); move32(); } return 0; } UWord8 apa_exec_ivas_fx( apa_state_t *ps, /* i/o: state struct */ const Word16 a_in[], /* i : input samples */ UWord16 l_in, /* i : number of input samples */ UWord16 maxScaling, /* i : allowed number of inserted/removed samples */ Word16 a_out[], /* o : output samples */ UWord16 *l_out /* o : number of output samples */ ) { UWord16 i; Word16 frm_in[APA_BUF]; /* TODO(mcjbm): this buffer could be smaller - always allocates space for 16 channels */ UWord16 l_frm_out; Word16 l_rem; Word32 dl_scaled, dl_copied, l_frm_out_target; Word32 expScaling, actScaling; UWord32 statsResetThreshold, statsResetShift; statsResetThreshold = 1637; move32(); statsResetShift = 2; move32(); /* Convert max_scaling from "per channel" to total */ maxScaling = (UWord16) imult3216( maxScaling, ps->num_channels ); /* make sure no invalid output is used */ *l_out = 0; move16(); l_frm_out = 0; move16(); /* make sure pointer is valid */ IF( ps == NULL ) { return 1; } /* check available rate */ IF( ps->rate == 0 ) { return 2; } /* check size of input */ IF( NE_32( l_in, ps->l_frm ) ) { return 3; } /* get target length */ test(); test(); Loading Loading @@ -1231,6 +1436,7 @@ UWord8 apa_exec_fx( return 0; } #else uint8_t apa_exec( apa_state_t *ps, /* i/o: state struct */ Loading
lib_dec/jbm_pcmdsp_apa.h +1 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,7 @@ bool apa_set_quality( apa_state_t *s, float quality, uint16_t qualityred, uint16 bool apa_exit( apa_state_t **s ); uint8_t apa_exec( apa_state_t *s, const float a_in[], uint16_t l_in, uint16_t maxScaling, float a_out[], uint16_t *l_out ); uint8_t apa_exec_ivas_fx( apa_state_t *s, const Word16 a_in[], uint16_t l_in, uint16_t maxScaling, Word16 a_out[], uint16_t *l_out ); uint8_t apa_exec_fx( apa_state_t *s, const Word16 a_in[], uint16_t l_in, uint16_t maxScaling, Word16 a_out[], uint16_t *l_out ); #endif /* JBM_PCMDSP_APA_H */
lib_dec/lib_dec_fx.c +26 −10 Original line number Diff line number Diff line Loading @@ -1088,21 +1088,37 @@ ivas_error IVAS_DEC_GetSamples( // tmp apaExecBuffer Word16 tmp_apaExecBuffer[APA_BUF]; IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) ) { for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q12 ) ); tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q11 ) ); } IF( apa_exec_fx( hIvasDec->hTimeScaler, tmp_apaExecBuffer, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, tmp_apaExecBuffer, &nTimeScalerOutSamples ) != 0 ) { return IVAS_ERR_UNKNOWN; } for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { hIvasDec->apaExecBuffer_fx[i] = L_shl( tmp_apaExecBuffer[i], Q11 ); } } ELSE { for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q12 ) ); } IF( apa_exec_ivas_fx( hIvasDec->hTimeScaler, tmp_apaExecBuffer, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, tmp_apaExecBuffer, &nTimeScalerOutSamples ) != 0 ) { return IVAS_ERR_UNKNOWN; } for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { hIvasDec->apaExecBuffer_fx[i] = L_shl( tmp_apaExecBuffer[i], Q12 ); } } assert( LE_32( (Word32) nTimeScalerOutSamples, APA_BUF ) ); nSamplesTcsScaled = idiv1616( extract_l( nTimeScalerOutSamples ), nTransportChannels ); } Loading