Commit b4f19614 authored by multrus's avatar multrus
Browse files

Merge branch 'basop-2436-isar-do-not-reuse-cldfb-handles' into 'main'

[Split non-BE] Fix reused CLDFB state in rendering of OMASA to SR with lib_rend

See merge request !2540
parents e7ac6b20 da81988b
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -169,6 +169,7 @@
/* #################### Start NON-BE switches ############################ */
/* any switch which is non-be wrt. TS 26.258 V3.0 */
#define FIX_FLOAT_1493_MASA_ENCODE_STABILITY_IMPROVE    /* Nokia: float issue 1493: Improves float decision stability in MASA encoding by adjusting reduction code */
#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 ########################### */

+130 −1
Original line number Diff line number Diff line
@@ -454,6 +454,66 @@ static void accumulate2dArrayToBuffer(
    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()
 *
@@ -6063,16 +6123,25 @@ static ivas_error renderIsmToSplitBinaural(
    const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
    const SPLIT_REND_WRAPPER *pSplitRendWrapper;
    IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES];
    int16_t i, ch, slot_idx, num_bands;
    int16_t i;
    float tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k];
#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR
    int16_t ch, slot_idx, num_bands;
    float tmpBinaural_CldfbRe[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    float tmpBinaural_CldfbIm[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
#endif
    int16_t output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel;
    COMBINED_ORIENTATION_HANDLE pCombinedOrientationData;
    int16_t ism_md_subframe_update_ext;

    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;

@@ -6133,6 +6202,7 @@ static ivas_error renderIsmToSplitBinaural(
            return error;
        }

#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR
        if ( outAudio.config.is_cldfb )
        {
            /* Perform CLDFB analysis on rendered audio, since the output buffer is CLDFB domain */
@@ -6151,11 +6221,14 @@ static ivas_error renderIsmToSplitBinaural(
        }
        else
        {
#endif
            /* Copy rendered audio to tmp storage buffer. Copying directly to output would
             * overwrite original audio, which is still needed for rendering next head pose. */
            mvr2r( tmpProcessing[0], tmpBinaural[BINAURAL_CHANNELS * pos_idx], output_frame );
            mvr2r( tmpProcessing[1], tmpBinaural[BINAURAL_CHANNELS * pos_idx + 1], output_frame );
#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR
        }
#endif

        /* Overwrite processing buffer with original input audio again */
        copyBufferTo2dArray( ismInput->base.inputBuffer, tmpProcessing );
@@ -6167,14 +6240,18 @@ static ivas_error renderIsmToSplitBinaural(
        pCombinedOrientationData->Quaternions[i] = originalHeadRot[i];
    }

#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR
    if ( outAudio.config.is_cldfb )
    {
        accumulateCLDFBArrayToBuffer( tmpBinaural_CldfbRe, tmpBinaural_CldfbIm, &outAudio );
    }
    else
    {
#endif
        accumulate2dArrayToBuffer( tmpBinaural, &outAudio );
#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR
    }
#endif
    pop_wmops();

    /* Encoding to split rendering bitstream done at a higher level */
@@ -6281,6 +6358,42 @@ static ivas_error renderActiveInputsIsm(
    int16_t i;
    input_ism *pCurrentInput;
    ivas_error error;
#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 )
    {
@@ -6290,12 +6403,28 @@ static ivas_error renderActiveInputsIsm(
            continue;
        }

#ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR
        if ( ( error = renderInputIsm( pCurrentInput,
                                       hIvasRend->outputConfig,
                                       work_buffer ) ) != IVAS_ERR_OK )
#else
        if ( ( 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

    return IVAS_ERR_OK;
}