diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj
index e1c0f9ead1e80039fb23607500d3580bece6215c..2473e1bc5007f0bbf244d35611445a10c1248edc 100644
--- a/Workspace_msvc/lib_dec.vcxproj
+++ b/Workspace_msvc/lib_dec.vcxproj
@@ -290,6 +290,7 @@
+
diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters
index d1dedc413cef958bb637b92972c2b95ef1656319..0bd4a23fbfa389f044414d87b439fd0f2ab12e38 100644
--- a/Workspace_msvc/lib_dec.vcxproj.filters
+++ b/Workspace_msvc/lib_dec.vcxproj.filters
@@ -518,6 +518,9 @@
dec_ivas_c
+
+ dec_ivas_c
+
diff --git a/Workspace_msvc/lib_enc.vcxproj b/Workspace_msvc/lib_enc.vcxproj
index 15f0d535745d95fec1fd22eb4d139f5ca5e8d06f..3378ac10f0ccb8b95616f87f6d225f38af30bb3d 100644
--- a/Workspace_msvc/lib_enc.vcxproj
+++ b/Workspace_msvc/lib_enc.vcxproj
@@ -213,6 +213,7 @@
+
diff --git a/Workspace_msvc/lib_enc.vcxproj.filters b/Workspace_msvc/lib_enc.vcxproj.filters
index 21941038ec37e6a53cc81c9c3c915e69cbe0ac5f..b3970764c0f9218533e6f7e63c8f1d270540c0e1 100644
--- a/Workspace_msvc/lib_enc.vcxproj.filters
+++ b/Workspace_msvc/lib_enc.vcxproj.filters
@@ -587,6 +587,9 @@
enc_ivas_c
+
+ enc_ivas_c
+
diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h
index 01b11b21e4ce86baa3918453de4ccd4a8637b413..859968565eaa6ea27e7e8c2f025a0ce851b6c558 100755
--- a/lib_com/ivas_cnst.h
+++ b/lib_com/ivas_cnst.h
@@ -1261,7 +1261,12 @@ typedef enum
MC_MODE_NONE,
MC_MODE_MCT,
MC_MODE_PARAMMC,
+#ifndef MC_PARAMUPMIX_MODE
MC_MODE_MCMASA
+#else
+ MC_MODE_MCMASA,
+ MC_MODE_PARAMUPMIX
+#endif
} MC_MODE;
typedef enum
@@ -1321,6 +1326,57 @@ typedef enum
MCT_CHAN_MODE_IGNORE
} MCT_CHAN_MODE;
+#ifdef MC_PARAMUPMIX_MODE
+/*----------------------------------------------------------------------------------*
+ * MC Param-Upmix Mode Constants
+ *----------------------------------------------------------------------------------*/
+#define MC_PARAMUPMIX_MAX_TRANSPORT_CHANS 8
+#define MC_PARAMUPMIX_MAX_INPUT_CHANS 12
+#define MC_PARAMUPMIX_MAX_BITS 1024 /* Maximum number of bits for the MC Param-Upmix metadata */
+#define MC_PARAMUPMIX_COMBINATIONS 4 /* number of sets of 2 channels combined */
+#define MC_PARAMUPMIX_NCH 2 /* number of channels to combine into 1 */
+#define MC_PARAMUPMIX_MIN_CLDFB 8
+
+typedef struct {
+ const int32_t *value;
+ const uint16_t *length;
+} HUFF_TAB;
+
+typedef struct {
+ int32_t value[81];
+ unsigned short length[81];
+} HUFF_ELEMENTS;
+
+typedef struct {
+ HUFF_ELEMENTS df0;
+ HUFF_ELEMENTS df;
+ HUFF_ELEMENTS dt;
+} HUFF_TABLE;
+
+typedef enum {
+ ALPHA,
+ BETA
+} PAR_TYPE;
+
+typedef enum {
+ FINE,
+ COARSE
+} QUANT_TYPE;
+
+typedef struct {
+ int16_t nquant;
+ int16_t offset;
+ float data[35];
+} ACPL_QUANT_TABLE;
+
+typedef struct
+{
+ const int16_t (*alpha[2])[2];
+ const int16_t (*beta[2])[2];
+} HUFF_NODE_TABLE;
+
+
+#endif
/*----------------------------------------------------------------------------------*
* Parametric MC Constants
*----------------------------------------------------------------------------------*/
diff --git a/lib_com/ivas_mc_com.c b/lib_com/ivas_mc_com.c
index 027b68768668a713263e85509179d2a48df6ff0a..9bda9d49a4d27edd80a390f1a702c332acf801a0 100644
--- a/lib_com/ivas_mc_com.c
+++ b/lib_com/ivas_mc_com.c
@@ -103,10 +103,21 @@ MC_MODE ivas_mc_mode_select(
{
mc_mode = MC_MODE_MCMASA;
}
+#ifndef MC_PARAMUPMIX_MODE
else if ( total_brate < IVAS_192k )
{
mc_mode = MC_MODE_PARAMMC;
}
+#else
+ else if ( total_brate < IVAS_160k )
+ {
+ mc_mode = MC_MODE_PARAMMC;
+ }
+ else if ( total_brate < IVAS_192k )
+ {
+ mc_mode = MC_MODE_PARAMUPMIX;
+ }
+#endif
break;
default:
assert( 0 && "LS Setup not supported or defined for MC mode!\n" );
diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h
index 0355c00470244e4c5a33db19f2158a277d0051f0..5348abe1d78fd9f1478a6a03972d0be3af98a6d2 100644
--- a/lib_com/ivas_prot.h
+++ b/lib_com/ivas_prot.h
@@ -3703,6 +3703,42 @@ void calculate_hodirac_sector_parameters(
);
#endif
+#ifdef MC_PARAMUPMIX_MODE
+void ivas_mc_paramupmix_enc(
+ Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */
+ BSTR_ENC_HANDLE hMetaData, /* i/o: IVAS Metadata bitstream handle */
+ float data_f[][L_FRAME48k], /* i/o: input: CICP6, CICP12, CICP14, CICP16 or CICP19 MC data */
+ const int16_t input_frame /* i : input frame length */
+);
+ivas_error ivas_mc_paramupmix_enc_open(
+ Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */
+);
+void ivas_mc_paramupmix_enc_close(
+ MC_PARAMUPMIX_ENC_HANDLE *hMCParamUpmix, /* i/o: MC Param-Upmix encoder handle */
+ const int32_t sampling_rate
+);
+void ivas_mc_paramupmix_dec(
+ Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */
+ float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */
+);
+int16_t ivas_mc_paramupmix_getNumTransportChannels(
+ void
+);
+ivas_error ivas_mc_paramupmix_dec_open(
+ Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
+);
+void ivas_mc_paramupmix_dec_close(
+ MC_PARAMUPMIX_DEC_HANDLE *hMCParamUpmix_out /* i/o: Parametric MC decoder handle */
+);
+void ivas_mc_paramupmix_dec_read_BS(
+ const int32_t ivas_total_brate, /* i : IVAS total bitrate */
+ Decoder_State *st, /* i/o: decoder state structure */
+ Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
+ MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix, /* i/o: decoder MC Param-Upmix handle */
+ int16_t *nb_bits /* o : number of bits written */
+);
+#endif
+
void ivas_param_mc_metadata_open(
const MC_LS_SETUP mc_ls_setup, /* i : MC ls setup */
const int16_t lfe_index, /* i : channel index of LFE */
@@ -4469,6 +4505,14 @@ void ivas_td_decorr_process(
const int16_t output_frame /* i : output frame length */
);
+#ifdef MC_PARAMUPMIX_MODE
+void ivas_td_decorr_APD_iir_filter(
+ ivas_td_decorr_APD_filt_state_t *filter_state,
+ float *pIn_out,
+ const int16_t num_APD_sections,
+ const int16_t length
+);
+#endif
#define IVAS_CMULT_FLOAT( in1_re, in1_im, in2_re, in2_im, out1_re, out1_im ) \
out1_re = ( in1_re * in2_re ) - ( in1_im * in2_im ); MAC(1); MULT(1); \
@@ -4948,11 +4992,20 @@ void ivas_ls_setup_conversion_close(
LSSETUP_CONVERSION_HANDLE *hLsSetUpConversion /* i/o: LS converter handle */
);
+#ifdef MC_PARAMUPMIX_MODE
+void ivas_ls_setup_conversion(
+ Decoder_Struct *st_ivas, /* i : IVAS decoder structure */
+ const int16_t input_chans, /* i : number of input channels to the renderer */
+ const int16_t output_frame, /* i : frame length */
+ float output[][L_FRAME48k] /* i/o: LS input/output synthesis signal */
+);
+#else
void ivas_ls_setup_conversion(
Decoder_Struct *st_ivas, /* i : IVAS decoder structure */
const int16_t output_frame, /* i : frame length */
float output[][L_FRAME48k] /* i/o: LS input/output synthesis signal */
);
+#endif
void ivas_ls_setup_conversion_process_mdct(
Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c
index 72e46cbda37d0465d6ed5a445ad8c4351336b857..7ed0ec4a827c377d327ecab4b4edad4de6a620d3 100644
--- a/lib_com/ivas_rom_com.c
+++ b/lib_com/ivas_rom_com.c
@@ -6972,4 +6972,102 @@ const int16_t sns_1st_means_32k[2][16] = {
};
#endif
+#ifdef MC_PARAMUPMIX_MODE
+ACPL_QUANT_TABLE alpha_quant_table[] =
+{
+ { /* Alfa Fine */
+ 33, /* nquant */
+ 16, /* offset */
+ { -2.000000e+000f, -1.809375e+000f, -1.637500e+000f, -1.484375e+000f, -1.350000e+000f, -1.234375e+000f, -1.137500e+000f, -1.059375e+000f, -1.000000e+000f, -9.406250e-001f,
+ -8.625000e-001f, -7.656250e-001f, -6.500000e-001f, -5.156250e-001f, -3.625000e-001f, -1.906250e-001f, +0.000000e+000f, +1.906250e-001f, +3.625000e-001f, +5.156250e-001f,
+ +6.500000e-001f, +7.656250e-001f, +8.625000e-001f, +9.406250e-001f, +1.000000e+000f, +1.059375e+000f, +1.137500e+000f, +1.234375e+000f, +1.350000e+000f, +1.484375e+000f,
+ +1.637500e+000f, +1.809375e+000f, +2.000000e+000f } /* data */
+ }, /* End Alfa Fine */
+ { /* Alfa Coarse */
+ 17, /* nquant */
+ 8, /* offset */
+ { -2.000000e+000f, -1.637500e+000f, -1.350000e+000f, -1.137500e+000f, -1.000000e+000f, -8.625000e-001f, -6.500000e-001f, -3.625000e-001f, +0.000000e+000f, +3.625000e-001f,
+ +6.500000e-001f, +8.625000e-001f, +1.000000e+000f, +1.137500e+000f, +1.350000e+000f, +1.637500e+000f, +2.000000e+000f } /* data */
+ } /* End Alfa Coarse */
+};
+
+ACPL_QUANT_TABLE beta_quant_table[2][9] =
+{
+ {
+ { /* Beta Fine #1 */
+ 9, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +2.375000e-001f, +5.500000e-001f, +9.375000e-001f, +1.400000e+000f, +1.937500e+000f, +2.550000e+000f, +3.237500e+000f, +4.000000e+000f } /* data */
+ }, /* End Beta Fine #1 */
+ { /* Beta Fine #2 */
+ 9, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +2.035449e-001f, +4.713672e-001f, +8.034668e-001f, +1.199844e+000f, +1.660498e+000f, +2.185430e+000f, +2.774639e+000f, +3.428125e+000f } /* data */
+ }, /* End Beta Fine #2 */
+ { /* Beta Fine #3 */
+ 9, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +1.729297e-001f, +4.004688e-001f, +6.826172e-001f, +1.019375e+000f, +1.410742e+000f, +1.856719e+000f, +2.357305e+000f, +2.912500e+000f } /* data */
+ }, /* End Beta Fine #3 */
+ { /* Beta Fine #4 */
+ 9, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +1.456543e-001f, +3.373047e-001f, +5.749512e-001f, +8.585938e-001f, +1.188232e+000f, +1.563867e+000f, +1.985498e+000f, +2.453125e+000f } /* data */
+ }, /* End Beta Fine #4 */
+ { /* Beta Fine #5 */
+ 9, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +1.217188e-001f, +2.818750e-001f, +4.804688e-001f, +7.175000e-001f, +9.929688e-001f, +1.306875e+000f, +1.659219e+000f, +2.050000e+000f } /* data */
+ }, /* End Beta Fine #5 */
+ { /* Beta Fine #6 */
+ 9, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +1.011230e-001f, +2.341797e-001f, +3.991699e-001f, +5.960938e-001f, +8.249512e-001f, +1.085742e+000f, +1.378467e+000f, +1.703125e+000f } /* data */
+ }, /* End Beta Fine #6 */
+ { /* Beta Fine #7 */
+ 9, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +8.386719e-002f, +1.942188e-001f, +3.310547e-001f, +4.943750e-001f, +6.841797e-001f, +9.004688e-001f, +1.143242e+000f, +1.412500e+000f } /* data */
+ }, /* End Beta Fine #7 */
+ { /* Beta Fine #8 */
+ 9, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +6.995117e-002f, +1.619922e-001f, +2.761230e-001f, +4.123438e-001f, +5.706543e-001f, +7.510547e-001f, +9.535449e-001f, +1.178125e+000f } /* data */
+ }, /* End Beta Fine #8 */
+ { /* Beta Fine #9 */
+ 9, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +5.937500e-002f, +1.375000e-001f, +2.343750e-001f, +3.500000e-001f, +4.843750e-001f, +6.375000e-001f, +8.093750e-001f, +1.000000e+000f } /* data */
+ } /* End Beta Fine #9 */
+ },
+ {
+ { /* Beta Coarse #1 */
+ 5, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +5.500000e-001f, +1.400000e+000f, +2.550000e+000f, +4.000000e+000f } /* data */
+ }, /* End Beta Coarse #1 */
+ { /* Beta Coarse #2 */
+ 5, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +4.004688e-001f, +1.019375e+000f, +1.856719e+000f, +2.912500e+000f } /* data */
+ }, /* End Beta Coarse #2 */
+ { /* Beta Coarse #3 */
+ 5, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +2.818750e-001f, +7.175000e-001f, +1.306875e+000f, +2.050000e+000f } /* data */
+ }, /* End Beta Coarse #3 */
+ { /* Beta Coarse #4 */
+ 5, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +1.942188e-001f, +4.943750e-001f, +9.004688e-001f, +1.412500e+000f } /* data */
+ }, /* End Beta Coarse #4 */
+ { /* Beta Coarse #5 */
+ 5, /* nquant */
+ 0, /* offset */
+ { +0.000000e+000f, +1.375000e-001f, +3.500000e-001f, +6.375000e-001f, +1.000000e+000f } /* data */
+ } /* End Beta Coarse #5 */
+ }
+};
+#endif
+
/* clang-format on */
diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h
index dbd09e4537ccf90df29310593ba234786fa2c9d4..fd8bd41a3034cbf94686cf6f51c0896dbef503a2 100644
--- a/lib_com/ivas_rom_com.h
+++ b/lib_com/ivas_rom_com.h
@@ -477,6 +477,11 @@ extern const float ivas_sns_means_side_tcx10[];
#endif
#endif
+#ifdef MC_PARAMUPMIX_MODE
+extern ACPL_QUANT_TABLE alpha_quant_table[];
+extern ACPL_QUANT_TABLE beta_quant_table[2][9];
+#endif
+
#ifdef FIX_445_SNS_BUGFIXES
/* means and codebooks for the split VQ in the 2-stage SNS VQ */
extern const int16_t sns_1st_cdbk[2][2][8 * 32];
diff --git a/lib_com/ivas_td_decorr.c b/lib_com/ivas_td_decorr.c
index 0215bfcf56b5b682143cc448e5eaf76d81186556..b1947cdd253d21f3ad9354b36372407331d7beda 100644
--- a/lib_com/ivas_td_decorr.c
+++ b/lib_com/ivas_td_decorr.c
@@ -403,8 +403,11 @@ static void ivas_td_decorr_init(
*
* APD IIR filter
*-----------------------------------------------------------------------------------------*/
-
+#ifdef MC_PARAMUPMIX_MODE
+void ivas_td_decorr_APD_iir_filter(
+#else
static void ivas_td_decorr_APD_iir_filter(
+#endif
ivas_td_decorr_APD_filt_state_t *filter_state,
float *pIn_out,
const int16_t num_APD_sections,
diff --git a/lib_com/options.h b/lib_com/options.h
old mode 100755
new mode 100644
index 396d080b987e53349651476efc9c2f3084e60962..dfe0f53d0739224afe025cdab18bf399779b8263
--- a/lib_com/options.h
+++ b/lib_com/options.h
@@ -196,6 +196,8 @@
#define FIX_447_PARAMBIN_MASA_REGU_FAC /* Nokia: Issue 447: Fix issue by adjusting regularization factor minimum value. */
#define FIX_441_SBA_PARAMBIN_GAINS /* Nokia: Fix issue 441 by changing gains in SBA path of parametric binauralizer */
+#define MC_PARAMUPMIX_MODE /* Dlb: Contribution 39: Multichannel Parametric Upmix */
+
#define HODIRAC /* FhG: Sector-based HO-DirAC method for SBA at high bitrates */
#ifdef HODIRAC
@@ -211,8 +213,7 @@
//#define HODIRAC_READ_PARAMS
#endif
- /* ################## End DEVELOPMENT switches ######################### */
-
+/* ################## End DEVELOPMENT switches ######################### */
/* clang-format on */
#endif
diff --git a/lib_dec/init_dec.c b/lib_dec/init_dec.c
index 20bc7a0b845325f2517e94c9af43d36e0cf7a5c9..173623db6589f4e672d76673014d0ce540229fe6 100644
--- a/lib_dec/init_dec.c
+++ b/lib_dec/init_dec.c
@@ -702,7 +702,11 @@ ivas_error init_decoder(
* FD-CNG decoder
*-----------------------------------------------------------------*/
+#ifdef MC_PARAMUPMIX_MODE
+ if ( ( st->element_mode == IVAS_CPE_MDCT || idchan == 0 ) && mc_mode != MC_MODE_MCT && mc_mode != MC_MODE_PARAMUPMIX )
+#else
if ( ( st->element_mode == IVAS_CPE_MDCT || idchan == 0 ) && mc_mode != MC_MODE_MCT )
+#endif
{
/* Create FD_CNG instance */
if ( ( error = createFdCngDec( &st->hFdCngDec ) ) != IVAS_ERR_OK )
diff --git a/lib_dec/ivas_cpe_dec.c b/lib_dec/ivas_cpe_dec.c
old mode 100644
new mode 100755
diff --git a/lib_dec/ivas_dec.c b/lib_dec/ivas_dec.c
index fd1638b849b08473db0c3a65351975cfedf60295..d33dcbe1a187e492f039e742d77375afa2b43510 100644
--- a/lib_dec/ivas_dec.c
+++ b/lib_dec/ivas_dec.c
@@ -134,7 +134,11 @@ ivas_error ivas_dec(
/* Rendering */
if ( st_ivas->renderer_type == RENDERER_MC )
{
+#ifdef MC_PARAMUPMIX_MODE
+ ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, output );
+#else
ivas_ls_setup_conversion( st_ivas, output_frame, output );
+#endif
}
}
else if ( st_ivas->ivas_format == ISM_FORMAT )
@@ -482,7 +486,76 @@ ivas_error ivas_dec(
}
else if ( st_ivas->renderer_type == RENDERER_MC )
{
+#ifdef MC_PARAMUPMIX_MODE
+ ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, output );
+#else
ivas_ls_setup_conversion( st_ivas, output_frame, output );
+#endif
+ }
+ else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC )
+ {
+ ivas_mc2sba( st_ivas->hIntSetup, output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f );
+ }
+ else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD )
+ {
+ if ( ( ivas_td_binaural_renderer( st_ivas, output, output_frame ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ ivas_binaural_add_LFE( st_ivas, output_frame, output );
+ }
+ }
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ ivas_lfe_dec( st_ivas->hLFE, st, output_frame, st_ivas->bfi, output_lfe_ch );
+
+ ivas_mc_paramupmix_dec_read_BS( ivas_total_brate, st, st_ivas, st_ivas->hMCParamUpmix, &nb_bits_metadata[0] );
+
+ if ( ( error = ivas_mct_dec( st_ivas, output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ mvr2r( output_lfe_ch, output[LFE_CHANNEL], output_frame );
+
+ ivas_mc_paramupmix_dec( st_ivas, output );
+
+ /* HP filtering */
+ for ( n = 0; n < st_ivas->nchan_transport; n++ )
+ {
+ if ( n != LFE_CHANNEL )
+ {
+ hp20( output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs );
+ }
+ }
+
+ if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == AUDIO_CONFIG_FOA || st_ivas->intern_config == AUDIO_CONFIG_HOA2 || st_ivas->intern_config == AUDIO_CONFIG_HOA3 ) )
+ {
+ ivas_mc2sba( st_ivas->hTransSetup, output, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE );
+ }
+
+ /* Rendering */
+ if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM )
+ {
+ if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hHeadTrackData, &st_ivas->hIntSetup, st_ivas->hEFAPdata, output, output_Fs ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ ivas_binaural_add_LFE( st_ivas, output_frame, output );
+ }
+ else if ( st_ivas->renderer_type == RENDERER_MC )
+ {
+ if ( ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO ) || ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) )
+ {
+ ivas_ls_setup_conversion( st_ivas, audioCfg2channels( AUDIO_CONFIG_5_1_2 ), output_frame, output );
+ }
+ else
+ {
+ ivas_ls_setup_conversion( st_ivas, MC_PARAMUPMIX_MAX_INPUT_CHANS, output_frame, output );
+ }
}
else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC )
{
@@ -498,6 +571,7 @@ ivas_error ivas_dec(
ivas_binaural_add_LFE( st_ivas, output_frame, output );
}
}
+#endif
else if ( st_ivas->mc_mode == MC_MODE_PARAMMC )
{
/* read Parametric MC parameters from the bitstream */
@@ -527,7 +601,11 @@ ivas_error ivas_dec(
/* Rendering */
if ( output_config == AUDIO_CONFIG_MONO || output_config == AUDIO_CONFIG_STEREO )
{
+#ifdef MC_PARAMUPMIX_MODE
+ ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, output );
+#else
ivas_ls_setup_conversion( st_ivas, output_frame, output );
+#endif
}
else
{
diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c
index b317d81cd169c7c18b46720e3a202cc307ef6b24..3f777334da3e555114e345dbfbf6329b07585587 100644
--- a/lib_dec/ivas_init_dec.c
+++ b/lib_dec/ivas_init_dec.c
@@ -1072,6 +1072,48 @@ ivas_error ivas_init_decoder(
return error;
}
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ /* init EFAP for custom LS setup */
+ if ( output_config == AUDIO_CONFIG_LS_CUSTOM )
+ {
+ if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+ st_ivas->nSCE = 0;
+ st_ivas->nCPE = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS / 2;
+ st_ivas->nchan_transport = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS;
+
+ if ( ( error = ivas_mc_paramupmix_dec_open( st_ivas ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ st_ivas->element_mode_init = IVAS_CPE_MDCT;
+
+ for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ )
+ {
+ if ( ( error = create_cpe_dec( st_ivas, cpe_id, ( ivas_total_brate / ( st_ivas->nchan_transport - 1 ) * CPE_CHANNELS ) ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ for ( n = 0; n < CPE_CHANNELS; n++ )
+ {
+ reset_indices_dec( st_ivas->hCPE[cpe_id]->hCoreCoder[n] );
+ }
+ }
+
+ if ( ( error = create_mct_dec( st_ivas ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+#endif
else if ( st_ivas->mc_mode == MC_MODE_PARAMMC )
{
/* init EFAP for custom LS setup */
@@ -1325,8 +1367,11 @@ ivas_error ivas_init_decoder(
/*-----------------------------------------------------------------*
* LFE handles for rendering after rendering to adjust LFE delay to binaural filter delay
*-----------------------------------------------------------------*/
-
+#ifdef MC_PARAMUPMIX_MODE
+ if ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+#else
if ( st_ivas->mc_mode == MC_MODE_MCT )
+#endif
{
binauralization_delay_ns = st_ivas->binaural_latency_ns;
if ( st_ivas->hBinRenderer != NULL )
@@ -1592,6 +1637,9 @@ void ivas_initialize_handles_dec(
st_ivas->hMasa = NULL;
st_ivas->hQMetaData = NULL;
st_ivas->hMCT = NULL;
+#ifdef MC_PARAMUPMIX_MODE
+ st_ivas->hMCParamUpmix = NULL;
+#endif
st_ivas->hParamMC = NULL;
st_ivas->hLFE = NULL;
@@ -1729,6 +1777,11 @@ void ivas_destroy_dec(
/* LFE handle */
ivas_lfe_dec_close( &( st_ivas->hLFE ) );
+#ifdef MC_PARAMUPMIX_MODE
+ /* Param-Upmix MC handle */
+ ivas_mc_paramupmix_dec_close( &( st_ivas->hMCParamUpmix ) );
+#endif
+
/* Parametric MC handle */
ivas_param_mc_dec_close( &st_ivas->hParamMC );
@@ -1973,6 +2026,13 @@ void ivas_init_dec_get_num_cldfb_instances(
default:
assert( 0 && "Renderer not handled for CLDFB reservation." );
}
+#ifdef MC_PARAMUPMIX_MODE
+ if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_MONO && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_STEREO )
+ {
+ *numCldfbAnalyses = max( MC_PARAMUPMIX_MIN_CLDFB, *numCldfbAnalyses );
+ *numCldfbSyntheses = max( MC_PARAMUPMIX_MIN_CLDFB, *numCldfbSyntheses );
+ }
+#endif
return;
}
@@ -2056,7 +2116,11 @@ static ivas_error doSanityChecks_IVAS(
}
#ifdef DEBUGGING
+#ifdef MC_PARAMUPMIX_MODE
+ if ( ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) && ( ( st_ivas->ivas_format != MC_FORMAT && st_ivas->ivas_format != ISM_FORMAT ) || output_config != AUDIO_CONFIG_BINAURAL || ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) || ( st_ivas->ivas_format == MC_FORMAT && ( st_ivas->mc_mode != MC_MODE_MCT && st_ivas->mc_mode != MC_MODE_PARAMUPMIX ) ) ) )
+#else
if ( ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) && ( ( st_ivas->ivas_format != MC_FORMAT && st_ivas->ivas_format != ISM_FORMAT ) || output_config != AUDIO_CONFIG_BINAURAL || ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode != MC_MODE_MCT ) ) )
+#endif
{
return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration: Time Domain object renderer not supported in this configuration" );
}
diff --git a/lib_dec/ivas_mc_paramupmix_dec.c b/lib_dec/ivas_mc_paramupmix_dec.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b04578c847968d22a119522445036163d286d96
--- /dev/null
+++ b/lib_dec/ivas_mc_paramupmix_dec.c
@@ -0,0 +1,696 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#include
+#include "options.h"
+#include
+#include "cnst.h"
+#include "prot.h"
+#include "ivas_prot.h"
+#include "ivas_cnst.h"
+#include "ivas_rom_com.h"
+#include "ivas_rom_dec.h"
+#include "math.h"
+#ifdef DEBUGGING
+#include "debug.h"
+#endif
+#ifdef DEBUG_PLOT
+#include "deb_out.h"
+#endif
+#include "wmc_auto.h"
+#include "rom_dec.h"
+
+#ifdef MC_PARAMUPMIX_MODE
+/*-----------------------------------------------------------------------*
+ * Local function prototypes
+ *-----------------------------------------------------------------------*/
+static void ps_pred_process( MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix, float qmf_mod_re[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float qmf_mod_im[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float qmf_side_re[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float qmf_side_im[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], int16_t ch );
+
+static void paramupmix_td_decorr_process( ivas_td_decorr_state_t *hTdDecorr[], float pcm_in[][L_FRAME48k], float **pp_out_pcm, const int16_t output_frame );
+
+static int huff_read( Decoder_State *st, const int16_t ( *ht )[2] );
+
+static void huffman_decode( Decoder_State *st, int16_t nv, int16_t ivStart, PAR_TYPE parType, QUANT_TYPE quant_type, int16_t bNoDt, int32_t *vq );
+
+static void dequant_alpha( int16_t nv, int16_t ivStart, QUANT_TYPE quant_type, int32_t *vq, float *v );
+
+static void dequant_beta( int16_t nv, int16_t ivStart, QUANT_TYPE quant_type, int32_t *aq, int32_t *bq, float *beta );
+
+static void get_ec_data( Decoder_State *st, PAR_TYPE parType, QUANT_TYPE quant_type, int16_t nParBand, int16_t parBandStart, int32_t *parQ, int32_t *alphaQEnv, float ab[IVAS_MAX_NUM_BANDS] );
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_dec_read_BS()
+ *
+ * Read the ParamUpmix MC metadata
+ *------------------------------------------------------------------------*/
+
+void ivas_mc_paramupmix_dec_read_BS(
+ const int32_t ivas_total_brate, /* i : IVAS total bitrate */
+ Decoder_State *st, /* i/o: decoder state structure */
+ Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
+ MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix, /* i/o: decoder MC Param-Upmix handle */
+ int16_t *nb_bits /* o : number of bits written */
+)
+{
+ int16_t i, k;
+ int32_t alpha_quant[IVAS_MAX_NUM_BANDS];
+ int16_t nb_bits_read_orig;
+ int16_t next_bit_pos_orig, last_bit_pos;
+ uint16_t bstr_meta[MAX_BITS_METADATA], *bit_stream_orig;
+
+ push_wmops( "mc_paramupmix_read_bs" );
+ *nb_bits = 0;
+
+ if ( st->bfi )
+ {
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ for ( k = 0; k < IVAS_MAX_NUM_BANDS; k++ )
+ {
+ hMCParamUpmix->alphas[i][k] = hMCParamUpmix->alpha_prev[i][k];
+ hMCParamUpmix->betas[i][k] = hMCParamUpmix->beta_prev[i][k];
+ }
+ }
+ hMCParamUpmix->first_frame = 1;
+ }
+ else /* if (!st->bfi) */
+ {
+ bit_stream_orig = st->bit_stream;
+ next_bit_pos_orig = st->next_bit_pos;
+ last_bit_pos = (int16_t) ( ( ivas_total_brate / FRAMES_PER_SEC ) - 1 );
+ nb_bits_read_orig = 0;
+ last_bit_pos -= nb_bits_read_orig; /* reverse the bitstream for easier reading of indices */
+ for ( i = 0; i < min( MAX_BITS_METADATA, last_bit_pos ); i++ )
+ {
+ bstr_meta[i] = st_ivas->bit_stream[last_bit_pos - i];
+ }
+ st->bit_stream = bstr_meta;
+ st->next_bit_pos = 0;
+ st->bits_frame = min( MAX_BITS_METADATA, last_bit_pos + 1 );
+ st->total_brate = st_ivas->hDecoderConfig->ivas_total_brate; /* to avoid BER detect */
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ get_ec_data( st, ALPHA, FINE /*quant_type*/, IVAS_MAX_NUM_BANDS /*nParBand*/,
+ 0 /*parBandStart*/, hMCParamUpmix->alpha_quant[i], alpha_quant, hMCParamUpmix->alphas[i] );
+
+ get_ec_data( st, BETA, FINE /*quant_type*/, IVAS_MAX_NUM_BANDS /*nParBand*/,
+ 0 /*parBandStart*/, hMCParamUpmix->beta_quant[i], alpha_quant, hMCParamUpmix->betas[i] );
+ }
+ *nb_bits += st->next_bit_pos;
+ st->bit_stream = bit_stream_orig;
+ st->next_bit_pos = next_bit_pos_orig;
+
+ if ( hMCParamUpmix->first_frame )
+ {
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ mvr2r( hMCParamUpmix->alphas[i], hMCParamUpmix->alpha_prev[i], IVAS_MAX_NUM_BANDS );
+ mvr2r( hMCParamUpmix->betas[i], hMCParamUpmix->beta_prev[i], IVAS_MAX_NUM_BANDS );
+ }
+ hMCParamUpmix->first_frame = 0;
+ }
+ }
+
+ pop_wmops();
+
+ return;
+}
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_dec()
+ *
+ * MC ParamUpmix decoding process
+ *------------------------------------------------------------------------*/
+void ivas_mc_paramupmix_dec(
+ Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */
+ float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels */
+)
+{
+ MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix;
+ int16_t i, k, ch;
+ int16_t slot_idx;
+ int16_t first_empty_channel;
+ int16_t nchan_out_transport;
+ /*CLDFB*/
+ float Cldfb_RealBuffer[MC_PARAMUPMIX_MAX_TRANSPORT_CHANS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
+ float Cldfb_ImagBuffer[MC_PARAMUPMIX_MAX_TRANSPORT_CHANS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
+ int16_t channel_active[MAX_OUTPUT_CHANNELS];
+ int32_t output_Fs;
+ int16_t output_frame;
+ float Pcm_decorr[MC_PARAMUPMIX_COMBINATIONS][L_FRAME48k]; /* decorrelated channels */
+ float *pPcm_temp[MC_PARAMUPMIX_COMBINATIONS * 2]; /* decorrelated and undecorrelated*/
+ int16_t noparamupmix_delay;
+ AUDIO_CONFIG output_config;
+
+ hMCParamUpmix = st_ivas->hMCParamUpmix;
+ assert( hMCParamUpmix );
+
+ push_wmops( "mc_paramupmix_dec" );
+
+ set_s( channel_active, 0, MAX_CICP_CHANNELS );
+ nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe;
+ set_s( channel_active, 1, nchan_out_transport ); /* change to nchan_out_transport */
+ output_Fs = st_ivas->hDecoderConfig->output_Fs;
+ output_config = st_ivas->hDecoderConfig->output_config;
+ output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC );
+
+ if ( ( output_config == AUDIO_CONFIG_STEREO ) || ( output_config == AUDIO_CONFIG_MONO ) )
+ {
+ first_empty_channel = 8; /* Don't upmix */
+ }
+ else
+ {
+ first_empty_channel = 12;
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ pPcm_temp[i] = Pcm_decorr[i]; /* decorrelated */
+ }
+
+ paramupmix_td_decorr_process( hMCParamUpmix->hTdDecorr, &( output_f[4] ), pPcm_temp, output_frame );
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ pPcm_temp[2 * i] = output_f[i + 4]; /* un-decorrelated */
+ pPcm_temp[2 * i + 1] = Pcm_decorr[i]; /* decorrelated */
+ }
+
+ /* CLDFB Analysis*/
+ for ( ch = 0; ch < MC_PARAMUPMIX_COMBINATIONS * 2; ch++ )
+ {
+ /* slot loop for gathering the input data */
+ for ( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ )
+ {
+ cldfbAnalysis_ts( &( pPcm_temp[ch][hMCParamUpmix->num_freq_bands * slot_idx] ), Cldfb_RealBuffer[ch][slot_idx], Cldfb_ImagBuffer[ch][slot_idx], hMCParamUpmix->num_freq_bands, st_ivas->cldfbAnaDec[ch] );
+ }
+ }
+ for ( ch = 0; ch < MC_PARAMUPMIX_COMBINATIONS; ch++ )
+ {
+ ps_pred_process( hMCParamUpmix,
+ Cldfb_RealBuffer[2 * ch], /* in/out */
+ Cldfb_ImagBuffer[2 * ch],
+ Cldfb_RealBuffer[2 * ch + 1], /* in/out decorr */
+ Cldfb_ImagBuffer[2 * ch + 1],
+ ch );
+
+ /*-- m, s -> l, r ----------------------------*/
+ for ( i = 0; i < CLDFB_NO_COL_MAX; i++ )
+ {
+ for ( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ )
+ {
+ float qlre = Cldfb_RealBuffer[2 * ch][i][k];
+ float qlim = Cldfb_ImagBuffer[2 * ch][i][k];
+ float qrre = Cldfb_RealBuffer[2 * ch + 1][i][k];
+ float qrim = Cldfb_ImagBuffer[2 * ch + 1][i][k];
+
+ Cldfb_RealBuffer[2 * ch][i][k] = qlre + qrre;
+ Cldfb_ImagBuffer[2 * ch][i][k] = qlim + qrim;
+ Cldfb_RealBuffer[2 * ch + 1][i][k] = qlre - qrre;
+ Cldfb_ImagBuffer[2 * ch + 1][i][k] = qlim - qrim;
+ }
+ }
+
+ mvr2r( hMCParamUpmix->alphas[ch], hMCParamUpmix->alpha_prev[ch], IVAS_MAX_NUM_BANDS );
+ mvr2r( hMCParamUpmix->betas[ch], hMCParamUpmix->beta_prev[ch], IVAS_MAX_NUM_BANDS );
+ }
+
+ /* boxes = { 0 1 2 3 [4 6] [5 7] [8 10] [9 11] }; */
+ pPcm_temp[0] = output_f[4];
+ pPcm_temp[1] = output_f[6];
+ pPcm_temp[2] = output_f[5];
+ pPcm_temp[3] = output_f[7];
+ pPcm_temp[4] = output_f[8];
+ pPcm_temp[5] = output_f[10];
+ pPcm_temp[6] = output_f[9];
+ pPcm_temp[7] = output_f[11];
+
+ /* CLDFB synthesis */
+ for ( ch = 0; ch < MC_PARAMUPMIX_COMBINATIONS * 2; ch++ )
+ {
+ for ( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ )
+ {
+ float *ptr_im[1], *ptr_re[1];
+ ptr_re[0] = Cldfb_RealBuffer[ch][slot_idx];
+ ptr_im[0] = Cldfb_ImagBuffer[ch][slot_idx];
+
+ cldfbSynthesis( ptr_re, ptr_im, &( pPcm_temp[ch][hMCParamUpmix->num_freq_bands * slot_idx] ),
+ hMCParamUpmix->num_freq_bands, st_ivas->cldfbSynDec[ch] );
+ }
+ }
+
+ /* adjust delay of other channels */
+ noparamupmix_delay = NS2SA( output_Fs, IVAS_FB_DEC_DELAY_NS );
+ for ( ch = 0; ch < MC_PARAMUPMIX_COMBINATIONS; ch++ )
+ {
+ float tmp_buf[L_SUBFRAME5MS_48k];
+ mvr2r( &output_f[ch][output_frame - noparamupmix_delay], tmp_buf, noparamupmix_delay );
+ mvr2r( output_f[ch], &output_f[ch][noparamupmix_delay], output_frame - noparamupmix_delay );
+ mvr2r( hMCParamUpmix->pcm_delay[ch], output_f[ch], noparamupmix_delay );
+ mvr2r( tmp_buf, hMCParamUpmix->pcm_delay[ch], noparamupmix_delay );
+ }
+ }
+
+ for ( ch = first_empty_channel; ch < MAX_OUTPUT_CHANNELS; ch++ )
+ {
+ set_f( output_f[ch], 0.0, L_FRAME48k );
+ }
+ pop_wmops();
+
+ return;
+}
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_getNumTransportChannels()
+ *
+ *
+ *------------------------------------------------------------------------*/
+int16_t ivas_mc_paramupmix_getNumTransportChannels()
+{
+ int16_t nchan_transport;
+ nchan_transport = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS; /* 5.1.2 */
+ return nchan_transport;
+}
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_dec_open()
+ *
+ * Open Parametric MC decoder handle
+ *-------------------------------------------------------------------------*/
+
+ivas_error ivas_mc_paramupmix_dec_open(
+ Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
+)
+{
+ MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix;
+ int32_t output_Fs;
+ int16_t nchan_transport;
+ uint16_t i;
+ ivas_error error;
+
+ error = IVAS_ERR_OK;
+
+ /*-----------------------------------------------------------------*
+ * prepare library opening
+ *-----------------------------------------------------------------*/
+
+ if ( ( hMCParamUpmix = (MC_PARAMUPMIX_DEC_HANDLE) malloc( sizeof( MC_PARAMUPMIX_DEC_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param-Upmix MC\n" ) );
+ }
+ output_Fs = st_ivas->hDecoderConfig->output_Fs;
+ hMCParamUpmix->first_frame = 1;
+
+ st_ivas->nchan_transport = ivas_mc_paramupmix_getNumTransportChannels();
+ nchan_transport = st_ivas->nchan_transport;
+
+ switch ( nchan_transport )
+ {
+ case 8:
+ st_ivas->nCPE = 4;
+ st_ivas->nSCE = 0;
+ st_ivas->element_mode_init = IVAS_CPE_MDCT;
+ break;
+#ifdef DEBUGGING
+ default:
+ assert( 0 && "Number of TC not supported for MC ParamUpmix!" );
+#endif
+ }
+ /*-----------------------------------------------------------------*
+ * set input parameters
+ *-----------------------------------------------------------------*/
+
+ hMCParamUpmix->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ ivas_td_decorr_dec_open( &( hMCParamUpmix->hTdDecorr[i] ), output_Fs, 2, 1 );
+ }
+
+ for ( i = 0; i < MC_PARAMUPMIX_MAX_TRANSPORT_CHANS; i++ )
+ {
+ if ( ( hMCParamUpmix->pcm_delay[i] = (float *) malloc( 240 * sizeof( float ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for delay buffer\n" ) );
+ }
+ set_zero( hMCParamUpmix->pcm_delay[i], 240 );
+ }
+
+ st_ivas->hMCParamUpmix = hMCParamUpmix;
+
+ return error;
+}
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_dec_close()
+ *
+ * Close ParamUpmix MC memories
+ *------------------------------------------------------------------------*/
+
+void ivas_mc_paramupmix_dec_close(
+ MC_PARAMUPMIX_DEC_HANDLE *hMCParamUpmix /* i/o: Parametric MC decoder handle */
+)
+{
+ int16_t i;
+
+ if ( hMCParamUpmix == NULL || *hMCParamUpmix == NULL )
+ {
+ return;
+ }
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ ivas_td_decorr_dec_close( &( ( *hMCParamUpmix )->hTdDecorr[i] ) );
+ }
+ for ( i = 0; i < MC_PARAMUPMIX_MAX_TRANSPORT_CHANS; i++ )
+ {
+ if ( ( *hMCParamUpmix )->pcm_delay[i] != NULL )
+ {
+ free( ( *hMCParamUpmix )->pcm_delay[i] );
+ }
+ }
+ free( *hMCParamUpmix );
+
+ *hMCParamUpmix = NULL;
+
+ return;
+}
+
+/*****************************************************************************************/
+/* local functions */
+/*****************************************************************************************/
+
+static void ps_pred_process(
+ MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix,
+ float qmf_mod_re[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* in/out */
+ float qmf_mod_im[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
+ float qmf_side_re[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* in/out */
+ float qmf_side_im[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
+ int16_t ch )
+{
+ float vmre, vmim, vsre, vsim;
+ int16_t iqmf, ipar, ismp, iismp;
+ float alpha_smp, dalpha, beta_smp, dbeta;
+ float *alpha1, *alpha2;
+ float *beta1, *beta2;
+ float *alpha_prev = hMCParamUpmix->alpha_prev[ch];
+ float *beta_prev = hMCParamUpmix->beta_prev[ch];
+
+ int16_t qmf_to_par_band[] = {
+ 0, 1, 2, 3, 4, 5, 5, 6, 6, 7,
+ 7, 7, 8, 8, 8, 8, 9, 9, 9, 9,
+ 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
+ };
+
+ for ( iqmf = 0; iqmf < CLDFB_NO_CHANNELS_MAX; iqmf++ )
+ {
+ /* For changing no of parameter bands (ipar1 != ipar2), TIGGER_FRAMING assumed */
+ ipar = qmf_to_par_band[iqmf];
+ alpha1 = alpha_prev;
+ beta1 = beta_prev;
+
+ ismp = 0;
+ alpha2 = hMCParamUpmix->alphas[ch];
+ beta2 = hMCParamUpmix->betas[ch];
+ alpha_smp = alpha1[ipar];
+ beta_smp = beta1[ipar];
+ dalpha = ( alpha2[ipar] - alpha1[ipar] ) / CLDFB_NO_COL_MAX;
+ dbeta = ( beta2[ipar] - beta1[ipar] ) / CLDFB_NO_COL_MAX;
+
+ for ( iismp = 0; iismp < CLDFB_NO_COL_MAX; iismp++ )
+ {
+ alpha_smp += dalpha;
+ beta_smp += dbeta;
+
+ vmre = qmf_mod_re[ismp][iqmf];
+ vmim = qmf_mod_im[ismp][iqmf];
+ vsre = qmf_side_re[ismp][iqmf];
+ vsim = qmf_side_im[ismp][iqmf];
+
+ qmf_side_re[ismp][iqmf] = alpha_smp * vmre + beta_smp * vsre;
+ qmf_side_im[ismp][iqmf] = alpha_smp * vmim + beta_smp * vsim;
+
+ ismp++;
+ }
+
+ alpha1 = alpha2;
+ beta1 = beta2;
+ }
+}
+
+static void paramupmix_td_decorr_process(
+ ivas_td_decorr_state_t *hTdDecorr[], /* i/o: SPAR Covar. decoder handle */
+ float pcm_in[][L_FRAME48k], /* i : input audio channels */
+ float **pp_out_pcm, /* o : output audio channels */
+ const int16_t output_frame /* i : output frame length */
+)
+{
+ int16_t j, k;
+ int16_t offset;
+ float in_duck_gain[L_FRAME48k], out_duck_gain[L_FRAME48k];
+
+ offset = (int16_t) ( output_frame * FRAMES_PER_SEC * IVAS_DECORR_PARM_LOOKAHEAD_TAU );
+
+ /* Look-ahead delay */
+ for ( k = 0; k < MC_PARAMUPMIX_COMBINATIONS; k++ )
+ {
+ mvr2r( pcm_in[k], pp_out_pcm[k], output_frame );
+ delay_signal( pp_out_pcm[k], output_frame, hTdDecorr[k]->look_ahead_buf, offset );
+
+ /* In ducking gains */
+ if ( hTdDecorr[k]->ducking_flag )
+ {
+ ivas_td_decorr_get_ducking_gains( hTdDecorr[k]->pTrans_det, pcm_in[k], in_duck_gain, out_duck_gain, output_frame, 0 );
+
+ for ( j = 0; j < output_frame; j++ )
+ {
+ pp_out_pcm[k][j] = pp_out_pcm[k][j] * in_duck_gain[j];
+ }
+ }
+
+ /* All pass delay section */
+ ivas_td_decorr_APD_iir_filter( &hTdDecorr[k]->APD_filt_state[0], pp_out_pcm[k], hTdDecorr[k]->num_apd_sections, output_frame );
+
+ /* Out ducking gains */
+ if ( hTdDecorr[k]->ducking_flag )
+ {
+ for ( j = 0; j < output_frame; j++ )
+ {
+ pp_out_pcm[k][j] = pp_out_pcm[k][j] * out_duck_gain[j];
+ }
+ }
+ }
+
+ return;
+}
+
+static int huff_read(
+ Decoder_State *st,
+ const int16_t ( *ht )[2] )
+{
+ int16_t node = 0;
+ uint16_t next_bit = 0;
+
+ do
+ {
+ next_bit = st->bit_stream[st->next_bit_pos];
+ st->next_bit_pos++;
+ node = ht[node][next_bit];
+ } while ( node > 0 );
+
+ return -( node + 1 );
+}
+
+static void huffman_decode(
+ Decoder_State *st,
+ int16_t nv,
+ int16_t ivStart,
+ PAR_TYPE parType,
+ QUANT_TYPE quant_type,
+ int16_t bNoDt,
+ int32_t *vq )
+{
+ const int16_t( *huff_node_table )[2];
+ int16_t iv, bdt, nquant, offset;
+
+
+ nquant = 0;
+ switch ( parType )
+ {
+ case ALPHA:
+ nquant = alpha_quant_table[quant_type].nquant;
+ break;
+ case BETA:
+ nquant = beta_quant_table[quant_type][0].nquant;
+ break;
+ default:
+ assert( 0 );
+ }
+
+ offset = nquant - 1; /* range of df/dt [-(nquant - 1), nquant - 1] */
+
+ if ( bNoDt )
+ {
+ bdt = 0;
+ }
+ else
+ {
+ bdt = st->bit_stream[st->next_bit_pos];
+ st->next_bit_pos++;
+ }
+ if ( bdt )
+ { /* Get dt */
+ switch ( parType )
+ {
+ case ALPHA:
+ huff_node_table = huff_nodes_dt.alpha[quant_type];
+ break;
+ case BETA:
+ huff_node_table = huff_nodes_dt.beta[quant_type];
+ break;
+ default:
+ huff_node_table = NULL;
+ assert( 0 );
+ }
+ for ( iv = ivStart; iv < nv; iv++ )
+ {
+ vq[iv] = huff_read( st, huff_node_table ) + vq[iv] - offset;
+ }
+ }
+ else /* Get f0, df */
+ {
+ switch ( parType )
+ {
+ case ALPHA:
+ huff_node_table = huff_nodes_df0.alpha[quant_type];
+ break;
+ case BETA:
+ huff_node_table = huff_nodes_df0.beta[quant_type];
+ break;
+ default:
+ huff_node_table = NULL;
+ assert( 0 );
+ }
+ vq[ivStart] = huff_read( st, huff_node_table );
+
+ switch ( parType )
+ {
+ case ALPHA:
+ huff_node_table = huff_nodes_df.alpha[quant_type];
+ break;
+ case BETA:
+ huff_node_table = huff_nodes_df.beta[quant_type];
+ break;
+ default:
+ assert( 0 );
+ }
+
+ for ( iv = ivStart + 1; iv < nv; iv++ )
+ {
+ vq[iv] = huff_read( st, huff_node_table ) + vq[iv - 1] - offset;
+ }
+ }
+}
+
+static void dequant_alpha(
+ int16_t nv,
+ int16_t ivStart,
+ QUANT_TYPE quant_type,
+ int32_t *vq,
+ float *v )
+{
+ int16_t iv;
+ ACPL_QUANT_TABLE *quant_table = &alpha_quant_table[quant_type];
+
+ for ( iv = 0; iv < ivStart; iv++ )
+ {
+ v[iv] = 0;
+ }
+
+ for ( iv = ivStart; iv < nv; iv++ )
+ {
+ v[iv] = quant_table->data[vq[iv]];
+ }
+}
+
+static void dequant_beta(
+ int16_t nv,
+ int16_t ivStart,
+ QUANT_TYPE quant_type,
+ int32_t *aq,
+ int32_t *bq,
+ float *beta )
+{
+ int16_t iv;
+ ACPL_QUANT_TABLE *quant_table;
+ const int16_t qmap[2][33] = {
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
+ { 0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1, 0 }
+ };
+
+ for ( iv = 0; iv < ivStart; iv++ )
+ {
+ beta[iv] = 0;
+ }
+
+ for ( iv = ivStart; iv < nv; iv++ )
+ {
+ quant_table = &beta_quant_table[quant_type][qmap[quant_type][aq[iv]]];
+ beta[iv] = quant_table->data[bq[iv]];
+ }
+}
+
+static void get_ec_data(
+ Decoder_State *st,
+ PAR_TYPE parType,
+ QUANT_TYPE quant_type,
+ int16_t nParBand,
+ int16_t parBandStart,
+ int32_t *parQ,
+ int32_t *alphaQEnv,
+ float ab[IVAS_MAX_NUM_BANDS] )
+{
+ huffman_decode( st, nParBand, parBandStart, parType, quant_type, 0, parQ );
+ if ( parType == ALPHA )
+ {
+ dequant_alpha( nParBand, parBandStart, quant_type, parQ, ab );
+ mvl2l( parQ, alphaQEnv, (int16_t) nParBand );
+ }
+ else
+ {
+ dequant_beta( nParBand, parBandStart, quant_type, alphaQEnv, parQ, ab );
+ }
+}
+
+#endif
diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c
old mode 100644
new mode 100755
index 4d6f8343084bf4e1dc02862741c7351cd47389c5..a4beb49d94d021ce1b5945c16228900aa955ea60
--- a/lib_dec/ivas_mct_dec.c
+++ b/lib_dec/ivas_mct_dec.c
@@ -195,6 +195,7 @@ ivas_error ivas_mct_dec(
/* Equalization in MDCT Domain */
ivas_ls_setup_conversion_process_mdct( st_ivas, output );
}
+
else if ( st_ivas->renderer_type == RENDERER_MC_PARAMMC && ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) )
{
float *x_all[MAX_CICP_CHANNELS][NB_DIV];
@@ -273,7 +274,11 @@ ivas_error ivas_mct_dec(
#endif
}
/* move channels after LFE to correct output for multi-channel MCT */
+#ifdef MC_PARAMUPMIX_MODE
+ if ( st_ivas->ivas_format == MC_FORMAT && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) )
+#else
if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT )
+#endif
{
float tmp[L_FRAME48k];
@@ -344,6 +349,12 @@ ivas_error create_mct_dec(
{
hMCT->nchan_out_woLFE = st_ivas->nchan_transport - st_ivas->hTransSetup.num_lfe;
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ hMCT->nchan_out_woLFE = st_ivas->nchan_transport - st_ivas->hTransSetup.num_lfe;
+ }
+#endif
else
{
assert( !"IVAS format currently not supported for MCT" );
@@ -449,6 +460,12 @@ ivas_error mct_dec_reconfigure(
{
hMCT->nchan_out_woLFE = st_ivas->nchan_transport - st_ivas->hTransSetup.num_lfe;
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ hMCT->nchan_out_woLFE = st_ivas->nchan_transport - st_ivas->hTransSetup.num_lfe;
+ }
+#endif
else
{
assert( !"IVAS format currently not supported for MCT" );
@@ -723,7 +740,9 @@ static ivas_error ivas_mc_dec_reconfig(
/* remove ls conversion if it was allocated by ParamMC */
ivas_ls_setup_conversion_close( &st_ivas->hLsSetUpConversion );
}
-
+#ifdef MC_PARAMUPMIX_MODE
+ ivas_mc_paramupmix_dec_close( &( st_ivas->hMCParamUpmix ) );
+#endif
/* De-allocate McMasa-related handles */
ivas_masa_dec_close( &( st_ivas->hMasa ) );
ivas_qmetadata_close( &st_ivas->hQMetaData );
@@ -738,6 +757,48 @@ static ivas_error ivas_mc_dec_reconfig(
}
}
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ st_ivas->nSCE = 0;
+ st_ivas->nCPE = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS / 2;
+ st_ivas->nchan_transport = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS;
+
+ if ( last_mc_mode != MC_MODE_PARAMUPMIX )
+ /* This should always be the case, only supporting one bitrate currently */
+ {
+ /*De-allocate handles for other MC modes*/
+ if ( st_ivas->hParamMC != NULL )
+ {
+ ivas_param_mc_dec_close( &st_ivas->hParamMC );
+
+ /* remove ls conversion if it was allocated by ParamMC */
+ ivas_ls_setup_conversion_close( &st_ivas->hLsSetUpConversion );
+ }
+
+ ivas_masa_dec_close( &( st_ivas->hMasa ) );
+ ivas_qmetadata_close( &st_ivas->hQMetaData );
+
+ /* init LS conversion if the renderer type asks for it */
+ if ( ( st_ivas->renderer_type == RENDERER_MC ) && st_ivas->hLsSetUpConversion == NULL )
+ {
+ if ( ( error = ivas_ls_setup_conversion_open( st_ivas ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+ if ( ( error = ivas_mc_paramupmix_dec_open( st_ivas ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+ else
+ {
+ assert( 0 );
+ }
+ }
+#endif
else if ( st_ivas->mc_mode == MC_MODE_PARAMMC )
{
if ( last_mc_mode != MC_MODE_PARAMMC )
@@ -799,6 +860,10 @@ static ivas_error ivas_mc_dec_reconfig(
ivas_ls_setup_conversion_close( &st_ivas->hLsSetUpConversion );
}
+#ifdef MC_PARAMUPMIX_MODE
+ ivas_mc_paramupmix_dec_close( &( st_ivas->hMCParamUpmix ) );
+#endif
+
if ( st_ivas->hParamMC != NULL )
{
ivas_param_mc_dec_close( &st_ivas->hParamMC );
@@ -892,6 +957,13 @@ static ivas_error ivas_mc_dec_reconfig(
new_brate_SCE = 0;
new_brate_CPE = ( ivas_total_brate / ( st_ivas->nchan_transport - 1 ) ) * CPE_CHANNELS;
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ new_brate_SCE = 0;
+ new_brate_CPE = ( ivas_total_brate / ( st_ivas->nchan_transport - 1 ) ) * CPE_CHANNELS;
+ }
+#endif
else
{
new_brate_SCE = 0; /* ivas_total_brate / st_ivas->nchan_transport;*/
@@ -942,8 +1014,11 @@ static ivas_error ivas_mc_dec_reconfig(
/*-----------------------------------------------------------------*
* Allocate the LFE handle that is coded seperately after the allocation of the core coders
*-----------------------------------------------------------------*/
-
+#ifdef MC_PARAMUPMIX_MODE
+ if ( ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) && st_ivas->hLFE == NULL )
+#else
if ( st_ivas->mc_mode == MC_MODE_MCT && st_ivas->hLFE == NULL )
+#endif
{
int32_t binauralization_delay_ns = st_ivas->binaural_latency_ns;
if ( st_ivas->hBinRenderer != NULL )
diff --git a/lib_dec/ivas_out_setup_conversion.c b/lib_dec/ivas_out_setup_conversion.c
index 2fb04af8d78f3dda0f1b974a1215b51c46f4bebf..c4cb10ff859a5a479ca280538093652b4343084c 100644
--- a/lib_dec/ivas_out_setup_conversion.c
+++ b/lib_dec/ivas_out_setup_conversion.c
@@ -312,7 +312,18 @@ ivas_error ivas_ls_setup_conversion_open(
int16_t output_frame;
int32_t output_Fs;
int16_t nchan_out;
+#ifdef MC_PARAMUPMIX_MODE
+ int16_t paramUpmixMonoStereo;
+ if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX && ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) )
+ {
+ paramUpmixMonoStereo = TRUE;
+ }
+ else
+ {
+ paramUpmixMonoStereo = FALSE;
+ }
+#endif
output_Fs = st_ivas->hDecoderConfig->output_Fs;
nchan_out = st_ivas->hDecoderConfig->nchan_out;
output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC );
@@ -351,7 +362,26 @@ ivas_error ivas_ls_setup_conversion_open(
}
else
{
+#ifdef MC_PARAMUPMIX_MODE
+ if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ if ( paramUpmixMonoStereo == TRUE )
+ {
+ inChannels = audioCfg2channels( AUDIO_CONFIG_5_1_2 );
+ }
+ else
+ {
+ inChannels = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe;
+ }
+ }
+ else
+ {
+ inChannels = st_ivas->nchan_transport;
+ }
+#else
inChannels = st_ivas->nchan_transport;
+#endif
+
/*Initialization of MDCT bands with TCX20 resolution */
ivas_lssetupconversion_mdct_init_bands( output_frame, TCX_20_CORE, &hLsSetUpConversion->sfbOffset[0], &hLsSetUpConversion->sfbCnt );
if ( ( hLsSetUpConversion->targetEnergyPrev[0] = (float *) malloc( ( MAX_SFB + 2 ) * sizeof( float ) ) ) == NULL )
@@ -397,7 +427,18 @@ ivas_error ivas_ls_setup_conversion_open(
{
if ( st_ivas->transport_config != AUDIO_CONFIG_INVALID )
{
+#ifdef MC_PARAMUPMIX_MODE
+ if ( paramUpmixMonoStereo == TRUE )
+ {
+ get_ls_conversion_matrix( hLsSetUpConversion, AUDIO_CONFIG_5_1_2, st_ivas->hDecoderConfig->output_config );
+ }
+ else
+ {
+ get_ls_conversion_matrix( hLsSetUpConversion, st_ivas->transport_config, st_ivas->hDecoderConfig->output_config );
+ }
+#else
get_ls_conversion_matrix( hLsSetUpConversion, st_ivas->transport_config, st_ivas->hDecoderConfig->output_config );
+#endif
}
else
{
@@ -464,7 +505,10 @@ void ivas_ls_setup_conversion_close(
*-------------------------------------------------------------------------*/
void ivas_ls_setup_conversion(
- Decoder_Struct *st_ivas, /* i : IVAS decoder structure */
+ Decoder_Struct *st_ivas, /* i : IVAS decoder structure */
+#ifdef MC_PARAMUPMIX_MODE
+ const int16_t input_chans, /* i : number of input channels to the renderer */
+#endif
const int16_t output_frame, /* i : frame length */
float output[][L_FRAME48k] /* i/o: LS input/output synthesis signal */
)
@@ -481,7 +525,11 @@ void ivas_ls_setup_conversion(
for ( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
{
set_zero( output_tmp[chOutIdx], output_frame );
+#ifdef MC_PARAMUPMIX_MODE
+ for ( chInIdx = 0; chInIdx < input_chans; chInIdx++ )
+#else
for ( chInIdx = 0; chInIdx < st_ivas->nchan_transport; chInIdx++ )
+#endif
{
dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx];
diff --git a/lib_dec/ivas_output_config.c b/lib_dec/ivas_output_config.c
index 42e7c8506825c37c0fff7239790a3562fb68bf30..f0d9ad84c315c67af470a8275616b072ec4222a1 100644
--- a/lib_dec/ivas_output_config.c
+++ b/lib_dec/ivas_output_config.c
@@ -195,17 +195,29 @@ void ivas_renderer_select(
*internal_config = transport_config;
if ( output_config == AUDIO_CONFIG_BINAURAL )
{
+#ifdef MC_PARAMUPMIX_MODE
+#ifdef DEBUGGING
+ if ( ( ( ( st_ivas->transport_config == AUDIO_CONFIG_5_1 || st_ivas->transport_config == AUDIO_CONFIG_7_1 ) && st_ivas->hDecoderConfig->Opt_Headrotation ) || ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) ) && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) && !( st_ivas->hDecoderConfig->force_rend == FORCE_CLDFB_RENDERER ) )
+#else
+ if ( ( st_ivas->transport_config == AUDIO_CONFIG_5_1 || st_ivas->transport_config == AUDIO_CONFIG_7_1 ) && st_ivas->hDecoderConfig->Opt_Headrotation && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) )
+#endif
+#else
#ifdef DEBUGGING
if ( ( ( ( st_ivas->transport_config == AUDIO_CONFIG_5_1 || st_ivas->transport_config == AUDIO_CONFIG_7_1 ) && st_ivas->hDecoderConfig->Opt_Headrotation ) || ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) ) && ( st_ivas->mc_mode == MC_MODE_MCT ) && !( st_ivas->hDecoderConfig->force_rend == FORCE_CLDFB_RENDERER ) )
#else
if ( ( st_ivas->transport_config == AUDIO_CONFIG_5_1 || st_ivas->transport_config == AUDIO_CONFIG_7_1 ) && st_ivas->hDecoderConfig->Opt_Headrotation && ( st_ivas->mc_mode == MC_MODE_MCT ) )
+#endif
#endif
{
*renderer_type = RENDERER_BINAURAL_OBJECTS_TD;
}
else
{
+#ifdef MC_PARAMUPMIX_MODE
+ if ( ( st_ivas->mc_mode == MC_MODE_MCT ) || ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) )
+#else
if ( st_ivas->mc_mode == MC_MODE_MCT )
+#endif
{
*renderer_type = RENDERER_BINAURAL_MIXER_CONV;
}
@@ -233,7 +245,11 @@ void ivas_renderer_select(
}
else /* AUDIO_CONFIG_BINAURAL_ROOM */
{
+#ifdef MC_PARAMUPMIX_MODE
+ if ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+#else
if ( st_ivas->mc_mode == MC_MODE_MCT )
+#endif
{
*renderer_type = RENDERER_BINAURAL_MIXER_CONV_ROOM;
}
@@ -360,6 +376,23 @@ void ivas_renderer_select(
*renderer_type = RENDERER_SBA_LINEAR_ENC;
}
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ *internal_config = transport_config;
+ if ( *internal_config != output_config )
+ {
+ if ( output_config != AUDIO_CONFIG_FOA && output_config != AUDIO_CONFIG_HOA2 && output_config != AUDIO_CONFIG_HOA3 )
+ {
+ *renderer_type = RENDERER_MC;
+ }
+ else
+ {
+ *renderer_type = RENDERER_SBA_LINEAR_ENC;
+ }
+ }
+ }
+#endif
else if ( st_ivas->mc_mode == MC_MODE_PARAMMC )
{
if ( output_config == AUDIO_CONFIG_FOA || output_config == AUDIO_CONFIG_HOA2 || output_config == AUDIO_CONFIG_HOA3 )
diff --git a/lib_dec/ivas_rom_dec.c b/lib_dec/ivas_rom_dec.c
index 9daef50fa1bbec8394c00c10d1fbc4b25d6deb49..2b034655f3427156e9b7a77c65379ff41099ed3c 100644
--- a/lib_dec/ivas_rom_dec.c
+++ b/lib_dec/ivas_rom_dec.c
@@ -553,3 +553,293 @@ const float dmxmtx_table[BINAURAL_CHANNELS][11] =
/* clang-format on */
+
+#ifdef MC_PARAMUPMIX_MODE
+
+const int16_t huff_nodes_first_band_alpha[32][2] = { /* Alpha Fine Huffman table df0 */
+ { -17, 1 },
+ { 3, 2 },
+ { -16, -18 },
+ { 5, 4 },
+ { -15, 6 },
+ { -19, 7 },
+ { 9, 8 },
+ { 11, 10 },
+ { -14, -20 },
+ { 13, 12 },
+ { -21, 14 },
+ { -13, 15 },
+ { 17, 16 },
+ { -22, 18 },
+ { -12, 19 },
+ { -9, -10 },
+ { -11, 20 },
+ { -23, 21 },
+ { -8, 22 },
+ { -24, 23 },
+ { -25, 24 },
+ { -7, 25 },
+ { -26, 26 },
+ { 28, 27 },
+ { -6, -27 },
+ { -33, 29 },
+ { -1, -28 },
+ { -5, 30 },
+ { -29, -30 },
+ { -4, 31 },
+ { -3, -31 },
+ { -2, -32 }
+};
+const int16_t huff_nodes_first_band_alpha_coarse[16][2] = { /* Alpha Coarse Huffman table df0 */
+ { -9, 1 },
+ { -8, 2 },
+ { -10, 3 },
+ { 5, 4 },
+ { -7, 6 },
+ { -11, 7 },
+ { -5, 8 },
+ { -6, 9 },
+ { -12, 10 },
+ { -13, 11 },
+ { -4, 12 },
+ { -14, 13 },
+ { -3, 14 },
+ { -15, 15 },
+ { -2, -16 },
+ { -1, -17 }
+};
+
+
+const int16_t huff_nodes_alpha_1D_DF[64][2] = { /* Alpha Fine Huffman table df */
+ { -33, 1 },
+ { 3, 2 },
+ { -32, -34 },
+ { 5, 4 },
+ { -31, -35 },
+ { 7, 6 },
+ { -30, 8 },
+ { -36, 9 },
+ { 11, 10 },
+ { -37, 12 },
+ { -29, 13 },
+ { -28, 14 },
+ { -38, 15 },
+ { 17, 16 },
+ { -27, -39 },
+ { 19, 18 },
+ { -26, 20 },
+ { -40, 21 },
+ { 23, 22 },
+ { -41, 24 },
+ { -25, 25 },
+ { -24, 26 },
+ { -42, 27 },
+ { -43, 28 },
+ { -23, 29 },
+ { -44, 30 },
+ { -22, 31 },
+ { -45, 32 },
+ { -21, 33 },
+ { -20, 34 },
+ { -46, 35 },
+ { -19, 36 },
+ { -47, 37 },
+ { -18, -48 },
+ { 39, 38 },
+ { -17, -49 },
+ { 41, 40 },
+ { -16, 42 },
+ { -1, -50 },
+ { -65, 43 },
+ { 45, 44 },
+ { -51, 46 },
+ { -15, 47 },
+ { 49, 48 },
+ { -52, 50 },
+ { -14, 51 },
+ { 53, 52 },
+ { -13, 54 },
+ { -53, 55 },
+ { 57, 56 },
+ { -12, 58 },
+ { -54, 59 },
+ { 61, 60 },
+ { -55, 62 },
+ { -11, 63 },
+ { -10, -61 },
+ { -5, -57 },
+ { -58, -60 },
+ { -56, -59 },
+ { -4, -6 },
+ { -7, -64 },
+ { -9, -63 },
+ { -3, -8 },
+ { -2, -62 }
+};
+const int16_t huff_nodes_alpha_1D_DF_coarse[32][2] = { /* Alpha Coarse Huffman table df */
+ { -17, 1 },
+ { -18, 2 },
+ { -16, 3 },
+ { -15, 4 },
+ { -19, 5 },
+ { 7, 6 },
+ { -14, -20 },
+ { 9, 8 },
+ { -13, -21 },
+ { 11, 10 },
+ { -22, 12 },
+ { -12, 13 },
+ { -23, 14 },
+ { -11, 15 },
+ { -10, 16 },
+ { -24, 17 },
+ { -9, -25 },
+ { 19, 18 },
+ { -26, 20 },
+ { -8, 21 },
+ { 23, 22 },
+ { 25, 24 },
+ { -27, 26 },
+ { -7, 27 },
+ { -1, -33 },
+ { -6, 28 },
+ { -28, 29 },
+ { -29, 30 },
+ { -5, -31 },
+ { -30, 31 },
+ { -3, -4 },
+ { -2, -32 }
+};
+
+const int16_t huff_nodes_alpha_1D_DT[64][2] = { /* Alpha Fine Huffman table dt */
+ { -33, 1 },
+ { -34, 2 },
+ { -32, 3 },
+ { 5, 4 },
+ { -31, -35 },
+ { 7, 6 },
+ { -36, 8 },
+ { -30, 9 },
+ { 11, 10 },
+ { -29, -37 },
+ { 13, 12 },
+ { 15, 14 },
+ { -28, -38 },
+ { 17, 16 },
+ { -27, -39 },
+ { 19, 18 },
+ { -40, 20 },
+ { -26, 21 },
+ { 23, 22 },
+ { -25, -41 },
+ { 25, 24 },
+ { -24, -42 },
+ { 27, 26 },
+ { -23, -43 },
+ { 29, 28 },
+ { -22, -44 },
+ { 31, 30 },
+ { -45, 32 },
+ { -21, 33 },
+ { -20, 34 },
+ { -46, 35 },
+ { -47, 36 },
+ { -19, 37 },
+ { -48, 38 },
+ { -18, 39 },
+ { 41, 40 },
+ { -17, -49 },
+ { 43, 42 },
+ { -50, 44 },
+ { -16, 45 },
+ { 47, 46 },
+ { -51, 48 },
+ { -15, 49 },
+ { 51, 50 },
+ { -52, -65 },
+ { -1, -14 },
+ { 53, 52 },
+ { -53, 54 },
+ { -13, 55 },
+ { 57, 56 },
+ { -12, 58 },
+ { -54, 59 },
+ { 61, 60 },
+ { -11, -55 },
+ { -56, 62 },
+ { -10, 63 },
+ { -9, -57 },
+ { -5, -6 },
+ { -58, -61 },
+ { -7, -59 },
+ { -8, -62 },
+ { -4, -60 },
+ { -3, -64 },
+ { -2, -63 }
+};
+const int16_t huff_nodes_alpha_1D_DT_coarse[32][2] = { /* Alpha Coarse Huffman table dt */
+ { -17, 1 },
+ { -18, 2 },
+ { -16, 3 },
+ { -19, 4 },
+ { -15, 5 },
+ { 7, 6 },
+ { -14, -20 },
+ { 9, 8 },
+ { -21, 10 },
+ { -13, 11 },
+ { 13, 12 },
+ { -12, -22 },
+ { 15, 14 },
+ { -11, -23 },
+ { 17, 16 },
+ { -24, 18 },
+ { -10, 19 },
+ { -25, 20 },
+ { -9, 21 },
+ { 23, 22 },
+ { -26, 24 },
+ { -8, 25 },
+ { 27, 26 },
+ { -1, -33 },
+ { -7, -27 },
+ { 29, 28 },
+ { -28, 30 },
+ { -6, 31 },
+ { -5, -29 },
+ { -3, -31 },
+ { -4, -30 },
+ { -2, -32 }
+};
+
+const int16_t huff_nodes_first_band_beta[8][2] = /* Beta Fine Huffman table df0 */
+ { { -1, 1 }, { -2, 2 }, { -3, 3 }, { -4, 4 }, { -5, 5 }, { -6, 6 }, { -7, 7 }, { -8, -9 } };
+const int16_t huff_nodes_first_band_beta_coarse[4][2] = /* Beta Coarse Huffman table df0 */
+ { { -1, 1 }, { -2, 2 }, { -3, 3 }, { -4, -5 } };
+
+const int16_t huff_nodes_beta_1D_DF[16][2] = /* Beta Fine Huffman table df */
+ { { -9, 1 }, { -10, 2 }, { -8, 3 }, { -11, 4 }, { -7, 5 }, { 7, 6 }, { -6, -12 }, { 9, 8 }, { -5, -13 }, { 11, 10 }, { -4, -14 }, { -15, 12 }, { -3, 13 }, { -16, 14 }, { -2, 15 }, { -1, -17 } };
+const int16_t huff_nodes_beta_1D_DF_coarse[8][2] = /* Beta Coarse Huffman table df */
+ { { -5, 1 }, { -6, 2 }, { -4, 3 }, { -3, 4 }, { -7, 5 }, { -2, 6 }, { -8, 7 }, { -1, -9 } };
+
+const int16_t huff_nodes_beta_1D_DT[16][2] = /* Beta Fine Huffman table dt */
+ { { -9, 1 }, { -10, 2 }, { -8, 3 }, { -11, 4 }, { -7, 5 }, { 7, 6 }, { -6, -12 }, { -13, 8 }, { -5, 9 }, { -14, 10 }, { -4, 11 }, { -15, 12 }, { -3, 13 }, { -16, 14 }, { -2, 15 }, { -1, -17 } };
+const int16_t huff_nodes_beta_1D_DT_coarse[8][2] = /* Beta Coarse Huffman table dt */
+ { { -5, 1 }, { -6, 2 }, { -4, 3 }, { -7, 4 }, { -3, 5 }, { -8, 6 }, { -2, 7 }, { -1, -9 } };
+
+HUFF_NODE_TABLE huff_nodes_df0 = {
+ { huff_nodes_first_band_alpha, huff_nodes_first_band_alpha_coarse },
+ { huff_nodes_first_band_beta, huff_nodes_first_band_beta_coarse }
+};
+
+HUFF_NODE_TABLE huff_nodes_df = {
+ { huff_nodes_alpha_1D_DF, huff_nodes_alpha_1D_DF_coarse },
+ { huff_nodes_beta_1D_DF, huff_nodes_beta_1D_DF_coarse }
+};
+
+HUFF_NODE_TABLE huff_nodes_dt = {
+ { huff_nodes_alpha_1D_DT, huff_nodes_alpha_1D_DT_coarse },
+ { huff_nodes_beta_1D_DT, huff_nodes_beta_1D_DT_coarse }
+};
+
+#endif
diff --git a/lib_dec/ivas_rom_dec.h b/lib_dec/ivas_rom_dec.h
index c3e21278c062af2de64db6be8ff260090bd8029b..81aec535a2b901fcb5df063b8967694b713e1284 100644
--- a/lib_dec/ivas_rom_dec.h
+++ b/lib_dec/ivas_rom_dec.h
@@ -129,4 +129,28 @@ extern const int16_t sba_map_tc[8];
extern const float dmxmtx_table[BINAURAL_CHANNELS][11];
+#ifdef MC_PARAMUPMIX_MODE
+extern const int16_t huff_nodes_first_band_alpha[32][2];
+extern const int16_t huff_nodes_first_band_alpha_coarse[16][2];
+
+
+extern const int16_t huff_nodes_alpha_1D_DF[64][2];
+extern const int16_t huff_nodes_alpha_1D_DF_coarse[32][2];
+
+extern const int16_t huff_nodes_alpha_1D_DT[64][2];
+extern const int16_t huff_nodes_alpha_1D_DT_coarse[32][2];
+
+extern const int16_t huff_nodes_first_band_beta[8][2];
+extern const int16_t huff_nodes_first_band_beta_coarse[4][2];
+
+extern const int16_t huff_nodes_beta_1D_DF[16][2];
+extern const int16_t huff_nodes_beta_1D_DF_coarse[8][2];
+
+extern const int16_t huff_nodes_beta_1D_DT[16][2];
+extern const int16_t huff_nodes_beta_1D_DT_coarse[8][2];
+extern const HUFF_NODE_TABLE huff_nodes_df0;
+extern const HUFF_NODE_TABLE huff_nodes_df;
+extern const HUFF_NODE_TABLE huff_nodes_dt;
+#endif
+
#endif
diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h
index 69d03c03c52bd172deff5b584b910b18fd4175f1..0e2f01c574c0189fe64d0fb355cb1b705424ea30 100755
--- a/lib_dec/ivas_stat_dec.h
+++ b/lib_dec/ivas_stat_dec.h
@@ -773,7 +773,27 @@ typedef struct ivas_param_mc_dec_data_structure
} PARAM_MC_DEC_DATA, *PARAM_MC_DEC_HANDLE;
+#ifdef MC_PARAMUPMIX_MODE
+/*----------------------------------------------------------------------------------*
+ * MC Param-Upmix Mode structures
+ *----------------------------------------------------------------------------------*/
+/* ===== MC Param-Upmix Mode main structure ===== */
+typedef struct ivas_mc_paramupmix_dec_data_structure
+{
+ int16_t num_freq_bands;
+ ivas_td_decorr_state_t *hTdDecorr[MC_PARAMUPMIX_COMBINATIONS];
+ float alphas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ float betas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ float alpha_prev[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ float beta_prev[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ int32_t alpha_quant[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ int32_t beta_quant[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ bool first_frame;
+ float *pcm_delay[MC_PARAMUPMIX_MAX_TRANSPORT_CHANS];
+
+} MC_PARAMUPMIX_DEC_DATA, *MC_PARAMUPMIX_DEC_HANDLE;
+#endif
/*------------------------------------------------------------------------------------------*
* SPAR decoder structures
*------------------------------------------------------------------------------------------*/
@@ -1216,6 +1236,9 @@ typedef struct Decoder_Struct
IVAS_QMETADATA_HANDLE hQMetaData; /* q_metadata handle */
MCT_DEC_HANDLE hMCT; /* MCT handle */
PARAM_MC_DEC_HANDLE hParamMC; /* Parametric MC handle */
+#ifdef MC_PARAMUPMIX_MODE
+ MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix; /* MC Param-Upmix handle */
+#endif
MASA_DECODER_HANDLE hMasa; /* MASA handle */
LFE_DEC_HANDLE hLFE; /* LFE handle */
diff --git a/lib_dec/ivas_stereo_switching_dec.c b/lib_dec/ivas_stereo_switching_dec.c
index 0a436ec0d28eec23fc6ba6d080122ca92bbbed81..898908c96e4dda4e55538efeb2c4bb0bdd51b51b 100644
--- a/lib_dec/ivas_stereo_switching_dec.c
+++ b/lib_dec/ivas_stereo_switching_dec.c
@@ -963,7 +963,11 @@ ivas_error stereo_memory_dec(
if ( ivas_format == MC_FORMAT && hCPE->element_mode == IVAS_CPE_MDCT )
{
+#ifdef MC_PARAMUPMIX_MODE
+ if ( mc_mode == MC_MODE_MCT || mc_mode == MC_MODE_PARAMUPMIX )
+#else
if ( mc_mode == MC_MODE_MCT )
+#endif
{
/* deallocate the FdCNG handle */
for ( i = 0; i < CPE_CHANNELS; ++i )
diff --git a/lib_enc/ivas_enc.c b/lib_enc/ivas_enc.c
index fa293221d4457b95925cef5ae49f2e3bd8826efd..50ea332a7a1e1eab725e275436253840897fa45e 100644
--- a/lib_enc/ivas_enc.c
+++ b/lib_enc/ivas_enc.c
@@ -307,6 +307,22 @@ ivas_error ivas_enc(
return error;
}
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+
+ /* encode MC ParamUpmix parameters and write bitstream */
+ ivas_mc_paramupmix_enc( st_ivas, hMetaData, data_f, input_frame );
+
+ st_ivas->hLFE->hBstr = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0]->hBstr : st_ivas->hCPE[0]->hCoreCoder[0]->hBstr;
+ ivas_lfe_enc( st_ivas->hLFE, data_f[LFE_CHANNEL], input_frame, st_ivas->hLFE->hBstr );
+
+ if ( ( error = ivas_mct_enc( st_ivas, data_f, input_frame, hMetaData->nb_bits_tot ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+#endif
else if ( st_ivas->mc_mode == MC_MODE_PARAMMC )
{
/* encode Parametric MC parameters and write bitstream */
diff --git a/lib_enc/ivas_enc_cov_handler.c b/lib_enc/ivas_enc_cov_handler.c
index e7a4f2d76f15161b4733bb06acf715048e11f252..7390ba8b38dd11f1b23a3901016d9ab816faf8ba 100644
--- a/lib_enc/ivas_enc_cov_handler.c
+++ b/lib_enc/ivas_enc_cov_handler.c
@@ -92,6 +92,13 @@ ivas_error ivas_spar_covar_enc_open(
cov_smooth_cfg.max_bands = IVAS_MAX_NUM_BANDS;
cov_smooth_cfg.max_update_rate = MAX_UPDATE_RATE;
cov_smooth_cfg.min_pool_size = MIN_POOL_SIZE;
+#ifdef MC_PARAMUPMIX_MODE
+ if ( nchan_inp == 3 ) /* to discriminate between SPAR and mc there could be a better solution */
+ {
+ cov_smooth_cfg.max_update_rate = 1.0f;
+ cov_smooth_cfg.min_pool_size = 20;
+ }
+#endif
if ( ( error = ivas_spar_covar_smooth_enc_open( &hCovState->pCov_state, &cov_smooth_cfg, pFb, nchan_inp, ivas_total_brate ) ) != IVAS_ERR_OK )
{
diff --git a/lib_enc/ivas_init_enc.c b/lib_enc/ivas_init_enc.c
index 83a733fe480b976346090496e36141106f17235e..c706d9bb64ca4dc11b3a8851bc3af220f66873ff 100644
--- a/lib_enc/ivas_init_enc.c
+++ b/lib_enc/ivas_init_enc.c
@@ -209,6 +209,12 @@ int16_t getNumChanAnalysis(
{
n = st_ivas->hEncoderConfig->nchan_inp;
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->hEncoderConfig->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ n = st_ivas->hEncoderConfig->nchan_inp;
+ }
+#endif
else if ( st_ivas->hEncoderConfig->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM )
{
n = st_ivas->hEncoderConfig->nchan_inp;
@@ -309,6 +315,11 @@ void ivas_initialize_handles_enc(
/* MCT handle */
st_ivas->hMCT = NULL;
+#ifdef MC_PARAMUPMIX_MODE
+ /* MC Param-Upmix handle */
+ st_ivas->hMCParamUpmix = NULL;
+#endif
+
/* Parametric MC handle */
st_ivas->hParamMC = NULL;
@@ -593,6 +604,51 @@ ivas_error ivas_init_encoder(
st_ivas->nchan_transport = ivas_mc_ls_setup_get_num_channels( st_ivas->hEncoderConfig->mc_input_setup );
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ st_ivas->nSCE = 0;
+ st_ivas->nCPE = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS / 2;
+ st_ivas->nchan_transport = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS;
+
+ if ( ( error = ivas_mc_paramupmix_enc_open( st_ivas ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ )
+ {
+ if ( ( error = create_cpe_enc( st_ivas, cpe_id, ( ivas_total_brate / st_ivas->nCPE ) ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ for ( n = 0; n < CPE_CHANNELS; n++ )
+ {
+ /* we need the correct bitstream also for the LFE channel since it might become a proper coded channel when
+ switching to ParamMC and ind_list is only visible here, can't be done later */
+ st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->ind_list = ind_list[cpe_id * CPE_CHANNELS + n];
+ reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, MAX_NUM_INDICES );
+ }
+ /* Metadata only initialized for the last CPE index*/
+ if ( cpe_id == st_ivas->nCPE - 1 )
+ {
+ st_ivas->hCPE[cpe_id]->hMetaData->ind_list = ind_list_metadata[st_ivas->nSCE];
+ reset_indices_enc( st_ivas->hCPE[cpe_id]->hMetaData, MAX_BITS_METADATA );
+ }
+ }
+
+ if ( ( error = create_mct_enc( st_ivas ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ if ( ( error = ivas_create_lfe_enc( &st_ivas->hLFE, input_Fs ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+#endif
else if ( st_ivas->mc_mode == MC_MODE_PARAMMC )
{
if ( ( error = ivas_param_mc_enc_open( st_ivas ) ) != IVAS_ERR_OK )
@@ -968,6 +1024,11 @@ void ivas_destroy_enc(
/* LFE handle */
ivas_lfe_enc_close( &( st_ivas->hLFE ) );
+#ifdef MC_PARAMUPMIX_MODE
+ /* Param-Upmix MC handle */
+ ivas_mc_paramupmix_enc_close( &( st_ivas->hMCParamUpmix ), st_ivas->hEncoderConfig->input_Fs );
+#endif
+
/* Parametric MC handle */
ivas_param_mc_enc_close( &( st_ivas->hParamMC ), st_ivas->hEncoderConfig->input_Fs );
diff --git a/lib_enc/ivas_mc_paramupmix_enc.c b/lib_enc/ivas_mc_paramupmix_enc.c
new file mode 100644
index 0000000000000000000000000000000000000000..a44121f9a77b6b35978b3873417a07224b2e3dfb
--- /dev/null
+++ b/lib_enc/ivas_mc_paramupmix_enc.c
@@ -0,0 +1,848 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+#include "rom_enc.h"
+#include "rom_com.h"
+#include "prot.h"
+#include "ivas_prot.h"
+#include "ivas_cnst.h"
+#include "ivas_rom_com.h"
+#include "ivas_rom_enc.h"
+#ifdef DEBUGGING
+#include "debug.h"
+#endif
+#ifdef DEBUG_PLOT
+#include "deb_out.h"
+#endif
+#include "wmc_auto.h"
+
+#ifdef MC_PARAMUPMIX_MODE
+/*-------------------------------------------------------------------------
+ * Local function prototypes
+ *------------------------------------------------------------------------*/
+
+static void ivas_mc_paramupmix_dmx( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, float data_f[][L_FRAME48k], const int16_t input_frame );
+
+static void ivas_mc_paramupmix_param_est_enc( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, float input_frame_t[][L_FRAME48k], const int16_t input_frame, float alphas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS], float betas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS] );
+
+static void get_huff_table( PAR_TYPE par_type, QUANT_TYPE quant_type, HUFF_TAB *df0, HUFF_TAB *df, HUFF_TAB *dt );
+
+static void write_huff_bits( int32_t value, uint16_t length, uint16_t bit_buffer[MC_PARAMUPMIX_MAX_BITS], int16_t *bit_pos );
+
+static void huffman_encode( int16_t bdfOnly, int16_t bdtAllowed, int16_t nv, int16_t ivStart, int32_t *vqPrev, int32_t *vq, PAR_TYPE parType, QUANT_TYPE quant_type, int16_t nq, uint16_t bit_buffer[MC_PARAMUPMIX_MAX_BITS], int16_t *bit_pos );
+
+static void put_ec_data( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, int16_t ch, float pars[IVAS_MAX_NUM_BANDS], float alphas[IVAS_MAX_NUM_BANDS], PAR_TYPE parType, uint16_t bit_buffer[MC_PARAMUPMIX_MAX_BITS], int16_t *bit_pos );
+
+static void quantize_alpha( int16_t nv, const float *alpha, QUANT_TYPE quant_type, int16_t *pnq, int32_t aq[IVAS_MAX_NUM_BANDS], float *adeq );
+
+static void quantize_pars( int16_t nv, const float *v, int16_t nq, const float *data, int32_t vq[IVAS_MAX_NUM_BANDS], float *vdeq );
+
+static void quantize_pars( int16_t nv, const float *v, int16_t nq, const float *data, int32_t vq[IVAS_MAX_NUM_BANDS], float *vdeq );
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_enc()
+ *
+ * MC ParamUpmix Encoder main encoding function
+ *------------------------------------------------------------------------*/
+
+void ivas_mc_paramupmix_enc(
+ Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */
+ BSTR_ENC_HANDLE hBStr, /* i/o: IVAS Metadata bitstream handle */
+ float data_f[][L_FRAME48k], /* i/o: input: CICP6, CICP12, CICP14, CICP16 or CICP19 MC data */
+ const int16_t input_frame /* i : input frame length */
+)
+{
+ MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix;
+ int16_t i;
+ float alphas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ float betas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ uint16_t bit_buffer[MC_PARAMUPMIX_MAX_BITS];
+ int16_t bit_pos;
+
+ push_wmops( "mc_paramupmix_enc" );
+
+ hMCParamUpmix = st_ivas->hMCParamUpmix;
+ bit_pos = 0;
+
+ /* Parameter estimation */
+ ivas_mc_paramupmix_param_est_enc( hMCParamUpmix, data_f, input_frame, alphas, betas );
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ put_ec_data( hMCParamUpmix, i, alphas[i], NULL, ALPHA, bit_buffer, &bit_pos );
+ put_ec_data( hMCParamUpmix, i, betas[i], alphas[i], BETA, bit_buffer, &bit_pos );
+ }
+
+ /* push the PARAM UPMIX MC side info from the temporary buffer into the medatdata bitstream*/
+ push_next_bits( hBStr, bit_buffer, bit_pos );
+
+ /* DMX generation*/
+ ivas_mc_paramupmix_dmx( hMCParamUpmix, data_f, input_frame );
+
+ pop_wmops();
+
+ return;
+}
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_enc_open()
+ *
+ * Initialize MC ParamUpmix encoder handle
+ *------------------------------------------------------------------------*/
+
+ivas_error ivas_mc_paramupmix_enc_open(
+ Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */
+)
+{
+ IVAS_FB_CFG *fb_cfg;
+ MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix;
+ int32_t input_Fs;
+ int32_t input_frame;
+ int16_t i, k, b, j;
+ ivas_error error;
+
+ error = IVAS_ERR_OK;
+ input_Fs = st_ivas->hEncoderConfig->input_Fs;
+ input_frame = (int32_t) st_ivas->hEncoderConfig->input_Fs / FRAMES_PER_SEC;
+
+ /* Sanity Checks */
+ if ( ( hMCParamUpmix = (MC_PARAMUPMIX_ENC_HANDLE) malloc( sizeof( MC_PARAMUPMIX_ENC_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MC_MODE_PARAMUPMIX\n" ) );
+ }
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ for ( k = 0; k < MC_PARAMUPMIX_NCH; k++ )
+ {
+ if ( ( hMCParamUpmix->midside[i][k] = (float *) malloc( sizeof( float ) * input_frame ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MC_MODE_PARAMUPMIX\n" ) );
+ }
+ set_zero( hMCParamUpmix->midside[i][k], (int16_t) input_frame );
+ }
+ }
+ hMCParamUpmix->first_frame = 1;
+
+ /* MC_LS_SETUP_5_1_2 is the only current configuration */
+ st_ivas->nchan_transport = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS;
+
+ /* set core coder dependent on the number of transport channels */
+ switch ( st_ivas->nchan_transport )
+ {
+ case 8:
+ st_ivas->nCPE = 4;
+ st_ivas->nSCE = 0;
+ st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_MDCT;
+ break;
+#ifdef DEBUGGING
+ default:
+ assert( 0 && "Number of transport channels not supported by MC PARAM UPMIX MODE!\n" );
+#endif
+ }
+
+
+ /* Transient Detector handle */
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ )
+ {
+ if ( ( error = ivas_transient_det_open( &( hMCParamUpmix->hTranDet[i] ), input_Fs ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+ /* set FB config. */
+ /* need to set num output channels to a value > 0 to get pFb != NULL */
+ if ( ( error = ivas_fb_set_cfg( &fb_cfg, MC_FORMAT, SBA_MODE_SPAR, MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH, MC_PARAMUPMIX_COMBINATIONS, 0, input_Fs
+#ifdef HODIRAC
+ ,
+ 0
+#endif
+ ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ fb_cfg->remix_order = mc_paramupmix_fb_remix_order;
+ /* override latency, could be moved to ivas_fb_set_cfg */
+ /* assuming parameters are calculated at end of frame, compensate for MCT delay and half of decoder fb */
+ /* still 1.5ms off, since MCT delay is not large enough */
+ /* param at end of frame */
+ fb_cfg->prior_input_length = (int16_t) ( NS2SA( input_Fs, 12000000L ) + NS2SA( input_Fs, DELAY_FB_4_NS / 2 ) - input_frame / 2 - NS2SA( input_Fs, DELAY_FB_1_NS / 2 ) );
+ fb_cfg->prior_input_length = (int16_t) max( fb_cfg->prior_input_length, input_frame / MAX_PARAM_SPATIAL_SUBFRAMES );
+
+ /* Allocate and initialize FB mixer handle */
+ if ( ( error = ivas_FB_mixer_open( &( hMCParamUpmix->hFbMixer ), input_Fs, fb_cfg, 0 ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ /* Covariance handle */
+ if ( ( error = ivas_spar_covar_enc_open( &( hMCParamUpmix->hCovEnc[i] ), hMCParamUpmix->hFbMixer->pFb, input_Fs, MC_PARAMUPMIX_NCH + 1, st_ivas->hEncoderConfig->ivas_total_brate ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+
+ for ( b = 0; b < MC_PARAMUPMIX_COMBINATIONS; b++ )
+ {
+ if ( ( hMCParamUpmix->cov_real[b] = (float ***) malloc( MC_PARAMUPMIX_NCH * sizeof( float ** ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov real matrix" );
+ }
+ for ( i = 0; i < MC_PARAMUPMIX_NCH; i++ )
+ {
+ if ( ( hMCParamUpmix->cov_real[b][i] = (float **) malloc( MC_PARAMUPMIX_NCH * sizeof( float * ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov real matrix" );
+ }
+ for ( j = 0; j < MC_PARAMUPMIX_NCH; j++ )
+ {
+ if ( ( hMCParamUpmix->cov_real[b][i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov real matrix" );
+ }
+ }
+ }
+
+ if ( ( hMCParamUpmix->cov_dtx_real[b] = (float ***) malloc( MC_PARAMUPMIX_NCH * sizeof( float ** ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov dtx real matrix" );
+ }
+ for ( i = 0; i < MC_PARAMUPMIX_NCH; i++ )
+ {
+ if ( ( hMCParamUpmix->cov_dtx_real[b][i] = (float **) malloc( MC_PARAMUPMIX_NCH * sizeof( float * ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov dtx real matrix" );
+ }
+ for ( j = 0; j < MC_PARAMUPMIX_NCH; j++ )
+ {
+ if ( ( hMCParamUpmix->cov_dtx_real[b][i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov dtx real matrix" );
+ }
+ }
+ }
+ }
+
+ st_ivas->hMCParamUpmix = hMCParamUpmix;
+
+ return error;
+}
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_enc_close()
+ *
+ * Close MC Param-Upmix encoder handle
+ *------------------------------------------------------------------------*/
+
+void ivas_mc_paramupmix_enc_close(
+ MC_PARAMUPMIX_ENC_HANDLE *hMCParamUpmix, /* i/o: MC Param-Upmix encoder handle */
+ const int32_t sampling_rate )
+{
+ int16_t i, k;
+ int16_t b, j;
+
+ if ( hMCParamUpmix == NULL || *hMCParamUpmix == NULL )
+ {
+ return;
+ }
+ for ( b = 0; b < MC_PARAMUPMIX_COMBINATIONS; b++ )
+ {
+ if ( ( *hMCParamUpmix )->cov_real[b] != NULL )
+ {
+ for ( i = 0; i < MC_PARAMUPMIX_NCH; i++ )
+ {
+ if ( ( *hMCParamUpmix )->cov_real[b][i] != NULL )
+ {
+ for ( j = 0; j < MC_PARAMUPMIX_NCH; j++ )
+ {
+ if ( ( *hMCParamUpmix )->cov_real[b][i][j] != NULL )
+ {
+ free( ( *hMCParamUpmix )->cov_real[b][i][j] );
+ }
+ }
+ free( ( *hMCParamUpmix )->cov_real[b][i] );
+ }
+ }
+ free( ( *hMCParamUpmix )->cov_real[b] );
+ }
+ if ( ( *hMCParamUpmix )->cov_dtx_real[b] != NULL )
+ {
+ for ( i = 0; i < MC_PARAMUPMIX_NCH; i++ )
+ {
+ if ( ( *hMCParamUpmix )->cov_dtx_real[b][i] != NULL )
+ {
+ for ( j = 0; j < MC_PARAMUPMIX_NCH; j++ )
+ {
+ if ( ( *hMCParamUpmix )->cov_dtx_real[b][i][j] != NULL )
+ {
+ free( ( *hMCParamUpmix )->cov_dtx_real[b][i][j] );
+ }
+ }
+ free( ( *hMCParamUpmix )->cov_dtx_real[b][i] );
+ }
+ }
+ free( ( *hMCParamUpmix )->cov_dtx_real[b] );
+ }
+ }
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ for ( k = 0; k < MC_PARAMUPMIX_NCH; k++ )
+ {
+ free( ( *hMCParamUpmix )->midside[i][k] );
+ }
+ }
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ )
+ {
+ ivas_transient_det_close( &( *hMCParamUpmix )->hTranDet[i] );
+ }
+
+ if ( ( *hMCParamUpmix )->hFbMixer != NULL )
+ {
+ ivas_FB_mixer_close( &( *hMCParamUpmix )->hFbMixer, sampling_rate, 0 );
+ }
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ /* Covariance handle */
+ if ( ( *hMCParamUpmix )->hCovEnc[i] != NULL )
+ {
+ ivas_spar_covar_enc_close( &( *hMCParamUpmix )->hCovEnc[i], ( MC_PARAMUPMIX_NCH + 1 ) );
+ }
+ }
+
+ free( *hMCParamUpmix );
+ *hMCParamUpmix = NULL;
+ return;
+}
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_getNumTransportChannels()
+ *
+ *
+ *------------------------------------------------------------------------*/
+
+/* r : number of IVAS transport channels */
+int16_t ivas_mc_paramupmix_getNumTransportChannels()
+{
+ int16_t nchan_transport;
+
+ /* LFE not included */
+ nchan_transport = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS - 1; /*5_1_2*/
+
+ return nchan_transport;
+}
+
+
+/*****************************************************************************************/
+/* local functions */
+/*****************************************************************************************/
+static void get_huff_table(
+ PAR_TYPE par_type,
+ QUANT_TYPE quant_type,
+ HUFF_TAB *df0,
+ HUFF_TAB *df,
+ HUFF_TAB *dt )
+{
+ switch ( par_type )
+ {
+ case ALPHA:
+ df0->value = huff_alpha_table[quant_type].df0.value;
+ df0->length = huff_alpha_table[quant_type].df0.length;
+ df->value = huff_alpha_table[quant_type].df.value;
+ df->length = huff_alpha_table[quant_type].df.length;
+ dt->value = huff_alpha_table[quant_type].dt.value;
+ dt->length = huff_alpha_table[quant_type].dt.length;
+ break;
+ case BETA:
+ df0->value = huff_beta_table[quant_type].df0.value;
+ df0->length = huff_beta_table[quant_type].df0.length;
+ df->value = huff_beta_table[quant_type].df.value;
+ df->length = huff_beta_table[quant_type].df.length;
+ dt->value = huff_beta_table[quant_type].dt.value;
+ dt->length = huff_beta_table[quant_type].dt.length;
+ break;
+ }
+}
+
+static void write_huff_bits(
+ int32_t value,
+ uint16_t length,
+ uint16_t bit_buffer[MC_PARAMUPMIX_MAX_BITS],
+ int16_t *bit_pos )
+{
+ int16_t k;
+ for ( k = length - 1; k >= 0; k-- )
+ {
+ bit_buffer[( *bit_pos )++] = (uint16_t) ( ( value >> k ) & 1 );
+ }
+}
+
+static void huffman_encode(
+ int16_t bdfOnly,
+ int16_t bdtAllowed,
+ int16_t nv,
+ int16_t ivStart,
+ int32_t *vqPrev,
+ int32_t *vq,
+ PAR_TYPE parType,
+ QUANT_TYPE quant_type,
+ int16_t nq,
+ uint16_t bit_buffer[MC_PARAMUPMIX_MAX_BITS],
+ int16_t *bit_pos )
+{
+ int16_t iv, ndf, ndt;
+ int32_t icode;
+ int16_t offset;
+ HUFF_TAB df0, df, dt;
+
+ get_huff_table( parType, quant_type, &df0, &df, &dt );
+
+ offset = nq - 1; /* range [-(nquant - 1), nquant - 1] */
+
+ /* Get code length for time and freq diff coding */
+ ndf = 0;
+ ndt = 0;
+ for ( iv = ivStart; iv < nv; iv++ )
+ {
+ if ( iv == ivStart )
+ {
+ icode = vq[iv];
+ ndf += df0.length[icode];
+ }
+ else
+ {
+ icode = vq[iv] - vq[iv - 1] + offset;
+ ndf += df.length[icode];
+ }
+
+ icode = vq[iv] - vqPrev[iv] + offset;
+ ndt += dt.length[icode];
+ }
+
+ if ( !bdtAllowed ) /* Time diff not allowed due to conformance or other reason even if bdfOnly = 0 */
+ {
+ ndt = ndf + 1;
+ }
+
+ /* Write the bitstream */
+ if ( bdfOnly || ndf < ndt )
+ {
+ bit_buffer[( *bit_pos )++] = (uint16_t) 0 & 1;
+ for ( iv = ivStart; iv < nv; iv++ )
+ {
+ if ( iv == ivStart )
+ {
+ icode = vq[iv];
+ write_huff_bits( df0.value[icode], df0.length[icode], bit_buffer, bit_pos );
+ }
+ else
+ {
+ icode = vq[iv] - vq[iv - 1] + offset;
+ write_huff_bits( df.value[icode], df.length[icode], bit_buffer, bit_pos );
+ }
+ }
+ }
+ else
+ {
+ bit_buffer[( *bit_pos )++] = (uint16_t) 1 & 1;
+ for ( iv = ivStart; iv < nv; iv++ )
+ {
+ icode = vq[iv] - vqPrev[iv] + offset;
+ if ( icode < 0 || icode >= 2 * nq - 1 )
+ {
+ assert( 0 );
+ }
+ write_huff_bits( dt.value[icode], dt.length[icode], bit_buffer, bit_pos );
+ }
+ }
+}
+
+static void quantize_pars(
+ int16_t nv,
+ const float *v,
+ int16_t nq,
+ const float *data,
+ int32_t vq[IVAS_MAX_NUM_BANDS],
+ float *vdeq )
+{
+ int16_t iv, iq, iq0, iq1;
+
+ for ( iv = 0; iv < nv; iv++ )
+ {
+ iq0 = 0;
+ iq1 = nq - 1;
+
+ while ( iq1 - iq0 > 1 )
+ {
+ iq = ( iq0 + iq1 ) / 2;
+ if ( v[iv] < data[iq] )
+ {
+ iq1 = iq;
+ }
+ else
+ {
+ iq0 = iq;
+ }
+ }
+
+ if ( fabs( v[iv] - data[iq0] ) < fabs( v[iv] - data[iq1] ) )
+ {
+ vq[iv] = iq0;
+ vdeq[iv] = data[iq0];
+ }
+ else
+ {
+ vq[iv] = iq1;
+ vdeq[iv] = data[iq1];
+ }
+ }
+}
+
+static void quantize_alpha(
+ int16_t nv,
+ const float *alpha,
+ QUANT_TYPE quant_type,
+ int16_t *pnq,
+ int32_t aq[IVAS_MAX_NUM_BANDS],
+ float *adeq )
+{
+ int16_t nq;
+ const float *data;
+
+ nq = alpha_quant_table[quant_type].nquant;
+ data = alpha_quant_table[quant_type].data;
+
+ quantize_pars( nv, alpha, nq, data, aq, adeq );
+
+ *pnq = nq;
+}
+
+static void quantize_beta(
+ int16_t nv,
+ const float *beta,
+ const int32_t aq[IVAS_MAX_NUM_BANDS],
+ QUANT_TYPE quant_type,
+ int16_t *pnq,
+ int32_t bq[IVAS_MAX_NUM_BANDS],
+ float *bdeq )
+{
+ int16_t iv, iq, iq0, iq1;
+ ACPL_QUANT_TABLE *tables = beta_quant_table[quant_type];
+ ACPL_QUANT_TABLE quant_table;
+ const int16_t qmap[2][33] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
+ { 0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1, 0 } };
+ for ( iv = 0; iv < nv; iv++ )
+ {
+ quant_table = tables[qmap[quant_type][aq[iv]]];
+
+ iq0 = 0;
+ iq1 = quant_table.nquant - 1;
+
+ while ( iq1 - iq0 > 1 )
+ {
+ iq = ( iq0 + iq1 ) / 2;
+ if ( beta[iv] < quant_table.data[iq] )
+ {
+ iq1 = iq;
+ }
+ else
+ {
+ iq0 = iq;
+ }
+ }
+
+ if ( fabs( beta[iv] - quant_table.data[iq0] ) < fabs( beta[iv] - quant_table.data[iq1] ) )
+ {
+ bq[iv] = iq0;
+ bdeq[iv] = quant_table.data[iq0];
+ }
+ else
+ {
+ bq[iv] = iq1;
+ bdeq[iv] = quant_table.data[iq1];
+ }
+ }
+
+ *pnq = beta_quant_table[quant_type][0].nquant;
+}
+
+static void put_ec_data(
+ MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix,
+ int16_t ch,
+ float pars[IVAS_MAX_NUM_BANDS],
+ float alphas[IVAS_MAX_NUM_BANDS],
+ PAR_TYPE parType,
+ uint16_t bit_buffer[MC_PARAMUPMIX_MAX_BITS],
+ int16_t *bit_pos )
+{
+ int16_t npar = IVAS_MAX_NUM_BANDS;
+ int16_t onlyFreq = 1;
+ int16_t nq;
+ QUANT_TYPE quant_type = FINE;
+ int32_t alphaQuant[IVAS_MAX_NUM_BANDS];
+ int32_t betaQuant[IVAS_MAX_NUM_BANDS];
+ float alphaDequant[IVAS_MAX_NUM_BANDS];
+ float betaDequant[IVAS_MAX_NUM_BANDS];
+
+ if ( parType == ALPHA )
+ {
+ quantize_alpha( npar, pars, quant_type, &nq, alphaQuant, alphaDequant );
+ }
+ else
+ {
+ quantize_alpha( npar, alphas, quant_type, &nq, alphaQuant, alphaDequant );
+ quantize_beta( npar, pars, alphaQuant, quant_type, &nq, betaQuant, betaDequant );
+ }
+ if ( hMCParamUpmix->first_frame )
+ {
+ mvl2l( &( alphaQuant[0] ), &( hMCParamUpmix->alpha_quant_prev[ch][0] ), IVAS_MAX_NUM_BANDS );
+ if ( parType == BETA )
+ {
+ mvl2l( &( betaQuant[0] ), &( hMCParamUpmix->beta_quant_prev[ch][0] ), IVAS_MAX_NUM_BANDS );
+ if ( ch == ( MC_PARAMUPMIX_COMBINATIONS - 1 ) )
+ {
+ hMCParamUpmix->first_frame = 0;
+ }
+ }
+ }
+
+ /* Always one parameter set per frame for transient frames. Original PS framing is used internally. */
+ if ( parType == ALPHA )
+ {
+ huffman_encode( onlyFreq, 1, npar, 0, hMCParamUpmix->alpha_quant_prev[ch], alphaQuant, ALPHA, quant_type, nq, bit_buffer, bit_pos );
+ }
+ else
+ {
+ huffman_encode( onlyFreq, 1, npar, 0, hMCParamUpmix->beta_quant_prev[ch], betaQuant, BETA, quant_type, nq, bit_buffer, bit_pos );
+ }
+
+ if ( parType == ALPHA )
+ {
+ mvl2l( alphaQuant, hMCParamUpmix->alpha_quant_prev[ch], IVAS_MAX_NUM_BANDS );
+ }
+ else
+ {
+ mvl2l( betaQuant, hMCParamUpmix->beta_quant_prev[ch], IVAS_MAX_NUM_BANDS );
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_dmx()
+ *
+ * Computes the time domain down mix signal
+ *------------------------------------------------------------------------*/
+
+static void ivas_mc_paramupmix_dmx(
+ MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, /* i/o: MC ParamUpmix encoder handle */
+ float data_f[][L_FRAME48k], /* i/o : Input, downmix out */
+ const int16_t input_frame /* i : Input frame length */
+)
+{
+ int16_t i, l;
+ int16_t chan1s[4] = { 4, 5, 8, 9 };
+ int16_t chan2s[4] = { 6, 7, 10, 11 };
+ int16_t chanOut[4] = { 4, 5, 6, 7 };
+ int16_t chanZero[4] = { 8, 9, 10, 11 };
+
+ /* boxes = { 0 1 2 3 [4 6] [5 7] [8 10] [9 11] }; */
+ /* 9+11 -> 7 */
+ /* 8+10 -> 6 */
+ /* 5+7 -> 5 */
+ /* 4+6 -> 4 */
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ for ( l = 0; l < input_frame; l++ )
+ {
+ /* mid */
+ hMCParamUpmix->midside[i][0][l] = ( data_f[chan1s[i]][l] + data_f[chan2s[i]][l] ) * (float) 0.5;
+ /* side */
+ hMCParamUpmix->midside[i][1][l] = ( data_f[chan1s[i]][l] - data_f[chan2s[i]][l] ) * (float) 0.5;
+ data_f[chanOut[i]][l] = hMCParamUpmix->midside[i][0][l];
+ }
+ }
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ set_zero( data_f[chanZero[i]], input_frame );
+ }
+ return;
+}
+
+
+/*-------------------------------------------------------------------------
+ * ivas_mc_paramupmix_param_est_enc()
+ *
+ * run the CLDFB analysis on the input signal
+ * estimate the input and down mix covariances
+ *------------------------------------------------------------------------*/
+
+static void ivas_mc_paramupmix_param_est_enc(
+ MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, /* i/o: MC Param-Upmix encoder handle */
+ float input_frame_t[][L_FRAME48k], /* i : Input frame in the time domain */
+ const int16_t input_frame, /* i : Input frame length */
+ float alphas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS],
+ float betas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS] )
+{
+ float *pcm_in[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH];
+ float fr_realbuffer[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH][L_FRAME48k];
+ float fr_imagbuffer[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH][L_FRAME48k];
+ float FR_Real_Mid[L_FRAME48k], FR_Imag_Mid[L_FRAME48k];
+ float *p_fr_realbuffer[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH];
+ float *p_fr_imagbuffer[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH];
+ float *pp_in_fr_real[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH];
+ float *pp_in_fr_imag[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH];
+ float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH];
+ float *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH];
+ float rxx, rxy, ryy, cmat, rxxest, drxx, wetaux;
+
+ int16_t l_ts;
+ int16_t b, i, j, ts, bnd;
+
+ int16_t transient_det[MC_PARAMUPMIX_COMBINATIONS][2];
+ int16_t transient_det_l[2], transient_det_r[2];
+ int16_t chan1s[4] = { 4, 5, 8, 9 };
+ int16_t chan2s[4] = { 6, 7, 10, 11 };
+
+#ifdef SPAR_TUNING
+ const int16_t HOA_md_ind[IVAS_SPAR_MAX_CH] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+#endif
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ pcm_in[2 * i] = input_frame_t[chan1s[i]];
+ pcm_in[2 * i + 1] = input_frame_t[chan2s[i]];
+ }
+
+ /*-----------------------------------------------------------------------------------------*
+ * Transient detector
+ *-----------------------------------------------------------------------------------------*/
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ )
+ {
+ ivas_transient_det_process( hMCParamUpmix->hTranDet[2 * i], pcm_in[2 * i], input_frame, transient_det_l );
+ ivas_transient_det_process( hMCParamUpmix->hTranDet[2 * i + 1], pcm_in[2 * i + 1], input_frame, transient_det_r );
+ transient_det[i][0] = transient_det_l[0] || transient_det_r[0];
+ transient_det[i][1] = transient_det_l[0] || transient_det_r[0];
+ /* should probably be transient_det_l[1] || transient_det_r[1] , but choosing 0 reproduces the before merge state */
+ }
+
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ )
+ {
+ p_fr_realbuffer[i] = fr_realbuffer[i];
+ p_fr_imagbuffer[i] = fr_imagbuffer[i];
+ }
+
+ /* prepare Parameter MDFT analysis */
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ )
+ {
+ pp_in_fr_real[i] = p_fr_realbuffer[i];
+ pp_in_fr_imag[i] = p_fr_imagbuffer[i];
+ }
+
+ l_ts = input_frame / MAX_PARAM_SPATIAL_SUBFRAMES;
+ for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ )
+ {
+ ivas_fb_mixer_get_windowed_fr( hMCParamUpmix->hFbMixer, pcm_in, pp_in_fr_real, pp_in_fr_imag, l_ts, l_ts
+#ifdef HODIRAC
+ ,
+ hMCParamUpmix->hFbMixer->fb_cfg->num_in_chans
+#endif
+ );
+ ivas_fb_mixer_update_prior_input( hMCParamUpmix->hFbMixer, pcm_in, l_ts
+#ifdef HODIRAC
+ ,
+ hMCParamUpmix->hFbMixer->fb_cfg->num_in_chans
+#endif
+ );
+ for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ )
+ {
+ pcm_in[i] += l_ts;
+ pp_in_fr_real[i] += l_ts;
+ pp_in_fr_imag[i] += l_ts;
+ }
+ }
+
+ /*-----------------------------------------------------------------------------------------*
+ * Covariance process
+ *-----------------------------------------------------------------------------------------*/
+ for ( b = 0; b < MC_PARAMUPMIX_COMBINATIONS; b++ )
+ {
+ pp_in_fr_real[0] = p_fr_realbuffer[2 * b];
+ pp_in_fr_imag[0] = p_fr_imagbuffer[2 * b];
+ pp_in_fr_real[1] = FR_Real_Mid;
+ pp_in_fr_imag[1] = FR_Imag_Mid;
+ v_add( pp_in_fr_real[0], p_fr_realbuffer[2 * b + 1], pp_in_fr_real[1], L_FRAME48k );
+ v_add( pp_in_fr_imag[0], p_fr_imagbuffer[2 * b + 1], pp_in_fr_imag[1], L_FRAME48k );
+ for ( i = 0; i < MC_PARAMUPMIX_NCH; i++ )
+ {
+ for ( j = 0; j < MC_PARAMUPMIX_NCH; j++ )
+ {
+ cov_real[i][j] = hMCParamUpmix->cov_real[b][i][j];
+ cov_dtx_real[i][j] = hMCParamUpmix->cov_dtx_real[b][i][j];
+ }
+ }
+#ifdef SPAR_TUNING
+ ivas_enc_cov_handler_process( hMCParamUpmix->hCovEnc[b], pp_in_fr_real, pp_in_fr_imag, cov_real, cov_dtx_real, hMCParamUpmix->hFbMixer->pFb, 0, hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands, MC_PARAMUPMIX_NCH, 0 /*dtx_vad*/, transient_det[b], HOA_md_ind );
+#else
+ ivas_enc_cov_handler_process( hMCParamUpmix->hCovEnc[b], pp_in_fr_real, pp_in_fr_imag, cov_real, cov_dtx_real, hMCParamUpmix->hFbMixer->pFb, 0, hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands, MC_PARAMUPMIX_NCH, 0 /*dtx_vad*/, transient_det[b] );
+#endif
+ }
+
+ for ( b = 0; b < MC_PARAMUPMIX_COMBINATIONS; b++ )
+ {
+ for ( bnd = 0; bnd < IVAS_MAX_NUM_BANDS; bnd++ )
+ {
+ rxy = hMCParamUpmix->cov_real[b][1][0][bnd];
+ ryy = hMCParamUpmix->cov_real[b][1][1][bnd];
+ cmat = rxy / ( ryy + EPSILON );
+ alphas[b][bnd] = (float) 2.0 * cmat - (float) 1.0;
+
+ rxx = hMCParamUpmix->cov_real[b][0][0][bnd];
+ rxxest = cmat * cmat * ryy;
+ drxx = rxx - rxxest;
+ drxx = (float) max( drxx, 0.0 );
+ wetaux = (float) sqrt( drxx / ( ryy + EPSILON ) );
+ betas[b][bnd] = (float) 2.0 * wetaux;
+ }
+ }
+
+ return;
+}
+
+#endif
diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c
index f2f5d2346103c6856570ba8b5f66348e772720ef..393c60f49eada48a8d03d7d4c1baa127fb8df467 100644
--- a/lib_enc/ivas_mct_enc.c
+++ b/lib_enc/ivas_mct_enc.c
@@ -116,8 +116,11 @@ static void map_input_to_cpe_channels(
pdata[i] = data[n];
i++;
}
-
+#ifdef MC_PARAMUPMIX_MODE
+ if ( st_ivas->hEncoderConfig->ivas_format == MC_FORMAT && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) )
+#else
if ( st_ivas->hEncoderConfig->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT )
+#endif
{
for ( n = LFE_CHANNEL + 1; n < st_ivas->nchan_transport; n++ )
{
@@ -136,7 +139,11 @@ static void map_input_to_cpe_channels(
}
/* odd channel CPE*/
+#ifdef MC_PARAMUPMIX_MODE
+ if ( ( st_ivas->nchan_transport < st_ivas->nCPE * CPE_CHANNELS ) || ( ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) && st_ivas->hMCT->nchan_out_woLFE < st_ivas->nCPE * CPE_CHANNELS ) )
+#else
if ( ( st_ivas->nchan_transport < st_ivas->nCPE * CPE_CHANNELS ) || ( st_ivas->mc_mode == MC_MODE_MCT && st_ivas->hMCT->nchan_out_woLFE < st_ivas->nCPE * CPE_CHANNELS ) )
+#endif
{
pdata[st_ivas->nCPE * CPE_CHANNELS - 1] = NULL;
}
@@ -234,11 +241,19 @@ ivas_error ivas_mct_enc(
}
/* joint MCT encoding */
+#ifdef MC_PARAMUPMIX_MODE
+ ivas_mct_core_enc( ivas_format, hMCT, st_ivas->hCPE,
+ hMCT->nchan_out_woLFE,
+ ivas_total_brate, switch_bw,
+ ( ivas_format == MC_FORMAT && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) ) ? (int16_t) st_ivas->hLFE->lfe_bits : 0,
+ st_ivas->hEncoderConfig->sba_order );
+#else
ivas_mct_core_enc( ivas_format, hMCT, st_ivas->hCPE,
hMCT->nchan_out_woLFE,
ivas_total_brate, switch_bw,
( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) ? (int16_t) st_ivas->hLFE->lfe_bits : 0,
st_ivas->hEncoderConfig->sba_order );
+#endif
/* Spectrum quantization and coding */
for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ )
@@ -310,6 +325,12 @@ ivas_error create_mct_enc(
{
hMCT->nchan_out_woLFE = ivas_param_mc_getNumTransportChannels( ivas_total_brate, st_ivas->hEncoderConfig->mc_input_setup );
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ hMCT->nchan_out_woLFE = ivas_mc_paramupmix_getNumTransportChannels();
+ }
+#endif
else if ( ivas_format == SBA_FORMAT )
{
hMCT->nchan_out_woLFE = ivas_sba_get_nchan( st_ivas->sba_analysis_order, st_ivas->hEncoderConfig->sba_planar );
@@ -418,6 +439,12 @@ ivas_error mct_enc_reconfigure(
{
hMCT->nchan_out_woLFE = st_ivas->hEncoderConfig->nchan_inp - 1; /* LFE channel is coded separately */
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ hMCT->nchan_out_woLFE = ivas_mc_paramupmix_getNumTransportChannels();
+ }
+#endif
else if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC )
{
hMCT->nchan_out_woLFE = ivas_param_mc_getNumTransportChannels( ivas_total_brate, st_ivas->hEncoderConfig->mc_input_setup );
@@ -657,6 +684,13 @@ static ivas_error ivas_mc_enc_reconfig(
if ( last_mc_mode != MC_MODE_MCT )
{
+#ifdef MC_PARAMUPMIX_MODE
+ if ( st_ivas->hLFE != NULL )
+ {
+ /* LFE handle */
+ ivas_lfe_enc_close( &( st_ivas->hLFE ) );
+ }
+#endif
/* create LFE handle */
if ( ( error = ivas_create_lfe_enc( &st_ivas->hLFE, st_ivas->hEncoderConfig->input_Fs ) ) != IVAS_ERR_OK )
{
@@ -666,6 +700,9 @@ static ivas_error ivas_mc_enc_reconfig(
/*De-allocate handles for other MC modes*/
ivas_param_mc_enc_close( &( st_ivas->hParamMC ), st_ivas->hEncoderConfig->input_Fs );
+#ifdef MC_PARAMUPMIX_MODE
+ ivas_mc_paramupmix_enc_close( &( st_ivas->hMCParamUpmix ), st_ivas->hEncoderConfig->input_Fs );
+#endif
/* De-allocate McMasa-related handles */
ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs );
@@ -674,6 +711,52 @@ static ivas_error ivas_mc_enc_reconfig(
ivas_qmetadata_close( &st_ivas->hQMetaData );
}
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ st_ivas->nSCE = 0;
+ st_ivas->nCPE = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS / 2;
+ st_ivas->nchan_transport = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS;
+
+ if ( last_mc_mode != MC_MODE_PARAMUPMIX )
+ {
+ if ( st_ivas->hLFE != NULL )
+ {
+ /* LFE handle */
+ ivas_lfe_enc_close( &( st_ivas->hLFE ) );
+ }
+
+ /* create LFE handle */
+ if ( ( error = ivas_create_lfe_enc( &st_ivas->hLFE, st_ivas->hEncoderConfig->input_Fs ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+ if ( last_mc_mode != MC_MODE_PARAMUPMIX )
+ /* This should always be the case, only supporting one bitrate currently */
+ {
+ if ( ( error = ivas_mc_paramupmix_enc_open( st_ivas ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+ else
+ {
+ assert( 0 );
+ }
+
+ /*De-allocate handles for other MC modes*/
+ ivas_param_mc_enc_close( &st_ivas->hParamMC, st_ivas->hEncoderConfig->input_Fs );
+
+ /* De-allocate McMasa-related handles */
+ ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs );
+
+ ivas_masa_enc_close( &( st_ivas->hMasa ) );
+
+ ivas_qmetadata_close( &st_ivas->hQMetaData );
+ }
+#endif
else if ( st_ivas->mc_mode == MC_MODE_PARAMMC )
{
if ( last_mc_mode != MC_MODE_PARAMMC )
@@ -699,6 +782,14 @@ static ivas_error ivas_mc_enc_reconfig(
ivas_masa_enc_close( &( st_ivas->hMasa ) );
st_ivas->hMasa = NULL;
}
+#ifdef MC_PARAMUPMIX_MODE
+ ivas_mc_paramupmix_enc_close( &( st_ivas->hMCParamUpmix ), st_ivas->hEncoderConfig->input_Fs );
+ if ( last_mc_mode == MC_MODE_PARAMUPMIX && st_ivas->hLFE != NULL )
+ {
+ /* LFE handle */
+ ivas_lfe_enc_close( &( st_ivas->hLFE ) );
+ }
+#endif
ivas_qmetadata_close( &st_ivas->hQMetaData );
@@ -745,6 +836,14 @@ static ivas_error ivas_mc_enc_reconfig(
}
ivas_param_mc_enc_close( &( st_ivas->hParamMC ), st_ivas->hEncoderConfig->input_Fs );
+#ifdef MC_PARAMUPMIX_MODE
+ ivas_mc_paramupmix_enc_close( &( st_ivas->hMCParamUpmix ), st_ivas->hEncoderConfig->input_Fs );
+ if ( last_mc_mode == MC_MODE_PARAMUPMIX && st_ivas->hLFE != NULL )
+ {
+ /* LFE handle */
+ ivas_lfe_enc_close( &( st_ivas->hLFE ) );
+ }
+#endif
if ( last_mc_mode == MC_MODE_MCT )
{
@@ -819,6 +918,13 @@ static ivas_error ivas_mc_enc_reconfig(
new_brate_SCE = 0;
new_brate_CPE = ( st_ivas->hEncoderConfig->ivas_total_brate / ( st_ivas->nchan_transport - 1 ) ) * CPE_CHANNELS;
}
+#ifdef MC_PARAMUPMIX_MODE
+ else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
+ {
+ new_brate_SCE = 0;
+ new_brate_CPE = ( st_ivas->hEncoderConfig->ivas_total_brate / ( st_ivas->nchan_transport - 1 ) ) * CPE_CHANNELS;
+ }
+#endif
else
{
new_brate_SCE = 0; /*st_ivas->hEncoderConfig->ivas_total_brate / st_ivas->nchan_transport;*/
diff --git a/lib_enc/ivas_rom_enc.c b/lib_enc/ivas_rom_enc.c
index ae7cd2ee1a6c29c3f1fdcb2ae51b93bf31803ce1..3a26ce03e52c9d9c2d85b805f01b6549176d5dfa 100644
--- a/lib_enc/ivas_rom_enc.c
+++ b/lib_enc/ivas_rom_enc.c
@@ -723,4 +723,121 @@ const float Stereo_dmx_wnd_coef_48k[L_FRAME48k] = {
};
+#ifdef MC_PARAMUPMIX_MODE
+const HUFF_TABLE huff_alpha_table[2] =
+{
+ { /* Alfa Fine */
+ { /* df0 */
+ { 0x0002ce, 0x000b5e, 0x0004fe, 0x0005ae, 0x00027e, 0x0002de, 0x00016a, 0x0000b2, 0x00004a, 0x00004b,
+ 0x0000b6, 0x00004e, 0x000024, 0x00002e, 0x00000a, 0x000006, 0x000000, 0x000007, 0x000008, 0x00002f,
+ 0x000026, 0x000058, 0x0000b4, 0x00009e, 0x00016e, 0x000166, 0x0002df, 0x0002cf, 0x00027c, 0x00027d,
+ 0x0004ff, 0x000b5f, 0x0002d6 },
+ { 10, 12, 11, 11, 10, 10, 9, 8, 7, 7,
+ 8, 7, 6, 6, 4, 3, 1, 3, 4, 6,
+ 6, 7, 8, 8, 9, 9, 10, 10, 10, 10,
+ 11, 12, 10 }
+ },
+ { /* df */
+ { 0x0011de, 0x011ffe, 0x013dea, 0x013df6, 0x008eea, 0x013df7, 0x013dee, 0x013deb, 0x013dec, 0x008eee,
+ 0x008ffe, 0x009efe, 0x0047fe, 0x004f7c, 0x0023fe, 0x0011fe, 0x0013fe, 0x0008f6, 0x0009ee, 0x000476,
+ 0x00047a, 0x0004f6, 0x00023a, 0x00027a, 0x00027e, 0x00013e, 0x00009a, 0x00004c, 0x00004e, 0x000012,
+ 0x00000a, 0x000006, 0x000000, 0x000007, 0x00000b, 0x000010, 0x000022, 0x000046, 0x00009b, 0x00013c,
+ 0x00011c, 0x00023e, 0x00023c, 0x0004fe, 0x00047e, 0x0009fe, 0x0008fe, 0x0008f7, 0x0013ff, 0x0011df,
+ 0x0027bc, 0x004f7e, 0x004776, 0x009efa, 0x009ef4, 0x013dfe, 0x008eeb, 0x008ee8, 0x013dff, 0x008ee9,
+ 0x008eef, 0x011fff, 0x013ded, 0x013def, 0x0011dc },
+ { 13, 17, 17, 17, 16, 17, 17, 17, 17, 16,
+ 16, 16, 15, 15, 14, 13, 13, 12, 12, 11,
+ 11, 11, 10, 10, 10, 9, 8, 7, 7, 5,
+ 4, 3, 1, 3, 4, 5, 6, 7, 8, 9,
+ 9, 10, 10, 11, 11, 12, 12, 12, 13, 13,
+ 14, 15, 15, 16, 16, 17, 16, 16, 17, 16,
+ 16, 17, 17, 17, 13 }
+ },
+ { /* dt */
+ { 0x00eeee, 0x03b3ee, 0x03b3f6, 0x03b3fc, 0x01d9bc, 0x01d9bd, 0x01d9b2, 0x03b3fe, 0x01d9be, 0x01d9f6,
+ 0x01d9fc, 0x00ecda, 0x00ecfa, 0x00eeef, 0x00766e, 0x007776, 0x003b3a, 0x003bba, 0x001d9a, 0x001ddc,
+ 0x001dde, 0x000eec, 0x000764, 0x000772, 0x0003b0, 0x0003b8, 0x0001da, 0x0001de, 0x000072, 0x000038,
+ 0x00001e, 0x000006, 0x000000, 0x000002, 0x00001f, 0x00003a, 0x000073, 0x0001df, 0x0001db, 0x0003ba,
+ 0x0003b1, 0x000773, 0x000765, 0x000eed, 0x000ecc, 0x001d9e, 0x001d9c, 0x003bbe, 0x003b3b, 0x00777e,
+ 0x00767c, 0x00eefe, 0x00ecfc, 0x00ecd8, 0x01d9fd, 0x01d9fa, 0x01d9bf, 0x01d9b6, 0x01d9b3, 0x03b3fd,
+ 0x01d9b7, 0x03b3ff, 0x03b3ef, 0x03b3f7, 0x00eeff },
+ { 16, 18, 18, 18, 17, 17, 17, 18, 17, 17,
+ 17, 16, 16, 16, 15, 15, 14, 14, 13, 13,
+ 13, 12, 11, 11, 10, 10, 9, 9, 7, 6,
+ 5, 3, 1, 2, 5, 6, 7, 9, 9, 10,
+ 10, 11, 11, 12, 12, 13, 13, 14, 14, 15,
+ 15, 16, 16, 16, 17, 17, 17, 17, 17, 18,
+ 17, 18, 18, 18, 16 }
+ }
+ }, /* End Alfa Fine */
+ { /* Alfa Coarse */
+ { /* df0 */
+ { 0x0003be, 0x0003fe, 0x0001fe, 0x0000fe, 0x00003e, 0x00003a, 0x00001e, 0x000002, 0x000000, 0x000006,
+ 0x00001c, 0x00007e, 0x000076, 0x0000ee, 0x0001de, 0x0003ff, 0x0003bf },
+ { 10, 10, 9, 8, 6, 6, 5, 2, 1, 3,
+ 5, 7, 7, 8, 9, 10, 10 }
+ },
+ { /* df */
+ { 0x007c76, 0x03e3fe, 0x01f1f6, 0x01f1f7, 0x00f8ea, 0x007c74, 0x007c7c, 0x001f1c, 0x000f9e, 0x0007ce,
+ 0x0003e2, 0x0001f0, 0x0000fa, 0x00007e, 0x00000e, 0x000006, 0x000000, 0x000002, 0x00001e, 0x00007f,
+ 0x0000fb, 0x0001f2, 0x0003e6, 0x0007c6, 0x000f9f, 0x001f1e, 0x007c7e, 0x00f8fe, 0x00f8fa, 0x01f1fe,
+ 0x00f8eb, 0x03e3ff, 0x007c77 },
+ { 15, 18, 17, 17, 16, 15, 15, 13, 12, 11,
+ 10, 9, 8, 7, 4, 3, 1, 2, 5, 7,
+ 8, 9, 10, 11, 12, 13, 15, 16, 16, 17,
+ 16, 18, 15 }
+ },
+ { /* dt */
+ { 0x003efc, 0x00fbfa, 0x007ddc, 0x00fbfe, 0x007dde, 0x007dfc, 0x003ef6, 0x001f76, 0x000fba, 0x000fbe,
+ 0x0003ec, 0x0001f2, 0x0000f8, 0x00007e, 0x00001e, 0x000006, 0x000000, 0x000002, 0x00000e, 0x00007f,
+ 0x0000fa, 0x0001f3, 0x0003ed, 0x0007dc, 0x000fbc, 0x001f7a, 0x003ef7, 0x007dfe, 0x007ddf, 0x00fbff,
+ 0x007ddd, 0x00fbfb, 0x003efd },
+ { 14, 16, 15, 16, 15, 15, 14, 13, 12, 12,
+ 10, 9, 8, 7, 5, 3, 1, 2, 4, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 15, 16,
+ 15, 16, 14 }
+ }
+ } /* End Alfa Coarse */
+};
+
+const HUFF_TABLE huff_beta_table[2] =
+{
+ { /* Beta Fine */
+ { /* df0 */
+ { 0x000000, 0x000002, 0x000006, 0x00000e, 0x00001e, 0x00003e, 0x00007e, 0x0000fe, 0x0000ff },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 8 }
+ },
+ { /* df */
+ { 0x001f1e, 0x000f8e, 0x0003e2, 0x0001f2, 0x0000fa, 0x00007e, 0x00001e, 0x000006, 0x000000, 0x000002,
+ 0x00000e, 0x00007f, 0x0000fb, 0x0001f3, 0x0001f0, 0x0007c6, 0x001f1f },
+ { 13, 12, 10, 9, 8, 7, 5, 3, 1, 2,
+ 4, 7, 8, 9, 9, 11, 13 }
+ },
+ { /* dt */
+ { 0x007dfe, 0x003efe, 0x000fbe, 0x0003ee, 0x0000fa, 0x00007e, 0x00001e, 0x000006, 0x000000, 0x000002,
+ 0x00000e, 0x00007f, 0x00007c, 0x0001f6, 0x0007de, 0x001f7e, 0x007dff },
+ { 15, 14, 12, 10, 8, 7, 5, 3, 1, 2,
+ 4, 7, 7, 9, 11, 13, 15 }
+ }
+ }, /* End Beta Fine */
+ { /* Beta Coarse */
+ { /* df0 */
+ { 0x000000, 0x000002, 0x000006, 0x00000e, 0x00000f },
+ { 1, 2, 3, 4, 4 }
+ },
+ { /* df */
+ { 0x0000fe, 0x00003e, 0x00000e, 0x000006, 0x000000, 0x000002, 0x00001e, 0x00007e, 0x0000ff },
+ { 8, 6, 4, 3, 1, 2, 5, 7, 8 }
+ },
+ { /* dt */
+ { 0x0000fe, 0x00007e, 0x00001e, 0x000006, 0x000000, 0x000002, 0x00000e, 0x00003e, 0x0000ff },
+ { 8, 7, 5, 3, 1, 2, 4, 6, 8 }
+ }
+ } /* End Beta Coarse */
+};
+
+const int16_t mc_paramupmix_fb_remix_order[4] = {0, 1, 2, 3};
+
+#endif
+
/* clang-format on */
diff --git a/lib_enc/ivas_rom_enc.h b/lib_enc/ivas_rom_enc.h
index d240fb69187fded50b89d4c3ae5056002b238f30..9fe2015eee5d579314cbc1c5a6f3223031aed5ed 100644
--- a/lib_enc/ivas_rom_enc.h
+++ b/lib_enc/ivas_rom_enc.h
@@ -126,5 +126,10 @@ extern const float Stereo_dmx_s_wnd_coef_48k[L_FRAME48k >> 4];
extern const float Stereo_dmx_wnd_coef_32k[L_FRAME32k];
extern const float Stereo_dmx_wnd_coef_48k[L_FRAME48k];
+#ifdef MC_PARAMUPMIX_MODE
+extern const HUFF_TABLE huff_alpha_table[2];
+extern const HUFF_TABLE huff_beta_table[2];
+extern const int16_t mc_paramupmix_fb_remix_order[4];
+#endif
#endif
diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h
index 5eced57880563a0edad11a10d9fa31a13d17fc69..8ba9484661b41547eeebb376f94f08a4ce2dd46e 100644
--- a/lib_enc/ivas_stat_enc.h
+++ b/lib_enc/ivas_stat_enc.h
@@ -719,6 +719,23 @@ typedef struct ivas_param_mc_enc_data_structure
} PARAM_MC_ENC_DATA, *PARAM_MC_ENC_HANDLE;
+#ifdef MC_PARAMUPMIX_MODE
+/*----------------------------------------------------------------------------------*
+ * MC ParamUpmix Mode encoder structures
+ *----------------------------------------------------------------------------------*/
+typedef struct ivas_mc_paramupmix_enc_data_structure
+{
+ ivas_trans_det_state_t *hTranDet[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH];
+ IVAS_FB_MIXER_HANDLE hFbMixer;
+ ivas_enc_cov_handler_state_t *hCovEnc[MC_PARAMUPMIX_COMBINATIONS];
+ float ***cov_real[MC_PARAMUPMIX_COMBINATIONS];
+ float ***cov_dtx_real[MC_PARAMUPMIX_COMBINATIONS];
+ float *midside[MC_PARAMUPMIX_COMBINATIONS][MC_PARAMUPMIX_NCH]; /* hold PCM of mid-side data */
+ int32_t alpha_quant_prev[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ int32_t beta_quant_prev[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS];
+ bool first_frame;
+} MC_PARAMUPMIX_ENC_DATA, *MC_PARAMUPMIX_ENC_HANDLE;
+#endif
/*----------------------------------------------------------------------------------*
* MASA encoder structures
@@ -1093,6 +1110,9 @@ typedef struct
IVAS_QMETADATA_HANDLE hQMetaData; /* Metadata handle for q_metadata parametric spatial coding DirAC/MASA*/
MCT_ENC_HANDLE hMCT; /* MCT handle */
PARAM_MC_ENC_HANDLE hParamMC; /* Parametric MC handle */
+#ifdef MC_PARAMUPMIX_MODE
+ MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix; /* MC Param-Upmix handle */
+#endif
MCMASA_ENC_HANDLE hMcMasa; /* Multi-channel MASA data handle */
LFE_ENC_HANDLE hLFE; /* LFE data handle */
diff --git a/scripts/config/self_test.prm b/scripts/config/self_test.prm
index 91bca7eef212539b05ae367039d1072f8871248f..429abcf2e637e1b6dc17d7e83e75b0b3386ff653 100644
--- a/scripts/config/self_test.prm
+++ b/scripts/config/self_test.prm
@@ -900,6 +900,14 @@
../IVAS_cod -mc 7_1_4 96000 48 testv/stv714MC48c.wav bit
../IVAS_dec -fec 5 5_1 48 bit testv/stv714MC48c.wav_MC714_96000_48-48_5_1_FEC5.tst
+// Multi-channel 7_1_4 at 160 kbps, 48kHz in, 48kHz out, BINAURAL out
+../IVAS_cod -mc 7_1_4 160000 48 testv/stv714MC48c.wav bit
+../IVAS_dec BINAURAL 48 bit testv/stv714MC48c.wav_MC714_160000_48-48_MC_binaural.tst
+
+// Multi-channel 7_1_4 at 160 kbps, 48kHz in, 48kHz out, 7_1_4 out
+../IVAS_cod -mc 7_1_4 160000 48 testv/stv714MC48c.wav bit
+../IVAS_dec 7_1_4 48 bit testv/stv714MC48c.wav_MC714_160000_48-48_MC714.tst
+
// Multi-channel 5_1_2 at 32 kbps, 48kHz in, 48kHz out, STEREO out, random FEC at 5%
../IVAS_cod -mc 5_1_2 32000 48 testv/stv512MC48c.wav bit
../IVAS_dec -fec 5 STEREO 48 bit testv/stv512MC48c.wav_MC714_32000_48-48_Stereo.tst