Commit e57ebca8 authored by Archit Tamarapu's avatar Archit Tamarapu
Browse files

Merge branch '194-rendering-fix-delay-alignment-of-lfe-in-external-renderer' into 'main'

[split-non-BE][rend-non-BE] Resolve "[rendering] fix delay alignment of LFE in external renderer"

See merge request !846
parents 48abfcd2 e12cd535
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -187,6 +187,7 @@
#define NONBE_FIX_589_JBM_TC_OFFSETS                    /* FhG: issue 589: wrong offset into the TC buffers is used in some rendering paths in the JBM main rendering function */
#define FIX_MEM_REALLOC_IND_LIST                        /* VA: issue 601: failure of the automatic memory re-allocation mechanism when ind_list[] buffer is depleted in MASA mode with 2 TC*/
#define JBM_PARAMUPMIX                                  /* Dlb: Issue 471: Integrate the Multichannel Parametric Upmix into the JBM path */
#define FIX_194_LFE_DELAY_EXTREND                       /* FhG: Issue 194: Fix delay alignment of LFE in external renderer */
#define FIX_582_INDEX_OUT_OF_BOUNDS_SNS_AVQ_DEC         /* FhG: fix an undefined behaviour error in SNS AVQ decoding */
#define FIX_614_ADD_TO_NULL_PTR_DIRAC_SETUP             /* FhG: Issue 614: prevent adding to a null pointer in dirac setup code */
#define UPDATE_REVERB_UTILS                             /* Use CLDFB HRTFs of the appropriate SBA order in get_IR_from_filter_taps() */
+107 −3
Original line number Diff line number Diff line
@@ -61,6 +61,10 @@
#define MAX_CLDFB_BUFFER_LENGTH ( MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS )
#define MAX_BIN_BUFFER_LENGTH   ( MAX_BUFFER_LENGTH_PER_CHANNEL * BINAURAL_CHANNELS )

#ifdef FIX_194_LFE_DELAY_EXTREND
#define MAX_BIN_DELAY_SAMPLES 50 /* Maximum supported rendering latency for binaural IRs */
#endif

#else
#define MAX_BUFFER_LENGTH ( MAX_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS )
#endif
@@ -178,6 +182,10 @@ typedef struct
    float nonDiegeticPanGain;
    lfe_routing lfeRouting;
    float *bufferData;
#ifdef FIX_194_LFE_DELAY_EXTREND
    int16_t binauralDelaySmp;
    float *lfeDelayBuffer;
#endif
    MCMASA_ANA_HANDLE hMcMasa;
} input_mc;

@@ -289,6 +297,30 @@ static void freeInputBaseBufferData( float **data )
    return;
}

#ifdef FIX_194_LFE_DELAY_EXTREND
static ivas_error allocateMcLfeDelayBuffer( float **lfeDelayBuffer, const int16_t data_size )
{
    *lfeDelayBuffer = (float *) malloc( data_size * sizeof( float ) );
    if ( *lfeDelayBuffer == NULL )
    {
        return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for LFE delay buffer" );
    }

    return IVAS_ERR_OK;
}

static void freeMcLfeDelayBuffer( float **lfeDelayBuffer )
{
    if ( *lfeDelayBuffer != NULL )
    {
        free( *lfeDelayBuffer );
        *lfeDelayBuffer = NULL;
    }

    return;
}

#endif
static IVAS_QUATERNION quaternionInit(
    void )
{
@@ -2136,6 +2168,9 @@ static ivas_error initMcBinauralRendering(
    ivas_error error;
#ifdef SPLIT_REND_WITH_HEAD_ROT
    int16_t i;
#endif
#ifdef FIX_194_LFE_DELAY_EXTREND
    int32_t binauralDelayNs;
#endif
    int32_t outSampleRate;

@@ -2254,6 +2289,18 @@ static ivas_error initMcBinauralRendering(
        }
    }

#ifdef FIX_194_LFE_DELAY_EXTREND
    /* determine binaural delay ( used for aligning LFE to output signal ) */
    binauralDelayNs = max( ( inputMc->crendWrapper != NULL ) ? inputMc->crendWrapper->binaural_latency_ns : 0,
                           inputMc->tdRendWrapper.binaural_latency_ns );
    inputMc->binauralDelaySmp = (int16_t) roundf( (float) binauralDelayNs * *inputMc->base.ctx.pOutSampleRate / 1000000000.f );

    if ( inputMc->binauralDelaySmp > MAX_BIN_DELAY_SAMPLES )
    {
        return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid delay for LFE binaural rendering!)" );
    }

