Loading lib_com/ivas_cnst.h +5 −0 Original line number Diff line number Diff line Loading @@ -172,8 +172,13 @@ typedef enum #define JBM_CLDFB_SLOTS_IN_SUBFRAME 4 #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 #ifdef UNIFIED_DECODING_PATHS_LEFTOVERS #define MAX_CLDFB_DIGEST_CHANNELS 3 /* == maximum of ParamISM TCs and ParamMC TCs */ Loading lib_com/ivas_prot.h +21 −3 Original line number Diff line number Diff line Loading @@ -262,13 +262,28 @@ uint32_t ivas_syn_output( int16_t *synth_out /* o : integer 16 bits synthesis signal */ ); #ifdef JBM_MEMORY_OPT void ivas_buffer_interleaved_to_deinterleaved( float *audio, /* i/o: audio buffer */ const int16_t n_channels, /* i : number of channels */ const int16_t frame_length, /* i : frame length (one channel) */ const int16_t n_samp_full /* i : full frame length (one channel) */ ); void ivas_buffer_deinterleaved_to_interleaved( float *audio[], /* i : deinterleaved audio buffer */ const int16_t n_channels, /* i : number of channels */ const int16_t frame_length, /* i : frame length (one channel) */ float *audio_out /* o : interleaved audio buffer */ ); #else void ivas_syn_output_f( float *synth[], /* i/o: float synthesis signal */ const int16_t output_frame, /* i : output frame length (one channel) */ const int16_t n_channels, /* i : number of output channels */ float *synth_out /* o : integer 16 bits synthesis signal */ ); #endif void ivas_initialize_handles_enc( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ); Loading Loading @@ -849,8 +864,11 @@ ivas_error ivas_jbm_dec_flush_renderer( void ivas_jbm_dec_feed_tc_to_renderer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t nSamplesForRendering, /* i : number of TC samples available for rendering */ int16_t *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ float *data /* i/o: transport channels/output synthesis signal */ int16_t *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ #ifndef JBM_MEMORY_OPT , float *data /* i/o: time-scaled transport channels */ #endif ); void ivas_dec_prepare_renderer( Loading lib_com/ivas_tools.c +65 −1 Original line number Diff line number Diff line Loading @@ -148,6 +148,70 @@ uint32_t ivas_syn_output( return noClipping; } #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( float *audio, /* i/o: audio buffer */ const int16_t n_channels, /* i : number of channels */ const int16_t frame_length, /* i : frame length (one channel) */ const int16_t n_samp_full /* i : full frame length (one channel) */ ) { int16_t offset, ch, m; float 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]; } } offset = 0; for ( ch = 0; ch < n_channels; ch++ ) { mvr2r( buffer[ch], audio + offset, frame_length ); 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( float *audio[], /* i/o: deinterleaved audio buffer */ const int16_t n_channels, /* i : number of channels */ const int16_t frame_length, /* i : frame length (one channel) */ float *audio_out /* o : interleaved audio buffer */ ) { int16_t 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]; } } return; } #else /*-------------------------------------------------------------------* * ivas_syn_output_f() Loading Loading @@ -180,7 +244,7 @@ void ivas_syn_output_f( return; } #endif /*-------------------------------------------------------------------* * mvr2r_inc() Loading lib_com/options.h +1 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ #define UNIFIED_DECODING_PATHS_LEFTOVERS /* VA: issue 880: remove leftovers after NONBE_UNIFIED_DECODING_PATHS */ #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 */ // object-editing feature porting #define FIX_HRTF_LOAD_API // solves API conflicts between HRTF and object-editing features Loading lib_dec/ivas_jbm_dec.c +228 −2 Original line number Diff line number Diff line Loading @@ -795,12 +795,20 @@ ivas_error ivas_jbm_dec_tc( void ivas_jbm_dec_feed_tc_to_renderer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t nSamplesForRendering, /* i : number of TC samples available for rendering */ int16_t *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ int16_t *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ #ifndef JBM_MEMORY_OPT , float *data /* i : transport channels */ #endif ) { #ifdef JBM_MEMORY_OPT float tmp_buf[MAX_JBM_L_FRAME48k]; float *p_data_f[FOA_CHANNELS + MAX_NUM_OBJECTS]; #else float data_f[MAX_CLDFB_DIGEST_CHANNELS][MAX_JBM_L_FRAME48k]; /* 'float' buffer for transport channels that will be directly converted with the CLDFB */ float *p_data_f[MAX_CLDFB_DIGEST_CHANNELS]; #endif int16_t n, n_render_timeslots, n_ch_cldfb; int16_t ch; DECODER_TC_BUFFER_HANDLE hTcBuffer; Loading @@ -810,6 +818,38 @@ void ivas_jbm_dec_feed_tc_to_renderer( if ( st_ivas->hDecoderConfig->Opt_tsm ) { #ifdef JBM_MEMORY_OPT int16_t n_samples_still_available; int16_t n_ch_full_copy, n_ch_res_copy; n_samples_still_available = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered; hTcBuffer->n_samples_buffered = n_samples_still_available + nSamplesForRendering + hTcBuffer->n_samples_discard; hTcBuffer->n_samples_available = hTcBuffer->n_samples_granularity * ( hTcBuffer->n_samples_buffered / hTcBuffer->n_samples_granularity ); *nSamplesResidual = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_available; n_ch_full_copy = min( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); n_ch_res_copy = hTcBuffer->nchan_transport_jbm - hTcBuffer->nchan_buffer_full; for ( ch = 0; ch < n_ch_full_copy; ch++ ) { mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); set_zero( hTcBuffer->tc[ch], hTcBuffer->n_samples_discard ); mvr2r( hTcBuffer->tc_buffer_old[ch], hTcBuffer->tc[ch] + hTcBuffer->n_samples_discard, n_samples_still_available ); mvr2r( tmp_buf, hTcBuffer->tc[ch] + n_samples_still_available + hTcBuffer->n_samples_discard, nSamplesForRendering - *nSamplesResidual ); mvr2r( tmp_buf + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old[ch], *nSamplesResidual ); } if ( n_ch_res_copy > 0 ) { for ( ; ch < hTcBuffer->nchan_transport_jbm; ch++ ) { p_data_f[ch] = hTcBuffer->tc[ch]; mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); mvr2r( hTcBuffer->tc_buffer_old[ch], p_data_f[ch], n_samples_still_available ); mvr2r( tmp_buf, p_data_f[ch] + n_samples_still_available, nSamplesForRendering - *nSamplesResidual ); mvr2r( tmp_buf + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old[ch], *nSamplesResidual ); } } #else int16_t n_samples_still_available, m; int16_t n_ch_full_copy; int16_t n_ch_res_copy; Loading Loading @@ -849,6 +889,7 @@ void ivas_jbm_dec_feed_tc_to_renderer( mvr2r( p_data_f[ch] + hTcBuffer->n_samples_available, hTcBuffer->tc[ch], *nSamplesResidual ); } } #endif n_render_timeslots = hTcBuffer->n_samples_available / hTcBuffer->n_samples_granularity; } Loading Loading @@ -1017,7 +1058,11 @@ ivas_error ivas_jbm_dec_render( p_tc[n] = &p_output[n][st_ivas->hTcBuffer->n_samples_rendered]; } #endif #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[n] = p_output[n]; } Loading Loading @@ -1513,7 +1558,11 @@ ivas_error ivas_jbm_dec_render( break; case PCM_FLOAT32: #ifdef JBM_MEMORY_OPT ivas_buffer_deinterleaved_to_interleaved( p_output, nchan_out_syn_output, *nSamplesRendered, (float *) data ); #else ivas_syn_output_f( p_output, *nSamplesRendered, nchan_out_syn_output, (float *) data ); #endif break; default: error = IVAS_ERR_UNKNOWN; Loading Loading @@ -1576,6 +1625,15 @@ ivas_error ivas_jbm_dec_flush_renderer( { int16_t ch_idx; #ifdef JBM_MEMORY_OPT /* render available full slots (with new lower granularity) */ for ( ch_idx = 0; ch_idx < max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); ch_idx++ ) { /* move it at the beginning of the TC buffer with zero padding */ mvr2r( hTcBuffer->tc_buffer_old[ch_idx], hTcBuffer->tc[ch_idx], n_samples_to_render ); set_zero( hTcBuffer->tc[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++ ) { Loading @@ -1584,6 +1642,7 @@ ivas_error ivas_jbm_dec_flush_renderer( set_zero( hTcBuffer->tc[ch_idx] + n_samples_to_render, hTcBuffer->n_samples_granularity - n_samples_to_render ); mvr2r( hTcBuffer->tc[ch_idx] + hTcBuffer->n_samples_rendered + n_samples_to_render, hTcBuffer->tc[ch_idx] + hTcBuffer->n_samples_granularity, n_samples_still_available ); } #endif /* simple change of the slot info */ hTcBuffer->num_slots = 1; Loading Loading @@ -1820,7 +1879,11 @@ ivas_error ivas_jbm_dec_flush_renderer( break; case PCM_FLOAT32: #ifdef JBM_MEMORY_OPT ivas_buffer_deinterleaved_to_interleaved( p_output, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, (float *) data ); #else ivas_syn_output_f( p_output, *nSamplesRendered, st_ivas->hDecoderConfig->nchan_out, (float *) data ); #endif break; default: error = IVAS_ERR_UNKNOWN; Loading Loading @@ -2331,6 +2394,128 @@ int16_t ivas_jbm_dec_get_render_granularity( } #endif #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( 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 */ ) { int16_t nsamp_to_allocate; int16_t ch_idx, n_samp_full, n_samp_residual, offset; if ( Opt_tsm ) { n_samp_full = ( NS2SA( output_Fs, MAX_JBM_L_FRAME_NS ) ); n_samp_residual = hTcBuffer->n_samples_granularity - 1; } else { n_samp_full = (int16_t) ( output_Fs / FRAMES_PER_SEC ); n_samp_residual = 0; } nsamp_to_allocate = 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 = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); } set_zero( hTcBuffer->tc_buffer, nsamp_to_allocate ); offset = 0; for ( ch_idx = 0; ch_idx < max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); ch_idx++ ) { hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; offset += n_samp_full; } for ( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc[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[ch_idx] = (float *) malloc( n_samp_residual * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); } set_zero( hTcBuffer->tc_buffer_old[ch_idx], n_samp_residual ); } for ( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc_buffer_old[ch_idx] = NULL; } } else { hTcBuffer->tc_buffer = NULL; for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc[ch_idx] = NULL; } for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc_buffer_old[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( DECODER_TC_BUFFER_HANDLE hTcBuffer /* i/o: JBM TSM buffer handle */ ) { int16_t ch_idx; if ( hTcBuffer != NULL ) { if ( hTcBuffer->tc_buffer != NULL ) { for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc[ch_idx] = NULL; } free( hTcBuffer->tc_buffer ); hTcBuffer->tc_buffer = NULL; } for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { if ( hTcBuffer->tc_buffer_old[ch_idx] != NULL ) { free( hTcBuffer->tc_buffer_old[ch_idx] ); hTcBuffer->tc_buffer_old[ch_idx] = NULL; } } } return; } #endif /*--------------------------------------------------------------------------* * ivas_jbm_dec_tc_buffer_open() Loading @@ -2347,11 +2532,17 @@ ivas_error ivas_jbm_dec_tc_buffer_open( const int16_t n_samples_granularity /* i : granularity of the renderer/buffer */ ) { #ifndef JBM_MEMORY_OPT int16_t nsamp_to_allocate; #endif DECODER_TC_BUFFER_HANDLE hTcBuffer; int16_t nMaxSlotsPerSubframe; #ifdef JBM_MEMORY_OPT ivas_error error; #else int16_t nchan_residual; int16_t ch_idx; #endif /*-----------------------------------------------------------------* * prepare library opening Loading @@ -2366,7 +2557,9 @@ ivas_error ivas_jbm_dec_tc_buffer_open( hTcBuffer->nchan_transport_jbm = nchan_transport_jbm; hTcBuffer->nchan_transport_internal = nchan_transport_internal; hTcBuffer->nchan_buffer_full = nchan_full; #ifndef JBM_MEMORY_OPT nchan_residual = nchan_transport_internal - nchan_full; #endif hTcBuffer->n_samples_granularity = n_samples_granularity; hTcBuffer->n_samples_available = 0; hTcBuffer->n_samples_buffered = 0; Loading @@ -2376,12 +2569,20 @@ ivas_error ivas_jbm_dec_tc_buffer_open( hTcBuffer->n_samples_discard = 0; hTcBuffer->n_samples_flushed = 0; hTcBuffer->nb_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; #ifndef JBM_MEMORY_OPT nsamp_to_allocate = 0; #endif nMaxSlotsPerSubframe = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / hTcBuffer->n_samples_granularity; hTcBuffer->num_slots = nMaxSlotsPerSubframe * MAX_PARAM_SPATIAL_SUBFRAMES; set_s( hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); set_s( hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); #ifdef JBM_MEMORY_OPT if ( ( error = ivas_jbm_dec_tc_audio_allocate( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) { return error; } #else { int16_t n_samp_full, n_samp_residual; int32_t offset; Loading Loading @@ -2441,6 +2642,7 @@ ivas_error ivas_jbm_dec_tc_buffer_open( } } } #endif st_ivas->hTcBuffer = hTcBuffer; Loading @@ -2463,8 +2665,13 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure( const int16_t n_samples_granularity /* i : new granularity of the renderer/buffer */ ) { #ifdef JBM_MEMORY_OPT ivas_error error; #else int16_t nsamp_to_allocate, n_samp_full, n_samp_residual, offset, nchan_residual; int16_t ch_idx; #endif DECODER_TC_BUFFER_HANDLE hTcBuffer; hTcBuffer = st_ivas->hTcBuffer; Loading Loading @@ -2506,9 +2713,21 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure( hTcBuffer->nchan_transport_jbm = nchan_transport_jbm; hTcBuffer->nchan_transport_internal = nchan_transport_internal; hTcBuffer->nchan_buffer_full = nchan_full; #ifndef JBM_MEMORY_OPT nchan_residual = nchan_transport_internal - nchan_full; #endif hTcBuffer->n_samples_granularity = n_samples_granularity; #ifdef JBM_MEMORY_OPT /* reallocate TC audio buffers */ ivas_jbm_dec_tc_audio_deallocate( hTcBuffer ); if ( ( error = ivas_jbm_dec_tc_audio_allocate( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) { return error; } #else #ifdef DEBUGGING /* what is remaining from last frames needs always be smaller than n_samples_granularity */ assert( ( hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered ) < n_samples_granularity ); Loading Loading @@ -2572,6 +2791,7 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure( hTcBuffer->tc_buffer = NULL; } } #endif return IVAS_ERR_OK; } Loading Loading @@ -2630,10 +2850,15 @@ void ivas_jbm_dec_tc_buffer_close( DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ ) { #ifndef JBM_MEMORY_OPT int16_t i; #endif if ( *phTcBuffer != NULL ) { #ifdef JBM_MEMORY_OPT ivas_jbm_dec_tc_audio_deallocate( *phTcBuffer ); #else for ( i = 0; i < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; i++ ) { ( *phTcBuffer )->tc[i] = NULL; Loading @@ -2644,6 +2869,7 @@ void ivas_jbm_dec_tc_buffer_close( free( ( *phTcBuffer )->tc_buffer ); ( *phTcBuffer )->tc_buffer = NULL; } #endif free( *phTcBuffer ); *phTcBuffer = NULL; Loading Loading
lib_com/ivas_cnst.h +5 −0 Original line number Diff line number Diff line Loading @@ -172,8 +172,13 @@ typedef enum #define JBM_CLDFB_SLOTS_IN_SUBFRAME 4 #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 #ifdef UNIFIED_DECODING_PATHS_LEFTOVERS #define MAX_CLDFB_DIGEST_CHANNELS 3 /* == maximum of ParamISM TCs and ParamMC TCs */ Loading
lib_com/ivas_prot.h +21 −3 Original line number Diff line number Diff line Loading @@ -262,13 +262,28 @@ uint32_t ivas_syn_output( int16_t *synth_out /* o : integer 16 bits synthesis signal */ ); #ifdef JBM_MEMORY_OPT void ivas_buffer_interleaved_to_deinterleaved( float *audio, /* i/o: audio buffer */ const int16_t n_channels, /* i : number of channels */ const int16_t frame_length, /* i : frame length (one channel) */ const int16_t n_samp_full /* i : full frame length (one channel) */ ); void ivas_buffer_deinterleaved_to_interleaved( float *audio[], /* i : deinterleaved audio buffer */ const int16_t n_channels, /* i : number of channels */ const int16_t frame_length, /* i : frame length (one channel) */ float *audio_out /* o : interleaved audio buffer */ ); #else void ivas_syn_output_f( float *synth[], /* i/o: float synthesis signal */ const int16_t output_frame, /* i : output frame length (one channel) */ const int16_t n_channels, /* i : number of output channels */ float *synth_out /* o : integer 16 bits synthesis signal */ ); #endif void ivas_initialize_handles_enc( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ); Loading Loading @@ -849,8 +864,11 @@ ivas_error ivas_jbm_dec_flush_renderer( void ivas_jbm_dec_feed_tc_to_renderer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t nSamplesForRendering, /* i : number of TC samples available for rendering */ int16_t *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ float *data /* i/o: transport channels/output synthesis signal */ int16_t *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ #ifndef JBM_MEMORY_OPT , float *data /* i/o: time-scaled transport channels */ #endif ); void ivas_dec_prepare_renderer( Loading
lib_com/ivas_tools.c +65 −1 Original line number Diff line number Diff line Loading @@ -148,6 +148,70 @@ uint32_t ivas_syn_output( return noClipping; } #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( float *audio, /* i/o: audio buffer */ const int16_t n_channels, /* i : number of channels */ const int16_t frame_length, /* i : frame length (one channel) */ const int16_t n_samp_full /* i : full frame length (one channel) */ ) { int16_t offset, ch, m; float 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]; } } offset = 0; for ( ch = 0; ch < n_channels; ch++ ) { mvr2r( buffer[ch], audio + offset, frame_length ); 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( float *audio[], /* i/o: deinterleaved audio buffer */ const int16_t n_channels, /* i : number of channels */ const int16_t frame_length, /* i : frame length (one channel) */ float *audio_out /* o : interleaved audio buffer */ ) { int16_t 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]; } } return; } #else /*-------------------------------------------------------------------* * ivas_syn_output_f() Loading Loading @@ -180,7 +244,7 @@ void ivas_syn_output_f( return; } #endif /*-------------------------------------------------------------------* * mvr2r_inc() Loading
lib_com/options.h +1 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ #define UNIFIED_DECODING_PATHS_LEFTOVERS /* VA: issue 880: remove leftovers after NONBE_UNIFIED_DECODING_PATHS */ #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 */ // object-editing feature porting #define FIX_HRTF_LOAD_API // solves API conflicts between HRTF and object-editing features Loading
lib_dec/ivas_jbm_dec.c +228 −2 Original line number Diff line number Diff line Loading @@ -795,12 +795,20 @@ ivas_error ivas_jbm_dec_tc( void ivas_jbm_dec_feed_tc_to_renderer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t nSamplesForRendering, /* i : number of TC samples available for rendering */ int16_t *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ int16_t *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ #ifndef JBM_MEMORY_OPT , float *data /* i : transport channels */ #endif ) { #ifdef JBM_MEMORY_OPT float tmp_buf[MAX_JBM_L_FRAME48k]; float *p_data_f[FOA_CHANNELS + MAX_NUM_OBJECTS]; #else float data_f[MAX_CLDFB_DIGEST_CHANNELS][MAX_JBM_L_FRAME48k]; /* 'float' buffer for transport channels that will be directly converted with the CLDFB */ float *p_data_f[MAX_CLDFB_DIGEST_CHANNELS]; #endif int16_t n, n_render_timeslots, n_ch_cldfb; int16_t ch; DECODER_TC_BUFFER_HANDLE hTcBuffer; Loading @@ -810,6 +818,38 @@ void ivas_jbm_dec_feed_tc_to_renderer( if ( st_ivas->hDecoderConfig->Opt_tsm ) { #ifdef JBM_MEMORY_OPT int16_t n_samples_still_available; int16_t n_ch_full_copy, n_ch_res_copy; n_samples_still_available = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered; hTcBuffer->n_samples_buffered = n_samples_still_available + nSamplesForRendering + hTcBuffer->n_samples_discard; hTcBuffer->n_samples_available = hTcBuffer->n_samples_granularity * ( hTcBuffer->n_samples_buffered / hTcBuffer->n_samples_granularity ); *nSamplesResidual = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_available; n_ch_full_copy = min( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); n_ch_res_copy = hTcBuffer->nchan_transport_jbm - hTcBuffer->nchan_buffer_full; for ( ch = 0; ch < n_ch_full_copy; ch++ ) { mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); set_zero( hTcBuffer->tc[ch], hTcBuffer->n_samples_discard ); mvr2r( hTcBuffer->tc_buffer_old[ch], hTcBuffer->tc[ch] + hTcBuffer->n_samples_discard, n_samples_still_available ); mvr2r( tmp_buf, hTcBuffer->tc[ch] + n_samples_still_available + hTcBuffer->n_samples_discard, nSamplesForRendering - *nSamplesResidual ); mvr2r( tmp_buf + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old[ch], *nSamplesResidual ); } if ( n_ch_res_copy > 0 ) { for ( ; ch < hTcBuffer->nchan_transport_jbm; ch++ ) { p_data_f[ch] = hTcBuffer->tc[ch]; mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); mvr2r( hTcBuffer->tc_buffer_old[ch], p_data_f[ch], n_samples_still_available ); mvr2r( tmp_buf, p_data_f[ch] + n_samples_still_available, nSamplesForRendering - *nSamplesResidual ); mvr2r( tmp_buf + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old[ch], *nSamplesResidual ); } } #else int16_t n_samples_still_available, m; int16_t n_ch_full_copy; int16_t n_ch_res_copy; Loading Loading @@ -849,6 +889,7 @@ void ivas_jbm_dec_feed_tc_to_renderer( mvr2r( p_data_f[ch] + hTcBuffer->n_samples_available, hTcBuffer->tc[ch], *nSamplesResidual ); } } #endif n_render_timeslots = hTcBuffer->n_samples_available / hTcBuffer->n_samples_granularity; } Loading Loading @@ -1017,7 +1058,11 @@ ivas_error ivas_jbm_dec_render( p_tc[n] = &p_output[n][st_ivas->hTcBuffer->n_samples_rendered]; } #endif #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[n] = p_output[n]; } Loading Loading @@ -1513,7 +1558,11 @@ ivas_error ivas_jbm_dec_render( break; case PCM_FLOAT32: #ifdef JBM_MEMORY_OPT ivas_buffer_deinterleaved_to_interleaved( p_output, nchan_out_syn_output, *nSamplesRendered, (float *) data ); #else ivas_syn_output_f( p_output, *nSamplesRendered, nchan_out_syn_output, (float *) data ); #endif break; default: error = IVAS_ERR_UNKNOWN; Loading Loading @@ -1576,6 +1625,15 @@ ivas_error ivas_jbm_dec_flush_renderer( { int16_t ch_idx; #ifdef JBM_MEMORY_OPT /* render available full slots (with new lower granularity) */ for ( ch_idx = 0; ch_idx < max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); ch_idx++ ) { /* move it at the beginning of the TC buffer with zero padding */ mvr2r( hTcBuffer->tc_buffer_old[ch_idx], hTcBuffer->tc[ch_idx], n_samples_to_render ); set_zero( hTcBuffer->tc[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++ ) { Loading @@ -1584,6 +1642,7 @@ ivas_error ivas_jbm_dec_flush_renderer( set_zero( hTcBuffer->tc[ch_idx] + n_samples_to_render, hTcBuffer->n_samples_granularity - n_samples_to_render ); mvr2r( hTcBuffer->tc[ch_idx] + hTcBuffer->n_samples_rendered + n_samples_to_render, hTcBuffer->tc[ch_idx] + hTcBuffer->n_samples_granularity, n_samples_still_available ); } #endif /* simple change of the slot info */ hTcBuffer->num_slots = 1; Loading Loading @@ -1820,7 +1879,11 @@ ivas_error ivas_jbm_dec_flush_renderer( break; case PCM_FLOAT32: #ifdef JBM_MEMORY_OPT ivas_buffer_deinterleaved_to_interleaved( p_output, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, (float *) data ); #else ivas_syn_output_f( p_output, *nSamplesRendered, st_ivas->hDecoderConfig->nchan_out, (float *) data ); #endif break; default: error = IVAS_ERR_UNKNOWN; Loading Loading @@ -2331,6 +2394,128 @@ int16_t ivas_jbm_dec_get_render_granularity( } #endif #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( 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 */ ) { int16_t nsamp_to_allocate; int16_t ch_idx, n_samp_full, n_samp_residual, offset; if ( Opt_tsm ) { n_samp_full = ( NS2SA( output_Fs, MAX_JBM_L_FRAME_NS ) ); n_samp_residual = hTcBuffer->n_samples_granularity - 1; } else { n_samp_full = (int16_t) ( output_Fs / FRAMES_PER_SEC ); n_samp_residual = 0; } nsamp_to_allocate = 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 = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); } set_zero( hTcBuffer->tc_buffer, nsamp_to_allocate ); offset = 0; for ( ch_idx = 0; ch_idx < max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); ch_idx++ ) { hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; offset += n_samp_full; } for ( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc[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[ch_idx] = (float *) malloc( n_samp_residual * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); } set_zero( hTcBuffer->tc_buffer_old[ch_idx], n_samp_residual ); } for ( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc_buffer_old[ch_idx] = NULL; } } else { hTcBuffer->tc_buffer = NULL; for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc[ch_idx] = NULL; } for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc_buffer_old[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( DECODER_TC_BUFFER_HANDLE hTcBuffer /* i/o: JBM TSM buffer handle */ ) { int16_t ch_idx; if ( hTcBuffer != NULL ) { if ( hTcBuffer->tc_buffer != NULL ) { for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { hTcBuffer->tc[ch_idx] = NULL; } free( hTcBuffer->tc_buffer ); hTcBuffer->tc_buffer = NULL; } for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { if ( hTcBuffer->tc_buffer_old[ch_idx] != NULL ) { free( hTcBuffer->tc_buffer_old[ch_idx] ); hTcBuffer->tc_buffer_old[ch_idx] = NULL; } } } return; } #endif /*--------------------------------------------------------------------------* * ivas_jbm_dec_tc_buffer_open() Loading @@ -2347,11 +2532,17 @@ ivas_error ivas_jbm_dec_tc_buffer_open( const int16_t n_samples_granularity /* i : granularity of the renderer/buffer */ ) { #ifndef JBM_MEMORY_OPT int16_t nsamp_to_allocate; #endif DECODER_TC_BUFFER_HANDLE hTcBuffer; int16_t nMaxSlotsPerSubframe; #ifdef JBM_MEMORY_OPT ivas_error error; #else int16_t nchan_residual; int16_t ch_idx; #endif /*-----------------------------------------------------------------* * prepare library opening Loading @@ -2366,7 +2557,9 @@ ivas_error ivas_jbm_dec_tc_buffer_open( hTcBuffer->nchan_transport_jbm = nchan_transport_jbm; hTcBuffer->nchan_transport_internal = nchan_transport_internal; hTcBuffer->nchan_buffer_full = nchan_full; #ifndef JBM_MEMORY_OPT nchan_residual = nchan_transport_internal - nchan_full; #endif hTcBuffer->n_samples_granularity = n_samples_granularity; hTcBuffer->n_samples_available = 0; hTcBuffer->n_samples_buffered = 0; Loading @@ -2376,12 +2569,20 @@ ivas_error ivas_jbm_dec_tc_buffer_open( hTcBuffer->n_samples_discard = 0; hTcBuffer->n_samples_flushed = 0; hTcBuffer->nb_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; #ifndef JBM_MEMORY_OPT nsamp_to_allocate = 0; #endif nMaxSlotsPerSubframe = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / hTcBuffer->n_samples_granularity; hTcBuffer->num_slots = nMaxSlotsPerSubframe * MAX_PARAM_SPATIAL_SUBFRAMES; set_s( hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); set_s( hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); #ifdef JBM_MEMORY_OPT if ( ( error = ivas_jbm_dec_tc_audio_allocate( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) { return error; } #else { int16_t n_samp_full, n_samp_residual; int32_t offset; Loading Loading @@ -2441,6 +2642,7 @@ ivas_error ivas_jbm_dec_tc_buffer_open( } } } #endif st_ivas->hTcBuffer = hTcBuffer; Loading @@ -2463,8 +2665,13 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure( const int16_t n_samples_granularity /* i : new granularity of the renderer/buffer */ ) { #ifdef JBM_MEMORY_OPT ivas_error error; #else int16_t nsamp_to_allocate, n_samp_full, n_samp_residual, offset, nchan_residual; int16_t ch_idx; #endif DECODER_TC_BUFFER_HANDLE hTcBuffer; hTcBuffer = st_ivas->hTcBuffer; Loading Loading @@ -2506,9 +2713,21 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure( hTcBuffer->nchan_transport_jbm = nchan_transport_jbm; hTcBuffer->nchan_transport_internal = nchan_transport_internal; hTcBuffer->nchan_buffer_full = nchan_full; #ifndef JBM_MEMORY_OPT nchan_residual = nchan_transport_internal - nchan_full; #endif hTcBuffer->n_samples_granularity = n_samples_granularity; #ifdef JBM_MEMORY_OPT /* reallocate TC audio buffers */ ivas_jbm_dec_tc_audio_deallocate( hTcBuffer ); if ( ( error = ivas_jbm_dec_tc_audio_allocate( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) { return error; } #else #ifdef DEBUGGING /* what is remaining from last frames needs always be smaller than n_samples_granularity */ assert( ( hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered ) < n_samples_granularity ); Loading Loading @@ -2572,6 +2791,7 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure( hTcBuffer->tc_buffer = NULL; } } #endif return IVAS_ERR_OK; } Loading Loading @@ -2630,10 +2850,15 @@ void ivas_jbm_dec_tc_buffer_close( DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ ) { #ifndef JBM_MEMORY_OPT int16_t i; #endif if ( *phTcBuffer != NULL ) { #ifdef JBM_MEMORY_OPT ivas_jbm_dec_tc_audio_deallocate( *phTcBuffer ); #else for ( i = 0; i < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; i++ ) { ( *phTcBuffer )->tc[i] = NULL; Loading @@ -2644,6 +2869,7 @@ void ivas_jbm_dec_tc_buffer_close( free( ( *phTcBuffer )->tc_buffer ); ( *phTcBuffer )->tc_buffer = NULL; } #endif free( *phTcBuffer ); *phTcBuffer = NULL; Loading