Skip to content
Commits on Source (21)
......@@ -1717,7 +1717,12 @@ static ivas_error initOnFirstGoodFrame(
for ( int16_t j = 0; j < numInitialBadFrames; ++j )
{
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
float delayMs = (float) ( pFullDelayNumSamples[0] ) / (float) ( *delayTimeScale );
if ( ( error = MasaFileWriter_writeFrame( *ppMasaWriter, hMasaExtOutMeta, &delayMs ) ) != IVAS_ERR_OK )
#else
if ( ( error = MasaFileWriter_writeFrame( *ppMasaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK )
#endif
{
fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( *ppMasaWriter ) );
return error;
......@@ -2101,13 +2106,28 @@ static ivas_error decodeG192(
if ( bsFormat == IVAS_DEC_BS_MASA || bsFormat == IVAS_DEC_BS_MASA_ISM )
{
IVAS_MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
int16_t fullDelayNumSamples[3];
float delayMs;
/* delayNumSamples is zeroed, and delayNumSamples_orig is updated only on first good frame, so need to re-fetch delay info */
if ( ( error = IVAS_DEC_GetDelay( hIvasDec, fullDelayNumSamples, &delayTimeScale ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nUnable to get delay of decoder: %s\n", ivas_error_to_string( error ) );
}
#endif
if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta, 0 ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) );
goto cleanup;
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
delayMs = (float) ( fullDelayNumSamples[0] ) / (float) ( delayTimeScale );
if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta, &delayMs ) ) != IVAS_ERR_OK )
#else
if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK )
#endif
{
fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) );
goto cleanup;
......@@ -2233,13 +2253,27 @@ static ivas_error decodeG192(
if ( bsFormat == IVAS_DEC_BS_MASA || bsFormat == IVAS_DEC_BS_MASA_ISM )
{
IVAS_MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
int16_t fullDelayNumSamples[3];
float delayMs;
if ( ( error = IVAS_DEC_GetDelay( hIvasDec, fullDelayNumSamples, &delayTimeScale ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nUnable to get delay of decoder: %s\n", ivas_error_to_string( error ) );
}
#endif
if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta, 0 ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) );
goto cleanup;
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
delayMs = (float) ( fullDelayNumSamples[0] ) / (float) ( delayTimeScale );
if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta, &delayMs ) ) != IVAS_ERR_OK )
#else
if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK )
#endif
{
fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) );
goto cleanup;
......@@ -2785,13 +2819,28 @@ static ivas_error decodeVoIP(
if ( bsFormat == IVAS_DEC_BS_MASA || bsFormat == IVAS_DEC_BS_MASA_ISM )
{
IVAS_MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
int16_t fullDelayNumSamples[3];
float delayMs;
/* delayNumSamples_orig is fetched only for the first good frame, but here the delay can change between frames, so need to re-fetch */
if ( ( error = IVAS_DEC_GetDelay( hIvasDec, fullDelayNumSamples, &delayTimeScale ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nUnable to get delay of decoder: %s\n", ivas_error_to_string( error ) );
}
#endif
if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta, 1 ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) );
goto cleanup;
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
delayMs = (float) ( fullDelayNumSamples[0] ) / (float) ( delayTimeScale );
if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta, &delayMs ) ) != IVAS_ERR_OK )
#else
if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK )
#endif
{
fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) );
goto cleanup;
......
......@@ -1987,8 +1987,11 @@ int main(
}
}
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMetaOutput, NULL ) ) != IVAS_ERR_OK ) /* NULL -> use default metadata delay settings */
#else
if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMetaOutput ) ) != IVAS_ERR_OK )
#endif
{
fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) );
}
......
......@@ -147,7 +147,13 @@ typedef enum
RENDERER_NON_DIEGETIC_DOWNMIX,
RENDERER_OSBA_STEREO,
RENDERER_OSBA_AMBI,
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
RENDERER_OSBA_LS,
RENDERER_OMASA_OBJECT_EXT,
RENDERER_OMASA_MIX_EXT
#else
RENDERER_OSBA_LS
#endif
} RENDERER_TYPE;
#define MAX_FREQUENCY_BANDS 64
......
......@@ -156,6 +156,33 @@ void ivas_omasa_rearrange_channels_fx(
const Word16 output_frame /* i : output frame length per channel */
);
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
ivas_error ivas_omasa_combine_separate_ism_with_masa_open_fx(
Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
);
void ivas_omasa_combine_separate_ism_with_masa_fx(
Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */
Word32 *output[], /* o : output synthesis signal */
Word16 *output_q, /* i/o: output Q value */
const int16_t nchan_ism, /* i : number of ISMs */
const int16_t output_frame /* i : output frame length per channel */
);
ivas_error ivas_omasa_render_objects_from_mix_open_fx(
Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
);
void ivas_omasa_render_objects_from_mix_fx(
Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */
Word32 *output[], /* o : output synthesis signal */
const int16_t nchan_ism, /* i : number of ISMs */
const int16_t output_frame, /* i : output frame length per channel */
Word16 *output_q /* i/o: output Q value */
);
#endif
ivas_error ivas_omasa_ism_metadata_dec_fx(
Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
const Word32 ism_total_brate, /* i : ISM total bitrate */
......
......@@ -157,18 +157,17 @@
#ifdef NONBE_FIX_1058_DECODER_ERROR_WITH_REVERB_ROOM
#endif
#define USE_NEW_HRTF_BINARY_FILE_FORMAT /* Orange: to activate when decided to change the hrtf binary file format */
#define NONBE_FIX_984_OMASA_EXT_OUTPUT /* Nokia: issue #984: complete the OMASA EXT output implementation */
#define USE_NEW_HRTF_BINARY_FILE_FORMAT /* Orange: to activate when decided to change the hrtf binary file format */
#define FIX_WARNING_RENDER_CONFIG /* Orange: fix warning on windows build */
#define NONBE_FIX_991_PARAMBIN_BINARY_HRTF /* Nokia: issue #991: fix using of binary file HRTF in ParamBin (to activate when USE_NEW_HRTF_BINARY_FILE_FORMAT and FIX_777_COMBI_RENDER_CONFIG_FILE are on ) */
#define FIX_1741_REVERB_TIMES_Q_FORMAT /* Philips: reverberation times in Q26 format instead of Q31 */
#define FIX_1831_REVERB_REGRESSION /* Philips: fixes reverb regression issues */
#define FIX_1835_REVERB_ACTIVATION /* FhG: Modified reverberation activation logic and corrected factEQ calculation */
#define NON_BE_FIX_EVS_USAN_ERR_IN_WAVEADJUST /* FhG: address issue 1037 */
#define FIX_1038_OFFSET_TO_NULL_PTR_IN_EVS_TCX_BFI /* FhG: move setting of pointers for parameter decoding so they are skipped in lost frames when they are not needed */
/* #################### End BASOP porting switches ############################ */
#endif
......@@ -718,12 +718,20 @@ void decoder_LPD_fx(
FOR( k = 0; k < 2; k++ )
{
#ifndef FIX_1038_OFFSET_TO_NULL_PTR_IN_EVS_TCX_BFI
/* Set pointer to parameters */
prm = param + ( k * DEC_NPRM_DIV );
/* Stability Factor */
#endif
IF( bfi == 0 )
{
#ifdef FIX_1038_OFFSET_TO_NULL_PTR_IN_EVS_TCX_BFI
/* Set pointer to parameters */
prm = param + ( k * DEC_NPRM_DIV );
/* Stability Factor */
#endif
st->stab_fac_fx = lsf_stab_fx( &lsf[( ( k + 1 ) ) * M], &lsf[k * M], 0, L_FRAME );
move16();
}
......
......@@ -4411,7 +4411,15 @@ void decoder_tcx_invQ_fx(
tnsSize = 0;
move16();
#ifndef FIX_1038_OFFSET_TO_NULL_PTR_IN_EVS_TCX_BFI
prm_target = NULL; /* just to suppress MSVC warnigs */
#else
/* just to suppress MSVC warnigs */
prm_target = NULL;
prm_ltp = NULL;
prm_tns = NULL;
prm_sqQ = NULL;
#endif
/*-----------------------------------------------------------------*
* Initializations
......@@ -4435,8 +4443,10 @@ void decoder_tcx_invQ_fx(
move16();
}
#ifndef FIX_1038_OFFSET_TO_NULL_PTR_IN_EVS_TCX_BFI
prm_ltp = &prm[1 + NOISE_FILL_RANGES];
prm_tns = prm_ltp + LTPSIZE;
#endif
gainCompensate = ONE_IN_Q14;
move16();
......@@ -4452,6 +4462,10 @@ void decoder_tcx_invQ_fx(
IF( !bfi )
{
#ifdef FIX_1038_OFFSET_TO_NULL_PTR_IN_EVS_TCX_BFI
prm_ltp = &prm[1 + NOISE_FILL_RANGES];
prm_tns = prm_ltp + LTPSIZE;
#endif
index = prm[0];
move16();
......@@ -4473,9 +4487,11 @@ void decoder_tcx_invQ_fx(
move16();
}
#ifndef FIX_1038_OFFSET_TO_NULL_PTR_IN_EVS_TCX_BFI
prm_hm = prm_tns + tnsSize;
prm_sqQ = prm_hm + NPRM_CTX_HM;
*prm_sqQ1 = prm_sqQ;
#endif
/*-----------------------------------------------------------*
* Spectrum data *
......@@ -4483,6 +4499,11 @@ void decoder_tcx_invQ_fx(
IF( !bfi )
{
#ifdef FIX_1038_OFFSET_TO_NULL_PTR_IN_EVS_TCX_BFI
prm_hm = prm_tns + tnsSize;
prm_sqQ = prm_hm + NPRM_CTX_HM;
*prm_sqQ1 = prm_sqQ;
#endif
/*-----------------------------------------------------------*
* Context HM *
*-----------------------------------------------------------*/
......
......@@ -386,6 +386,26 @@ ivas_error ivas_dec_setup(
st_ivas->nchan_transport = 1;
move16();
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
/* this should be non-zero if original input format was MASA_ISM_FORMAT */
st_ivas->nchan_ism = add( st_ivas->bit_stream[L_sub( res_dec, 3 )], shl( st_ivas->bit_stream[L_sub( res_dec, 2 )], 1 ) );
IF( GT_16( st_ivas->nchan_ism, 0 ) )
{
/* the input_ivas_format should be MASA_ISM_FORMAT, but we cannot initialize it now */
test();
IF( EQ_16( st_ivas->nchan_transport, 2 ) && EQ_16( st_ivas->nchan_ism, 3 ) )
{
st_ivas->nchan_ism = 4;
move16();
}
/* for MASA_ISM_FORMAT at input the number of MASA transport channels is always 2 */
st_ivas->nchan_transport = 2;
element_mode_flag = 1;
move16();
move16();
}
#endif
IF( st_ivas->ini_frame > 0 )
{
......@@ -1232,6 +1252,9 @@ ivas_error ivas_init_decoder_fx(
IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
{
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
#endif
IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
{
hDecoderConfig->nchan_out = audioCfg2channels( IVAS_AUDIO_CONFIG_HOA3 );
......@@ -1239,7 +1262,11 @@ ivas_error ivas_init_decoder_fx(
hDecoderConfig->nchan_out = add( hDecoderConfig->nchan_out, st_ivas->nchan_ism );
move16();
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) || EQ_32( st_ivas->ivas_format, MASA_FORMAT ) )
#else
ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
#endif
{
hDecoderConfig->nchan_out = add( st_ivas->nchan_transport, st_ivas->nchan_ism );
move16();
......@@ -2391,7 +2418,39 @@ ivas_error ivas_init_decoder_fx(
return error;
}
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) )
{
/* Allocate 'hIsmRendererData' handle and memory for delay buffer within 'hMasaIsmData' */
error = ivas_omasa_render_objects_from_mix_open_fx( st_ivas );
move32();
IF( NE_32( error, IVAS_ERR_OK ) )
{
return error;
}
error = ivas_spat_hSpatParamRendCom_config_fx( &st_ivas->hSpatParamRendCom, DIRAC_OPEN, 0,
st_ivas->ivas_format, st_ivas->mc_mode, output_Fs, 0, 0 );
move32();
IF( NE_32( error, IVAS_ERR_OK ) )
{
return error;
}
}
IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) )
{
/* Allocate 'hIsmRendererData' handle */
error = ivas_omasa_combine_separate_ism_with_masa_open_fx( st_ivas );
move32();
IF( NE_32( error, IVAS_ERR_OK ) )
{
return error;
}
}
#endif
test();
test();
test();
......@@ -3360,6 +3419,19 @@ void ivas_init_dec_get_num_cldfb_instances(
move16();
}
BREAK;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
case RENDERER_OMASA_OBJECT_EXT:
*numCldfbAnalyses = st_ivas->nchan_transport;
*numCldfbSyntheses = st_ivas->hDecoderConfig->nchan_out;
move16();
move16();
break;
case RENDERER_OMASA_MIX_EXT:
*numCldfbAnalyses = add( st_ivas->nchan_transport, 1 );
*numCldfbSyntheses = 0;
move16();
break;
#endif
default:
assert( 0 && "Renderer not handled for CLDFB reservation." );
}
......@@ -3621,6 +3693,19 @@ void ivas_init_dec_get_num_cldfb_instances_ivas_fx(
move16();
}
BREAK;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
case RENDERER_OMASA_OBJECT_EXT:
*numCldfbAnalyses = st_ivas->nchan_transport;
*numCldfbSyntheses = st_ivas->hDecoderConfig->nchan_out;
move16();
move16();
break;
case RENDERER_OMASA_MIX_EXT:
*numCldfbAnalyses = add( st_ivas->nchan_transport, 1 );
*numCldfbSyntheses = 0;
move16();
break;
#endif
default:
assert( 0 && "Renderer not handled for CLDFB reservation." );
}
......@@ -3777,6 +3862,7 @@ static ivas_error doSanityChecks_IVAS(
}
}
#ifndef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
{
test();
......@@ -3786,7 +3872,7 @@ static ivas_error doSanityChecks_IVAS(
return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified for combined MASA and ISM format" );
}
}
#endif
return IVAS_ERR_OK;
}
......@@ -668,6 +668,20 @@ ivas_error ivas_jbm_dec_tc_fx(
{
Scale_sig32( p_output_fx[i], output_frame, negate( q_shift ) );
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
/* external output */
IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) &&
EQ_32( st_ivas->hMasa->config.input_ivas_format, MASA_ISM_FORMAT ) )
{
FOR( n = 0; n < st_ivas->nchan_ism; n++ )
{
set_zero_fx( p_output_fx[add( st_ivas->nchan_transport, n )], output_frame );
}
ivas_omasa_rearrange_channels_fx( p_output_fx, st_ivas->nchan_ism, output_frame );
}
#endif
}
ELSE IF( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) && ( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) )
{
......@@ -792,6 +806,22 @@ ivas_error ivas_jbm_dec_tc_fx(
}
ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
{
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
{
ivas_omasa_rearrange_channels_fx( p_output_fx, nchan_transport_ism, output_frame );
}
ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
{
/* Convert separate object to MASA, combine with the original MASA, and output combined MASA + empty objects. */
ivas_omasa_combine_separate_ism_with_masa_fx( st_ivas, p_output_fx, &output_q, st_ivas->nchan_ism, output_frame );
}
ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
{
/* Extract objects from MASA, output MASA + all objects (i.e., extracted and separated objects) */
ivas_omasa_render_objects_from_mix_fx( st_ivas, p_output_fx, st_ivas->nchan_ism, output_frame, &output_q );
}
#else
/* sanity check in case of bitrate switching */
IF( NE_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
{
......@@ -799,9 +829,7 @@ ivas_error ivas_jbm_dec_tc_fx(
}
ivas_omasa_rearrange_channels_fx( p_output_fx, nchan_transport_ism, output_frame );
output_q = 11;
move16();
#endif
ivas_jbm_dec_copy_masa_meta_to_buffer( st_ivas );
}
......@@ -1706,6 +1734,16 @@ void ivas_jbm_dec_feed_tc_to_renderer_fx(
}
ELSE IF( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
{
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) || EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) )
{
ivas_jbm_dec_td_renderers_adapt_subframes( st_ivas );
ivas_jbm_masa_sf_to_slot_map( st_ivas, n_render_timeslots );
}
ELSE
{
#endif
test();
IF( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
{
......@@ -1729,6 +1767,9 @@ void ivas_jbm_dec_feed_tc_to_renderer_fx(
{
ivas_ism_dec_digest_tc_fx( st_ivas );
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
}
#endif
if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_DIRAC )
{
......@@ -2110,6 +2151,9 @@ ivas_error ivas_jbm_dec_render_fx(
move16();
test();
test();
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
#endif
IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) )
{
test();
......@@ -2129,6 +2173,14 @@ ivas_error ivas_jbm_dec_render_fx(
{
ivas_omasa_dirac_rend_jbm_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx );
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) ||
EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) )
{
ivas_jbm_dec_tc_buffer_playout_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output_fx );
ivas_omasa_rearrange_channels_fx( p_output_fx, st_ivas->nchan_ism, *nSamplesRendered );
}
#endif
}
ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
{
......@@ -3927,6 +3979,10 @@ TC_BUFFER_MODE ivas_jbm_dec_get_tc_buffer_mode(
case RENDERER_PARAM_ISM:
case RENDERER_BINAURAL_MIXER_CONV:
case RENDERER_BINAURAL_MIXER_CONV_ROOM:
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
case RENDERER_OMASA_OBJECT_EXT:
case RENDERER_OMASA_MIX_EXT:
#endif
case RENDERER_OSBA_AMBI:
case RENDERER_OSBA_LS:
buffer_mode = TC_BUFFER_MODE_RENDERER;
......
......@@ -320,7 +320,33 @@ ivas_error ivas_masa_decode_fx(
}
}
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
/* read 2 bits:
'00' - MASA format at the encoder
'01' - MASA_ISM_FORMAT at the encoder, with 1 object
'10' - MASA_ISM_FORMAT at the encoder, with 2 objects
'11' - MASA_ISM_FORMAT at the encoder, with 3 or 4 objects
reading if 3 or 4 object is performed later
*/
byteBuffer = st->bit_stream[st->next_bit_pos];
move16();
st->next_bit_pos = sub( st->next_bit_pos, 1 );
byteBuffer = add( byteBuffer, shl( st->bit_stream[st->next_bit_pos], 1 ) );
st->next_bit_pos = sub( st->next_bit_pos, 1 );
test();
IF( EQ_16( byteBuffer, 0 ) && EQ_32( ivas_format, MASA_FORMAT ) )
{
hMasa->config.input_ivas_format = MASA_FORMAT;
move32();
}
ELSE
{
hMasa->config.input_ivas_format = MASA_ISM_FORMAT;
move32();
}
#else
/* read the MASA_ISM_FORMAT bit */
byteBuffer = st->bit_stream[( st->next_bit_pos )--];
move16();
......@@ -337,6 +363,7 @@ ivas_error ivas_masa_decode_fx(
/* reserved bit */
byteBuffer = st->bit_stream[( st->next_bit_pos )--];
move16();
#endif
*nb_bits_read = add( *nb_bits_read, MASA_HEADER_BITS );
/* read number of directions */
......@@ -418,7 +445,8 @@ ivas_error ivas_masa_decode_fx(
{
IF( st_ivas->hDirAC != NULL )
{
*nb_bits_read = add( *nb_bits_read, ivas_decode_masaism_metadata_fx( hQMetaData, st_ivas->hMasa, st_ivas->hMasaIsmData, st_ivas->nchan_ism, st->bit_stream, &st->next_bit_pos,
*nb_bits_read = add( *nb_bits_read,
ivas_decode_masaism_metadata_fx( hQMetaData, st_ivas->hMasa, st_ivas->hMasaIsmData, st_ivas->nchan_ism, st->bit_stream, &st->next_bit_pos,
st_ivas->hMasaIsmData->idx_separated_ism, ism_imp, st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx, st_ivas->hSpatParamRendCom->dirac_md_buffer_length ) );
move16();
FOR( obj = 0; obj <= st_ivas->nchan_ism; obj++ )
......@@ -439,6 +467,14 @@ ivas_error ivas_masa_decode_fx(
}
}
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) )
{
*nb_bits_read = add( *nb_bits_read, ivas_decode_masaism_metadata_fx( hQMetaData, st_ivas->hMasa, st_ivas->hMasaIsmData,
st_ivas->nchan_ism, st->bit_stream, &st->next_bit_pos,
st_ivas->hMasaIsmData->idx_separated_ism, ism_imp, st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx, st_ivas->hSpatParamRendCom->dirac_md_buffer_length ) );
}
#endif
ELSE
{
*nb_bits_read = add( *nb_bits_read, ivas_decode_masaism_metadata_fx( hQMetaData, st_ivas->hMasa, st_ivas->hMasaIsmData, st_ivas->nchan_ism, st->bit_stream, &st->next_bit_pos,
......@@ -587,7 +623,19 @@ ivas_error ivas_masa_decode_fx(
ivas_qmetadata_to_dirac_fx( hQMetaData, st_ivas->hDirAC, hMasa, st_ivas->hSpatParamRendCom, ivas_total_brate, ivas_format, 0, 0 );
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) )
{
Word16 index = add( st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx, MAX_PARAM_SPATIAL_SUBFRAMES );
IF( GE_16( index, st_ivas->hSpatParamRendCom->dirac_md_buffer_length ) )
{
index = sub( index, st_ivas->hSpatParamRendCom->dirac_md_buffer_length );
}
st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx = index;
move16();
}
#endif
IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
{
IF( hQMetaData->q_direction == NULL )
......@@ -743,7 +791,18 @@ ivas_error ivas_masa_dec_open_fx(
ism_total_brate = 0;
move32();
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
/* ISM metadata */
test();
test();
if ( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) &&
st_ivas->hIsmMetaData[0] != NULL &&
EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
{
/* these are not needed -> clean. EXT metafile writer in OMASA needs only the number of ISMs and writes default null-data */
ivas_ism_metadata_close( st_ivas->hIsmMetaData, 0 );
}
#endif
test();
test();
test();
......@@ -826,7 +885,10 @@ ivas_error ivas_masa_dec_open_fx(
nchan_transport = ivas_jbm_dec_get_num_tc_channels_fx( st_ivas );
nchan_to_allocate = nchan_transport;
move16();
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
test();
#endif
test();
test();
IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) )
......@@ -836,6 +898,15 @@ ivas_error ivas_masa_dec_open_fx(
nchan_to_allocate = 1;
move16();
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) &&
( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) ||
EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) ) )
{
nchan_transport = add( st_ivas->nchan_transport, st_ivas->nchan_ism );
nchan_to_allocate = add( st_ivas->nchan_transport, st_ivas->nchan_ism );
}
#endif
ELSE IF( EQ_16( st_ivas->nchan_transport, 1 ) && EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) )
{
/* addtl channel for CNG */
......@@ -1830,8 +1901,18 @@ ivas_error ivas_masa_dec_reconfigure_fx(
IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) )
{
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( NE_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
{
move16();
st_ivas->nchan_ism = 0; /* Initialization if it has not been already read from the end of the bitstream at the same time
with reading of the format: nchan_ism is needed in MASA format because for the EXT output in
MASA-only (pre-rendering mode of OMASA) the number of ISMs to output correct number of empty objects is needed */
}
#else
st_ivas->nchan_ism = 0;
move16();
#endif
st_ivas->ism_mode = ISM_MODE_NONE;
move16();
}
......@@ -1854,6 +1935,10 @@ ivas_error ivas_masa_dec_reconfigure_fx(
test();
test();
test();
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
test();
#endif
IF( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_16( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) )
{
IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
......@@ -1894,7 +1979,15 @@ ivas_error ivas_masa_dec_reconfigure_fx(
/* addtl channel for CNG */
tc_nchan_to_allocate = add( tc_nchan_to_allocate, 1 );
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) &&
( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) ||
EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) ) )
{
tc_nchan_transport = add( st_ivas->nchan_transport, st_ivas->nchan_ism );
tc_nchan_to_allocate = add( st_ivas->nchan_transport, st_ivas->nchan_ism );
}
#endif
test();
test();
IF( NE_16( tc_nchan_transport, st_ivas->hTcBuffer->nchan_transport_jbm ) || NE_16( tc_nchan_to_allocate, st_ivas->hTcBuffer->nchan_transport_internal ) || NE_16( buffer_mode_new, st_ivas->hTcBuffer->tc_buffer_mode ) )
......@@ -3332,6 +3425,14 @@ static Word16 ivas_decode_masaism_metadata_fx(
hMasaIsmData->energy_ratio_ism_fx[dir][meta_write_index][b] = energy_ratio_ism_fx[i][band][dir];
move32();
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( hMasaIsmData->hExtData != NULL )
{
hMasaIsmData->hExtData->masa_render_masa_to_total[meta_write_index][b] =
hMasaIsmData->masa_to_total_energy_ratio_fx[i][band];
move32();
}
#endif
}
}
}
......
......@@ -32,6 +32,9 @@
#include "options.h"
#include <stdlib.h>
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
#include <math.h>
#endif
#include "ivas_cnst.h"
#include "ivas_prot_fx.h"
#include "prot_fx.h"
......@@ -45,6 +48,223 @@
* Local constants
*------------------------------------------------------------------------*/
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
#define EXT_RENDER_IIR_FAC 0.95f
#define MULT_17_DIV_20_Q15 ( Word16 )( ( 17.0 / 20.0f ) * pow( 2, 15 ) + 0.5f )
#define MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 ( Word16 )( ( 1.0 / CLDFB_NO_COL_MAX ) * pow( 2, 15 ) + 0.5f )
#define ONEMINUX_EXT_RENDER_IIR_FAC_Q31 ( Word32 )( ( 1.0f - EXT_RENDER_IIR_FAC ) * pow( 2, 31 ) + 0.5f )
#define EXT_RENDER_IIR_FAC_Q31 ( Word32 )( EXT_RENDER_IIR_FAC * pow( 2, 31 ) + 0.5f )
// Calculated as (Word16)(((1.0f / (50 * MAX_PARAM_SPATIAL_SUBFRAMES)) * pow(2, 15)) + 0.5f)
#define OMASA_DELAYFRAMES_PER_SEC_Q15 (Word16) 164 // Q15
static Word16 interpolator_table_48k_q15[] = {
0, 137, 273, 410, 546, 683, 819, 956, 1092, 1229,
1365, 1502, 1638, 1775, 1911, 2048, 2185, 2321, 2458, 2594,
2731, 2867, 3004, 3140, 3277, 3413, 3550, 3686, 3823, 3959,
4096, 4233, 4369, 4506, 4642, 4779, 4915, 5052, 5188, 5325,
5461, 5598, 5734, 5871, 6007, 6144, 6281, 6417, 6554, 6690,
6827, 6963, 7100, 7236, 7373, 7509, 7646, 7782, 7919, 8055,
8192, 8329, 8465, 8602, 8738, 8875, 9011, 9148, 9284, 9421,
9557, 9694, 9830, 9967, 10103, 10240, 10377, 10513, 10650, 10786,
10923, 11059, 11196, 11332, 11469, 11605, 11742, 11878, 12015, 12151,
12288, 12425, 12561, 12698, 12834, 12971, 13107, 13244, 13380, 13517,
13653, 13790, 13926, 14063, 14199, 14336, 14473, 14609, 14746, 14882,
15019, 15155, 15292, 15428, 15565, 15701, 15838, 15974, 16111, 16247,
16384, 16521, 16657, 16794, 16930, 17067, 17203, 17340, 17476, 17613,
17749, 17886, 18022, 18159, 18295, 18432, 18569, 18705, 18842, 18978,
19115, 19251, 19388, 19524, 19661, 19797, 19934, 20070, 20207, 20343,
20480, 20617, 20753, 20890, 21026, 21163, 21299, 21436, 21572, 21709,
21845, 21982, 22118, 22255, 22391, 22528, 22665, 22801, 22938, 23074,
23211, 23347, 23484, 23620, 23757, 23893, 24030, 24166, 24303, 24439,
24576, 24713, 24849, 24986, 25122, 25259, 25395, 25532, 25668, 25805,
25941, 26078, 26214, 26351, 26487, 26624, 26761, 26897, 27034, 27170,
27307, 27443, 27580, 27716, 27853, 27989, 28126, 28262, 28399, 28535,
28672, 28809, 28945, 29082, 29218, 29355, 29491, 29628, 29764, 29901,
30037, 30174, 30310, 30447, 30583, 30720, 30857, 30993, 31130, 31266,
31403, 31539, 31676, 31812, 31949, 32085, 32222, 32358, 32495, 32631
};
static Word16 interpolator_table_32k_q15[] = {
0, 205, 410, 614, 819, 1024, 1229, 1434, 1638, 1843,
2048, 2253, 2458, 2662, 2867, 3072, 3277, 3482, 3686, 3891,
4096, 4301, 4506, 4710, 4915, 5120, 5325, 5530, 5734, 5939,
6144, 6349, 6554, 6758, 6963, 7168, 7373, 7578, 7782, 7987,
8192, 8397, 8602, 8806, 9011, 9216, 9421, 9626, 9830, 10035,
10240, 10445, 10650, 10854, 11059, 11264, 11469, 11674, 11878, 12083,
12288, 12493, 12698, 12902, 13107, 13312, 13517, 13722, 13926, 14131,
14336, 14541, 14746, 14950, 15155, 15360, 15565, 15770, 15974, 16179,
16384, 16589, 16794, 16998, 17203, 17408, 17613, 17818, 18022, 18227,
18432, 18637, 18842, 19046, 19251, 19456, 19661, 19866, 20070, 20275,
20480, 20685, 20890, 21094, 21299, 21504, 21709, 21914, 22118, 22323,
22528, 22733, 22938, 23142, 23347, 23552, 23757, 23962, 24166, 24371,
24576, 24781, 24986, 25190, 25395, 25600, 25805, 26010, 26214, 26419,
26624, 26829, 27034, 27238, 27443, 27648, 27853, 28058, 28262, 28467,
28672, 28877, 29082, 29286, 29491, 29696, 29901, 30106, 30310, 30515,
30720, 30925, 31130, 31334, 31539, 31744, 31949, 32154, 32358, 32563
};
static Word16 interpolator_table_16k_q15[] = {
0, 410, 819, 1229, 1638, 2048, 2458, 2867, 3277, 3686,
4096, 4506, 4915, 5325, 5734, 6144, 6554, 6963, 7373, 7782,
8192, 8602, 9011, 9421, 9830, 10240, 10650, 11059, 11469, 11878,
12288, 12698, 13107, 13517, 13926, 14336, 14746, 15155, 15565, 15974,
16384, 16794, 17203, 17613, 18022, 18432, 18842, 19251, 19661, 20070,
20480, 20890, 21299, 21709, 22118, 22528, 22938, 23347, 23757, 24166,
24576, 24986, 25395, 25805, 26214, 26624, 27034, 27443, 27853, 28262,
28672, 29082, 29491, 29901, 30310, 30720, 31130, 31539, 31949, 32358
};
/**
* Calculate mantissa (Q31) * gain (Q31).
*
* Exponent for the mantissa value is also included as input parameter.
* Adjust the result so that accuracy of the mantissa multiplication is maximixed
* and the corresponding exponent is minimized.
*/
static Word32 mult32_mantissa_fx( Word32 mantissa, Word32 gain, Word16 exp, Word16 *exp_result )
{
Word64 mult = W_mult_32_32( mantissa, gain ); // Q31 * Q31 -> Q63
Word16 norm = W_norm( mult );
Word32 result = W_extract_h( W_shl( mult, norm ) ); // Q63 -> Q31
*exp_result = sub( exp, norm );
return result;
}
/**
* Calculate re^2 + im^2 using exponent (Q0) and mantissa (Q31) format.
*/
static Word32 sample_energy_fx( Word32 re_m, Word16 re_e, Word32 im_m, Word16 im_e, Word16 *exp_result )
{
Word16 re_exp = add( re_e, re_e );
Word32 re_mult = mult32_mantissa_fx( re_m, re_m, re_exp, &re_exp );
move32();
Word16 im_exp = add( im_e, im_e );
Word32 im_mult = mult32_mantissa_fx( im_m, im_m, im_exp, &im_exp );
move32();
return BASOP_Util_Add_Mant32Exp( re_mult, re_exp, im_mult, im_exp, exp_result );
}
/**
* Accumulate sum of re^2 + im^2 over the specified length using exponent (Q0) and mantissa (Q31) format.
*/
static void sample_energy_acc_fx( Word32 *re_m, Word16 *re_e, Word32 *im_m, Word16 *im_e, Word32 *out_m, Word16 *out_e, Word16 len )
{
Word16 i;
FOR( i = 0; i < len; i++ )
{
Word16 exp;
// energy = re^2 + im^2
Word32 mantissa = sample_energy_fx( re_m[i], re_e[i], im_m[i], im_e[i], &exp );
move32();
// Accumulate energy
*out_m = BASOP_Util_Add_Mant32Exp( *out_m, *out_e, mantissa, exp, out_e );
move32();
}
}
// Multiplication of vector (comprising of exponent and mantissa parts) by constant value (Q31)
static void v_multc_exp_mantissa_fx(
const Word32 *in_mantissa,
const Word16 *in_exp,
Word32 c,
Word32 *out_mantissa,
Word16 *out_exp,
Word16 len )
{
Word16 i;
FOR( i = 0; i < len; i++ )
{
out_mantissa[i] = mult32_mantissa_fx( in_mantissa[i], c, in_exp[i], &out_exp[i] );
move32();
}
}
// Multiplication of vector (comprising of exponent and mantissa parts) by constant acumulate to the output
static void v_multc_acc_exp_mantissa_fx(
const Word32 *in_mantissa,
const Word16 *in_exp,
Word32 c,
Word32 *out_mantissa,
Word16 *out_exp,
Word16 len )
{
Word16 i;
FOR( i = 0; i < len; i++ )
{
Word16 exp;
Word32 mantissa = mult32_mantissa_fx( in_mantissa[i], c, in_exp[i], &exp );
move32();
out_mantissa[i] = BASOP_Util_Add_Mant32Exp( out_mantissa[i], out_exp[i],
mantissa, exp, &out_exp[i] );
move32();
}
}
// Calculate min( 4, sqrtf( target / proto ) )
// target and proto values are expressed using exponent and mantissa
static Word32 get_processing_gain_fx( Word32 proto_m, Word16 proto_e, Word32 target_m, Word16 target_e, Word16 *exp )
{
Word16 b = extract_h( proto_m );
IF( EQ_16( b, 0 ) )
{
b = 1;
move16();
}
Word16 mantissa;
BASOP_Util_Divide_MantExp( extract_h( target_m ), target_e, b, proto_e, &mantissa, exp );
Word32 sqrt_mantissa = Sqrt32( L_shl( mantissa, 16 ), exp );
Word16 norm = norm_l( sqrt_mantissa );
sqrt_mantissa = L_shl( sqrt_mantissa, norm );
*exp = sub( *exp, norm );
test();
IF( GT_16( *exp, 2 ) && NE_32( sqrt_mantissa, 0 ) )
{
// (2^3) * (1073741824 / 2^31) == 4.0
sqrt_mantissa = ONE_IN_Q30; // 0.5 in Q31
*exp = 3;
move32();
move16();
}
return sqrt_mantissa;
}
static void mantissa_exp_to_qvalue( Word16 *exp, Word32 *output, Word16 target_exp, Word16 len )
{
Word16 bin;
FOR( bin = 0; bin < len; bin++ )
{
IF( LT_16( exp[bin], -Q31 ) )
{
output[bin] = 0;
move32();
}
ELSE
{
Word16 shift = sub( target_exp, exp[bin] );
output[bin] = W_sat_l( W_shr( output[bin], shift ) );
}
}
}
#endif
/*-------------------------------------------------------------------*
* ivas_omasa_data_open()
......@@ -110,6 +330,51 @@ ivas_error ivas_omasa_data_open_fx(
set16_fx( hMasaIsmData->azimuth_separated_ism, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
set16_fx( hMasaIsmData->elevation_separated_ism, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
hMasaIsmData->hExtData = NULL;
move32();
IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
{
MASA_ISM_EXT_DATA_HANDLE hExtData;
hExtData = (MASA_ISM_EXT_DATA_HANDLE) malloc( sizeof( MASA_ISM_EXT_DATA ) );
move32();
IF( hExtData == NULL )
{
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA ISM data\n" ) );
}
hExtData->prev_idx_separated_ism = 0;
move16();
FOR( ch = 0; ch < MAX_NUM_OBJECTS; ch++ )
{
set32_fx( hExtData->prev_panning_gains[ch], 0, 2 );
}
FOR( ch = 0; ch < MAX_NUM_OBJECTS; ch++ )
{
set32_fx( hExtData->ism_render_proto_energy_frac[ch], 0, CLDFB_NO_CHANNELS_MAX );
set16_fx( hExtData->ism_render_proto_energy_exp[ch], 0, CLDFB_NO_CHANNELS_MAX );
set32_fx( hExtData->ism_render_target_energy_frac[ch], 0, CLDFB_NO_CHANNELS_MAX );
set16_fx( hExtData->ism_render_target_energy_exp[ch], 0, CLDFB_NO_CHANNELS_MAX );
}
set32_fx( hExtData->masa_render_proto_energy_frac, 0, CLDFB_NO_CHANNELS_MAX );
set16_fx( hExtData->masa_render_proto_energy_exp, 0, CLDFB_NO_CHANNELS_MAX );
set32_fx( hExtData->masa_render_target_energy_frac, 0, CLDFB_NO_CHANNELS_MAX );
set16_fx( hExtData->masa_render_target_energy_exp, 0, CLDFB_NO_CHANNELS_MAX );
FOR( sf = 0; sf < add( MAX_PARAM_SPATIAL_SUBFRAMES, DELAY_MASA_PARAM_DEC_SFR ); sf++ )
{
set32_fx( hExtData->masa_render_masa_to_total[sf], 0, CLDFB_NO_CHANNELS_MAX );
}
hMasaIsmData->hExtData = hExtData;
move32();
}
#endif
st_ivas->hMasaIsmData = hMasaIsmData;
return IVAS_ERR_OK;
......@@ -143,7 +408,14 @@ void ivas_omasa_data_close_fx(
free( ( *hMasaIsmData )->delayBuffer_fx );
( *hMasaIsmData )->delayBuffer_fx = NULL;
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( ( *hMasaIsmData )->hExtData != NULL )
{
free( ( *hMasaIsmData )->hExtData );
( *hMasaIsmData )->hExtData = NULL;
move32();
}
#endif
free( *hMasaIsmData );
*hMasaIsmData = NULL;
......@@ -293,7 +565,59 @@ ivas_error ivas_omasa_dec_config_fx(
/* ISM MD reconfig. */
n_MD = 0;
move16();
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
{
/* the full number of hIsmMetaData are needed for EXT output */
move16();
n_MD = st_ivas->nchan_ism;
ivas_ism_metadata_close( st_ivas->hIsmMetaData, 0 );
error = ivas_ism_metadata_dec_create_fx( st_ivas, st_ivas->nchan_ism, NULL );
move32();
IF( NE_32( error, IVAS_ERR_OK ) )
{
return error;
}
ivas_ism_metadata_close( st_ivas->hIsmMetaData, n_MD );
}
ELSE
{
test();
IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
{
n_MD = 1;
move16();
IF( st_ivas->hIsmMetaData[0] == NULL )
{
error = ivas_ism_metadata_dec_create_fx( st_ivas, 1, NULL );
move32();
IF( NE_32( error, IVAS_ERR_OK ) )
{
return error;
}
}
}
ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
{
n_MD = st_ivas->nchan_ism;
move16();
ivas_ism_metadata_close( st_ivas->hIsmMetaData, 0 );
error = ivas_ism_metadata_dec_create_fx( st_ivas, st_ivas->nchan_ism, NULL );
move32();
IF( NE_32( error, IVAS_ERR_OK ) )
{
return error;
}
}
ivas_ism_metadata_close( st_ivas->hIsmMetaData, n_MD );
}
#else
test();
IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
{
......@@ -322,7 +646,7 @@ ivas_error ivas_omasa_dec_config_fx(
}
ivas_ism_metadata_close( st_ivas->hIsmMetaData, n_MD );
#endif
st_ivas->hCPE[0]->element_brate = L_sub( ivas_total_brate, ism_total_brate );
/*-----------------------------------------------------------------*
......@@ -351,8 +675,15 @@ ivas_error ivas_omasa_dec_config_fx(
}
/* objects renderer reconfig. */
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
IF( st_ivas->hMasaIsmData != NULL || st_ivas->hIsmRendererData != NULL )
{
/* this calls also ivas_ism_renderer_close() closing st_ivas->hIsmRendererData used by the EXT renderers. also cleans st_ivas->hMasaIsmData */
#else
IF( st_ivas->hMasaIsmData != NULL )
{
#endif
ivas_omasa_separate_object_renderer_close( st_ivas );
}
......@@ -414,7 +745,49 @@ ivas_error ivas_omasa_dec_config_fx(
ivas_omasa_separate_object_renderer_close( st_ivas );
}
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) )
{
/* Allocate 'hIsmRendererData' handle */
error = ivas_omasa_combine_separate_ism_with_masa_open_fx( st_ivas );
move32();
IF( NE_32( error, IVAS_ERR_OK ) )
{
return error;
}
}
IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) )
{
DIRAC_CONFIG_FLAG common_rend_config_flag;
IF( st_ivas->hSpatParamRendCom == NULL )
{
common_rend_config_flag = DIRAC_OPEN;
}
ELSE
{
common_rend_config_flag = DIRAC_RECONFIGURE;
}
move32();
/* Allocate 'hIsmRendererData' handle and memory for delay buffer within 'hMasaIsmData' */
error = ivas_omasa_render_objects_from_mix_open_fx( st_ivas );
move32();
IF( NE_32( error, IVAS_ERR_OK ) )
{
return error;
}
error = ivas_spat_hSpatParamRendCom_config_fx( &st_ivas->hSpatParamRendCom,
common_rend_config_flag, 0,
st_ivas->ivas_format, st_ivas->mc_mode, st_ivas->hDecoderConfig->output_Fs, 0, 0 );
move32();
IF( NE_32( error, IVAS_ERR_OK ) )
{
return error;
}
}
#endif
/*-----------------------------------------------------------------*
* TD Decorrelator
*-----------------------------------------------------------------*/
......@@ -600,7 +973,9 @@ ivas_error ivas_omasa_ism_metadata_dec_fx(
*nchan_transport_ism = 1;
move16();
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
#endif
test();
IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
{
......@@ -666,6 +1041,37 @@ ivas_error ivas_omasa_ism_metadata_dec_fx(
}
}
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) &&
EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
{
azimuth_ism = extract_l( L_shr_r( L_abs( st_ivas->hIsmMetaData[0]->azimuth_fx ), 22 ) );
if ( st_ivas->hIsmMetaData[0]->azimuth_fx < 0 )
{
azimuth_ism = negate( azimuth_ism );
}
elevation_ism = extract_l( L_shr_r( L_abs( st_ivas->hIsmMetaData[0]->elevation_fx ), 22 ) );
if ( st_ivas->hIsmMetaData[0]->elevation_fx < 0 )
{
elevation_ism = negate( elevation_ism );
}
FOR( block = 0; block < 2; block++ )
{
st_ivas->hMasaIsmData->azimuth_separated_ism[block] = st_ivas->hMasaIsmData->azimuth_separated_ism[add( block, 2 )];
st_ivas->hMasaIsmData->elevation_separated_ism[block] = st_ivas->hMasaIsmData->elevation_separated_ism[add( block, 2 )];
move16();
move16();
}
FOR( block = 2; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ )
{
st_ivas->hMasaIsmData->azimuth_separated_ism[block] = azimuth_ism;
st_ivas->hMasaIsmData->elevation_separated_ism[block] = elevation_ism;
move16();
move16();
}
}
#endif
}
return IVAS_ERR_OK;
......@@ -865,3 +1271,846 @@ void ivas_omasa_rearrange_channels_fx(
return;
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
/*-------------------------------------------------------------------------*
* ivas_omasa_combine_separate_ism_with_masa_open_fx()
*
* Open structures, reserve memory, and init values.
*-------------------------------------------------------------------------*/
ivas_error ivas_omasa_combine_separate_ism_with_masa_open_fx( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
)
{
Word16 i;
Word16 *tmp;
st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) malloc( sizeof( ISM_RENDERER_DATA ) );
move32();
IF( st_ivas->hIsmRendererData == NULL )
{
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM renderer \n" ) );
}
FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
{
set_zero_fx( st_ivas->hIsmRendererData->prev_gains_fx[i], MAX_OUTPUT_CHANNELS );
}
test();
test();
IF( EQ_32( st_ivas->hDecoderConfig->output_Fs, 16000 ) ||
EQ_32( st_ivas->hDecoderConfig->output_Fs, 32000 ) ||
EQ_32( st_ivas->hDecoderConfig->output_Fs, 48000 ) )
{
IF( EQ_32( st_ivas->hDecoderConfig->output_Fs, 16000 ) )
{
st_ivas->hIsmRendererData->interpolator_len = 80;
tmp = interpolator_table_16k_q15;
}
ELSE IF( EQ_32( st_ivas->hDecoderConfig->output_Fs, 32000 ) )
{
st_ivas->hIsmRendererData->interpolator_len = 160;
tmp = interpolator_table_32k_q15;
}
ELSE
{
st_ivas->hIsmRendererData->interpolator_len = 240;
tmp = interpolator_table_48k_q15;
}
move16();
move32();
st_ivas->hIsmRendererData->interpolator_fx =
(Word16 *) malloc( sizeof( Word16 ) * st_ivas->hIsmRendererData->interpolator_len );
IF( st_ivas->hIsmRendererData->interpolator_fx == NULL )
{
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA ISM renderer interpolator\n" ) );
}
FOR( i = 0; i < st_ivas->hIsmRendererData->interpolator_len; i++ )
{
st_ivas->hIsmRendererData->interpolator_fx[i] = tmp[i];
move16();
}
}
ELSE
{
return ( IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Unsupported output sample rate\n" ) );
}
return IVAS_ERR_OK;
}
/*--------------------------------------------------------------------------*
* ivas_omasa_combine_separate_ism_with_masa_fx()
*
* in case of external rendering, combine separated ISM signal with MASA stream
*--------------------------------------------------------------------------*/
void ivas_omasa_combine_separate_ism_with_masa_fx(
Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */
Word32 *output[], /* i/o: output synthesis signal */
Word16 *output_q, /* i/o: output Q value */
const int16_t nchan_ism, /* i : number of ISMs */
const int16_t output_frame /* i : output frame length per channel */
)
{
Word16 n, sf, band, k;
MASA_DECODER_EXT_OUT_META_HANDLE masaMetaHandle;
MASA_DECODER_EXT_OUT_META_HANDLE ismMetaHandle;
MASA_DECODER_EXT_OUT_META ismMeta;
Word32 inRe[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word32 inIm[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
UWord16 directionIndex;
Word16 nchan_in;
Word16 nBins;
Word16 slot;
Word16 mrange[2], brange[2];
Word16 processing_len, offset;
Word32 old_panning_gains_fx[2];
Word32 new_panning_gains_fx[2];
Word16 inRe_exp[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word16 inIm_exp[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word16 out_exp[MASA_MAX_TRANSPORT_CHANNELS + 1][L_FRAME48k];
Word16 eneMasa_exp[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
Word32 eneMasa_frac[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
Word16 eneIsm_exp[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
Word32 eneIsm_frac[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
Word16 old_panning_gains_q15_fx[2];
Word16 new_panning_gains_q15_fx[2];
Word16 exp;
masaMetaHandle = st_ivas->hMasa->data.extOutMeta;
ismMetaHandle = &ismMeta;
move32();
move32();
/* Compute CLDFB analysis */
nchan_in = add( st_ivas->nchan_transport, 1 );
nBins = mult( output_frame, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 ); // Q15
FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
{
FOR( n = 0; n < nchan_in; n++ )
{
Word16 in_q = *output_q;
move16();
cldfbAnalysis_ts_fx_var_q( &( output[n][L_mult0( nBins, slot )] ),
inRe[n][slot],
inIm[n][slot],
nBins, st_ivas->cldfbAnaDec[n], &in_q );
/* Assign input exponent */
exp = sub( Q31, in_q );
set16_fx( inRe_exp[n][slot], exp, nBins );
set16_fx( inIm_exp[n][slot], exp, nBins );
}
}
/* Convert output to exponent+mantissa representation */
exp = sub( Q31, *output_q );
FOR( n = 0; n < add( MASA_MAX_TRANSPORT_CHANNELS, 1 ); n++ )
{
set16_fx( out_exp[n], exp, output_frame );
}
FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
{
set16_fx( eneMasa_exp[sf], 0, MASA_FREQUENCY_BANDS );
set32_fx( eneMasa_frac[sf], 0, MASA_FREQUENCY_BANDS );
set16_fx( eneIsm_exp[sf], 0, MASA_FREQUENCY_BANDS );
set32_fx( eneIsm_frac[sf], 0, MASA_FREQUENCY_BANDS );
}
/* Determine energies */
FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
{
mrange[0] = st_ivas->hMasa->config.block_grouping[sf];
mrange[1] = st_ivas->hMasa->config.block_grouping[add( sf, 1 )];
move16();
move16();
FOR( slot = mrange[0]; slot < mrange[1]; slot++ )
{
FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
{
brange[0] = st_ivas->hMasa->config.band_grouping[band];
brange[1] = st_ivas->hMasa->config.band_grouping[add( band, 1 )];
move16();
move16();
IF( GT_16( brange[1], nBins ) )
{
brange[1] = nBins;
move16();
}
Word16 len = sub( brange[1], brange[0] );
FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
{
sample_energy_acc_fx( &inRe[n][slot][brange[0]],
&inRe_exp[n][slot][brange[0]],
&inIm[n][slot][brange[0]],
&inIm_exp[n][slot][brange[0]],
&eneMasa_frac[sf][band],
&eneMasa_exp[sf][band],
len );
}
sample_energy_acc_fx( &inRe[MASA_MAX_TRANSPORT_CHANNELS][slot][brange[0]],
&inRe_exp[MASA_MAX_TRANSPORT_CHANNELS][slot][brange[0]],
&inIm[MASA_MAX_TRANSPORT_CHANNELS][slot][brange[0]],
&inIm_exp[MASA_MAX_TRANSPORT_CHANNELS][slot][brange[0]],
&eneIsm_frac[sf][band],
&eneIsm_exp[sf][band],
len );
}
}
}
/* Determine MASA metadata for the object */
ismMetaHandle->descriptiveMeta.numberOfDirections = 0u;
move16();
FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
{
Word32 ele, azi;
ele = st_ivas->hMasaIsmData->elevation_separated_ism[sf];
azi = st_ivas->hMasaIsmData->azimuth_separated_ism[sf];
directionIndex = index_theta_phi_16_fx( &ele, &azi, st_ivas->hMasa->data.sph_grid16 );
FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
{
ismMetaHandle->directionIndex[0][sf][band] = directionIndex;
ismMetaHandle->directToTotalRatio[0][sf][band] = UINT8_MAX;
ismMetaHandle->spreadCoherence[0][sf][band] = 0;
ismMetaHandle->surroundCoherence[sf][band] = 0;
ismMetaHandle->diffuseToTotalRatio[sf][band] = 0;
move16();
move16();
move16();
move16();
move16();
}
}
/* Merge MASA metadatas */
ivas_prerend_merge_masa_metadata_fx( masaMetaHandle, masaMetaHandle,
IVAS_REND_AUDIO_CONFIG_TYPE_MASA,
eneMasa_frac, eneMasa_exp, ismMetaHandle, IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED,
eneIsm_frac, eneIsm_exp );
/* Mix the separated object audio signal to the MASA audio signals */
ivas_get_stereo_panning_gains_fx( st_ivas->hMasaIsmData->azimuth_separated_ism[0],
st_ivas->hMasaIsmData->elevation_separated_ism[0], old_panning_gains_q15_fx );
ivas_get_stereo_panning_gains_fx( st_ivas->hMasaIsmData->azimuth_separated_ism[2],
st_ivas->hMasaIsmData->elevation_separated_ism[2], new_panning_gains_q15_fx );
/* Subsequent processing in Q31 format */
FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
{
new_panning_gains_fx[n] = L_shl( new_panning_gains_q15_fx[n], Q16 );
old_panning_gains_fx[n] = L_shl( old_panning_gains_q15_fx[n], Q16 );
}
processing_len = shr( output_frame, 1 );
FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
{
v_multc_acc_exp_mantissa_fx( output[MASA_MAX_TRANSPORT_CHANNELS],
out_exp[MASA_MAX_TRANSPORT_CHANNELS],
old_panning_gains_fx[n],
output[n],
out_exp[n],
processing_len );
}
offset = processing_len;
move16();
processing_len = shr( output_frame, 2 ); /* divide by MAX_PARAM_SPATIAL_SUBFRAMES; */
FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
{
Word32 mantissa;
/* k == 0->gain == old_panning_gains[n] */
/* output[n][offset] += gain * output[MASA_MAX_TRANSPORT_CHANNELS][offset]; */
mantissa = mult32_mantissa_fx( output[MASA_MAX_TRANSPORT_CHANNELS][offset],
old_panning_gains_fx[n],
out_exp[MASA_MAX_TRANSPORT_CHANNELS][offset], &exp );
output[n][offset] = BASOP_Util_Add_Mant32Exp( output[n][offset], out_exp[n][offset],
mantissa, exp, &out_exp[n][offset] );
move32();
move32();
FOR( k = 1; k < processing_len; k++ )
{
Word16 index = add( k, offset );
Word32 g1_fx = L_shl( st_ivas->hIsmRendererData->interpolator_fx[k], Q16 );
/* 1.0f - g1 */
Word32 g2_fx = L_sub( MAX_32, L_sub( g1_fx, 1 ) );
/* g1 *new_panning_gains[n] + g2 *old_panning_gains[n] */
Word32 gain_k = W_extract_h( W_add( W_mult_32_32( g1_fx, new_panning_gains_fx[n] ),
W_mult_32_32( g2_fx, old_panning_gains_fx[n] ) ) );
/* output[n][k + offset] += gain_k * output[MASA_MAX_TRANSPORT_CHANNELS][k + offset]; */
mantissa = mult32_mantissa_fx( output[MASA_MAX_TRANSPORT_CHANNELS][index], gain_k,
out_exp[MASA_MAX_TRANSPORT_CHANNELS][index], &exp );
output[n][index] = BASOP_Util_Add_Mant32Exp( output[n][index], out_exp[n][index],
mantissa, exp, &out_exp[n][index] );
move32();
move32();
}
}
offset = add( offset, processing_len );
FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
{
v_multc_acc_exp_mantissa_fx( &output[MASA_MAX_TRANSPORT_CHANNELS][offset],
&out_exp[MASA_MAX_TRANSPORT_CHANNELS][offset],
new_panning_gains_fx[n],
&output[n][offset],
&out_exp[n][offset],
processing_len );
}
/* Convert output from exponent+mantissa representation to Q11 */
FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
{
mantissa_exp_to_qvalue( &out_exp[n][0], &output[n][0], Q20, output_frame );
}
/* Zero output object channels */
FOR( n = 0; n < nchan_ism; n++ )
{
set_zero_fx( output[add( MASA_MAX_TRANSPORT_CHANNELS, n )], output_frame );
}
}
/*-------------------------------------------------------------------------*
* ivas_omasa_render_objects_from_mix_open_fx()
*
* Open structures, reserve memory, and init values.
*-------------------------------------------------------------------------*/
ivas_error ivas_omasa_render_objects_from_mix_open_fx(
Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
)
{
Word16 i;
Word32 size;
st_ivas->hMasaIsmData->delayBuffer_nchan = 1;
move16();
st_ivas->hMasaIsmData->delayBuffer_size = extract_l( Mult_32_16( st_ivas->hDecoderConfig->output_Fs,
OMASA_DELAYFRAMES_PER_SEC_Q15 ) );
size = L_mult0( st_ivas->hMasaIsmData->delayBuffer_nchan, sizeof( Word16 * ) );
st_ivas->hMasaIsmData->delayBuffer_fx = (Word32 **) malloc( size );
move32();
IF( st_ivas->hMasaIsmData->delayBuffer_fx == NULL )
{
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
}
size = L_mult0( st_ivas->hMasaIsmData->delayBuffer_size, sizeof( Word32 ) );
FOR( i = 0; i < st_ivas->hMasaIsmData->delayBuffer_nchan; i++ )
{
st_ivas->hMasaIsmData->delayBuffer_fx[i] = (Word32 *) malloc( size );
move32();
IF( st_ivas->hMasaIsmData->delayBuffer_fx[i] == NULL )
{
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
}
set_zero_fx( st_ivas->hMasaIsmData->delayBuffer_fx[i], st_ivas->hMasaIsmData->delayBuffer_size );
}
return IVAS_ERR_OK;
}
/*--------------------------------------------------------------------------*
* ivas_omasa_render_objects_from_mix()
*
* In case of external rendering, render objects from the transport signal
* mix containing MASA audio and object audio.
*--------------------------------------------------------------------------*/
void ivas_omasa_render_objects_from_mix_fx(
Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */
Word32 *output[], /* o : output synthesis signal */
const int16_t nchan_ism, /* i : number of ISMs */
const int16_t output_frame, /* i : output frame length per channel */
Word16 *output_q /* i/o: output Q value */
)
{
Word16 n, m, i;
MASA_ISM_EXT_DATA_HANDLE hExtData;
Word32 separated_object[L_FRAME48k];
Word32 rendered_objects[MAX_NUM_OBJECTS][L_FRAME48k];
Word16 coding_delay;
Word32 inRe[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word32 inIm[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word32 outRe[MAX_NUM_OBJECTS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word32 outIm[MAX_NUM_OBJECTS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word16 slot;
Word16 sf;
Word16 bin;
Word16 nchan_transport;
Word16 nBins;
Word16 inRe_exp[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word16 inIm_exp[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word16 outRe_exp[MAX_NUM_OBJECTS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word16 outIm_exp[MAX_NUM_OBJECTS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word16 transport_energy_exp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word32 transport_energy_frac[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
/* Create slot to metadata map */
slot = 0;
move16();
FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
{
Word16 index;
FOR( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
{
st_ivas->hSpatParamRendCom->render_to_md_map[slot] = st_ivas->hSpatParamRendCom->dirac_read_idx;
move16();
slot = add( slot, 1 );
}
index = add( st_ivas->hSpatParamRendCom->dirac_read_idx, 1 );
IF( GE_16( index, st_ivas->hSpatParamRendCom->dirac_md_buffer_length ) )
{
index = 0;
move16();
}
st_ivas->hSpatParamRendCom->dirac_read_idx = index;
move16();
}
/* Move separated object signal and object channels */
mvl2l( output[CPE_CHANNELS], separated_object, output_frame );
FOR( n = 0; n < nchan_ism; n++ )
{
set_zero_fx( output[CPE_CHANNELS + n], output_frame );
}
/* Delay the separated object signal by the CLDFB delay */
delay_signal32_fx( separated_object, output_frame, st_ivas->hMasaIsmData->delayBuffer_fx[0],
st_ivas->hMasaIsmData->delayBuffer_size );
/* Set object metadata to the ism struct */
FOR( n = 0; n < nchan_ism; n++ )
{
// Q0 -> Q22
Word32 azi = L_shl( st_ivas->hMasaIsmData->azimuth_ism[n][st_ivas->hSpatParamRendCom->dirac_read_idx], Q22 );
Word32 ele = L_shl( st_ivas->hMasaIsmData->elevation_ism[n][st_ivas->hSpatParamRendCom->dirac_read_idx], Q22 );
st_ivas->hIsmMetaData[n]->azimuth_fx = azi;
st_ivas->hIsmMetaData[n]->elevation_fx = ele;
move16();
move16();
}
/* Move the separated object signal to the correct output channel */
hExtData = st_ivas->hMasaIsmData->hExtData;
move32();
coding_delay = mult( output_frame, MULT_17_DIV_20_Q15 ); /* Q15: 17 ms of coding and CLDFB delay */
mvl2l( separated_object, output[add( CPE_CHANNELS, hExtData->prev_idx_separated_ism )], coding_delay );
mvl2l( &separated_object[coding_delay],
&output[add( CPE_CHANNELS, st_ivas->hMasaIsmData->idx_separated_ism )][coding_delay],
sub( output_frame, coding_delay ) );
/* Compute CLDFB analysis */
nchan_transport = st_ivas->nchan_transport;
move16();
nBins = mult( output_frame, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 ); // Q15
FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
{
FOR( n = 0; n < nchan_transport; n++ )
{
Word16 in_q = *output_q;
move16();
cldfbAnalysis_ts_fx_var_q( &( output[n][L_mult0( nBins, slot )] ),
inRe[n][slot],
inIm[n][slot],
nBins, st_ivas->cldfbAnaDec[n], &in_q );
/* Assign input exponent */
Word16 exp = sub( Q31, in_q );
set16_fx( inRe_exp[n][slot], exp, nBins );
set16_fx( inIm_exp[n][slot], exp, nBins );
}
}
/* Create prototype signals */
for ( n = 0; n < nchan_ism; n++ )
{
Word32 panning_gains_fx[2];
Word16 new_panning_gains_fx[2];
Word16 azimuth_fx, elevation_fx;
// Q22 -> Q0
azimuth_fx = extract_l( L_shr( st_ivas->hIsmMetaData[n]->azimuth_fx, Q22 ) );
elevation_fx = extract_l( L_shr( st_ivas->hIsmMetaData[n]->elevation_fx, Q22 ) );
ivas_get_stereo_panning_gains_fx( azimuth_fx, elevation_fx, new_panning_gains_fx );
Word16 interpValInc = 0;
move16();
// Represents (1.0f - interpVal) value
Word16 interpValDec = extract_l( L_sub( -MIN16B, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 ) );
FOR( slot = 0; slot < sub( CLDFB_NO_COL_MAX, 1 ); slot++ )
{
interpValInc = add( interpValInc, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 );
FOR( m = 0; m < 2; m++ )
{
Word32 prev_gain = hExtData->prev_panning_gains[n][m];
move32();
Word32 new_gain = L_shl( new_panning_gains_fx[m], 16 ); // Q15 -> Q31
panning_gains_fx[m] = L_add( Mpy_32_16( extract_h( prev_gain ), extract_l( prev_gain ),
interpValDec ),
Mpy_32_16( extract_h( new_gain ), extract_l( new_gain ),
interpValInc ) );
}
interpValDec = sub( interpValDec, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 );
v_multc_exp_mantissa_fx( inRe[0][slot], inRe_exp[0][slot], panning_gains_fx[0],
outRe[n][slot], outRe_exp[n][slot], nBins );
v_multc_exp_mantissa_fx( inIm[0][slot], inIm_exp[0][slot], panning_gains_fx[0],
outIm[n][slot], outIm_exp[n][slot], nBins );
v_multc_acc_exp_mantissa_fx( inRe[1][slot], inRe_exp[1][slot], panning_gains_fx[1],
outRe[n][slot], outRe_exp[n][slot], nBins );
v_multc_acc_exp_mantissa_fx( inIm[1][slot], inIm_exp[1][slot], panning_gains_fx[1],
outIm[n][slot], outIm_exp[n][slot], nBins );
}
// Special case where (1.0f - interpVal) = 0 and interpVal = 1
FOR( m = 0; m < 2; m++ )
{
panning_gains_fx[m] = L_shl( new_panning_gains_fx[m], 16 ); // Q15 -> Q31
}
v_multc_exp_mantissa_fx( inRe[0][slot], inRe_exp[0][slot], panning_gains_fx[0],
outRe[n][slot], outRe_exp[n][slot], nBins );
v_multc_exp_mantissa_fx( inIm[0][slot], inIm_exp[0][slot], panning_gains_fx[0],
outIm[n][slot], outIm_exp[n][slot], nBins );
v_multc_acc_exp_mantissa_fx( inRe[1][slot], inRe_exp[1][slot], panning_gains_fx[1],
outRe[n][slot], outRe_exp[n][slot], nBins );
v_multc_acc_exp_mantissa_fx( inIm[1][slot], inIm_exp[1][slot], panning_gains_fx[1],
outIm[n][slot], outIm_exp[n][slot], nBins );
FOR( m = 0; m < 2; m++ )
{
hExtData->prev_panning_gains[n][m] = panning_gains_fx[m];
move32();
}
}
/* Determine transport energy */
FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
{
set_zero_fx( &transport_energy_frac[slot][0], nBins );
set16_zero_fx( &transport_energy_exp[slot][0], nBins );
}
FOR( n = 0; n < CPE_CHANNELS; n++ )
{
FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
{
FOR( bin = 0; bin < nBins; bin++ )
{
Word16 exp;
// energy = re^2 + im^2
Word32 mantissa = sample_energy_fx( inRe[n][slot][bin], inRe_exp[n][slot][bin],
inIm[n][slot][bin], inIm_exp[n][slot][bin], &exp );
move32();
// Accumulate energy
transport_energy_frac[slot][bin] = BASOP_Util_Add_Mant32Exp( transport_energy_frac[slot][bin],
transport_energy_exp[slot][bin],
mantissa,
exp,
&transport_energy_exp[slot][bin] );
move32();
}
}
}
/* Determine temporally smoothed energies and determine gains using them */
FOR( n = 0; n < nchan_ism; n++ )
{
FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
{
Word16 md_idx = st_ivas->hSpatParamRendCom->render_to_md_map[slot];
move16();
FOR( bin = 0; bin < nBins; bin++ )
{
Word16 exp, exp_mult, proto_e, target_e;
Word32 mantissa, proto_m, target_m;
Word32 ism_target_energy_frac;
Word16 ism_target_energy_exp;
Word32 ism_proto_energy_frac;
Word16 ism_proto_energy_exp;
// r1 = transport_energy[slot][bin] * st_ivas->hMasaIsmData->energy_ratio_ism[n][md_idx][bin]
ism_target_energy_frac = mult32_mantissa_fx( transport_energy_frac[slot][bin],
st_ivas->hMasaIsmData->energy_ratio_ism_fx[n][md_idx][bin],
add( transport_energy_exp[slot][bin], 1 ),
&ism_target_energy_exp );
move32();
// r2 = r1 * (1.0 - EXT_RENDER_IIR_FAC)
ism_target_energy_frac = mult32_mantissa_fx( ism_target_energy_frac,
ONEMINUX_EXT_RENDER_IIR_FAC_Q31,
ism_target_energy_exp,
&ism_target_energy_exp );
move32();
// r3 = re^2 + im^2
mantissa = sample_energy_fx( outRe[n][slot][bin],
outRe_exp[n][slot][bin],
outIm[n][slot][bin],
outIm_exp[n][slot][bin],
&exp );
move32();
// r4 = r3 * (1 - EXT_RENDER_IIR_FAC)
ism_proto_energy_frac = mult32_mantissa_fx( mantissa, ONEMINUX_EXT_RENDER_IIR_FAC_Q31,
exp, &ism_proto_energy_exp );
move32();
// r5 = ism_render_proto_energy[n][bin] * EXT_RENDER_IIR_FAC
proto_m = mult32_mantissa_fx( hExtData->ism_render_proto_energy_frac[n][bin], EXT_RENDER_IIR_FAC_Q31,
hExtData->ism_render_proto_energy_exp[n][bin], &proto_e );
move32();
// r6 = r5 + r4
proto_m = BASOP_Util_Add_Mant32Exp( proto_m, proto_e,
ism_proto_energy_frac,
ism_proto_energy_exp,
&proto_e );
move32();
// r7 = ism_render_target_energy[n][bin] * EXT_RENDER_IIR_FAC
target_m = mult32_mantissa_fx( hExtData->ism_render_target_energy_frac[n][bin], EXT_RENDER_IIR_FAC_Q31,
hExtData->ism_render_target_energy_exp[n][bin], &target_e );
move32();
// r8 = r7 + r2
target_m = BASOP_Util_Add_Mant32Exp( target_m, target_e,
ism_target_energy_frac,
ism_target_energy_exp,
&target_e );
move32();
hExtData->ism_render_proto_energy_frac[n][bin] = proto_m;
hExtData->ism_render_proto_energy_exp[n][bin] = proto_e;
move32();
move16();
hExtData->ism_render_target_energy_frac[n][bin] = target_m;
hExtData->ism_render_target_energy_exp[n][bin] = target_e;
move32();
move16();
// r9 = sqrt(r8 / r6)
mantissa = get_processing_gain_fx( proto_m, proto_e, target_m, target_e, &exp );
move32();
// outRe[n][slot][bin] *= r9
exp_mult = add( exp, outRe_exp[n][slot][bin] );
outRe[n][slot][bin] = mult32_mantissa_fx( outRe[n][slot][bin], mantissa, exp_mult,
&outRe_exp[n][slot][bin] );
move32();
// outIm[n][slot][bin] *= r9
exp_mult = add( exp, outIm_exp[n][slot][bin] );
outIm[n][slot][bin] = mult32_mantissa_fx( outIm[n][slot][bin], mantissa, exp_mult,
&outIm_exp[n][slot][bin] );
move32();
}
}
}
FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
{
Word16 md_idx = st_ivas->hSpatParamRendCom->render_to_md_map[slot];
move16();
FOR( bin = 0; bin < nBins; bin++ )
{
Word16 exp, proto_e, target_e, transport_exp;
Word32 mantissa, proto_m, target_m, transport_mantissa;
Word32 masa_target_energy_frac;
Word16 masa_target_energy_exp;
// r1 = transport_energy[slot][bin] * hExtData->masa_render_masa_to_total[md_idx][bin]
masa_target_energy_frac = mult32_mantissa_fx( transport_energy_frac[slot][bin],
hExtData->masa_render_masa_to_total[md_idx][bin],
add( transport_energy_exp[slot][bin], 1 ),
&masa_target_energy_exp );
move32();
// r2 = r1 * EXT_RENDER_IIR_FAC
masa_target_energy_frac = mult32_mantissa_fx( masa_target_energy_frac,
ONEMINUX_EXT_RENDER_IIR_FAC_Q31,
masa_target_energy_exp,
&masa_target_energy_exp );
move32();
// r3 = masa_render_proto_energy[bin] * EXT_RENDER_IIR_FAC
proto_m = mult32_mantissa_fx( hExtData->masa_render_proto_energy_frac[bin], EXT_RENDER_IIR_FAC_Q31,
hExtData->masa_render_proto_energy_exp[bin], &proto_e );
move32();
// r4 = transport_energy[slot][bin] * EXT_RENDER_IIR_FAC
transport_mantissa = mult32_mantissa_fx( transport_energy_frac[slot][bin],
ONEMINUX_EXT_RENDER_IIR_FAC_Q31,
transport_energy_exp[slot][bin], &transport_exp );
move32();
// r5 = r3 + r4
proto_m = BASOP_Util_Add_Mant32Exp( proto_m, proto_e,
transport_mantissa,
transport_exp,
&proto_e );
move32();
// r6 = masa_render_target_energy[bin] * EXT_RENDER_IIR_FAC
target_m = mult32_mantissa_fx( hExtData->masa_render_target_energy_frac[bin], EXT_RENDER_IIR_FAC_Q31,
hExtData->masa_render_target_energy_exp[bin], &target_e );
move32();
// r7 = r6 + r2
target_m = BASOP_Util_Add_Mant32Exp( target_m, target_e,
masa_target_energy_frac,
masa_target_energy_exp,
&target_e );
move32();
hExtData->masa_render_proto_energy_frac[bin] = proto_m;
hExtData->masa_render_proto_energy_exp[bin] = proto_e;
move16();
move32();
hExtData->masa_render_target_energy_frac[bin] = target_m;
hExtData->masa_render_target_energy_exp[bin] = target_e;
move16();
move32();
// r8 = sqrt(r7 / r5)
mantissa = get_processing_gain_fx( proto_m, proto_e, target_m, target_e, &exp );
move32();
FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
{
Word16 exp_mult;
// inRe[n][slot][bin] *= r8
exp_mult = add( exp, inRe_exp[n][slot][bin] );
inRe[n][slot][bin] = mult32_mantissa_fx( inRe[n][slot][bin], mantissa, exp_mult,
&inRe_exp[n][slot][bin] );
move32();
// inIm[n][slot][bin] *= r8
exp_mult = add( exp, inIm_exp[n][slot][bin] );
inIm[n][slot][bin] = mult32_mantissa_fx( inIm[n][slot][bin], mantissa, exp_mult,
&inIm_exp[n][slot][bin] );
move32();
}
}
}
*output_q = Q11;
/* Compute CLDFB synthesis */
FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
{
Word32 *outSlotRePr, *outSlotImPr;
Word32 index = L_mult0( nBins, slot );
FOR( n = 0; n < nchan_transport; n++ )
{
outSlotRePr = &( inRe[n][slot][0] );
outSlotImPr = &( inIm[n][slot][0] );
move32();
move32();
FOR( bin = 0; bin < nBins; bin++ )
{
inRe_exp[n][slot][bin] = sub( inRe_exp[n][slot][bin], Q2 );
inIm_exp[n][slot][bin] = sub( inIm_exp[n][slot][bin], Q2 );
}
mantissa_exp_to_qvalue( &inRe_exp[n][slot][0], &inRe[n][slot][0], Q20, nBins );
mantissa_exp_to_qvalue( &inIm_exp[n][slot][0], &inIm[n][slot][0], Q20, nBins );
cldfbSynthesis_ivas_fx( &outSlotRePr, &outSlotImPr, &output[n][index],
nBins, Q2, 1, st_ivas->cldfbSynDec[n] );
}
FOR( n = 0; n < nchan_ism; n++ )
{
Word32 index2 = add( n, CPE_CHANNELS );
outSlotRePr = &( outRe[n][slot][0] );
outSlotImPr = &( outIm[n][slot][0] );
move32();
move32();
mantissa_exp_to_qvalue( &outRe_exp[n][slot][0], &outRe[n][slot][0], Q20, nBins );
mantissa_exp_to_qvalue( &outIm_exp[n][slot][0], &outIm[n][slot][0], Q20, nBins );
cldfbSynthesis_ivas_fx( &outSlotRePr, &outSlotImPr, &rendered_objects[n][index],
nBins, 0, 1, st_ivas->cldfbSynDec[index2] );
}
}
/* Combine the rendered objects with the separated objects */
FOR( n = 0; n < nchan_ism; n++ )
{
Word16 index = add( CPE_CHANNELS, n );
v_add_32( output[index], rendered_objects[n], output[index], output_frame );
}
hExtData->prev_idx_separated_ism = st_ivas->hMasaIsmData->idx_separated_ism;
move16();
}
#endif
......@@ -479,8 +479,26 @@ void ivas_renderer_select(
}
ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
{
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
{
*renderer_type = RENDERER_OMASA_OBJECT_EXT;
move32();
}
ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
{
*renderer_type = RENDERER_OMASA_MIX_EXT;
move32();
}
ELSE
{
*renderer_type = RENDERER_DISABLE;
move32();
}
#else
*renderer_type = RENDERER_DISABLE;
move16();
#endif
}
}
ELSE IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) )
......
......@@ -771,7 +771,12 @@ void ivas_sba_dec_digest_tc_fx(
Word16 ch_idx, nchan_transport;
/* set the md map */
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
IF( st_ivas->hDirAC != NULL || EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) )
#else
IF( st_ivas->hDirAC )
#endif
{
ivas_dirac_dec_set_md_map_fx( st_ivas, nCldfbSlots );
}
......
......@@ -926,6 +926,25 @@ typedef struct ivas_masa_decoder_struct
} MASA_DECODER, *MASA_DECODER_HANDLE;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
/* Data structure for MASA_ISM EXT rendering */
typedef struct ivas_masa_ism_ext_data_structure
{
Word16 prev_idx_separated_ism; // Q0 (Integer)
Word32 prev_panning_gains[MAX_NUM_OBJECTS][2]; // Q31
Word16 ism_render_proto_energy_exp[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; // Q0 (Integer exponent)
Word32 ism_render_proto_energy_frac[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; // Q31
Word16 ism_render_target_energy_exp[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; // Q0 (Integer exponent)
Word32 ism_render_target_energy_frac[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; // Q31
Word16 masa_render_proto_energy_exp[CLDFB_NO_CHANNELS_MAX]; // Q0 (Integer exponent)
Word32 masa_render_proto_energy_frac[CLDFB_NO_CHANNELS_MAX]; // Q31
Word16 masa_render_target_energy_exp[CLDFB_NO_CHANNELS_MAX]; // Q0 (Integer exponent)
Word32 masa_render_target_energy_frac[CLDFB_NO_CHANNELS_MAX]; // Q31
Word32 masa_render_masa_to_total[MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR][CLDFB_NO_CHANNELS_MAX]; // Q30
} MASA_ISM_EXT_DATA, *MASA_ISM_EXT_DATA_HANDLE;
#endif
/* Data structure for MASA_ISM rendering */
typedef struct ivas_masa_ism_data_structure
{
......@@ -955,7 +974,9 @@ typedef struct ivas_masa_ism_data_structure
Word32 **delayBuffer_fx; /* Q11 */
Word16 delayBuffer_size;
Word16 delayBuffer_nchan;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
MASA_ISM_EXT_DATA_HANDLE hExtData;
#endif
} MASA_ISM_DATA, *MASA_ISM_DATA_HANDLE;
......
......@@ -1987,14 +1987,37 @@ ivas_error IVAS_DEC_GetNumObjects(
UWord16 *numObjects /* o : number of objects for which the decoder has been configured */
)
{
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
Word16 is_masa_ism;
is_masa_ism = 0;
move16();
#endif
test();
IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
{
return IVAS_ERR_UNEXPECTED_NULL_POINTER;
}
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( hIvasDec->st_ivas->hMasa != NULL )
{
IF( EQ_32( hIvasDec->st_ivas->hMasa->config.input_ivas_format, MASA_ISM_FORMAT ) )
{
is_masa_ism = 1;
move16();
}
}
test();
test();
test();
IF( EQ_32( hIvasDec->st_ivas->ivas_format, ISM_FORMAT ) ||
EQ_32( hIvasDec->st_ivas->ivas_format, SBA_ISM_FORMAT ) ||
EQ_32( hIvasDec->st_ivas->ivas_format, MASA_ISM_FORMAT ) ||
EQ_16( is_masa_ism, 1 ) )
#else
test();
test();
IF( EQ_16( (Word16) hIvasDec->st_ivas->ivas_format, ISM_FORMAT ) || EQ_16( (Word16) hIvasDec->st_ivas->ivas_format, SBA_ISM_FORMAT ) || EQ_16( (Word16) hIvasDec->st_ivas->ivas_format, MASA_ISM_FORMAT ) )
#endif
{
*numObjects = hIvasDec->st_ivas->nchan_ism;
}
......@@ -2029,7 +2052,14 @@ ivas_error IVAS_DEC_GetFormat(
*format = IVAS_DEC_BS_UNKOWN;
}
move32();
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
if ( EQ_32( *format, IVAS_DEC_BS_MASA ) && EQ_32( hIvasDec->st_ivas->hMasa->config.input_ivas_format, MASA_ISM_FORMAT ) )
{
*format = IVAS_DEC_BS_MASA_ISM;
move32();
}
#endif
return IVAS_ERR_OK;
}
......@@ -2140,7 +2170,11 @@ ivas_error IVAS_DEC_GetObjectMetadata(
{
Decoder_Struct *st_ivas;
ISM_METADATA_HANDLE hIsmMeta;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
Word16 is_masa_ism;
is_masa_ism = 0;
move16();
#endif
test();
IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
{
......@@ -2148,9 +2182,27 @@ ivas_error IVAS_DEC_GetObjectMetadata(
}
st_ivas = hIvasDec->st_ivas;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( hIvasDec->st_ivas->hMasa != NULL )
{
IF( EQ_32( hIvasDec->st_ivas->hMasa->config.input_ivas_format, MASA_ISM_FORMAT ) )
{
is_masa_ism = 1;
move16();
}
}
test();
test();
test();
if ( NE_32( st_ivas->ivas_format, ISM_FORMAT ) &&
NE_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) &&
NE_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) &&
EQ_16( is_masa_ism, 0 ) )
#else
test();
test();
IF( NE_16( st_ivas->ivas_format, ISM_FORMAT ) && NE_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) && NE_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
#endif
{
return IVAS_ERR_WRONG_MODE;
}
......@@ -2161,8 +2213,16 @@ ivas_error IVAS_DEC_GetObjectMetadata(
}
hIsmMeta = st_ivas->hIsmMetaData[objectIdx];
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
test();
test();
IF( hIsmMeta == NULL ||
EQ_16( zero_flag, 1 ) ||
( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) )
#else
IF( hIsmMeta == NULL || zero_flag )
#endif
{
metadata->azimuth_fx = 0; // Q22
metadata->elevation_fx = 0; // Q22
......@@ -2834,9 +2894,13 @@ ivas_error IVAS_DEC_GetDelay(
out_fs_fx = FS_48K_IN_NS_Q31;
}
move32();
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
nSamples[1] = NS2SA_FX2( hDecoderConfig->output_Fs, get_delay_fx( DEC, hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->cldfbSynDec[0], hDecoderConfig->output_config ) );
move16();
#else
nSamples[1] = NS2SA_FX2( hDecoderConfig->output_Fs, get_delay_fx( DEC, hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->cldfbAnaDec[0], hDecoderConfig->output_config ) );
move16();
#endif
nSamples[2] = extract_l( W_round64_L( W_mult0_32_32( L_shl( st_ivas->binaural_latency_ns, 1 ), out_fs_fx ) ) );
move16();
nSamples[0] = add( nSamples[1], nSamples[2] );
......
......@@ -930,7 +930,20 @@ void concealment_decode_fix(
/* sign randomization */
FOR( i = 0; i < N; i++ )
{
#ifdef NON_BE_FIX_EVS_USAN_ERR_IN_WAVEADJUST
Word16 rnd;
rnd = own_random_fix( seed );
IF( GE_16( rnd, 0 ) )
{
sign = 1;
}
ELSE IF( LT_16( rnd, 0 ) )
{
sign = -1;
}
#else
sign = add( shl( shr( own_random_fix( seed ), 15 ), 1 ), 1 );
#endif
if ( EQ_16( sign, -1 ) )
{
invkoef[i] = L_negate( invkoef[i] );
......
......@@ -533,8 +533,28 @@ ivas_error ivas_masa_encode_fx(
}
ELSE
{
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
test();
IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MODE_NONE ) )
{
/* use the MASA number of transport channels bit to signal if there are 3 or 4 objects */
IF( EQ_16( nchan_ism, 4 ) )
{
push_next_indice( hMetaData, 1, MASA_TRANSP_BITS );
}
ELSE
{
push_next_indice( hMetaData, 0, MASA_TRANSP_BITS );
}
}
ELSE
{
#endif
/* write the number of MASA transport channels */
push_next_indice( hMetaData, sub( nchan_transport, 1 ), MASA_TRANSP_BITS );
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
}
#endif
hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_TRANSP_BITS );
move16();
}
......@@ -542,12 +562,25 @@ ivas_error ivas_masa_encode_fx(
test();
IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MODE_NONE ) )
{
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IF( LE_16( nchan_ism, 3 ) )
{
push_next_indice( hMetaData, nchan_ism, MASA_HEADER_BITS );
}
ELSE
{
push_next_indice( hMetaData, sub( nchan_ism, 1 ), MASA_HEADER_BITS );
}
hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_HEADER_BITS );
move16();
#else
/* signal MASA_ISM_FORMAT to decoder */
push_next_indice( hMetaData, 1, 1 );
/* write reserved bit */
push_next_indice( hMetaData, 0, MASA_HEADER_BITS - 1 );
hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_HEADER_BITS );
move16();
#endif
}
ELSE
{
......
......@@ -220,6 +220,7 @@ void diffuse_meta_merge_1x1_fx(
{
Word32 new_dir_ratio_fx, new_diff_ratio_fx;
Word16 new_dir_ratio_e;
outMeta->directionIndex[0][sf][band] = inMetaISM->directionIndex[0][sf][band];
move16();
outMeta->directToTotalRatio[0][sf][band] = inMetaISM->directToTotalRatio[0][sf][band];
......@@ -252,7 +253,8 @@ void diffuse_meta_merge_1x1_fx(
move16();
}
outMeta->directToTotalRatio[0][sf][band] = (UWord8) extract_l( L_shr( Mpy_32_16_1( new_dir_ratio_fx, UINT8_MAX ) /* (31 - new_dir_ratio_e) - 15*/, sub( 31 - 15, new_dir_ratio_e ) ) );
outMeta->directToTotalRatio[0][sf][band] = (UWord8) extract_l( L_shr( Mpy_32_16_1( new_dir_ratio_fx, UINT8_MAX ) /* (31 - new_dir_ratio_e) - 15*/, sub( 31 - 15, new_dir_ratio_e ) ) ); /* Q0 */
move16();
IF( GT_16( sub( 31, new_dir_ratio_e ), Q30 ) )
{
......
......@@ -41,11 +41,20 @@
typedef struct masaMetaDelayStorage
{
MASA_DECRIPTIVE_META descriptiveMeta;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
uint16_t directionIndex[MASA_MAXIMUM_DIRECTIONS][DELAY_MASA_PARAM_DEC_SFR + 1][MASA_FREQUENCY_BANDS];
uint8_t directToTotalRatio[MASA_MAXIMUM_DIRECTIONS][DELAY_MASA_PARAM_DEC_SFR + 1][MASA_FREQUENCY_BANDS];
uint8_t spreadCoherence[MASA_MAXIMUM_DIRECTIONS][DELAY_MASA_PARAM_DEC_SFR + 1][MASA_FREQUENCY_BANDS];
uint8_t surroundCoherence[DELAY_MASA_PARAM_DEC_SFR + 1][MASA_FREQUENCY_BANDS];
uint8_t diffuseToTotalRatio[DELAY_MASA_PARAM_DEC_SFR + 1][MASA_FREQUENCY_BANDS];
uint8_t prevDelay;
#else
uint16_t directionIndex[MASA_MAXIMUM_DIRECTIONS][DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS];
uint8_t directToTotalRatio[MASA_MAXIMUM_DIRECTIONS][DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS];
uint8_t spreadCoherence[MASA_MAXIMUM_DIRECTIONS][DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS];
uint8_t surroundCoherence[DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS];
uint8_t diffuseToTotalRatio[DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS];
#endif
} MASA_META_DELAY_STORAGE;
......@@ -88,14 +97,93 @@ static void getExtMasaMetadataFileName(
static void delayMasaMetadata(
MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o: New input metadata which is inplace replaced with delayed metadata frame */
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
MASA_META_DELAY_STORAGE *delayStorage, /* i/o: Storage for 15 ms of metadata and related descriptive metadata */
uint8_t delayNsf
#else
MASA_META_DELAY_STORAGE *delayStorage /* i/o: Storage for 10 ms of metadata and related descriptive metadata */
#endif
)
{
int16_t dir, sf, band;
uint8_t currentNumberOfDirections;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
int16_t storeReadOffset;
#endif
/* Move meta to delay and output. Always use two directions as the metadata is prepared to contain zero energy second direction
* if there is 1dir meta. */
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
/* stable state expected results delay change expected results
delayNsf = 2 delayNsf = 3 delayNsf = 3 (from 2) delayNsf = 2 (from 3)
ext[0] = delayStorage[0] (prev ext[2]) ext[0] = delayStorage[0] (prev ext[1]) ext[0] = delayStorage[0] (prev ext[2]) ext[0] = delayStorage[1] (prev ext[2])
ext[1] = delayStorage[1] (prev ext[3]) ext[1] = delayStorage[1] (prev ext[2]) ext[1] = delayStorage[1] (prev ext[3]) ext[1] = delayStorage[2] (prev ext[3])
ext[2] = ext[0] ext[2] = delayStorage[2] (prev ext[3]) ext[2] = delayStorage[1] (prev ext[3]) ext[2] = ext[0]
ext[3] = ext[1] ext[3] = ext[0] ext[3] = ext[0] ext[3] = ext[0]
delayStorage[0] = ext[2] delayStorage[0] = ext[1] delayStorage[0] = ext[1] delayStorage[0] = ext[2]
delayStorage[1] = ext[3] delayStorage[1] = ext[2] delayStorage[1] = ext[2] delayStorage[1] = ext[3]
delayStorage[2] = ext[3] delayStorage[2] = ext[3]
*/
storeReadOffset = delayStorage->prevDelay > delayNsf ? delayStorage->prevDelay - delayNsf : 0; /* delay decreases: read later from storage -> discard one sf */
for ( sf = 0; sf < delayNsf; sf++ )
{
for ( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
{
uint16_t temp_u16;
uint8_t temp_u8;
int16_t toStoreIdx, reOrgIdx, storeReadIdx;
toStoreIdx = sf + MAX_PARAM_SPATIAL_SUBFRAMES - delayNsf;
reOrgIdx = sf + delayNsf;
/* when switching to longer delay, repeat the last valid sf to fill the gap */
storeReadIdx = ( ( sf + storeReadOffset ) < delayStorage->prevDelay ) ? sf + storeReadOffset : delayStorage->prevDelay - 1;
for ( dir = 0; dir < MASA_MAXIMUM_DIRECTIONS; dir++ )
{
temp_u16 = delayStorage->directionIndex[dir][storeReadIdx][band];
delayStorage->directionIndex[dir][sf][band] = extOutMeta->directionIndex[dir][toStoreIdx][band];
if ( reOrgIdx < MAX_PARAM_SPATIAL_SUBFRAMES )
{
extOutMeta->directionIndex[dir][reOrgIdx][band] = extOutMeta->directionIndex[dir][sf][band];
}
extOutMeta->directionIndex[dir][sf][band] = temp_u16;
temp_u8 = delayStorage->directToTotalRatio[dir][storeReadIdx][band];
delayStorage->directToTotalRatio[dir][sf][band] = extOutMeta->directToTotalRatio[dir][toStoreIdx][band];
if ( reOrgIdx < MAX_PARAM_SPATIAL_SUBFRAMES )
{
extOutMeta->directToTotalRatio[dir][reOrgIdx][band] = extOutMeta->directToTotalRatio[dir][sf][band];
}
extOutMeta->directToTotalRatio[dir][sf][band] = temp_u8;
temp_u8 = delayStorage->spreadCoherence[dir][storeReadIdx][band];
delayStorage->spreadCoherence[dir][sf][band] = extOutMeta->spreadCoherence[dir][toStoreIdx][band];
if ( reOrgIdx < MAX_PARAM_SPATIAL_SUBFRAMES )
{
extOutMeta->spreadCoherence[dir][reOrgIdx][band] = extOutMeta->spreadCoherence[dir][sf][band];
}
extOutMeta->spreadCoherence[dir][sf][band] = temp_u8;
}
temp_u8 = delayStorage->surroundCoherence[storeReadIdx][band];
delayStorage->surroundCoherence[sf][band] = extOutMeta->surroundCoherence[toStoreIdx][band];
if ( reOrgIdx < MAX_PARAM_SPATIAL_SUBFRAMES )
{
extOutMeta->surroundCoherence[reOrgIdx][band] = extOutMeta->surroundCoherence[sf][band];
}
extOutMeta->surroundCoherence[sf][band] = temp_u8;
temp_u8 = delayStorage->diffuseToTotalRatio[storeReadIdx][band];
delayStorage->diffuseToTotalRatio[sf][band] = extOutMeta->diffuseToTotalRatio[toStoreIdx][band];
if ( reOrgIdx < MAX_PARAM_SPATIAL_SUBFRAMES )
{
extOutMeta->diffuseToTotalRatio[reOrgIdx][band] = extOutMeta->diffuseToTotalRatio[sf][band];
}
extOutMeta->diffuseToTotalRatio[sf][band] = temp_u8;
}
}
#else
for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES - DELAY_MASA_PARAM_DEC_SFR; sf++ )
{
for ( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
......@@ -131,6 +219,7 @@ static void delayMasaMetadata(
extOutMeta->diffuseToTotalRatio[sf][band] = temp_u8;
}
}
#endif
/* Finalize descriptive meta by using new frame except for number of directions which is the larger of the two */
currentNumberOfDirections = extOutMeta->descriptiveMeta.numberOfDirections;
......@@ -140,6 +229,9 @@ static void delayMasaMetadata(
}
delayStorage->descriptiveMeta.numberOfDirections = currentNumberOfDirections;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
delayStorage->prevDelay = delayNsf;
#endif
return;
}
......@@ -182,6 +274,9 @@ ivas_error MasaFileWriter_open(
if ( !delayCompensationEnabled )
{
self->delayStorage = calloc( sizeof( MASA_META_DELAY_STORAGE ), 1 );
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
self->delayStorage->prevDelay = DELAY_MASA_PARAM_DEC_SFR;
#endif
}
*masaWriter = self;
......@@ -198,7 +293,12 @@ ivas_error MasaFileWriter_open(
ivas_error MasaFileWriter_writeFrame(
MasaFileWriter *self, /* i/o: MasaFileWriter handle */
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta, /* i/o: MASA ext out meta handle to be written */
const float *decDelay /* i : decoding audio delay */
#else
MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta /* i/o: MASA ext out meta handle to be written */
#endif
)
{
if ( self == NULL )
......@@ -209,7 +309,17 @@ ivas_error MasaFileWriter_writeFrame(
uint16_t descMetaTemp = 0;
int16_t i, sf, dir, numDirections;
uint8_t writeTempOther[MASA_FREQUENCY_BANDS];
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
/* If delay storage has been reserved, then we are in the normal mode for the decoder
* (i.e., no delay compensation for PCM) which means that metadata should be delayed
* by two or three subframes (10 or 15 ms). Descriptive metadata is a combined result. */
if ( self->delayStorage )
{
uint8_t delayFrames = (uint8_t) ( (int32_t) ( ( *decDelay ) * 48000 ) / L_SPATIAL_SUBFR_48k );
delayMasaMetadata( hMasaExtOutMeta, self->delayStorage, delayFrames );
}
#else
/* If delay storage has been reserved, then we are in the normal mode for the decoder
* (i.e., no delay compensation for PCM) which means that metadata should be delayed
* by two subframes (10 ms). Descriptive metadata is a combined result. */
......@@ -217,7 +327,7 @@ ivas_error MasaFileWriter_writeFrame(
{
delayMasaMetadata( hMasaExtOutMeta, self->delayStorage );
}
#endif
numDirections = hMasaExtOutMeta->descriptiveMeta.numberOfDirections + 1;
if ( fwrite( &( hMasaExtOutMeta->descriptiveMeta.formatDescriptor ), sizeof( uint8_t ), 8, self->file ) != 8 )
......
......@@ -48,7 +48,12 @@ ivas_error MasaFileWriter_open(
ivas_error MasaFileWriter_writeFrame(
MasaFileWriter *self, /* i/o: MasaFileWriter handle */
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
IVAS_MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta, /* i/o: MASA ext out meta handle to be written */
const float *decDelay /* i : decoding audio delay */
#else
IVAS_MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta /* i/o: MASA ext out meta handle to be written */
#endif
);
void MasaFileWriter_close(
......