Loading lib_com/options.h +1 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ #define FIX_FLOAT_1533_BLEND_SUBFR2 /* FhG: float issue 1533: correct blending in blend_subfr2() */ #define FIX_2436_CLDFBANAHANDLE_ADRESS /*FhG: cldfb handle pointer were handed over in faulty manner*/ //#define FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR /*FhG: basop issue 2436 (related to basop 2283): fix garbage output for >1 object OMASA with extrend as ISAR prerenderer */ /* ##################### End NON-BE switches ########################### */ Loading lib_rend/lib_rend_fx.c +132 −1 Original line number Diff line number Diff line Loading @@ -564,6 +564,67 @@ static void accumulate2dArrayToBuffer_fx( return; } #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR /*-------------------------------------------------------------------* * audio_buffer_td_to_cldfb() * * Performs CLDFB analysis on contents of td_buffer and mixes the result into cldfb_buffer. * * This function **does not** clear the destination buffer before writing. * * The number of valid CLDFB handles in cldfbAna must be a least equal to the number of channels * in the audio buffers. *-------------------------------------------------------------------*/ static void audio_buffer_td_to_cldfb( IVAS_REND_AudioBuffer td_buffer, IVAS_REND_AudioBuffer cldfb_buffer, int32_t fs, HANDLE_CLDFB_FILTER_BANK *cldfbAna ) { int16_t ch, slot_idx; float *td_read_ptr; float *cldfb_write_ptr; int16_t num_bands, num_slots; assert( !td_buffer.config.is_cldfb ); assert( cldfb_buffer.config.is_cldfb ); assert( td_buffer.config.numChannels == cldfb_buffer.config.numChannels ); assert( td_buffer.config.numSamplesPerChannel * 2 == cldfb_buffer.config.numSamplesPerChannel ); td_read_ptr = td_buffer.data; cldfb_write_ptr = cldfb_buffer.data; num_bands = (int16_t) ( ( CLDFB_NO_CHANNELS_MAX * fs ) / 48000 ); assert( td_buffer.config.numSamplesPerChannel % num_bands == 0 ); num_slots = td_buffer.config.numSamplesPerChannel / num_bands; for ( ch = 0; ch < cldfb_buffer.config.numChannels; ++ch ) { for ( slot_idx = 0; slot_idx < num_slots; ++slot_idx ) { float re[CLDFB_NO_CHANNELS_MAX]; float im[CLDFB_NO_CHANNELS_MAX]; cldfbAnalysis_ts( td_read_ptr, re, im, num_bands, cldfbAna[ch] ); td_read_ptr += num_bands; v_add( re, cldfb_write_ptr, cldfb_write_ptr, num_bands ); cldfb_write_ptr += num_bands; v_add( im, cldfb_write_ptr, cldfb_write_ptr, num_bands ); cldfb_write_ptr += num_bands; } } } #endif /*-------------------------------------------------------------------* * limitRendererOutput() * Loading Loading @@ -7104,16 +7165,25 @@ static ivas_error renderIsmToSplitBinaural( const SPLIT_REND_WRAPPER *pSplitRendWrapper; IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; IVAS_QUATERNION localHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; Word16 i, ch, slot_idx, num_bands; Word16 i; #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR Word16 ch, slot_idx, num_bands; Word32 tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; Word32 tmpBinaural_CldfbRe[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 tmpBinaural_CldfbIm[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; #endif Word16 output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel; COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; Word16 ism_md_subframe_update_ext, exp; push_wmops( "renderIsmToSplitBinaural" ); #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR assert( !outAudio.config.is_cldfb && "ISM renderering only supports TD output. If CLDFB output was requested, " "we convert to CLDFB higher up the stack after rendering all ISMs" ); #endif pSplitRendWrapper = ismInput->base.ctx.pSplitRendWrapper; pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; Loading Loading @@ -7195,6 +7265,7 @@ static ivas_error renderIsmToSplitBinaural( } } #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR IF( NE_16( outAudio.config.is_cldfb, 0 ) ) { /* Perform CLDFB analysis on rendered audio, since the output buffer is CLDFB domain */ Loading Loading @@ -7246,12 +7317,15 @@ static ivas_error renderIsmToSplitBinaural( } ELSE { #endif /*FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR*/ /* Copy rendered audio to tmp storage buffer. Copying directly to output would * overwrite original audio, which is still needed for rendering next head pose. */ Copy32( tmpProcessing[0], tmpBinaural[i_mult( 2, pos_idx )], output_frame ); Copy32( tmpProcessing[1], tmpBinaural[add( i_mult( 2, pos_idx ), 1 )], output_frame ); #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR } #endif /* Overwrite processing buffer with original input audio again */ copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpProcessing ); Loading @@ -7263,6 +7337,7 @@ static ivas_error renderIsmToSplitBinaural( Copy_Quat_fx( &originalHeadRot[i], &pCombinedOrientationData->Quaternions[i] ); } #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( outAudio.config.is_cldfb ) { #ifdef FIX_2283_ACCU_CLDFB Loading @@ -7273,8 +7348,11 @@ static ivas_error renderIsmToSplitBinaural( } else { #endif /*FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR*/ accumulate2dArrayToBuffer_fx( tmpBinaural, &outAudio ); #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR } #endif pop_wmops(); /* Encoding to split rendering bitstream done at a higher level */ Loading Loading @@ -7427,6 +7505,44 @@ static ivas_error renderActiveInputsIsm( ivas_error error; Word16 input_q = outAudio.q_factor; move16(); #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR int16_t num_active_inputs; IVAS_REND_AudioBuffer work_buffer; float tmp_td_binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k]; // Early return in case there are no active ISM inputs num_active_inputs = 0; for ( i = 0, pCurrentInput = hIvasRend->inputsIsm; i < RENDERER_MAX_ISM_INPUTS; ++i, ++pCurrentInput ) { if ( pCurrentInput->base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) { ++num_active_inputs; } } if ( num_active_inputs == 0 ) { return IVAS_ERR_OK; } // By default (TD output), use outAudio as work_buffer. This means we render individual ISMs // directly to outAudio, since the `data` member of both these structs is pointing to the same memory. // Initializing this way also fixes MSVC's false-positive warning about work_buffer being used // without initialization in code below, as well as some WMC tool instrumentation problems. work_buffer = outAudio; // ISM rendering only supports TD output. If CLDFB output was requested, we first render // to TD in a temporary buffer and then convert to CLDFB. We do this by swapping out the // underlying memory of work_buffer and modifying its config to TD. if ( outAudio.config.is_cldfb ) { work_buffer.config.numSamplesPerChannel /= 2; work_buffer.config.is_cldfb = false; work_buffer.data = tmp_td_binaural; set_zero( tmp_td_binaural, MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k ); } #endif FOR( ( i = 0, pCurrentInput = hIvasRend->inputsIsm ); i < RENDERER_MAX_ISM_INPUTS; ( ++i, ++pCurrentInput ) ) { IF( EQ_32( pCurrentInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) ) Loading @@ -7437,10 +7553,25 @@ static ivas_error renderActiveInputsIsm( *outAudio.pq_fact = input_q; move16(); #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR IF( NE_32( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, work_buffer ) ), IVAS_ERR_OK ) ) #else IF( NE_32( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio ) ), IVAS_ERR_OK ) ) #endif { return error; } #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( outAudio.config.is_cldfb ) { audio_buffer_td_to_cldfb( work_buffer, outAudio, hIvasRend->sampleRateOut, hIvasRend->splitRendWrapper->hCldfbHandles->cldfbAna ); } #endif FOR( Word16 j = 0; j < outAudio.config.numSamplesPerChannel * outAudio.config.numChannels; ++j ) { outAudio.data_fx[j] = L_shl( outAudio.data_fx[j], sub( sub( input_q, 1 ), ( *outAudio.pq_fact ) ) ); /* Q(input_q - 1) */ Loading Loading
lib_com/options.h +1 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ #define FIX_FLOAT_1533_BLEND_SUBFR2 /* FhG: float issue 1533: correct blending in blend_subfr2() */ #define FIX_2436_CLDFBANAHANDLE_ADRESS /*FhG: cldfb handle pointer were handed over in faulty manner*/ //#define FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR /*FhG: basop issue 2436 (related to basop 2283): fix garbage output for >1 object OMASA with extrend as ISAR prerenderer */ /* ##################### End NON-BE switches ########################### */ Loading
lib_rend/lib_rend_fx.c +132 −1 Original line number Diff line number Diff line Loading @@ -564,6 +564,67 @@ static void accumulate2dArrayToBuffer_fx( return; } #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR /*-------------------------------------------------------------------* * audio_buffer_td_to_cldfb() * * Performs CLDFB analysis on contents of td_buffer and mixes the result into cldfb_buffer. * * This function **does not** clear the destination buffer before writing. * * The number of valid CLDFB handles in cldfbAna must be a least equal to the number of channels * in the audio buffers. *-------------------------------------------------------------------*/ static void audio_buffer_td_to_cldfb( IVAS_REND_AudioBuffer td_buffer, IVAS_REND_AudioBuffer cldfb_buffer, int32_t fs, HANDLE_CLDFB_FILTER_BANK *cldfbAna ) { int16_t ch, slot_idx; float *td_read_ptr; float *cldfb_write_ptr; int16_t num_bands, num_slots; assert( !td_buffer.config.is_cldfb ); assert( cldfb_buffer.config.is_cldfb ); assert( td_buffer.config.numChannels == cldfb_buffer.config.numChannels ); assert( td_buffer.config.numSamplesPerChannel * 2 == cldfb_buffer.config.numSamplesPerChannel ); td_read_ptr = td_buffer.data; cldfb_write_ptr = cldfb_buffer.data; num_bands = (int16_t) ( ( CLDFB_NO_CHANNELS_MAX * fs ) / 48000 ); assert( td_buffer.config.numSamplesPerChannel % num_bands == 0 ); num_slots = td_buffer.config.numSamplesPerChannel / num_bands; for ( ch = 0; ch < cldfb_buffer.config.numChannels; ++ch ) { for ( slot_idx = 0; slot_idx < num_slots; ++slot_idx ) { float re[CLDFB_NO_CHANNELS_MAX]; float im[CLDFB_NO_CHANNELS_MAX]; cldfbAnalysis_ts( td_read_ptr, re, im, num_bands, cldfbAna[ch] ); td_read_ptr += num_bands; v_add( re, cldfb_write_ptr, cldfb_write_ptr, num_bands ); cldfb_write_ptr += num_bands; v_add( im, cldfb_write_ptr, cldfb_write_ptr, num_bands ); cldfb_write_ptr += num_bands; } } } #endif /*-------------------------------------------------------------------* * limitRendererOutput() * Loading Loading @@ -7104,16 +7165,25 @@ static ivas_error renderIsmToSplitBinaural( const SPLIT_REND_WRAPPER *pSplitRendWrapper; IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; IVAS_QUATERNION localHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; Word16 i, ch, slot_idx, num_bands; Word16 i; #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR Word16 ch, slot_idx, num_bands; Word32 tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; Word32 tmpBinaural_CldfbRe[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 tmpBinaural_CldfbIm[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; #endif Word16 output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel; COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; Word16 ism_md_subframe_update_ext, exp; push_wmops( "renderIsmToSplitBinaural" ); #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR assert( !outAudio.config.is_cldfb && "ISM renderering only supports TD output. If CLDFB output was requested, " "we convert to CLDFB higher up the stack after rendering all ISMs" ); #endif pSplitRendWrapper = ismInput->base.ctx.pSplitRendWrapper; pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; Loading Loading @@ -7195,6 +7265,7 @@ static ivas_error renderIsmToSplitBinaural( } } #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR IF( NE_16( outAudio.config.is_cldfb, 0 ) ) { /* Perform CLDFB analysis on rendered audio, since the output buffer is CLDFB domain */ Loading Loading @@ -7246,12 +7317,15 @@ static ivas_error renderIsmToSplitBinaural( } ELSE { #endif /*FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR*/ /* Copy rendered audio to tmp storage buffer. Copying directly to output would * overwrite original audio, which is still needed for rendering next head pose. */ Copy32( tmpProcessing[0], tmpBinaural[i_mult( 2, pos_idx )], output_frame ); Copy32( tmpProcessing[1], tmpBinaural[add( i_mult( 2, pos_idx ), 1 )], output_frame ); #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR } #endif /* Overwrite processing buffer with original input audio again */ copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpProcessing ); Loading @@ -7263,6 +7337,7 @@ static ivas_error renderIsmToSplitBinaural( Copy_Quat_fx( &originalHeadRot[i], &pCombinedOrientationData->Quaternions[i] ); } #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( outAudio.config.is_cldfb ) { #ifdef FIX_2283_ACCU_CLDFB Loading @@ -7273,8 +7348,11 @@ static ivas_error renderIsmToSplitBinaural( } else { #endif /*FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR*/ accumulate2dArrayToBuffer_fx( tmpBinaural, &outAudio ); #ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR } #endif pop_wmops(); /* Encoding to split rendering bitstream done at a higher level */ Loading Loading @@ -7427,6 +7505,44 @@ static ivas_error renderActiveInputsIsm( ivas_error error; Word16 input_q = outAudio.q_factor; move16(); #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR int16_t num_active_inputs; IVAS_REND_AudioBuffer work_buffer; float tmp_td_binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k]; // Early return in case there are no active ISM inputs num_active_inputs = 0; for ( i = 0, pCurrentInput = hIvasRend->inputsIsm; i < RENDERER_MAX_ISM_INPUTS; ++i, ++pCurrentInput ) { if ( pCurrentInput->base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) { ++num_active_inputs; } } if ( num_active_inputs == 0 ) { return IVAS_ERR_OK; } // By default (TD output), use outAudio as work_buffer. This means we render individual ISMs // directly to outAudio, since the `data` member of both these structs is pointing to the same memory. // Initializing this way also fixes MSVC's false-positive warning about work_buffer being used // without initialization in code below, as well as some WMC tool instrumentation problems. work_buffer = outAudio; // ISM rendering only supports TD output. If CLDFB output was requested, we first render // to TD in a temporary buffer and then convert to CLDFB. We do this by swapping out the // underlying memory of work_buffer and modifying its config to TD. if ( outAudio.config.is_cldfb ) { work_buffer.config.numSamplesPerChannel /= 2; work_buffer.config.is_cldfb = false; work_buffer.data = tmp_td_binaural; set_zero( tmp_td_binaural, MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k ); } #endif FOR( ( i = 0, pCurrentInput = hIvasRend->inputsIsm ); i < RENDERER_MAX_ISM_INPUTS; ( ++i, ++pCurrentInput ) ) { IF( EQ_32( pCurrentInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) ) Loading @@ -7437,10 +7553,25 @@ static ivas_error renderActiveInputsIsm( *outAudio.pq_fact = input_q; move16(); #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR IF( NE_32( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, work_buffer ) ), IVAS_ERR_OK ) ) #else IF( NE_32( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio ) ), IVAS_ERR_OK ) ) #endif { return error; } #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( outAudio.config.is_cldfb ) { audio_buffer_td_to_cldfb( work_buffer, outAudio, hIvasRend->sampleRateOut, hIvasRend->splitRendWrapper->hCldfbHandles->cldfbAna ); } #endif FOR( Word16 j = 0; j < outAudio.config.numSamplesPerChannel * outAudio.config.numChannels; ++j ) { outAudio.data_fx[j] = L_shl( outAudio.data_fx[j], sub( sub( input_q, 1 ), ( *outAudio.pq_fact ) ) ); /* Q(input_q - 1) */ Loading