diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index b140ca71260bb31882a62854cd73a0650253047e..41ffda19f3e461c6c90339092008762fc8dff3c9 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -192,8 +192,13 @@ typedef enum #define JBM_CLDFB_SLOTS_IN_SUBFRAME_LOG2 2 /* To be used for shift operation instead of division */ #define MAX_JBM_CLDFB_TIMESLOTS 32 #define DEFAULT_JBM_CLDFB_TIMESLOTS 16 +#ifdef JBM_MEMORY_OPT +#define MAX_JBM_L_FRAME48k ( IVAS_MAX_FRAME_SIZE * 2 ) /* 1920: max. time-scaled frame buffer length (per channel) in samples */ +#define MAX_JBM_L_FRAME_NS 40000000L /* 40 ms: time-scaled frame size in ns, proportional to MAX_JBM_L_FRAME48k */ +#else #define MAX_JBM_L_FRAME48k 1920 #define MAX_JBM_L_FRAME_NS 40000000L +#endif #define MAX_SPAR_INTERNAL_CHANNELS IVAS_SPAR_MAX_CH #define MAX_CLDFB_DIGEST_CHANNELS 3 /* == maximum of ParamISM TCs and ParamMC TCs */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 10b6348f260a8a9ab268525d3f3e29601312729c..546f824a71120ec61bf4ced4c368de3e4f69dc5a 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -211,19 +211,6 @@ Word32 calculate_cpe_brate_MASA_ISM_fx( const Word16 nchan_ism /* i : number of objects */ ); -Word16 ivas_jbm_dec_get_num_tc_channels_fx( - Decoder_Struct *st_ivas /* i : IVAS decoder handle */ -); - -ivas_error ivas_jbm_dec_tc_buffer_open_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ - const Word16 nchan_transport_jbm, /* i : number of real transport channels */ - const Word16 nchan_transport_internal, /* i : number of totally buffered channels */ - const Word16 nchan_full, /* i : number of channels to fully store */ - const Word16 n_samples_granularity /* i : granularity of the renderer/buffer */ -); - void ivas_dct_windowing_fx( const Word16 fade_len, /*Q0*/ const Word16 full_len, /*Q0*/ @@ -939,15 +926,6 @@ void update_last_metadata_fx( const Word16 updt_flag[] /* i : last metadata update flag */ ); -ivas_error ivas_jbm_dec_tc_buffer_reconfigure_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const TC_BUFFER_MODE tc_buffer_mode, /* i : new buffer mode */ - const Word16 nchan_transport_jbm, /* i : new number of real transport channels */ - const Word16 nchan_transport_internal, /* i : new number of totally buffered channels */ - const Word16 nchan_full, /* i : new number of channels to fully store */ - const Word16 n_samples_granularity /* i : new granularity of the renderer/buffer */ -); - ivas_error ivas_dirac_allocate_parameters_fx( SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common data for spatial parametric rendering*/ const Word16 params_flag /* i : set of parameters flag */ @@ -991,12 +969,6 @@ Word16 IGF_MapBitRateToIndex( const Word16 rf_mode /* i : flag to signal the RF mode */ ); -Word16 ivas_jbm_dec_get_render_granularity_fx( - const RENDERER_TYPE renderer_type, /* i : renderer type */ - const RENDERER_TYPE renderer_type_sec, /* i : secondary renderer type */ - const int32_t output_Fs /* i : sampling rate */ -); - void stereo_dft_config_fx( STEREO_DFT_CONFIG_DATA_HANDLE hConfig, /* o : DFT stereo configuration */ const Word32 brate, /* i : IVAS/CPE/nominal total bitrate */ @@ -1078,12 +1050,6 @@ void ivas_ism_render_sf_fx( const Word16 n_samples_to_render /* i : output frame length per channel */ ); -void ivas_jbm_dec_get_adapted_linear_interpolator_fx( - const Word16 default_interp_length, /* i : default length of the (full-frame) interpolator */ - const Word16 interp_length, /* i : length of the interpolator to be created */ - Word16 *interpolator_fx /* o : the interpolator */ -); - void ivas_omasa_separate_object_render_jbm_fx( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const UWord16 nSamplesRendered, /* i : number of samples rendered */ @@ -2118,6 +2084,22 @@ UWord32 ivas_syn_output_fx( Word16 *synth_out /* o : integer 16 bits synthesis signal */ ); +#ifdef JBM_MEMORY_OPT +void ivas_buffer_interleaved_to_deinterleaved_fx( + Word32 *audio, /* i/o: audio buffer */ + const Word16 n_channels, /* i : number of channels */ + const Word16 frame_length, /* i : frame length (one channel) */ + const Word16 n_samp_full /* i : full frame length (one channel) */ +); + +void ivas_buffer_deinterleaved_to_interleaved_fx( + Word32 *audio[], /* i : deinterleaved audio buffer */ + const Word16 n_channels, /* i : number of channels */ + const Word16 frame_length, /* i : frame length (one channel) */ + Word32 *audio_out /* o : interleaved audio buffer */ +); + +#endif void stereo_tcx_core_dec_fx( Decoder_State *st, /* i/o: decoder state structure */ const FRAME_MODE frameMode, /* i : Decoder frame mode */ @@ -2543,14 +2525,6 @@ void ivas_omasa_dirac_rend_jbm_fx( Word32 *output_fx[] /* o : rendered time signal */ ); -ivas_error ivas_jbm_dec_render_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const UWord16 nSamplesAsked, /* i : number of samples wanted */ - UWord16 *nSamplesRendered, /* o : number of samples rendered */ - UWord16 *nSamplesAvailableNext, /* o : number of samples still available in the rendering pipeline */ - Word16 *data /* o : output synthesis signal */ -); - void ivas_sba_zero_vert_comp_fx( Word32 *sba_data[], /* i : SBA signals */ const Word16 sba_order, /* i : SBA order */ @@ -4036,13 +4010,14 @@ void inverseMS_fx( const Word32 norm_fac /* i : normalization factor Q31*/ ); +#ifndef JBM_MEMORY_OPT void ivas_syn_output_f_fx( Word32 *synth[], /* i/o: Word32 synthesis signal */ const Word16 output_frame, /* i : output frame length (one channel) */ const Word16 n_channels, /* i : number of output channels */ Word32 *synth_out /* o : integer 16 bits synthesis signal */ ); - +#endif ivas_error ivas_init_encoder_fx( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ); @@ -4194,56 +4169,6 @@ Word64 var_32_fx( Word16 q /* q : q-factor for the array */ ); -ivas_error ivas_jbm_dec_tc_fx( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -); - -ivas_error ivas_jbm_dec_flush_renderer_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const Word16 tc_granularity_new, /* i : new renderer granularity */ - const RENDERER_TYPE renderer_type_old, /* i : old renderer type */ - const AUDIO_CONFIG intern_config_old, /* i : old internal config */ - const IVAS_OUTPUT_SETUP_HANDLE hIntSetupOld, /* i : old internal output setup */ - const MC_MODE mc_mode_old, /* i : old MC mode */ - const ISM_MODE ism_mode_old, /* i : old ISM mode */ - UWord16 *nSamplesRendered, /* o : number of samples flushed */ - Word16 *data /* o : output synthesis signal */ -); - -void ivas_jbm_dec_feed_tc_to_renderer_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const Word16 nSamplesForRendering, /* i : number of TC samples available for rendering */ - Word16 *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ - Word32 *data_fx /* i/o: transport channels/output synthesis signal */ -); - -void ivas_dec_prepare_renderer_fx( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -); - -void ivas_jbm_dec_get_adapted_subframes( - const Word16 nCldfbTs, /* i : number of time slots in the current frame */ - Word16 *subframe_nbslots, /* i/o: subframe grid */ - Word16 *nb_subframes /* i/o: number of subframes in the frame */ -); - -void ivas_jbm_dec_get_md_map( - const Word16 default_len, /* i : default frame length in metadata slots */ - const Word16 len, /* i : length of the modfied frames in metadata slots */ - const Word16 subframe_len, /* i : default length of a subframe */ - const Word16 offset, /* i : current read offset into the md buffer */ - const Word16 buf_len, /* i : length of the metadata buffer */ - Word16 *map /* o : metadata index map */ -); - -void ivas_jbm_dec_get_md_map_even_spacing( - const Word16 len, /* i : length of the modfied frames in metadata slots */ - const Word16 subframe_len, /* i : default length of a subframe */ - const Word16 offset, /* i : current read offset into the md buffer */ - const Word16 buf_len, /* i : length of the metadata buffer */ - Word16 *map /* o : metadata index map */ -); - void bitbudget_to_brate( const Word16 x[], /* i : bitbudgets */ Word32 y[], /* o : bitrates */ @@ -6232,28 +6157,123 @@ Word16 is_DTXrate( * JBM prototypes *----------------------------------------------------------------------------------*/ +ivas_error ivas_jbm_dec_tc_fx( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + +ivas_error ivas_jbm_dec_render_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const UWord16 nSamplesAsked, /* i : number of samples wanted */ + UWord16 *nSamplesRendered, /* o : number of samples rendered */ + UWord16 *nSamplesAvailableNext, /* o : number of samples still available in the rendering pipeline */ + Word16 *data /* o : output synthesis signal */ +); + +ivas_error ivas_jbm_dec_flush_renderer_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 tc_granularity_new, /* i : new renderer granularity */ + const RENDERER_TYPE renderer_type_old, /* i : old renderer type */ + const AUDIO_CONFIG intern_config_old, /* i : old internal config */ + const IVAS_OUTPUT_SETUP_HANDLE hIntSetupOld, /* i : old internal output setup */ + const MC_MODE mc_mode_old, /* i : old MC mode */ + const ISM_MODE ism_mode_old, /* i : old ISM mode */ + UWord16 *nSamplesRendered, /* o : number of samples flushed */ + Word16 *data /* o : output synthesis signal */ +); + +void ivas_jbm_dec_feed_tc_to_renderer_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 nSamplesForRendering, /* i : number of TC samples available for rendering */ + Word16 *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ +#ifndef JBM_MEMORY_OPT + , + Word32 *data_fx /* i/o: transport channels/output synthesis signal */ +#endif +); + +void ivas_dec_prepare_renderer_fx( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + ivas_error ivas_jbm_dec_set_discard_samples_fx( - Decoder_Struct *st_ivas /* i/o: main IVAS decoder structre */ + Decoder_Struct *st_ivas /* i/o: main IVAS decoder structre */ +); + +void ivas_jbm_dec_get_adapted_linear_interpolator_fx( + const Word16 default_interp_length, /* i : default length of the (full-frame) interpolator */ + const Word16 interp_length, /* i : length of the interpolator to be created */ + Word16 *interpolator_fx /* o : the interpolator */ +); + +void ivas_jbm_dec_get_adapted_subframes( + const Word16 nCldfbTs, /* i : number of time slots in the current frame */ + Word16 *subframe_nbslots, /* i/o: subframe grid */ + Word16 *nb_subframes /* i/o: number of subframes in the frame */ +); + +void ivas_jbm_dec_get_md_map( + const Word16 default_len, /* i : default frame length in metadata slots */ + const Word16 len, /* i : length of the modfied frames in metadata slots */ + const Word16 subframe_len, /* i : default length of a subframe */ + const Word16 offset, /* i : current read offset into the md buffer */ + const Word16 buf_len, /* i : length of the metadata buffer */ + Word16 *map /* o : metadata index map */ +); + +Word16 ivas_jbm_dec_get_num_tc_channels_fx( + Decoder_Struct *st_ivas /* i : IVAS decoder handle */ +); + +void ivas_jbm_dec_get_md_map_even_spacing( + const Word16 len, /* i : length of the modfied frames in metadata slots */ + const Word16 subframe_len, /* i : default length of a subframe */ + const Word16 offset, /* i : current read offset into the md buffer */ + const Word16 buf_len, /* i : length of the metadata buffer */ + Word16 *map /* o : metadata index map */ ); TC_BUFFER_MODE ivas_jbm_dec_get_tc_buffer_mode_fx( - Decoder_Struct *st_ivas /* i : IVAS decoder handle */ + Decoder_Struct *st_ivas /* i : IVAS decoder handle */ +); + +Word16 ivas_jbm_dec_get_render_granularity_fx( + const RENDERER_TYPE renderer_type, /* i : renderer type */ + const RENDERER_TYPE renderer_type_sec, /* i : secondary renderer type */ + const int32_t output_Fs /* i : sampling rate */ +); + +ivas_error ivas_jbm_dec_tc_buffer_open_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ + const Word16 nchan_transport_jbm, /* i : number of real transport channels */ + const Word16 nchan_transport_internal, /* i : number of totally buffered channels */ + const Word16 nchan_full, /* i : number of channels to fully store */ + const Word16 n_samples_granularity /* i : granularity of the renderer/buffer */ +); + +ivas_error ivas_jbm_dec_tc_buffer_reconfigure_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : new buffer mode */ + const Word16 nchan_transport_jbm, /* i : new number of real transport channels */ + const Word16 nchan_transport_internal, /* i : new number of totally buffered channels */ + const Word16 nchan_full, /* i : new number of channels to fully store */ + const Word16 n_samples_granularity /* i : new granularity of the renderer/buffer */ ); void ivas_jbm_dec_tc_buffer_close_fx( - DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ + DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ ); void ivas_jbm_dec_td_renderers_adapt_subframes( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); ivas_error ivas_jbm_dec_metadata_open( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); void ivas_jbm_masa_sf_to_sf_map( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); diff --git a/lib_com/ivas_tools_fx.c b/lib_com/ivas_tools_fx.c index 46067d828c93467479e6b71edf697f4f246736ec..dc5c3b4e20429a90e2a4008c42e9af70fb88a79f 100644 --- a/lib_com/ivas_tools_fx.c +++ b/lib_com/ivas_tools_fx.c @@ -149,6 +149,73 @@ UWord32 ivas_syn_output_fx( return noClipping; /*Q0*/ } +#ifdef JBM_MEMORY_OPT + +/*-------------------------------------------------------------------* + * ivas_buffer_interleaved_to_deinterleaved() + * + * Convert an interleaved buffer of audio channels to deinterleaved one + *-------------------------------------------------------------------*/ + +void ivas_buffer_interleaved_to_deinterleaved_fx( + Word32 *audio, /* i/o: audio buffer */ + const Word16 n_channels, /* i : number of channels */ + const Word16 frame_length, /* i : frame length (one channel) */ + const Word16 n_samp_full /* i : full frame length (one channel) */ +) +{ + Word16 offset, ch, m; + Word32 buffer[MAX_TRANSPORT_CHANNELS][MAX_JBM_L_FRAME48k]; + + FOR( ch = 0; ch < n_channels; ch++ ) + { + FOR( m = 0; m < frame_length; m++ ) + { + buffer[ch][m] = audio[m * n_channels + ch]; + move32(); + } + } + + offset = 0; + move16(); + FOR( ch = 0; ch < n_channels; ch++ ) + { + Copy32( buffer[ch], audio + offset, frame_length ); + offset = add( offset, n_samp_full ); + } + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_buffer_deinterleaved_to_interleaved() + * + * Convert a deinterleaved buffer of audio channels to interleaved one + *-------------------------------------------------------------------*/ + +void ivas_buffer_deinterleaved_to_interleaved_fx( + Word32 *audio[], /* i/o: deinterleaved audio buffer */ + const Word16 n_channels, /* i : number of channels */ + const Word16 frame_length, /* i : frame length (one channel) */ + Word32 *audio_out /* o : interleaved audio buffer */ +) +{ + Word16 ch, m; + + FOR( ch = 0; ch < n_channels; ch++ ) + { + FOR( m = 0; m < frame_length; m++ ) + { + audio_out[m * n_channels + ch] = audio[ch][m]; + move32(); + } + } + + return; +} + +#else /*-------------------------------------------------------------------* * ivas_syn_output_f() @@ -183,6 +250,7 @@ void ivas_syn_output_f_fx( return; } +#endif /*-------------------------------------------------------------------* * mvr2r_inc() diff --git a/lib_com/options.h b/lib_com/options.h index c164c192e44d66bd3ad3a4872a83bb760a482b1a..be4d83b0519d523ecc2822c6db6cf2a292d7acd5 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -110,10 +110,12 @@ #define FIX_1288_SPLIT_REND_XSAN /* Dlb: Fix asan, msan and usan issues in split rendering mode*/ #define FIX_NCHAN_BUFFERS /* VA: issue 1322: Correct the number of float buffers (channels) at the decoder */ #define FIX_RENDERER_STACK /* VA: issue 1322: reduction of renderers' buffers size */ +#define JBM_MEMORY_OPT /* VA: issue 916: optimization of RAM in the JBM decoder */ #define FIX_1370_EXTERNAL_ORIENTATION_CHECK /* Nokia: add sanity check for Euler angles for external orientations */ #define FIX_1413_IGF_INIT_PRINTOUT /* FhG: use correct variable for IGF initiliazation */ #define CODE_IMPROVEMENTS + // object-editing feature porting #define TMP_FIX_SPLIT_REND // temporary fix to split-rendering (it follows the later state of the framework but it is needed now because of current test-conditions) #define TMP_FIX_OMASA_SR_BE // temporary fix to keep OMASA split-rendering BE diff --git a/lib_dec/ivas_init_dec_fx.c b/lib_dec/ivas_init_dec_fx.c index 39b41c1998a9909d26785f62c7e8e208748143e8..5cf6a86e16e1d630b6b8448ebb42e182818309f8 100644 --- a/lib_dec/ivas_init_dec_fx.c +++ b/lib_dec/ivas_init_dec_fx.c @@ -3395,12 +3395,14 @@ void ivas_destroy_dec_fx( /* Limiter struct */ ivas_limiter_close_fx( &( st_ivas->hLimiter ) ); + /* Decoder configuration structure */ IF( st_ivas->hDecoderConfig != NULL ) { free( st_ivas->hDecoderConfig ); st_ivas->hDecoderConfig = NULL; } + /* JBM TC buffer structure */ ivas_jbm_dec_tc_buffer_close_fx( &st_ivas->hTcBuffer ); IF( st_ivas->hJbmMetadata != NULL ) @@ -3409,7 +3411,7 @@ void ivas_destroy_dec_fx( st_ivas->hJbmMetadata = NULL; } - /* output audio buffers */ + /* output audio buffers */ FOR( i = 0; i < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; i++ ) { IF( st_ivas->p_output_fx[i] != NULL ) diff --git a/lib_dec/ivas_jbm_dec_fx.c b/lib_dec/ivas_jbm_dec_fx.c index eb264fa718757e7b2740b134a69eb6982021d827..efd212eda05e09f0057c3bb4a2ebc49c0b465b5f 100644 --- a/lib_dec/ivas_jbm_dec_fx.c +++ b/lib_dec/ivas_jbm_dec_fx.c @@ -1518,12 +1518,20 @@ ivas_error ivas_jbm_dec_tc_fx( void ivas_jbm_dec_feed_tc_to_renderer_fx( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const Word16 nSamplesForRendering, /* i : number of TC samples available for rendering */ - Word16 *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ - Word32 *data /* i : transport channels */ + Word16 *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ +#ifndef JBM_MEMORY_OPT + , + Word32 *data /* i : transport channels */ +#endif ) { +#ifdef JBM_MEMORY_OPT + Word32 tmp_buf_fx[MAX_JBM_L_FRAME48k]; + Word32 *p_data_fx[FOA_CHANNELS + MAX_NUM_OBJECTS]; +#else Word32 data_fx[MAX_CLDFB_DIGEST_CHANNELS][MAX_JBM_L_FRAME48k]; /* buffer for transport channels that will be directly converted with the CLDFB */ Word32 *p_data_fx[MAX_CLDFB_DIGEST_CHANNELS]; +#endif Word16 n, n_render_timeslots, n_ch_cldfb; Word16 ch; DECODER_TC_BUFFER_HANDLE hTcBuffer; @@ -1537,6 +1545,41 @@ void ivas_jbm_dec_feed_tc_to_renderer_fx( IF( st_ivas->hDecoderConfig->Opt_tsm ) { +#ifdef JBM_MEMORY_OPT + Word16 n_samples_still_available; + Word16 n_ch_full_copy, n_ch_res_copy; + + n_samples_still_available = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_rendered ); + hTcBuffer->n_samples_buffered = add( add( n_samples_still_available, nSamplesForRendering ), hTcBuffer->n_samples_discard ); + hTcBuffer->n_samples_available = i_mult( hTcBuffer->n_samples_granularity, idiv1616( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_granularity ) ); + *nSamplesResidual = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_available ); + move16(); + move16(); + move16(); + n_ch_full_copy = s_min( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); + n_ch_res_copy = sub( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); + + FOR( ch = 0; ch < n_ch_full_copy; ch++ ) + { + Copy32( hTcBuffer->tc_fx[ch], tmp_buf_fx, nSamplesForRendering ); + set_zero_fx( hTcBuffer->tc_fx[ch], hTcBuffer->n_samples_discard ); + Copy32( hTcBuffer->tc_buffer_old_fx[ch], hTcBuffer->tc_fx[ch] + hTcBuffer->n_samples_discard, n_samples_still_available ); + Copy32( tmp_buf_fx, hTcBuffer->tc_fx[ch] + n_samples_still_available + hTcBuffer->n_samples_discard, nSamplesForRendering - *nSamplesResidual ); + Copy32( tmp_buf_fx + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old_fx[ch], *nSamplesResidual ); + } + + IF( n_ch_res_copy > 0 ) + { + FOR( ; ch < hTcBuffer->nchan_transport_jbm; ch++ ) + { + p_data_fx[ch] = hTcBuffer->tc_fx[ch]; + Copy32( hTcBuffer->tc_fx[ch], tmp_buf_fx, nSamplesForRendering ); + Copy32( hTcBuffer->tc_buffer_old_fx[ch], p_data_fx[ch], n_samples_still_available ); + Copy32( tmp_buf_fx, p_data_fx[ch] + n_samples_still_available, sub( nSamplesForRendering, *nSamplesResidual ) ); + Copy32( tmp_buf_fx + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old_fx[ch], *nSamplesResidual ); + } + } +#else Word16 n_samples_still_available, m; Word16 n_ch_full_copy; Word16 n_ch_res_copy; @@ -1581,6 +1624,7 @@ void ivas_jbm_dec_feed_tc_to_renderer_fx( Copy32( p_data_fx[ch] + hTcBuffer->n_samples_available, hTcBuffer->tc_fx[ch], *nSamplesResidual ); } } +#endif n_render_timeslots = idiv1616( st_ivas->hTcBuffer->n_samples_available, st_ivas->hTcBuffer->n_samples_granularity ); } @@ -1593,7 +1637,11 @@ void ivas_jbm_dec_feed_tc_to_renderer_fx( } #ifdef FIX_NCHAN_BUFFERS +#ifdef JBM_MEMORY_OPT + ch = s_max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); +#else ch = ivas_get_nchan_buffers_dec_fx( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ); +#endif FOR( n = 0; n < ch; n++ ) #else FOR( n = 0; n < ivas_get_nchan_buffers_dec_fx( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ); n++ ) @@ -1690,7 +1738,11 @@ ivas_error ivas_jbm_dec_render_fx( IF( !st_ivas->hDecoderConfig->Opt_tsm ) { +#ifdef JBM_MEMORY_OPT + FOR( n = 0; n < MAX_INTERN_CHANNELS; n++ ) +#else FOR( n = 0; n < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; n++ ) +#endif { st_ivas->hTcBuffer->tc_fx[n] = st_ivas->p_output_fx[n]; } @@ -2491,6 +2543,15 @@ ivas_error ivas_jbm_dec_flush_renderer_fx( { Word16 ch_idx; +#ifdef JBM_MEMORY_OPT + /* render available full slots (with new lower granularity) */ + FOR( ch_idx = 0; ch_idx < s_max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); ch_idx++ ) + { + /* move it at the beginning of the TC buffer with zero padding */ + Copy32( hTcBuffer->tc_buffer_old_fx[ch_idx], hTcBuffer->tc_fx[ch_idx], n_samples_to_render ); + set_zero_fx( hTcBuffer->tc_fx[ch_idx] + n_samples_to_render, hTcBuffer->n_samples_granularity - n_samples_to_render ); + } +#else /* render what is still there with zero padding */ FOR( ch_idx = 0; ch_idx < hTcBuffer->nchan_buffer_full; ch_idx++ ) { @@ -2499,6 +2560,8 @@ ivas_error ivas_jbm_dec_flush_renderer_fx( set_zero_fx( hTcBuffer->tc_fx[ch_idx] + n_samples_to_render, hTcBuffer->n_samples_granularity - n_samples_to_render ); Copy32( hTcBuffer->tc_fx[ch_idx] + hTcBuffer->n_samples_rendered + n_samples_to_render, hTcBuffer->tc_fx[ch_idx] + hTcBuffer->n_samples_granularity, n_samples_still_available ); } +#endif + /* simple change of the slot info */ hTcBuffer->num_slots = 1; hTcBuffer->nb_subframes = 1; @@ -3277,6 +3340,129 @@ Word16 ivas_jbm_dec_get_render_granularity_fx( return render_granularity; } +#ifdef JBM_MEMORY_OPT + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_tc_audio_allocate() + * + * allocate and initialize TC audio buffer + *--------------------------------------------------------------------------*/ + +static ivas_error ivas_jbm_dec_tc_audio_allocate_fx( + DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: JBM TSM buffer handle */ + const int32_t output_Fs, /* i : output sampling rate */ + const int16_t Opt_tsm /* i : TSM option flag */ +) +{ + Word16 nsamp_to_allocate; + Word16 ch_idx, n_samp_full, n_samp_residual, offset; + + IF( Opt_tsm ) + { + n_samp_full = NS2SA_FX2( output_Fs, MAX_JBM_L_FRAME_NS ); + n_samp_residual = add( hTcBuffer->n_samples_granularity, 1 ); + } + ELSE + { + n_samp_full = extract_l( Mpy_32_32( output_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ); + n_samp_residual = 0; + move16(); + } + + nsamp_to_allocate = s_max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ) * n_samp_full; + + IF( Opt_tsm ) + { + /* note: this is stack memory buffer for time-scale modified audio signals */ + IF( ( hTcBuffer->tc_buffer_fx = (Word32 *) malloc( nsamp_to_allocate * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); + } + set_zero_fx( hTcBuffer->tc_buffer_fx, nsamp_to_allocate ); + + offset = 0; + move16(); + FOR( ch_idx = 0; ch_idx < max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = &hTcBuffer->tc_buffer_fx[offset]; + offset = add( offset, n_samp_full ); + } + FOR( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } + + /* memory buffer for TC audio samples not rendered in the previous frame */ + FOR( ch_idx = 0; ch_idx < hTcBuffer->nchan_transport_internal; ch_idx++ ) + { + IF( ( hTcBuffer->tc_buffer_old_fx[ch_idx] = (Word32 *) malloc( n_samp_residual * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); + } + set_zero_fx( hTcBuffer->tc_buffer_old_fx[ch_idx], n_samp_residual ); + } + FOR( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_buffer_old_fx[ch_idx] = NULL; + } + } + else + { + hTcBuffer->tc_buffer_fx = NULL; + + FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } + + FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_buffer_old_fx[ch_idx] = NULL; + } + } + + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_tc_audio_deallocate() + * + * deallocate TC audio buffer + *--------------------------------------------------------------------------*/ + +static void ivas_jbm_dec_tc_audio_deallocate_fx( + DECODER_TC_BUFFER_HANDLE hTcBuffer /* i/o: JBM TSM buffer handle */ +) +{ + Word16 ch_idx; + + IF( hTcBuffer != NULL ) + { + IF( hTcBuffer->tc_buffer_fx != NULL ) + { + FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } + + free( hTcBuffer->tc_buffer_fx ); + hTcBuffer->tc_buffer_fx = NULL; + } + + FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + IF( hTcBuffer->tc_buffer_old_fx[ch_idx] != NULL ) + { + free( hTcBuffer->tc_buffer_old_fx[ch_idx] ); + hTcBuffer->tc_buffer_old_fx[ch_idx] = NULL; + } + } + } + + return; +} +#endif /*--------------------------------------------------------------------------* * ivas_jbm_dec_tc_buffer_open() @@ -3294,11 +3480,17 @@ ivas_error ivas_jbm_dec_tc_buffer_open_fx( const Word16 n_samples_granularity /* i : granularity of the renderer/buffer */ ) { +#ifndef JBM_MEMORY_OPT Word16 nsamp_to_allocate; +#endif DECODER_TC_BUFFER_HANDLE hTcBuffer; Word16 nMaxSlotsPerSubframe; +#ifdef JBM_MEMORY_OPT + ivas_error error; +#else Word16 nchan_residual; Word16 ch_idx; +#endif Word16 tmp, tmp_e; Word32 tmp32; @@ -3319,7 +3511,9 @@ ivas_error ivas_jbm_dec_tc_buffer_open_fx( move16(); hTcBuffer->nchan_buffer_full = nchan_full; move16(); +#ifndef JBM_MEMORY_OPT nchan_residual = sub( nchan_transport_internal, nchan_full ); +#endif hTcBuffer->n_samples_granularity = n_samples_granularity; move16(); hTcBuffer->n_samples_available = 0; @@ -3338,8 +3532,10 @@ ivas_error ivas_jbm_dec_tc_buffer_open_fx( move16(); hTcBuffer->nb_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; move16(); +#ifndef JBM_MEMORY_OPT nsamp_to_allocate = 0; move16(); +#endif tmp32 = L_mult0( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, hTcBuffer->n_samples_granularity ); // Q0 tmp = BASOP_Util_Divide3232_Scale( st_ivas->hDecoderConfig->output_Fs, tmp32, &tmp_e ); @@ -3351,6 +3547,12 @@ ivas_error ivas_jbm_dec_tc_buffer_open_fx( set16_fx( hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); set16_fx( hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); +#ifdef JBM_MEMORY_OPT + IF( ( error = ivas_jbm_dec_tc_audio_allocate_fx( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) + { + return error; + } +#else { Word16 n_samp_full, n_samp_residual; Word32 offset; @@ -3413,6 +3615,7 @@ ivas_error ivas_jbm_dec_tc_buffer_open_fx( } } } +#endif st_ivas->hTcBuffer = hTcBuffer; @@ -3435,8 +3638,12 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure_fx( const Word16 n_samples_granularity /* i : new granularity of the renderer/buffer */ ) { +#ifdef JBM_MEMORY_OPT + ivas_error error; +#else Word16 nsamp_to_allocate, n_samp_full, n_samp_residual, offset, nchan_residual; Word16 ch_idx; +#endif DECODER_TC_BUFFER_HANDLE hTcBuffer; hTcBuffer = st_ivas->hTcBuffer; @@ -3472,10 +3679,22 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure_fx( move16(); hTcBuffer->nchan_buffer_full = nchan_full; move16(); +#ifndef JBM_MEMORY_OPT nchan_residual = sub( nchan_transport_internal, nchan_full ); +#endif hTcBuffer->n_samples_granularity = n_samples_granularity; move16(); +#ifdef JBM_MEMORY_OPT + /* reallocate TC audio buffers */ + + ivas_jbm_dec_tc_audio_deallocate_fx( hTcBuffer ); + + IF( ( error = ivas_jbm_dec_tc_audio_allocate_fx( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) + { + return error; + } +#else /* realloc buffers */ IF( hTcBuffer->tc_buffer_fx != NULL ) { @@ -3538,6 +3757,7 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure_fx( hTcBuffer->tc_buffer_fx = NULL; } } +#endif return IVAS_ERR_OK; } @@ -3605,10 +3825,15 @@ void ivas_jbm_dec_tc_buffer_close_fx( DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ ) { +#ifndef JBM_MEMORY_OPT Word16 i; - +#endif IF( *phTcBuffer != NULL ) { +#ifdef JBM_MEMORY_OPT + ivas_jbm_dec_tc_audio_deallocate_fx( *phTcBuffer ); +#else + FOR( i = 0; i < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; i++ ) { ( *phTcBuffer )->tc_fx[i] = NULL; @@ -3619,6 +3844,7 @@ void ivas_jbm_dec_tc_buffer_close_fx( free( ( *phTcBuffer )->tc_buffer_fx ); ( *phTcBuffer )->tc_buffer_fx = NULL; } +#endif free( *phTcBuffer ); *phTcBuffer = NULL; diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 289b91b775581bc1cc10616ad2cffb519a31b3f1..cf8017fb5d87b73d48078b9d78e9d18efe48daf0 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -1005,9 +1005,16 @@ typedef struct ivas_masa_ism_data_structure typedef struct decoder_tc_buffer_structure { - Word32 *tc_buffer_fx; /* the buffer itself */ /*stores memory length of tc buffer*/ - Word32 *tc_fx[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; /* pointers into the buffer to the beginning of each tc Q11 for ivas */ - Word16 no_channels; /*Stores no of channels in tc_fx with values*/ +#ifdef JBM_MEMORY_OPT + Word32 *tc_buffer_old_fx[MAX_INTERN_CHANNELS]; /* TC audio samples not rendered in the previous frame */ +#endif + Word32 *tc_buffer_fx; /* the buffer itself */ +#ifdef JBM_MEMORY_OPT + Word32 *tc_fx[MAX_INTERN_CHANNELS]; /* pointers into the buffer to the beginning of each tc */ +#else + Word32 *tc_fx[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; /* pointers into the buffer to the beginning of each tc Q11 for ivas */ +#endif + Word16 no_channels; /*Stores no of channels in tc_fx with values*/ Word16 q_tc_fx; TC_BUFFER_MODE tc_buffer_mode; /* mode of the buffer (no buffering, render buffering, out buffering) */ Word16 nchan_transport_jbm; /* number of TCs after TC decoding */ diff --git a/lib_dec/jbm_pcmdsp_apa.h b/lib_dec/jbm_pcmdsp_apa.h index 70e31eb75e64612743ea50e72108d69c5cf92309..98dd104c270fac938feced5ac51495e2103eabf6 100644 --- a/lib_dec/jbm_pcmdsp_apa.h +++ b/lib_dec/jbm_pcmdsp_apa.h @@ -50,9 +50,14 @@ */ /* size of IO buffers (a_in[], a_out[]) for apa_exec() */ +#ifdef JBM_MEMORY_OPT +#define APA_BUF_PER_CHANNEL ( IVAS_MAX_FRAME_SIZE * 2 ) /* == twice the max. frame length */ +#define APA_MAX_NUM_CHANNELS ( 12 ) /* == MAX_TRANSPORT_CHANNELS */ +#else #define APA_BUF_PER_CHANNEL ( IVAS_MAX_FRAME_SIZE * 3 ) #define APA_MAX_NUM_CHANNELS 16 -#define APA_BUF ( APA_BUF_PER_CHANNEL * APA_MAX_NUM_CHANNELS ) +#endif +#define APA_BUF ( APA_BUF_PER_CHANNEL * APA_MAX_NUM_CHANNELS ) /* min/max sampling rate [Hz] */ #define APA_MIN_RATE 1000 diff --git a/lib_dec/jbm_pcmdsp_apa_fx.c b/lib_dec/jbm_pcmdsp_apa_fx.c index bf853c7c5ae8c4348dc98bb2bad401a94718a257..37e3f51a755bfa0c4faf5aaded471bfd3c6824b5 100644 --- a/lib_dec/jbm_pcmdsp_apa_fx.c +++ b/lib_dec/jbm_pcmdsp_apa_fx.c @@ -682,15 +682,19 @@ bool apa_exit( */ UWord8 apa_exec_fx( apa_state_t *ps, /* i/o: state struct */ - const Word16 a_in[], /* i : input samples Q0 */ + const Word16 a_in[], /* i : input samples Q0 */ UWord16 l_in, /* i : number of input samples */ UWord16 maxScaling, /* i : allowed number of inserted/removed samples */ - Word16 a_out[], /* o : output samples Q0*/ + Word16 a_out[], /* o : output samples Q0*/ UWord16 *l_out /* o : number of output samples */ ) { UWord16 i; +#ifdef JBM_MEMORY_OPT + Word16 frm_in[CPE_CHANNELS * APA_BUF / APA_MAX_NUM_CHANNELS]; /* in EVS, 2 output channels */ /* NOTE: this buffer could be smaller if alocated dynamically based on the actual sampling rate and number of channels */ +#else Word16 frm_in[APA_BUF]; /* TODO(mcjbm): this buffer could be smaller - always allocates space for 16 channels */ +#endif UWord16 l_frm_out; Word16 l_rem; Word32 dl_scaled, dl_copied, l_frm_out_target; @@ -898,15 +902,19 @@ UWord8 apa_exec_fx( UWord8 apa_exec_ivas_fx( apa_state_t *ps, /* i/o: state struct */ - const Word32 a_in[], /* i : input samples Q(-1) */ + const Word32 a_in[], /* i : input samples Q(-1) */ UWord16 l_in, /* i : number of input samples */ UWord16 maxScaling, /* i : allowed number of inserted/removed samples */ - Word32 a_out[], /* o : output samples Q(-1) */ + Word32 a_out[], /* o : output samples Q(-1) */ UWord16 *l_out /* o : number of output samples */ ) { UWord16 i; +#ifdef JBM_MEMORY_OPT + Word16 frm_in[APA_BUF]; /* NOTE: this buffer could be smaller if alocated dynamically based on the actual sampling rate and number of channels */ +#else Word16 frm_in[APA_BUF]; /* TODO(mcjbm): this buffer could be smaller - always allocates space for 16 channels */ +#endif UWord16 l_frm_out; Word16 l_rem; Word32 dl_scaled, dl_copied, l_frm_out_target; diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index 5034c914421c82f83965bd6cb51a8dcdb4e63c27..248b8846b4c01d1030f45ac64fd5e445878ad9cf 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -83,9 +83,11 @@ struct IVAS_DEC #endif Word16 tsm_scale; /* scale for TSM operation */ Word16 tsm_max_scaling; - Word16 timeScalingDone; /* have we done already one TSM in a 20ms frame? */ - Word16 tsm_quality; /*Q14*/ + Word16 timeScalingDone; /* have we done already one TSM in a 20ms frame? */ + Word16 tsm_quality; /*Q14*/ +#ifndef JBM_MEMORY_OPT Word32 *apaExecBuffer_fx; /* Buffer for APA scaling */ +#endif PCMDSP_APA_HANDLE hTimeScaler; bool needNewFrame; bool hasBeenFedFrame; @@ -156,7 +158,9 @@ ivas_error IVAS_DEC_Open( hIvasDec = *phIvasDec; hIvasDec->hVoIP = NULL; +#ifndef JBM_MEMORY_OPT hIvasDec->apaExecBuffer_fx = NULL; +#endif hIvasDec->hTimeScaler = NULL; hIvasDec->tsm_scale = 100; hIvasDec->tsm_max_scaling = 0; @@ -411,11 +415,12 @@ void IVAS_DEC_Close( apa_exit( &( *phIvasDec )->hTimeScaler ); +#ifndef JBM_MEMORY_OPT IF( ( *phIvasDec )->apaExecBuffer_fx != NULL ) { free( ( *phIvasDec )->apaExecBuffer_fx ); } - +#endif IF( ( *phIvasDec )->flushbuffer != NULL ) { free( ( *phIvasDec )->flushbuffer ); @@ -3342,6 +3347,53 @@ ivas_error IVAS_DEC_ReadFormat( return IVAS_ERR_OK; } +#ifdef JBM_MEMORY_OPT + +/*---------------------------------------------------------------------* + * apa_exec_evs_wrapper( ) + * + * + *---------------------------------------------------------------------*/ + +static ivas_error apa_exec_evs_wrapper( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const UWord8 nTransportChannels, + UWord16 *nTimeScalerOutSamples ) +{ + Word16 ch; + UWord16 apa_buff_len; + Word16 tmp_apaExecBuffer[CPE_CHANNELS * APA_BUF / APA_MAX_NUM_CHANNELS]; /* in EVS, 2 output channels */ + DECODER_TC_BUFFER_HANDLE hTcBuffer; + + test(); + test(); + IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hTcBuffer == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + apa_buff_len = (UWord16) shl( mult0( hIvasDec->nSamplesFrame, nTransportChannels ), 1 ); + + hTcBuffer = hIvasDec->st_ivas->hTcBuffer; + + FOR( ch = 0; ch < apa_buff_len; ++ch ) + { + tmp_apaExecBuffer[ch] = extract_l( L_shr( hTcBuffer->tc_buffer_fx[ch], Q11 ) ); // Q0 + } + + IF( apa_exec_fx( hIvasDec->hTimeScaler, tmp_apaExecBuffer, (UWord16) mult0( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, tmp_apaExecBuffer, nTimeScalerOutSamples ) != 0 ) + { + return IVAS_ERR_UNKNOWN; + } + + FOR( ch = 0; ch < apa_buff_len; ++ch ) + { + hTcBuffer->tc_buffer_fx[ch] = L_shl( tmp_apaExecBuffer[ch], Q11 ); // Q11 + } + + return IVAS_ERR_OK; +} +#endif /*---------------------------------------------------------------------* * IVAS_DEC_GetSamplesDecoder( ) @@ -3362,6 +3414,7 @@ ivas_error IVAS_DEC_GetSamplesDecoder( Word16 nResidualSamples, nSamplesTcsScaled; bool isInitialized_voip; + test(); IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) { return IVAS_ERR_UNEXPECTED_NULL_POINTER; @@ -3374,8 +3427,12 @@ ivas_error IVAS_DEC_GetSamplesDecoder( } st_ivas = hIvasDec->st_ivas; - +#ifdef JBM_MEMORY_OPT + test(); + isInitialized_voip = hIvasDec->hTimeScaler != NULL; +#else isInitialized_voip = hIvasDec->apaExecBuffer_fx != NULL; +#endif test(); IF( !hIvasDec->isInitialized || hIvasDec->hasBeenFedFrame ) /* wait for the first good frame */ @@ -3436,16 +3493,26 @@ ivas_error IVAS_DEC_GetSamplesDecoder( return IVAS_ERR_UNKNOWN; } +#ifdef JBM_MEMORY_OPT + /* convert deinterleaved decoded TC audio channels buffer to an interleaved one */ + ivas_buffer_deinterleaved_to_interleaved_fx( st_ivas->p_output_fx, nTransportChannels, hIvasDec->nSamplesFrame, st_ivas->hTcBuffer->tc_buffer_fx ); +#else ivas_syn_output_f_fx( st_ivas->p_output_fx, hIvasDec->nSamplesFrame, nTransportChannels, hIvasDec->apaExecBuffer_fx ); +#endif - - // tmp apaExecBuffer IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) ) { +#ifdef JBM_MEMORY_OPT + apa_exec_evs_wrapper( hIvasDec, nTransportChannels, &nTimeScalerOutSamples ); +#else Word16 tmp_apaExecBuffer[APA_BUF]; FOR( Word32 i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { +#ifdef JBM_MEMORY_OPT + tmp_apaExecBuffer[i] = extract_l( L_shr( st_ivas->hTcBuffer->tc_buffer_fx[i], Q11 ) ); // Q0 +#else tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q11 ) ); // Q0 +#endif } IF( apa_exec_fx( hIvasDec->hTimeScaler, tmp_apaExecBuffer, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, tmp_apaExecBuffer, &nTimeScalerOutSamples ) != 0 ) @@ -3455,12 +3522,21 @@ ivas_error IVAS_DEC_GetSamplesDecoder( FOR( Word32 i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { - hIvasDec->apaExecBuffer_fx[i] = L_shl( tmp_apaExecBuffer[i], Q11 ); // Q11 +#ifdef JBM_MEMORY_OPT + st_ivas->hTcBuffer->tc_buffer_fx[i] = L_shl( tmp_apaExecBuffer[i], Q11 ); // Q11 +#else + hIvasDec->apaExecBuffer_fx[i] = L_shl( tmp_apaExecBuffer[i], Q11 ); // Q11 +#endif } +#endif } ELSE { +#ifdef JBM_MEMORY_OPT + IF( apa_exec_ivas_fx( hIvasDec->hTimeScaler, st_ivas->hTcBuffer->tc_buffer_fx, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, st_ivas->hTcBuffer->tc_buffer_fx, &nTimeScalerOutSamples ) != 0 ) +#else IF( apa_exec_ivas_fx( hIvasDec->hTimeScaler, hIvasDec->apaExecBuffer_fx, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, hIvasDec->apaExecBuffer_fx, &nTimeScalerOutSamples ) != 0 ) +#endif { return IVAS_ERR_UNKNOWN; } @@ -3470,6 +3546,11 @@ ivas_error IVAS_DEC_GetSamplesDecoder( nSamplesTcsScaled = idiv1616U( extract_l( nTimeScalerOutSamples ), nTransportChannels ); hIvasDec->timeScalingDone = 1; move16(); +#ifdef JBM_MEMORY_OPT + + /* convert interleaved time-scaled TC audio channels buffer to deinterleaved one */ + ivas_buffer_interleaved_to_deinterleaved_fx( st_ivas->hTcBuffer->tc_buffer_fx, nTransportChannels, nSamplesTcsScaled, NS2SA( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_L_FRAME_NS ) ); +#endif } else { @@ -3480,7 +3561,11 @@ ivas_error IVAS_DEC_GetSamplesDecoder( * Feed decoded transport channels samples to the renderer *-----------------------------------------------------------------*/ +#ifdef JBM_MEMORY_OPT + ivas_jbm_dec_feed_tc_to_renderer_fx( st_ivas, nSamplesTcsScaled, &nResidualSamples ); +#else ivas_jbm_dec_feed_tc_to_renderer_fx( st_ivas, nSamplesTcsScaled, &nResidualSamples, hIvasDec->apaExecBuffer_fx ); +#endif IF( st_ivas->hDecoderConfig->Opt_tsm ) { @@ -4915,12 +5000,20 @@ static ivas_error evs_dec_main_fx( IF( st_ivas->hDecoderConfig->Opt_tsm ) { - /* BE workaround: in order to keep EVS bit-exact wrt. TS 26.443, convert 'float' output data to 'short' before the TSM */ + /* BE workaround: in order to keep EVS bit-exact wrt. TS 26.443, convert 'float' output data to 'short' before the TSM */ // TODO: verify if it is still needed and if it works well for EVS stereo panning output +#ifdef JBM_MEMORY_OPT + Word32 pcm_buf_local[CPE_CHANNELS * L_FRAME48k]; +#else Word32 pcm_buf_local[L_FRAME48k]; +#endif FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) { +#ifdef JBM_MEMORY_OPT + ivas_buffer_deinterleaved_to_interleaved_fx( &p_output_fx[ch], st_ivas->hDecoderConfig->nchan_out, nOutSamples, pcm_buf_local ); +#else ivas_syn_output_f_fx( &p_output_fx[ch], nOutSamples, 1, pcm_buf_local ); +#endif Copy32( pcm_buf_local, p_output_fx[ch], nOutSamples ); } @@ -4990,7 +5083,9 @@ static ivas_error apa_setup( const bool isInitialized_voip, const UWord16 nTransportChannels ) { +#ifndef JBM_MEMORY_OPT Word16 apa_buffer_size; +#endif UWord16 l_ts; l_ts = (UWord16) hIvasDec->st_ivas->hTcBuffer->n_samples_granularity; @@ -5004,10 +5099,12 @@ static ivas_error apa_setup( Word32 startQuality; startQuality = L_shl( L_deposit_l( hIvasDec->tsm_quality ), Q2 ); /* Q14 --> Q16*/ +#ifndef JBM_MEMORY_OPT apa_buffer_size = APA_BUF_PER_CHANNEL; move16(); /* get current renderer type*/ +#endif hDecoderConfig = hIvasDec->st_ivas->hDecoderConfig; IF( EQ_32( hDecoderConfig->output_Fs, 8000 ) ) @@ -5057,13 +5154,14 @@ static ivas_error apa_setup( return IVAS_ERR_INIT_ERROR; } } - +#ifndef JBM_MEMORY_OPT IF( ( hIvasDec->apaExecBuffer_fx = malloc( sizeof( Word32 ) * L_mult0( apa_buffer_size, (Word16) nTransportChannels ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); } set_zero2_fx( hIvasDec->apaExecBuffer_fx, L_mult0( apa_buffer_size, (Word16) nTransportChannels ) ); +#endif } ELSE { @@ -5071,6 +5169,7 @@ static ivas_error apa_setup( { return IVAS_ERR_INIT_ERROR; } +#ifndef JBM_MEMORY_OPT apa_buffer_size = APA_BUF_PER_CHANNEL; move16(); free( hIvasDec->apaExecBuffer_fx ); @@ -5079,6 +5178,7 @@ static ivas_error apa_setup( return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); } set_zero2_fx( hIvasDec->apaExecBuffer_fx, L_mult0( apa_buffer_size, (Word16) nTransportChannels ) ); +#endif } hIvasDec->nTransportChannelsOld = nTransportChannels;