#endif /* FIX_194_LFE_DELAY_EXTREND */
    return IVAS_ERR_OK;
}

@@ -2370,6 +2417,13 @@ static ivas_error setRendInputActiveMc(
        return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED;
    }

#ifdef FIX_194_LFE_DELAY_EXTREND
    if ( ( error = allocateMcLfeDelayBuffer( &inputMc->lfeDelayBuffer, MAX_BIN_DELAY_SAMPLES ) ) != IVAS_ERR_OK )
    {
        return error;
    }

#endif
    if ( ( error = allocateInputBaseBufferData( &inputMc->bufferData, MAX_BUFFER_LENGTH ) ) != IVAS_ERR_OK )
    {
        return error;
@@ -2384,6 +2438,9 @@ static ivas_error setRendInputActiveMc(
    inputMc->hMcMasa = NULL;
    initRotGains( inputMc->rot_gains_prev );
    inputMc->lfeRouting = defaultLfeRouting( inConfig, inputMc->customLsInput, outConfig, *inputMc->base.ctx.pCustomLsOut );
#ifdef FIX_194_LFE_DELAY_EXTREND
    set_zero( inputMc->lfeDelayBuffer, MAX_BIN_DELAY_SAMPLES );
#endif

#ifdef SPLIT_REND_WITH_HEAD_ROT
    for ( i = 0; i < (int16_t) ( sizeof( inputMc->splitTdRendWrappers ) / sizeof( *inputMc->splitTdRendWrappers ) ); ++i )
@@ -2428,6 +2485,9 @@ static void clearInputMc(

    rendCtx = inputMc->base.ctx;

#ifdef FIX_194_LFE_DELAY_EXTREND
    freeMcLfeDelayBuffer( &inputMc->lfeDelayBuffer );
#endif
    freeInputBaseBufferData( &inputMc->bufferData );
    initRendInputBase( &inputMc->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx,
                       NULL, 0 );
@@ -3577,6 +3637,9 @@ ivas_error IVAS_REND_Open(
        hIvasRend->inputsMc[i].hReverb = NULL;
        hIvasRend->inputsMc[i].tdRendWrapper.hBinRendererTd = NULL;
        hIvasRend->inputsMc[i].bufferData = NULL;
#ifdef FIX_194_LFE_DELAY_EXTREND
        hIvasRend->inputsMc[i].lfeDelayBuffer = NULL;
#endif
        hIvasRend->inputsMc[i].nonDiegeticPan = nonDiegeticPan;
        hIvasRend->inputsMc[i].nonDiegeticPanGain = nonDiegeticPanGain;
        hIvasRend->inputsMc[i].hMcMasa = NULL;
@@ -6191,13 +6254,21 @@ static ivas_error renderLfeToBinaural(
#endif
    IVAS_REND_AudioBuffer outAudio )
{
    int16_t i;
    int16_t lfe_idx;
#ifdef SPLIT_REND_WITH_HEAD_ROT
    int16_t pose_idx, num_poses;
#endif
    float gain;
#ifdef FIX_194_LFE_DELAY_EXTREND
    int16_t ear_idx;
    float tmpLfeBuffer[MAX_BUFFER_LENGTH_PER_CHANNEL];
    int16_t frame_size, num_cpy_smpl_cur_frame, num_cpy_smpl_prev_frame;
    const float *lfeInput;
    float *writePtr;
#else
    int16_t i;
    float *readPtr, *writePtr;
#endif

#ifdef SPLIT_REND_WITH_HEAD_ROT
    assert( ( getAudioConfigType( outConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && "Must be binaural output" );
@@ -6223,8 +6294,24 @@ static ivas_error renderLfeToBinaural(
        return IVAS_ERR_OK;
    }

#ifdef FIX_194_LFE_DELAY_EXTREND
    /* --- Prepare LFE signal to be added to binaural output --- */
    lfeInput = getSmplPtr( mcInput->base.inputBuffer, lfe_idx, 0 );
    frame_size = mcInput->base.inputBuffer.config.numSamplesPerChannel;
    num_cpy_smpl_prev_frame = mcInput->binauralDelaySmp;
    num_cpy_smpl_cur_frame = frame_size - num_cpy_smpl_prev_frame;
    /* Assuming LFE should be delayed by less that the duration of one frame */
    assert( mcInput->binauralDelaySmp < frame_size );
    /* Get delayed LFE signal from previous frame, apply gain and save in tmp buffer */
    v_multc( mcInput->lfeDelayBuffer, gain, tmpLfeBuffer, num_cpy_smpl_prev_frame );
    /* Continue filling tmp buffer, now with LFE signal from current frame */
    v_multc( lfeInput, gain, tmpLfeBuffer + num_cpy_smpl_prev_frame, num_cpy_smpl_cur_frame );
    /* Save remaining LFE samples of current frame for next frame */
    mvr2r( lfeInput + num_cpy_smpl_cur_frame, mcInput->lfeDelayBuffer, num_cpy_smpl_prev_frame );
#endif

#ifdef SPLIT_REND_WITH_HEAD_ROT
    /* Copy LFE to left and right binaural channels */
    /* Copy LFE to left and right binaural channels for all poses */
    if ( mcInput->base.ctx.pSplitRendWrapper != NULL )
    {
        num_poses = mcInput->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses;
@@ -6236,6 +6323,13 @@ static ivas_error renderLfeToBinaural(

    for ( pose_idx = 0; pose_idx < num_poses; ++pose_idx )
    {
#ifdef FIX_194_LFE_DELAY_EXTREND
        for ( ear_idx = 0; ear_idx < BINAURAL_CHANNELS; ++ear_idx )
        {
            writePtr = getSmplPtr( outAudio, pose_idx * BINAURAL_CHANNELS + ear_idx, 0 );
            v_add( writePtr, tmpLfeBuffer, writePtr, frame_size );
        }
#else
        readPtr = getSmplPtr( mcInput->base.inputBuffer, lfe_idx, 0 );
        writePtr = getSmplPtr( outAudio, pose_idx * BINAURAL_CHANNELS, 0 );
        for ( i = 0; i < mcInput->base.inputBuffer.config.numSamplesPerChannel; i++ )
@@ -6249,9 +6343,17 @@ static ivas_error renderLfeToBinaural(
        {
            *writePtr++ += gain * ( *readPtr++ );
        }
#endif /* FIX_194_LFE_DELAY_EXTREND */
    }
#else /* SPLIT_REND_WITH_HEAD_ROT */
    /* Copy LFE to left and right ears */
#ifdef FIX_194_LFE_DELAY_EXTREND
    for ( ear_idx = 0; ear_idx < BINAURAL_CHANNELS; ++ear_idx )
    {
        writePtr = getSmplPtr( outAudio, pose_idx * BINAURAL_CHANNELS + ear_idx, 0 );
        v_add( writePtr, tmpLfeBuffer, writePtr, frame_size );
    }
#else
    readPtr = getSmplPtr( mcInput->base.inputBuffer, lfe_idx, 0 );
    writePtr = getSmplPtr( outAudio, 0, 0 );
    for ( i = 0; i < mcInput->base.inputBuffer.config.numSamplesPerChannel; i++ )
@@ -6265,7 +6367,9 @@ static ivas_error renderLfeToBinaural(
    {
        *writePtr++ += gain * ( *readPtr++ );
    }
#endif /* FIX_194_LFE_DELAY_EXTREND */
#endif /* SPLIT_REND_WITH_HEAD_ROT */

    pop_wmops();

    return IVAS_ERR_OK;