diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj
index 850e9c07039c635f335be8059df66edb26fa72f1..8f4a7ba25ad60dbcff5ccbea673cfe33240dcd0c 100644
--- a/Workspace_msvc/lib_dec.vcxproj
+++ b/Workspace_msvc/lib_dec.vcxproj
@@ -350,6 +350,7 @@
+
diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters
index 47995bb10b1f762212a0de19de97c94e0538bc3d..61337a076118a3aea034821b403591006b791eb6 100644
--- a/Workspace_msvc/lib_dec.vcxproj.filters
+++ b/Workspace_msvc/lib_dec.vcxproj.filters
@@ -815,6 +815,9 @@
decoder_evs_c
+
+ decoder_all_c
+
diff --git a/lib_com/cnst.h b/lib_com/cnst.h
index 9c19482007bd63b3baed142ba21a107f42c65b80..d4e8d02b4627b4b4e6235cd17072fe9ade6eb8bc 100644
--- a/lib_com/cnst.h
+++ b/lib_com/cnst.h
@@ -528,6 +528,7 @@ enum
#define FRAMES_PER_SEC 50
#define INV_FRAME_PER_SEC_Q15 656
+#define INV_FR_P_S_MX_PRM_SPL_SBFR_Q15 164
#define FRAME_SIZE_NS 20000000L
#define ACELP_LOOK_NS 8750000L
@@ -2934,5 +2935,9 @@ extern const Word16 Idx2Freq_Tbl[];
//tbs_vase.c
#define PRED_GAIN_E 8
+
+#define FS_48K_IN_NS_Q31 103079
+#define FS_32K_IN_NS_Q31 68719
+#define FS_16K_IN_NS_Q31 34360
/* clang-format on */
#endif /* CNST_H */
diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c
index 8c3cc277cee88add325e8645f96e459252d3e3e7..0c94cc4ecebd4ba158830ab01491aaf6a3cc5ca5 100644
--- a/lib_dec/lib_dec.c
+++ b/lib_dec/lib_dec.c
@@ -31,6 +31,7 @@
*******************************************************************************************************/
#include "lib_dec.h"
+#ifndef IVAS_FLOAT_FIXED
#include "ivas_cnst.h"
#include "ivas_prot.h"
#include "ivas_prot_rend.h"
@@ -204,7 +205,7 @@ ivas_error IVAS_DEC_Open(
st_ivas->writeFECoffset = 0;
#ifdef FIX_667_DISABLE_INITIAL_PLC_SUPPRESSION
hIvasDec->hasDecodedFirstGoodFrame = true; /* Functionality to suppress output for initial lost frames is disabled in EVS operation */
-#endif
+#endif
return IVAS_ERR_OK;
}
@@ -3006,7 +3007,7 @@ static ivas_error IVAS_DEC_VoIP_reconfigure(
return IVAS_ERR_OK;
}
-
+#endif // !IVAS_FLOAT_FIXED
diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h
index ad4efa505c05d56fbf52851c719847e8b8293663..2cc2cbad0cd40a43be2ab70f5d949bfa6a9d19d9 100644
--- a/lib_dec/lib_dec.h
+++ b/lib_dec/lib_dec.h
@@ -35,6 +35,7 @@
#include "common_api_types.h"
#include
+#include "typedef.h"
/*---------------------------------------------------------------------*
* Decoder enums
@@ -90,6 +91,7 @@ typedef ivas_error ( *JbmTraceFileWriterFn )( const void *data, void *writer );
/* clang-format off */
+#ifndef IVAS_FLOAT_FIXED
/*---------------------------------------------------------------------*
* Decoder function declarations
*---------------------------------------------------------------------*/
@@ -404,6 +406,322 @@ void IVAS_DEC_PrintDisclaimer(
void
);
+#else
+/*---------------------------------------------------------------------*
+ * Decoder function declarations
+ *---------------------------------------------------------------------*/
+
+ /* Open, configure, close functions - should be called once per decoder lifetime */
+
+ /*! r: error code */
+ivas_error IVAS_DEC_Open(
+ IVAS_DEC_HANDLE *phIvasDec, /* i/o: pointer to an IVAS decoder handle to be opened */
+ IVAS_DEC_MODE mode /* i : compatibility mode (EVS or IVAS) */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_Configure(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const UWord32 sampleRate, /* i : output sampling frequency */
+ const IVAS_AUDIO_CONFIG outputConfig, /* i : audio configuration */
+ const Word16 tsmEnabled, /* i : enable TSM */
+ const IVAS_RENDER_FRAMESIZE renderFramesize, /* i : rendering frame size */
+ const Word16 customLsOutputEnabled, /* i : enable custom loudspeaker setup handle */
+ const Word16 hrtfReaderEnabled, /* i : enable HRTF binary file input */
+ const Word16 enableHeadRotation, /* i : enable head rotation for binaural output */
+ const Word16 enableExternalOrientation, /* i : enable external orientations */
+ const IVAS_HEAD_ORIENT_TRK_T orientation_tracking, /* i : head orientation tracking type */
+ const Word16 renderConfigEnabled, /* i : enable Renderer config. file for binaural output */
+ const Word16 Opt_non_diegetic_pan, /* i : diegetic or not */
+ const float non_diegetic_pan_gain, /* i : non diegetic panning gain */
+ const Word16 Opt_dpid_on, /* i : enable directivity pattern option */
+ const UWord16 acousticEnvironmentId, /* i : Acoustic environment ID */
+ const Word16 delayCompensationEnabled /* i : enable delay compensation */
+);
+
+void IVAS_DEC_Close(
+ IVAS_DEC_HANDLE *phIvasDec /* i/o: pointer to IVAS decoder handle */
+);
+
+
+/* Decoding functions - should be called with a configured decoder handle */
+
+/*! r: error code */
+ivas_error IVAS_DEC_FeedFrame_Serial(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord16 *serial, /* i : buffer containing serial input bitstream. Each bit should be stored as a single UWord16 value */
+ const UWord16 num_bits, /* i : number of bits in input bitstream */
+ Word16 bfi /* i : bad frame indicator flag */
+);
+
+/*! r: decoder error code */
+ivas_error IVAS_DEC_GetSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 nSamplesAsked, /* i : number of samples wanted by the caller */
+ Word16 *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */
+ Word16 *nOutSamples, /* o : number of samples per channel written to output buffer */
+ bool *needNewFrame /* o : indication that the decoder needs a new frame */
+);
+
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetObjectMetadata(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_ISM_METADATA *metadata, /* o : struct where metadata decoded in most recently decoded frame will be written */
+ const UWord16 zero_flag, /* i : if this flag is enabled, this function outputs a zero-initialized metadata struct */
+ const UWord16 objectIdx /* i : index of the queried object */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetMasaMetadata(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_MASA_DECODER_EXT_OUT_META_HANDLE *hMasaExtOutMeta, /* o : pointer to handle, which will be set to point to metadata from the most recently decoded frame */
+ const UWord8 getFromJbmBuffer /* i : get metadata from a JBM buffer */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_FeedHeadTrackData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_QUATERNION orientation, /* i : head-tracking data, listener orientation */
+ IVAS_VECTOR3 Pos, /* i : listener position */
+ const Word16 subframe_idx /* i : subframe index */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_FeedRefRotData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_QUATERNION rotation /* i : reference rotation data */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_FeedRefVectorData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_VECTOR3 listenerPos, /* i : Listener position */
+ const IVAS_VECTOR3 refPos /* i : Reference position */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_FeedExternalOrientationData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_QUATERNION orientation, /* i : external orientation data */
+ Word8 enableHeadRotation, /* i : flag to enable head rotation for this frame */
+ Word8 enableExternalOrientation, /* i : flag to enable external orientation for this frame */
+ Word8 enableRotationInterpolation, /* i : flag to interpolate rotations from current and previous frames */
+ Word16 numFramesToTargetOrientation, /* i : number of frames until target orientation is reached */
+ const Word16 subframe_idx /* i : subframe index */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_VoIP_FeedFrame(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord8 *au, /* i : buffer containing input access unit */
+ const UWord16 auSize, /* i : size of the access unit */
+ const UWord16 rtpSequenceNumber, /* i : RTP sequence number (16 bits) */
+ const UWord32 rtpTimeStamp, /* i : RTP timestamp (32 bits) */
+ const UWord32 rcvTime_ms, /* i : receive time of the RTP packet in milliseconds */
+ const bool qBit /* i : Q bit for AMR-WB IO */
+);
+
+ivas_error IVAS_DEC_VoIP_SetScale(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 maxScaling, /* i : maximum allowed TSM scale */
+ const Word16 scale /* i : TSM scale to set */
+);
+
+ivas_error IVAS_DEC_TSM_SetQuality(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const float quality /* i : target TSM quality */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_VoIP_GetSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord16 nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */
+ Word16 *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */
+ const UWord32 systemTimestamp_ms /* i : current system timestamp */
+#ifdef SUPPORT_JBM_TRACEFILE
+ , JbmTraceFileWriterFn jbmWriterFn,
+ void* jbmWriter
+#endif
+);
+
+ivas_error IVAS_DEC_Flush(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */
+ Word16 *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */
+ Word16 *nSamplesFlushed /* o : number of samples flushed */
+);
+
+/* Setter functions - apply changes to decoder configuration */
+
+/*! r: error code */
+ivas_error IVAS_DEC_EnableVoIP(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 jbmSafetyMargin, /* i : allowed delay reserve for JBM, in milliseconds */
+ const IVAS_DEC_INPUT_FORMAT inputFormat /* i : format of the input bitstream */
+);
+
+
+ivas_error IVAS_DEC_SetRenderFramesize(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_RENDER_FRAMESIZE render_framesize /* i : render framesize */
+);
+
+ivas_error IVAS_DEC_GetRenderFramesize(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_RENDER_FRAMESIZE *render_framesize /* o : render framesize */
+);
+
+ivas_error IVAS_DEC_GetRenderFramesizeSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *render_framesize /* o : render framesize in samples */
+);
+
+ivas_error IVAS_DEC_GetReferencesUpdateFrequency(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *update_frequency /* o : update frequency */
+);
+
+ivas_error IVAS_DEC_GetNumOrientationSubframes(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *num_subframes /* o : render framesize */
+);
+
+ivas_error IVAS_DEC_GetRenderFramesizeMs(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord32 *render_framesize /* o : render framesize in samples */
+);
+
+
+/* Getter functions - retrieve information from a decoder through a handle */
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetNumObjects(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord16 *numObjects /* o : number of objects for which the decoder has been configured */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetFormat(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_BS_FORMAT *format /* o : format detected from bitstream fed to the decoder */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetOutputBufferSize(
+ const IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */
+ Word16 *outputBufferSize /* o : total number of samples expected in the output buffer for current decoder configuration */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetNumOutputChannels(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *numOutputChannels /* o : number of PCM output channels */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_FeedCustomLsData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_CUSTOM_LS_DATA hLsCustomData /* i : Custom loudspeaker setup data */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetHrtfHandle(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_HRTF_HANDLE *hHrtfTD /* o : HRTF handle */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetHrtfCRendHandle(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_HRTF_CREND_HANDLE *hSetOfHRTF /* o : Set of HRTF handle */
+);
+
+ivas_error IVAS_DEC_GetHrtfFastConvHandle(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */
+);
+
+ivas_error IVAS_DEC_GetHrtfParamBinHandle(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_HRTF_PARAMBIN_HANDLE *hHrtfParambin /* o : Parametric binauralizer HRTF handle */
+);
+
+
+/*! r: error code*/
+ivas_error IVAS_DEC_GetRenderConfig(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_RENDER_CONFIG_HANDLE hRCout /* o : Render config handle */
+);
+
+/*! r: error code*/
+ivas_error IVAS_DEC_GetDefaultRenderConfig(
+ IVAS_RENDER_CONFIG_HANDLE hRCout /* o : Render config handle */
+);
+
+/*! r: error code*/
+ivas_error IVAS_DEC_FeedRenderConfig(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_RENDER_CONFIG_DATA hRenderConfig /* i : Render config data structure */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetDelay(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *nSamples, /* o : decoder delay in samples */
+ Word32 *timeScale /* o : time scale of the delay, equal to decoder output sampling rate */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_HasDecodedFirstGoodFrame(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ bool *hasDecodedFirstGoodFrame /* o : flag indicating if the decoder has decoded a good frame since it was configured */
+);
+
+/*! r: error code */
+ivas_error IVAS_DEC_GetPcmFrameSize(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word32 *pcmFrameSize /* o : total size of the PCM output frame. This takes into account the number of output channels */
+);
+
+/*! r: true if decoder has no data in VoIP jitter buffer */
+bool IVAS_DEC_VoIP_IsEmpty(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 nSamplesAsked
+);
+
+ivas_error IVAS_DEC_VoIP_Get_CA_offset(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *optimum_offset,
+ Word16 *FEC_hi
+);
+
+#ifdef SUPPORT_JBM_TRACEFILE
+ivas_error IVAS_DEC_GetJbmData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_JBM_TRACE_DATA *JbmTraceData /* o : JBM Trace data */
+);
+#endif
+
+/* Utility functions */
+
+/*! r: pointer to an error message string */
+const char *IVAS_DEC_GetErrorMessage(
+ ivas_error error /* i : decoder error code enum */
+);
+
+void IVAS_DEC_PrintConfig(
+ const IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */
+ const bool quietModeEnabled, /* i : quiet mode flag: if true, reduces the amount of config info printed */
+ const bool voipMode
+);
+
+
+void IVAS_DEC_PrintDisclaimer(
+ void
+);
+#endif // IVAS_FLOAT_FIXED
+
/* clang-format on */
#endif
diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..02cf2b273acfa4b55383fc3b9f62e20416fa5868
--- /dev/null
+++ b/lib_dec/lib_dec_fx.c
@@ -0,0 +1,3038 @@
+/******************************************************************************************************
+
+ (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 "lib_dec.h"
+#ifdef IVAS_FLOAT_FIXED
+#include "ivas_cnst.h"
+#include "ivas_prot.h"
+#include "ivas_prot_rend.h"
+#include "prot.h"
+#include "prot_fx1.h"
+#include "prot_fx2.h"
+#include "jbm_jb4sb.h"
+#include "jbm_pcmdsp_apa.h"
+#include "jbm_pcmdsp_fifo.h"
+#include
+#include
+#include
+#include "wmc_auto.h"
+
+/*---------------------------------------------------------------------*
+ * Local structs
+ *---------------------------------------------------------------------*/
+struct IVAS_DEC_VOIP
+{
+ UWord16 nSamplesFrame; /* Total number of samples in a frame (includes number of channels) */
+ JB4_HANDLE hJBM;
+ UWord16 lastDecodedWasActive;
+ JB4_DATAUNIT_HANDLE hCurrentDataUnit; /* Points to the currently processed data unit */
+ UWord16 *bs_conversion_buf; /* Buffer for bitstream conversion from packed to serial */
+#ifdef SUPPORT_JBM_TRACEFILE
+ IVAS_JBM_TRACE_DATA JbmTraceData;
+#endif
+};
+
+typedef struct IVAS_DEC_VOIP IVAS_DEC_VOIP;
+
+struct IVAS_DEC
+{
+ IVAS_DEC_MODE mode;
+ UWord16 nSamplesFrame;
+ Decoder_Struct *st_ivas;
+ IVAS_DEC_VOIP *hVoIP;
+ bool hasBeenFedFirstGoodFrame; /* False on init. Gets set to true after first good frame has been fed into the decoder, but not decoded yet. */
+ bool hasDecodedFirstGoodFrame; /* False on init. Gets set to true after first good frame has been decoded -> all bitstream information is known from that point on */
+ bool isInitialized;
+
+ Word16 bitstreamformat; /* Bitstream format flag (G.192/MIME/VOIP_G192_RTP/VOIP_RTPDUMP) */
+ bool Opt_VOIP; /* flag indicating VOIP mode with JBM */
+ Word16 tsm_scale; /* scale for TSM operation */
+ Word16 tsm_max_scaling;
+ float tsm_quality;
+ float *apaExecBuffer; /* Buffer for APA scaling */
+ PCMDSP_APA_HANDLE hTimeScaler;
+ bool needNewFrame;
+ bool hasBeenFedFrame;
+ bool updateOrientation;
+ UWord16 nSamplesAvailableNext;
+ Word16 nSamplesRendered;
+ Word16 nTransportChannelsOld;
+ Word16 amrwb_rfc4867_flag; /* MIME from rfc4867 is used */
+ Word16 sdp_hf_only; /* RTP payload format parameter: only Header-Full format without zero padding for size collision avoidance */
+ Word16 prev_ft_speech; /* RXDTX handler: previous frametype flag for G.192 format AMRWB SID_FIRST detection */
+ Word16 CNG; /* RXDTX handler: CNG=1, nonCNG=0 */
+};
+
+/*---------------------------------------------------------------------*
+ * Local function declarations
+ *---------------------------------------------------------------------*/
+
+static void IVAS_DEC_Close_VoIP( IVAS_DEC_VOIP *hVoIP );
+#ifdef SUPPORT_JBM_TRACEFILE
+static void store_JbmData( IVAS_DEC_VOIP *hVoIP, JB4_DATAUNIT_HANDLE dataUnit, const UWord32 systemTimestamp_ms, const UWord16 extBufferedSamples, const Word32 output_Fs );
+#endif
+static ivas_error evs_dec_main( Decoder_Struct *st_ivas, const Word16 nOutSamples, float *floatBuf, Word16 *pcmBuf );
+static ivas_error input_format_API_to_internal( IVAS_DEC_INPUT_FORMAT input_format, Word16 *bitstream_format_internal, Word16 *sdp_hf_only, const bool is_voip_enabled );
+static void init_decoder_config( DECODER_CONFIG_HANDLE hDecoderConfig );
+static ivas_error IVAS_DEC_VoIP_reconfigure( IVAS_DEC_HANDLE hIvasDec, const UWord16 nTransportChannels, const UWord16 l_ts );
+static ivas_error IVAS_DEC_Setup( IVAS_DEC_HANDLE hIvasDec, UWord16 *nTcBufferGranularity, UWord8 *nTransportChannels, UWord8 *nOutChannels, UWord16 *nSamplesRendered, Word16 *data );
+static ivas_error IVAS_DEC_GetTcSamples( IVAS_DEC_HANDLE hIvasDec, float *pcmBuf, Word16 *nOutSamples );
+static ivas_error IVAS_DEC_RendererFeedTcSamples( IVAS_DEC_HANDLE hIvasDec, const Word16 nSamplesForRendering, Word16 *nSamplesResidual, float *pcmBuf );
+static ivas_error IVAS_DEC_GetRenderedSamples( IVAS_DEC_HANDLE hIvasDec, const UWord16 nSamplesForRendering, UWord16 *nSamplesRendered, UWord16 *nSamplesAvailableNext, Word16 *pcmBuf );
+static ivas_error IVAS_DEC_GetBufferedNumberOfSamples( IVAS_DEC_HANDLE hIvasDec, Word16 *nSamplesBuffered );
+static Word16 get_render_frame_size_ms( IVAS_RENDER_FRAMESIZE render_framesize );
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_Open()
+ *
+ * Open IVAS decoder
+ *---------------------------------------------------------------------*/
+
+/* may return an error but may still have allocated memory - thus run Close also in case of error to release memory */
+ivas_error IVAS_DEC_Open(
+ IVAS_DEC_HANDLE *phIvasDec, /* i/o: pointer to an IVAS decoder handle to be opened */
+ const IVAS_DEC_MODE mode /* i : compatibility mode (EVS or IVAS) */
+)
+{
+ IVAS_DEC_HANDLE hIvasDec;
+ Decoder_Struct *st_ivas;
+
+ IF( phIvasDec == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ /*-----------------------------------------------------------------*
+ * Allocate and initialize IVAS application decoder handle
+ *-----------------------------------------------------------------*/
+
+ IF( ( *phIvasDec = (IVAS_DEC_HANDLE) malloc( sizeof( struct IVAS_DEC ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS decoder handle" );
+ }
+ hIvasDec = *phIvasDec;
+ hIvasDec->hVoIP = NULL;
+ hIvasDec->apaExecBuffer = NULL;
+ hIvasDec->hTimeScaler = NULL;
+ hIvasDec->tsm_scale = 100;
+ hIvasDec->tsm_max_scaling = 0;
+ hIvasDec->tsm_quality = 1.0f;
+ hIvasDec->needNewFrame = false;
+ hIvasDec->nTransportChannelsOld = 0;
+ hIvasDec->nSamplesAvailableNext = 0;
+ hIvasDec->nSamplesRendered = 0;
+ hIvasDec->nSamplesFrame = 0;
+ hIvasDec->hasBeenFedFrame = false;
+ hIvasDec->hasBeenFedFirstGoodFrame = false;
+ hIvasDec->hasDecodedFirstGoodFrame = false;
+ hIvasDec->isInitialized = false;
+ hIvasDec->updateOrientation = false;
+
+ hIvasDec->mode = mode;
+
+ hIvasDec->bitstreamformat = G192;
+ hIvasDec->Opt_VOIP = 0;
+ hIvasDec->amrwb_rfc4867_flag = -1;
+ hIvasDec->prev_ft_speech = 1; /* RXDTX handler previous frametype flag for G.192 format AMRWB SID_FIRST detection */
+ hIvasDec->CNG = 0; /* RXDTX handler CNG = 1, no CNG = 0*/
+
+ /*-----------------------------------------------------------------*
+ * Initialize IVAS-codec decoder state
+ *-----------------------------------------------------------------*/
+
+ IF( ( hIvasDec->st_ivas = (Decoder_Struct *) malloc( sizeof( Decoder_Struct ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS decoder structure" );
+ }
+
+ IF( ( hIvasDec->st_ivas->hDecoderConfig = (DECODER_CONFIG_HANDLE) malloc( sizeof( DECODER_CONFIG ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Decoder config structure" );
+ }
+
+ /*-----------------------------------------------------------------*
+ * Initialize IVAS-codec decoder state
+ *-----------------------------------------------------------------*/
+
+ st_ivas = hIvasDec->st_ivas;
+
+ /* initialize Decoder Config. handle */
+ init_decoder_config( hIvasDec->st_ivas->hDecoderConfig );
+
+ /* initialize pointers to handles to NULL */
+ ivas_initialize_handles_dec( st_ivas );
+
+ /* set high-level parameters */
+ IF( EQ_16( mode, IVAS_DEC_MODE_EVS ) )
+ {
+ st_ivas->codec_mode = 0; /* unknown before first frame */
+ st_ivas->element_mode_init = EVS_MONO;
+ st_ivas->ivas_format = MONO_FORMAT;
+ st_ivas->transport_config = IVAS_AUDIO_CONFIG_INVALID;
+ st_ivas->intern_config = IVAS_AUDIO_CONFIG_INVALID;
+ st_ivas->writeFECoffset = 0;
+
+ return IVAS_ERR_OK;
+ }
+ ELSE IF( EQ_16( mode, IVAS_DEC_MODE_IVAS ) )
+ {
+ st_ivas->codec_mode = 0; /* unknown before first frame */
+ st_ivas->element_mode_init = -1;
+ st_ivas->ivas_format = UNDEFINED_FORMAT;
+ st_ivas->transport_config = IVAS_AUDIO_CONFIG_INVALID;
+ st_ivas->intern_config = IVAS_AUDIO_CONFIG_INVALID;
+ st_ivas->renderer_type = RENDERER_DISABLE;
+ st_ivas->ini_frame = 0;
+ st_ivas->ini_active_frame = 0;
+ st_ivas->writeFECoffset = 0;
+
+ st_ivas->ism_mode = ISM_MODE_NONE;
+ st_ivas->mc_mode = MC_MODE_NONE;
+
+ st_ivas->sba_order = 0;
+ st_ivas->sba_planar = 0;
+ st_ivas->sba_analysis_order = 0;
+
+ return IVAS_ERR_OK;
+ }
+
+ return IVAS_ERR_WRONG_PARAMS;
+}
+
+
+/*---------------------------------------------------------------------*
+ * init_decoder_config()
+ *
+ * Initialize Decoder Config. handle
+ *---------------------------------------------------------------------*/
+
+static void init_decoder_config(
+ DECODER_CONFIG_HANDLE hDecoderConfig /* i/o: configuration structure */
+)
+{
+ hDecoderConfig->Opt_AMR_WB = 0;
+ hDecoderConfig->nchan_out = 1;
+ hDecoderConfig->output_config = IVAS_AUDIO_CONFIG_INVALID;
+ hDecoderConfig->Opt_LsCustom = 0;
+ hDecoderConfig->Opt_HRTF_binary = 0;
+ hDecoderConfig->Opt_Headrotation = 0;
+ hDecoderConfig->Opt_RendConfigCustom = 0;
+ hDecoderConfig->orientation_tracking = IVAS_HEAD_ORIENT_TRK_NONE;
+ hDecoderConfig->Opt_non_diegetic_pan = 0;
+ hDecoderConfig->non_diegetic_pan_gain = 0;
+ hDecoderConfig->Opt_tsm = 0;
+ hDecoderConfig->Opt_delay_comp = 0;
+ hDecoderConfig->Opt_ExternalOrientation = 0;
+ hDecoderConfig->Opt_dpid_on = 0;
+ hDecoderConfig->Opt_aeid_on = 0;
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_Close( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+void IVAS_DEC_Close(
+ IVAS_DEC_HANDLE *phIvasDec /* i/o: pointer to IVAS decoder handle */
+)
+{
+ /* Free all memory */
+ IF( phIvasDec == NULL || *phIvasDec == NULL )
+ {
+ return;
+ }
+
+ IF( ( *phIvasDec )->hVoIP )
+ {
+ IVAS_DEC_Close_VoIP( ( *phIvasDec )->hVoIP );
+ ( *phIvasDec )->hVoIP = NULL;
+ }
+
+ IF( ( *phIvasDec )->st_ivas )
+ {
+ ivas_destroy_dec( ( *phIvasDec )->st_ivas );
+ ( *phIvasDec )->st_ivas = NULL;
+ }
+
+ apa_exit( &( *phIvasDec )->hTimeScaler );
+
+ IF( ( *phIvasDec )->apaExecBuffer != NULL )
+ {
+ free( ( *phIvasDec )->apaExecBuffer );
+ }
+ free( *phIvasDec );
+ *phIvasDec = NULL;
+ phIvasDec = NULL;
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * mapIvasFormat( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static IVAS_DEC_BS_FORMAT mapIvasFormat(
+ const IVAS_FORMAT ivas_format )
+{
+ SWITCH( ivas_format )
+ {
+ case MONO_FORMAT:
+ return IVAS_DEC_BS_MONO;
+ case STEREO_FORMAT:
+ return IVAS_DEC_BS_STEREO;
+ case ISM_FORMAT:
+ return IVAS_DEC_BS_OBJ;
+ case MC_FORMAT:
+ return IVAS_DEC_BS_MC;
+ case SBA_FORMAT:
+ return IVAS_DEC_BS_SBA;
+ case SBA_ISM_FORMAT:
+ return IVAS_DEC_BS_SBA_ISM;
+ case MASA_FORMAT:
+ return IVAS_DEC_BS_MASA;
+ case MASA_ISM_FORMAT:
+ return IVAS_DEC_BS_MASA_ISM;
+ default:
+ BREAK;
+ }
+
+ return IVAS_DEC_BS_UNKOWN;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_Configure( )
+ *
+ * Decoder configuration
+ * legacy code behavior: if no output format set, then it's EVS mono
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_Configure(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const UWord32 sampleRate, /* i : output sampling frequency */
+ const AUDIO_CONFIG outputConfig, /* i : output configuration */
+ const Word16 tsmEnabled, /* i : enable time scale modification */
+ const IVAS_RENDER_FRAMESIZE renderFramesize, /* i : rendering frame size */
+ const Word16 customLsOutputEnabled, /* i : enable custom loudspeaker setup handle */
+ const Word16 hrtfReaderEnabled, /* i : enable HRTF binary file input */
+ const Word16 enableHeadRotation, /* i : enable head rotation for binaural output */
+ const Word16 enableExternalOrientation, /* i : enable external orientations */
+ const IVAS_HEAD_ORIENT_TRK_T orientation_tracking, /* i : head orientation tracking type */
+ const Word16 renderConfigEnabled, /* i : enable Renderer config. file for binaural output */
+ const Word16 Opt_non_diegetic_pan, /* i : diegetic or not */
+ const float non_diegetic_pan_gain, /* i : non diegetic panning gain */
+ const Word16 Opt_dpid_on, /* i : enable directivity pattern option */
+ const UWord16 acousticEnvironmentId, /* i : Acoustic environment ID */
+ const Word16 delayCompensationEnabled /* i : enable delay compensation */
+)
+{
+ Decoder_Struct *st_ivas;
+ DECODER_CONFIG_HANDLE hDecoderConfig;
+ ivas_error error;
+
+ error = IVAS_ERR_OK;
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ IF( NE_32( sampleRate, 8000 ) && NE_32( sampleRate, 16000 ) && NE_32( sampleRate, 32000 ) && NE_32( sampleRate, 48000 ) )
+ {
+ return IVAS_ERR_WRONG_PARAMS;
+ }
+
+ IF( EQ_16( hIvasDec->mode, IVAS_DEC_MODE_EVS ) && !( ( EQ_16( outputConfig, IVAS_AUDIO_CONFIG_MONO ) && EQ_16( Opt_non_diegetic_pan, 0 ) ) ||
+ ( EQ_16( outputConfig, IVAS_AUDIO_CONFIG_STEREO ) && EQ_16( Opt_non_diegetic_pan, 1 ) ) ) )
+ {
+ return IVAS_ERR_WRONG_MODE;
+ }
+
+ st_ivas = hIvasDec->st_ivas;
+
+ hDecoderConfig = st_ivas->hDecoderConfig;
+
+ hDecoderConfig->output_config = outputConfig;
+ IF( EQ_16( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_INVALID ) )
+ {
+ return IVAS_ERR_WRONG_PARAMS;
+ }
+
+ hDecoderConfig->output_Fs = sampleRate;
+
+ IF( EQ_16( hIvasDec->mode, IVAS_DEC_MODE_EVS ) )
+ {
+ st_ivas->element_mode_init = EVS_MONO;
+ hDecoderConfig->nchan_out = 1;
+ }
+
+ IF( NE_16( outputConfig, IVAS_AUDIO_CONFIG_EXTERNAL ) && NE_16( outputConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
+ {
+ hDecoderConfig->nchan_out = audioCfg2channels( hDecoderConfig->output_config );
+ }
+
+ hDecoderConfig->Opt_tsm = tsmEnabled;
+ hDecoderConfig->Opt_LsCustom = customLsOutputEnabled;
+ hDecoderConfig->Opt_Headrotation = enableHeadRotation;
+ hDecoderConfig->orientation_tracking = orientation_tracking;
+ hDecoderConfig->Opt_HRTF_binary = hrtfReaderEnabled;
+ hDecoderConfig->Opt_RendConfigCustom = renderConfigEnabled;
+ hDecoderConfig->Opt_non_diegetic_pan = Opt_non_diegetic_pan;
+ hDecoderConfig->non_diegetic_pan_gain = non_diegetic_pan_gain;
+ hDecoderConfig->Opt_delay_comp = delayCompensationEnabled;
+ hDecoderConfig->Opt_ExternalOrientation = enableExternalOrientation;
+ hDecoderConfig->Opt_dpid_on = Opt_dpid_on;
+ hDecoderConfig->Opt_aeid_on = NE_32( (Word32) acousticEnvironmentId, 65535 ) ? TRUE : FALSE;
+
+ IF( EQ_16( renderFramesize, IVAS_RENDER_FRAMESIZE_UNKNOWN ) )
+ {
+ return IVAS_ERR_WRONG_PARAMS;
+ }
+ IF( EQ_16( outputConfig, IVAS_AUDIO_CONFIG_EXTERNAL ) )
+ {
+ hDecoderConfig->render_framesize = IVAS_RENDER_FRAMESIZE_20MS;
+ }
+ ELSE
+ {
+ hDecoderConfig->render_framesize = renderFramesize;
+ }
+
+
+ /* Set decoder parameters to initial values */
+ IF( ( error = ivas_init_decoder_front( st_ivas ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ IF( EQ_16( hIvasDec->mode, IVAS_DEC_MODE_EVS ) )
+ {
+ hIvasDec->st_ivas->ivas_format = MONO_FORMAT;
+ }
+
+ hIvasDec->nSamplesFrame = (UWord16) Mpy_32_16_1( hDecoderConfig->output_Fs, INV_FRAME_PER_SEC_Q15 );
+ hIvasDec->nSamplesAvailableNext = 0;
+ hIvasDec->nSamplesRendered = 0;
+ hIvasDec->tsm_scale = 100;
+ hIvasDec->tsm_max_scaling = 0;
+ hIvasDec->tsm_quality = 1.0f;
+
+ return error;
+}
+
+
+/*---------------------------------------------------------------------*
+ * get_render_framesize_ms( )
+ *
+ * Get the 5ms flag
+ *---------------------------------------------------------------------*/
+
+Word16 get_render_frame_size_ms(
+ const IVAS_RENDER_FRAMESIZE render_framesize )
+{
+ IF( EQ_16( render_framesize, IVAS_RENDER_FRAMESIZE_5MS ) )
+ {
+ return ( 1000 / ( FRAMES_PER_SEC * IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) );
+ }
+ ELSE IF( EQ_16( render_framesize, IVAS_RENDER_FRAMESIZE_10MS ) )
+ {
+ return shl( ( 1000 / ( FRAMES_PER_SEC * IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ), 1 );
+ }
+ ELSE IF( EQ_16( render_framesize, IVAS_RENDER_FRAMESIZE_20MS ) )
+ {
+ return shl( ( 1000 / ( FRAMES_PER_SEC * IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ), 2 );
+ }
+ return 0;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_SetRenderFramesize( )
+ *
+ * Get the 5ms flag
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_SetRenderFramesize(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_RENDER_FRAMESIZE render_framesize /* i : render framesize */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hDecoderConfig == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ hIvasDec->st_ivas->hDecoderConfig->render_framesize = render_framesize;
+
+ return IVAS_ERR_OK;
+}
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetGetRenderFramesize( )
+ *
+ * Get the 5ms flag
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetRenderFramesize(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_RENDER_FRAMESIZE *render_framesize /* o : render framesize */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || render_framesize == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ *render_framesize = hIvasDec->st_ivas->hDecoderConfig->render_framesize;
+
+ return IVAS_ERR_OK;
+}
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetGetRenderFramesizeSamples( )
+ *
+ * Get render framesize in samples
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetRenderFramesizeSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *render_framesize /* o : render framesize in samples */
+)
+{
+ Word16 tmp;
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || render_framesize == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ tmp = (Word16) Mpy_32_16_1( hIvasDec->st_ivas->hDecoderConfig->output_Fs, INV_FR_P_S_MX_PRM_SPL_SBFR_Q15 );
+
+ IF( EQ_16( hIvasDec->st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_5MS ) )
+ {
+ *render_framesize = tmp;
+ }
+ ELSE IF( EQ_16( hIvasDec->st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_10MS ) )
+ {
+ *render_framesize = shl( tmp, 1 );
+ }
+ ELSE IF( EQ_16( hIvasDec->st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_20MS ) )
+ {
+ *render_framesize = shl( tmp, 2 );
+ }
+ ELSE
+ {
+ *render_framesize = 0;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetGetRenderFramesizeMs( )
+ *
+ * Get render framesize in milliseconds
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetRenderFramesizeMs(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord32 *render_framesize /* o : render framesize in samples */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || render_framesize == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ *render_framesize = get_render_frame_size_ms( hIvasDec->st_ivas->hDecoderConfig->render_framesize );
+
+ return IVAS_ERR_OK;
+}
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetGetReferencesUpdateFrequency( )
+ *
+ * Get update frequency of the reference vector/orientation
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetReferencesUpdateFrequency(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *update_frequency /* o : update frequency */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || update_frequency == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ IF( EQ_16( hIvasDec->st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_5MS ) )
+ {
+ *update_frequency = IVAS_MAX_PARAM_SPATIAL_SUBFRAMES;
+ }
+ ELSE IF( EQ_16( hIvasDec->st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_10MS ) )
+ {
+ *update_frequency = shr( IVAS_MAX_PARAM_SPATIAL_SUBFRAMES, 1 );
+ }
+ ELSE IF( EQ_16( hIvasDec->st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_20MS ) )
+ {
+ *update_frequency = shr( IVAS_MAX_PARAM_SPATIAL_SUBFRAMES, 2 );
+ }
+
+ return IVAS_ERR_OK;
+}
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetGetNumOrientationSubframes( )
+ *
+ * Get the number of subframes for head/ecernal orientation per render frame
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetNumOrientationSubframes(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *num_subframes /* o : render framesize */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || num_subframes == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ *num_subframes = (Word16) hIvasDec->st_ivas->hDecoderConfig->render_framesize;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_EnableVoIP( )
+ *
+ * Intitialize JBM
+ * jbmSafetyMargin: allowed delay reserve in addition to network jitter
+ * to reduce late-loss, default: 60 [milliseconds]
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_EnableVoIP(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 jbmSafetyMargin, /* i : allowed delay reserve for JBM, in milliseconds */
+ const IVAS_DEC_INPUT_FORMAT inputFormat /* i : format of the input bitstream */
+)
+{
+ DECODER_CONFIG_HANDLE hDecoderConfig;
+ ivas_error error;
+
+ error = IVAS_ERR_OK;
+
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ hDecoderConfig = hIvasDec->st_ivas->hDecoderConfig;
+
+ hIvasDec->Opt_VOIP = 1;
+ hDecoderConfig->Opt_tsm = 1;
+ IF( NE_16( (Word16) hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
+ {
+ hDecoderConfig->nchan_out = audioCfg2channels( hDecoderConfig->output_config );
+ }
+
+ IF( ( error = input_format_API_to_internal( inputFormat, &hIvasDec->bitstreamformat, &hIvasDec->sdp_hf_only, true ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ IF( ( hIvasDec->hVoIP = malloc( sizeof( IVAS_DEC_VOIP ) ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" );
+ }
+
+ hIvasDec->hVoIP->lastDecodedWasActive = 0;
+ hIvasDec->hVoIP->hCurrentDataUnit = NULL;
+ hIvasDec->hVoIP->nSamplesFrame = (UWord16) Mpy_32_16_1( hDecoderConfig->output_Fs, INV_FRAME_PER_SEC_Q15 );
+
+#define WMC_TOOL_SKIP
+ /* Bitstream conversion is not counted towards complexity and memory usage */
+ hIvasDec->hVoIP->bs_conversion_buf = malloc( sizeof( UWord16 ) * ( MAX_BITS_PER_FRAME + 4 * 8 ) );
+#undef WMC_TOOL_SKIP
+
+ IF( hIvasDec->hVoIP->bs_conversion_buf == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" );
+ }
+
+ /* initialize JBM */
+ IF( ( error = JB4_Create( &hIvasDec->hVoIP->hJBM ) != IVAS_ERR_OK ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ IF( JB4_Init( hIvasDec->hVoIP->hJBM, jbmSafetyMargin ) != 0 )
+ {
+ return IVAS_ERR_FAILED_ALLOC;
+ }
+
+ return error;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_FeedFrame_Serial( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_FeedFrame_Serial(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord16 *serial, /* i : buffer containing serial input bitstream. Each bit should be stored as a single uint16_t value */
+ const UWord16 num_bits, /* i : number of bits in input bitstream */
+ Word16 bfi /* i : bad frame indicator flag */
+)
+{
+ ivas_error error;
+
+ IF( !hIvasDec->isInitialized )
+ {
+ /* Once first frame is fed, finish initialization in EVS Mono.
+ * In IVAS mode, initialization is done in ivas_dec(). */
+ IF( EQ_16( hIvasDec->mode, IVAS_DEC_MODE_EVS ) )
+ {
+ IF( ( error = ivas_init_decoder( hIvasDec->st_ivas ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ IF( hIvasDec->hVoIP != NULL && hIvasDec->hVoIP->hCurrentDataUnit != NULL )
+ {
+ DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0];
+ st->ini_frame = 0;
+ st->prev_use_partial_copy = 0;
+ hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = hIvasDec->hVoIP->hCurrentDataUnit->dataSize * FRAMES_PER_SEC;
+ }
+ ELSE
+ {
+ hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = ACELP_8k00;
+ }
+ hIvasDec->isInitialized = true;
+ }
+ }
+
+ IF( !bfi ) /* TODO(mcjbm): Is this ok for bfi == 2 (partial frame)? Is there enough info to fully configure decoder? */
+ {
+ hIvasDec->hasBeenFedFirstGoodFrame = true;
+ }
+
+ /* Update redundant frame information in EVS (pre- read indices) */
+ IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) && hIvasDec->hVoIP != NULL && hIvasDec->hVoIP->hCurrentDataUnit != NULL )
+ {
+ DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0];
+ st->bit_stream = serial;
+
+ IF( hIvasDec->hVoIP->hCurrentDataUnit->partial_frame || st->prev_use_partial_copy )
+ {
+ st->next_coder_type = hIvasDec->hVoIP->hCurrentDataUnit->nextCoderType;
+ }
+ ELSE
+ {
+ st->next_coder_type = INACTIVE;
+ }
+
+ IF( EQ_16( (Word16) hIvasDec->hVoIP->hCurrentDataUnit->partial_frame, 1 ) && NE_16( bfi, 1 ) )
+ {
+ bfi = 2;
+ }
+ }
+
+ IF( ( error = read_indices( hIvasDec->st_ivas, serial, num_bits, &hIvasDec->prev_ft_speech, &hIvasDec->CNG, bfi ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ /* Update redundant frame information in EVS (post- read indices) */
+ IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) &&
+ hIvasDec->hVoIP != NULL &&
+ hIvasDec->hVoIP->hCurrentDataUnit != NULL &&
+ NE_16( (Word16) hIvasDec->hVoIP->hCurrentDataUnit->partial_frame, 0 ) )
+ {
+ DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0];
+ st->codec_mode = MODE2;
+ st->use_partial_copy = 1;
+ }
+
+ hIvasDec->needNewFrame = false;
+ hIvasDec->hasBeenFedFrame = true;
+ hIvasDec->nSamplesRendered = 0;
+ hIvasDec->nSamplesAvailableNext = hIvasDec->nSamplesFrame;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetSamples( )
+ *
+ * Main function to decode to PCM data
+ *---------------------------------------------------------------------*/
+
+
+ivas_error IVAS_DEC_GetSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 nSamplesAsked, /* i : number of samples wanted by the caller */
+ Word16 *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */
+ Word16 *nOutSamples, /* o : number of samples per channel written to output buffer */
+ bool *needNewFrame /* o :indication that the decoder needs a new frame */
+)
+{
+ ivas_error error;
+ Word16 nOutSamplesElse, nSamplesToRender;
+ UWord16 nSamplesRendered, nSamplesRendered_loop, l_ts, nTimeScalerOutSamples;
+ UWord8 nTransportChannels, nOutChannels;
+
+ nSamplesRendered = 0;
+ nOutChannels = 0;
+ nSamplesRendered_loop = 0;
+ l_ts = 0;
+ nTransportChannels = 0;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ IF( hIvasDec->updateOrientation )
+ {
+ /*----------------------------------------------------------------*
+ * Combine orientations
+ *----------------------------------------------------------------*/
+
+ IF( ( error = combine_external_and_head_orientations_dec( hIvasDec->st_ivas->hHeadTrackData, hIvasDec->st_ivas->hExtOrientationData, hIvasDec->st_ivas->hCombinedOrientationData ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+
+ hIvasDec->updateOrientation = false;
+ }
+
+ IF( !hIvasDec->hasBeenFedFrame && EQ_16( hIvasDec->nSamplesAvailableNext, 0 ) )
+ {
+ /* no frame was fed, do nothing but ask for a frame */
+ *needNewFrame = true;
+ *nOutSamples = 0;
+ hIvasDec->needNewFrame = true;
+ return IVAS_ERR_OK;
+ }
+
+ /* check if we are still at the beginning with bad frames, put out zeroes, keep track of subframes */
+ IF( !hIvasDec->isInitialized && hIvasDec->st_ivas->bfi )
+ {
+ hIvasDec->hasBeenFedFrame = false;
+ set_s( pcmBuf, 0, hIvasDec->st_ivas->hDecoderConfig->nchan_out * nSamplesAsked );
+ hIvasDec->nSamplesRendered = add( hIvasDec->nSamplesRendered, nSamplesAsked );
+ *nOutSamples = nSamplesAsked;
+ hIvasDec->nSamplesAvailableNext = sub( hIvasDec->nSamplesAvailableNext, nSamplesAsked );
+ IF( EQ_16( hIvasDec->nSamplesAvailableNext, 0 ) )
+ {
+ hIvasDec->needNewFrame = true;
+ *needNewFrame = true;
+ }
+ }
+ ELSE
+ {
+ /* check if we need to run the setup function */
+ IF( !hIvasDec->isInitialized || hIvasDec->hasBeenFedFrame )
+ {
+ /* setup */
+
+ IF( ( error = IVAS_DEC_Setup( hIvasDec, &l_ts, &nTransportChannels, &nOutChannels, &nSamplesRendered_loop, pcmBuf + nSamplesRendered * nOutChannels ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+ {
+ /* check if we need to run the setup function, tc decoding and feeding the renderer */
+ IF( !hIvasDec->isInitialized || hIvasDec->hasBeenFedFrame )
+ {
+ Word16 nResidualSamples, nSamplesTcsScaled;
+ nSamplesRendered = add( nSamplesRendered, nSamplesRendered_loop );
+
+ IF( hIvasDec->st_ivas->hDecoderConfig->Opt_tsm && NE_16( (Word16) nTransportChannels, hIvasDec->nTransportChannelsOld ) )
+ {
+ IF( ( error = IVAS_DEC_VoIP_reconfigure( hIvasDec, nTransportChannels, l_ts ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+ /* IVAS decoder */
+ IF( ( error = IVAS_DEC_GetTcSamples( hIvasDec, hIvasDec->apaExecBuffer, &nOutSamplesElse ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ /* JBM */
+ IF( hIvasDec->st_ivas->hDecoderConfig->Opt_tsm )
+ {
+ IF( NE_16( (Word16) apa_set_scale( hIvasDec->hTimeScaler, hIvasDec->tsm_scale ), 0 ) )
+ {
+ return IVAS_ERR_UNKNOWN;
+ }
+
+ IF( NE_16( (Word16) apa_exec( hIvasDec->hTimeScaler, hIvasDec->apaExecBuffer, hIvasDec->nSamplesFrame * nTransportChannels, (UWord16) hIvasDec->tsm_max_scaling, hIvasDec->apaExecBuffer, &nTimeScalerOutSamples ), 0 ) )
+ {
+ return IVAS_ERR_UNKNOWN;
+ }
+
+ assert( LE_32( (Word32) nTimeScalerOutSamples, APA_BUF ) );
+ nSamplesTcsScaled = nTimeScalerOutSamples / nTransportChannels;
+ }
+ ELSE
+ {
+ nSamplesTcsScaled = hIvasDec->nSamplesFrame;
+ }
+
+ /* Feed decoded transport channels samples to the renderer */
+ IF( ( error = IVAS_DEC_RendererFeedTcSamples( hIvasDec, nSamplesTcsScaled, &nResidualSamples, hIvasDec->apaExecBuffer ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ IF( hIvasDec->st_ivas->hDecoderConfig->Opt_tsm )
+ {
+ /* feed residual samples to TSM for the next call */
+ IF( NE_16( (Word16) apa_set_renderer_residual_samples( hIvasDec->hTimeScaler, (UWord16) nResidualSamples ), 0 ) )
+ {
+ return IVAS_ERR_UNKNOWN;
+ }
+ }
+ hIvasDec->hasBeenFedFrame = false;
+ }
+
+ /* render IVAS frames directly to the output buffer */
+ nSamplesToRender = sub( nSamplesAsked, nSamplesRendered );
+ IF( ( error = IVAS_DEC_GetRenderedSamples( hIvasDec, nSamplesToRender, &nSamplesRendered_loop, &hIvasDec->nSamplesAvailableNext, pcmBuf + nSamplesRendered * nOutChannels ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ nSamplesRendered = add( nSamplesRendered, nSamplesRendered_loop );
+ nSamplesToRender = sub( nSamplesToRender, nSamplesRendered_loop );
+ IF( EQ_16( hIvasDec->nSamplesAvailableNext, 0 ) )
+ {
+ *needNewFrame = true;
+ hIvasDec->needNewFrame = true;
+ }
+ ELSE
+ {
+ *needNewFrame = false;
+ }
+ }
+ }
+
+ *nOutSamples = nSamplesRendered;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_Setup( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static ivas_error IVAS_DEC_Setup(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord16 *nTcBufferGranularity, /* o : granularity of the TC Buffer */
+ UWord8 *nTransportChannels, /* o : number of decoded transport PCM channels */
+ UWord8 *nOutChannels, /* o : number of decoded out channels (PCM or CLDFB) */
+ UWord16 *nSamplesRendered, /* o : number of samples flushed from the last frame */
+ Word16 *data /* o : output synthesis signal */
+)
+{
+ ivas_error error;
+
+ *nSamplesRendered = 0;
+
+ IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) )
+ {
+ IF( EQ_16( (Word16) hIvasDec->st_ivas->renderer_type, RENDERER_NON_DIEGETIC_DOWNMIX ) )
+ {
+ *nTransportChannels = MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN;
+ *nOutChannels = MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN;
+ }
+ ELSE
+ {
+ *nTransportChannels = 1;
+ *nOutChannels = 1;
+ }
+ }
+ ELSE
+ {
+ Decoder_Struct *st_ivas;
+
+ st_ivas = hIvasDec->st_ivas;
+
+ /*----------------------------------------------------------------*
+ * IVAS decoder setup
+ * - read IVAS format signaling
+ * - read IVAS format specific signaling
+ * - initialize decoder in the first frame based on IVAS format and number of transport channels
+ * - reconfigure the decoder when the number of TC or IVAS total bitrate change
+ *----------------------------------------------------------------*/
+
+ IF( EQ_16( st_ivas->bfi, 0 ) )
+ {
+ IF( ( error = ivas_dec_setup( st_ivas, nSamplesRendered, data ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+ *nTransportChannels = (UWord8) st_ivas->hTcBuffer->nchan_transport_jbm;
+ *nTcBufferGranularity = (UWord16) st_ivas->hTcBuffer->n_samples_granularity;
+ *nOutChannels = (UWord8) st_ivas->hDecoderConfig->nchan_out;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetTcSamples( )
+ *
+ * Main function to decode to PCM data of the transport channels
+ *---------------------------------------------------------------------*/
+
+static ivas_error IVAS_DEC_GetTcSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ float *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */
+ Word16 *nOutSamples /* o : number of samples per channel written to output buffer */
+)
+{
+ Decoder_Struct *st_ivas;
+ ivas_error error;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ st_ivas = hIvasDec->st_ivas;
+
+ *nOutSamples = (Word16) Mpy_32_16_1( st_ivas->hDecoderConfig->output_Fs, INV_FRAME_PER_SEC_Q15 );
+
+ IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) )
+ {
+ IF( ( error = evs_dec_main( st_ivas, *nOutSamples, pcmBuf, NULL ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+ ELSE IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_IVAS ) )
+ {
+ /* run the main IVAS decoding routine */
+ IF( ( error = ivas_jbm_dec_tc( st_ivas, pcmBuf ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ hIvasDec->isInitialized = true; /* Initialization done in ivas_dec() */
+ }
+
+ IF( hIvasDec->hasBeenFedFirstGoodFrame )
+ {
+ hIvasDec->hasDecodedFirstGoodFrame = true;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_Rendered_FeedTcSamples( )
+ *
+ * Feed decoded transport channels samples to the renderer
+ *---------------------------------------------------------------------*/
+
+static ivas_error IVAS_DEC_RendererFeedTcSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 nSamplesForRendering, /* i : number of TC samples wanted from the renderer */
+ Word16 *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call */
+ float *pcmBuf /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */
+)
+{
+ Decoder_Struct *st_ivas;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ st_ivas = hIvasDec->st_ivas;
+
+ /* feed the TCs to the IVAS renderer */
+ ivas_jbm_dec_feed_tc_to_renderer( st_ivas, nSamplesForRendering, nSamplesResidual, pcmBuf );
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetRenderedSamples( )
+ *
+ * Main function to render the transport channels to PCM output data
+ *---------------------------------------------------------------------*/
+
+static ivas_error IVAS_DEC_GetRenderedSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const UWord16 nSamplesForRendering, /* i : number of TC samples wanted from the renderer */
+ UWord16 *nSamplesRendered, /* o : number of samples rendered */
+ UWord16 *nSamplesAvailableNext, /* o : number of samples still available in the renerer pipeline */
+ Word16 *pcmBuf )
+{
+ Decoder_Struct *st_ivas;
+ ivas_error error;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ st_ivas = hIvasDec->st_ivas;
+
+ /* run the main IVAS decoding routine */
+ error = ivas_jbm_dec_render( st_ivas, nSamplesForRendering, nSamplesRendered, nSamplesAvailableNext, pcmBuf );
+
+ return error;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetBufferedNumberOfSamples( )
+ *
+ * Returns the number of objects available in the decoded bitstream
+ *---------------------------------------------------------------------*/
+
+static ivas_error IVAS_DEC_GetBufferedNumberOfSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *nSamplesBuffered /* o : number of samples still buffered */
+)
+{
+ *nSamplesBuffered = 0;
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ /* check if the TC buffer already exists, otherweise nothing is buffered anyway */
+ IF( hIvasDec->st_ivas->hTcBuffer != NULL )
+ {
+ *nSamplesBuffered = sub( hIvasDec->st_ivas->hTcBuffer->n_samples_buffered, hIvasDec->st_ivas->hTcBuffer->n_samples_rendered );
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetNumObjects( )
+ *
+ * Returns the number of objects available in the decoded bitstream
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetNumObjects(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord16 *numObjects /* o : number of objects for which the decoder has been configured */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+ IF( EQ_16( (Word16) hIvasDec->st_ivas->ivas_format, ISM_FORMAT ) || EQ_16( (Word16) hIvasDec->st_ivas->ivas_format, SBA_ISM_FORMAT ) || EQ_16( (Word16) hIvasDec->st_ivas->ivas_format, MASA_ISM_FORMAT ) )
+ {
+ *numObjects = hIvasDec->st_ivas->nchan_ism;
+ }
+ ELSE
+ {
+ *numObjects = 0;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetFormat( )
+ *
+ * Returns the format of currently decoded bitstream.
+ * Note: bitstream format is only known after the first (good) frame has been decoded.
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetFormat(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_BS_FORMAT *format /* o : format detected from bitstream fed to the decoder */
+)
+{
+ IF( hIvasDec->hasDecodedFirstGoodFrame )
+ {
+ *format = mapIvasFormat( hIvasDec->st_ivas->ivas_format );
+ }
+ ELSE
+ {
+ *format = IVAS_DEC_BS_UNKOWN;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * getInputBufferSize()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static Word16 getOutputBufferSize(
+ const Decoder_Struct *st_ivas /* i : IVAS decoder handle */
+)
+{
+ IF( st_ivas->hDecoderConfig == NULL )
+ {
+ return -1;
+ }
+
+ IF( EQ_16( (Word16) st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
+ {
+ return (Word16) ( st_ivas->hDecoderConfig->output_Fs * ( IVAS_MAX_OUTPUT_CHANNELS + IVAS_MAX_NUM_OBJECTS ) / FRAMES_PER_SEC );
+ }
+ ELSE IF( EQ_16( (Word16) st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
+ {
+ IF( st_ivas->hLsSetupCustom == NULL )
+ {
+ return -1;
+ }
+
+ return (Word16) ( st_ivas->hDecoderConfig->output_Fs * ( st_ivas->hLsSetupCustom->num_spk + st_ivas->hLsSetupCustom->num_lfe ) / FRAMES_PER_SEC );
+ }
+ ELSE
+ {
+ return (Word16) ( st_ivas->hDecoderConfig->output_Fs * st_ivas->hDecoderConfig->nchan_out / FRAMES_PER_SEC );
+ }
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetOutputBufferSize()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetOutputBufferSize(
+ const IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */
+ Word16 *outputBufferSize /* o : total number of samples expected in the output buffer for current decoder configuration */
+)
+{
+ IF( outputBufferSize == NULL || hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ *outputBufferSize = getOutputBufferSize( hIvasDec->st_ivas );
+
+ IF( EQ_16( *outputBufferSize, -1 ) )
+ {
+ return IVAS_ERR_INVALID_OUTPUT_BUFFER_SIZE;
+ }
+ ELSE
+ {
+ return IVAS_ERR_OK;
+ }
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetNumOutputChannels( )
+ *
+ * Returns number of output channels
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetNumOutputChannels(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *numOutputChannels /* o : number of PCM output channels */
+)
+{
+ IF( hIvasDec->hasDecodedFirstGoodFrame )
+ {
+ *numOutputChannels = hIvasDec->st_ivas->hDecoderConfig->nchan_out;
+ }
+ ELSE
+ {
+ *numOutputChannels = 0;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetObjectMetadata( )
+ *
+ * Get metadata of one object decoded in the most recent frame
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetObjectMetadata(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_ISM_METADATA *metadata, /* o : struct where metadata decoded in most recently decoded frame will be written */
+ const UWord16 zero_flag, /* i : if this flag is enabled, this function outputs a zero-initialized metadata struct */
+ const UWord16 objectIdx /* i : index of the queried object */
+)
+{
+ Decoder_Struct *st_ivas;
+ ISM_METADATA_HANDLE hIsmMeta;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ st_ivas = hIvasDec->st_ivas;
+ IF( NE_16( (Word16) st_ivas->ivas_format, ISM_FORMAT ) && NE_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) && NE_16( (Word16) st_ivas->ivas_format, SBA_ISM_FORMAT ) )
+ {
+ return IVAS_ERR_WRONG_MODE;
+ }
+
+ IF( GE_16( objectIdx, st_ivas->nchan_ism ) )
+ {
+ return IVAS_ERR_INVALID_INDEX;
+ }
+
+ hIsmMeta = st_ivas->hIsmMetaData[objectIdx];
+
+ IF( hIsmMeta == NULL || zero_flag )
+ {
+ metadata->azimuth = 0.f;
+ metadata->elevation = 0.f;
+ metadata->radius = 1.f;
+ metadata->spread = 0.f;
+ metadata->gainFactor = 1.f;
+ metadata->yaw = 0.f;
+ metadata->pitch = 0.f;
+ metadata->non_diegetic_flag = 0;
+ }
+ ELSE
+ {
+ metadata->azimuth = hIsmMeta->azimuth;
+ metadata->elevation = hIsmMeta->elevation;
+ metadata->radius = hIsmMeta->radius;
+ metadata->yaw = hIsmMeta->yaw;
+ metadata->pitch = hIsmMeta->pitch;
+ metadata->spread = 0.f;
+ metadata->gainFactor = 1.f;
+ metadata->non_diegetic_flag = hIsmMeta->non_diegetic_flag;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetMasaMetadata( )
+ *
+ * Get metadata of the most recently decoded MASA frame
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetMasaMetadata(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ MASA_DECODER_EXT_OUT_META_HANDLE *hMasaExtOutMeta, /* o : pointer to handle, which will be set to point to metadata from the most recently decoded frame */
+ const UWord8 getFromJbmBuffer /* i : get metadata from a JBM buffer */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ IF( NE_16( (Word16) hIvasDec->st_ivas->ivas_format, MASA_FORMAT ) && NE_16( (Word16) hIvasDec->st_ivas->ivas_format, MASA_ISM_FORMAT ) )
+ {
+ return IVAS_ERR_WRONG_MODE;
+ }
+
+ IF( getFromJbmBuffer )
+ {
+ ivas_jbm_masa_sf_to_sf_map( hIvasDec->st_ivas );
+ }
+
+ *hMasaExtOutMeta = hIvasDec->st_ivas->hMasa->data.extOutMeta;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_FeedHeadTrackData( )
+ *
+ * Feed the decoder with the head tracking data
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_FeedHeadTrackData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_QUATERNION orientation, /* i : head-tracking data, listener orientation */
+ IVAS_VECTOR3 Pos, /* i : listener position */
+ const Word16 subframe_idx /* i : subframe index */
+)
+{
+ HEAD_TRACK_DATA_HANDLE hHeadTrackData;
+ ivas_error error;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ hHeadTrackData = hIvasDec->st_ivas->hHeadTrackData;
+
+ IF( hHeadTrackData == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ /* Move head-tracking data to the decoder handle */
+ /* check for Euler angle signaling */
+ IF( orientation.w == -3.0f )
+ {
+ Euler2Quat( deg2rad( orientation.x ), deg2rad( orientation.y ), deg2rad( orientation.z ), &orientation );
+ }
+
+ IF( ( error = ivas_orient_trk_Process( hHeadTrackData->OrientationTracker, orientation, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &hHeadTrackData->Quaternions[subframe_idx] ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ hHeadTrackData->Pos[subframe_idx].x = Pos.x;
+ hHeadTrackData->Pos[subframe_idx].y = Pos.y;
+ hHeadTrackData->Pos[subframe_idx].z = Pos.z;
+
+ hIvasDec->updateOrientation = true;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_FeedRefRotData( )
+ *
+ * Feed the decoder with the reference rotation
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_FeedRefRotData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_QUATERNION rotation /* i : reference rotation data */
+)
+{
+ ivas_orient_trk_state_t *pOtr;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHeadTrackData == NULL || hIvasDec->st_ivas->hHeadTrackData->OrientationTracker == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ pOtr = hIvasDec->st_ivas->hHeadTrackData->OrientationTracker;
+
+ pOtr->refRot.w = rotation.w;
+ pOtr->refRot.x = rotation.x;
+ pOtr->refRot.z = rotation.z;
+ pOtr->refRot.y = rotation.y;
+
+ hIvasDec->updateOrientation = true;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_FeedRefVectorData( )
+ *
+ * Feed the decoder with a reference vector spanning from listenerPos
+ * to refPos. Only available in OTR_TRACKING_REF_POS and
+ * OTR_TRACKING_REF_POS_LEV modes.
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_FeedRefVectorData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_VECTOR3 listenerPos, /* i : Listener position */
+ const IVAS_VECTOR3 refPos /* i : Reference position */
+)
+{
+ ivas_orient_trk_state_t *pOtr;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHeadTrackData == NULL || hIvasDec->st_ivas->hHeadTrackData->OrientationTracker == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ pOtr = hIvasDec->st_ivas->hHeadTrackData->OrientationTracker;
+
+ hIvasDec->updateOrientation = true;
+
+ return ivas_orient_trk_SetReferenceVector( pOtr, listenerPos, refPos );
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_FeedExternalOrientationData( )
+ *
+ * Feed the decoder with the external orientation data
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_FeedExternalOrientationData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_QUATERNION orientation, /* i : external orientation data */
+ Word8 enableHeadRotation, /* i : flag to enable head rotation for this frame */
+ Word8 enableExternalOrientation, /* i : flag to enable external orientation for this frame */
+ Word8 enableRotationInterpolation, /* i : flag to interpolate rotations from current and previous frames */
+ Word16 numFramesToTargetOrientation, /* i : number of frames until target orientation is reached */
+ const Word16 subframe_idx /* i : subframe index */
+)
+{
+ EXTERNAL_ORIENTATION_HANDLE hExternalOrientationData;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ hExternalOrientationData = hIvasDec->st_ivas->hExtOrientationData;
+
+ IF( hExternalOrientationData == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ /* Move external orientation data to the decoder handle (invert orientations) */
+ QuaternionInverse( orientation, &hExternalOrientationData->Quaternions[subframe_idx] );
+
+ hExternalOrientationData->enableHeadRotation[subframe_idx] = enableHeadRotation;
+ hExternalOrientationData->enableExternalOrientation[subframe_idx] = enableExternalOrientation;
+ hExternalOrientationData->enableRotationInterpolation[subframe_idx] = enableRotationInterpolation;
+ hExternalOrientationData->numFramesToTargetOrientation[subframe_idx] = numFramesToTargetOrientation;
+
+ hIvasDec->updateOrientation = true;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_FeedCustomLsData( )
+ *
+ * Feed the decoder with the Custom loudspeaker data
+ *---------------------------------------------------------------------*/
+
+/*! r: error code */
+ivas_error IVAS_DEC_FeedCustomLsData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_CUSTOM_LS_DATA hLsCustomData /* i : Custom loudspeaker setup data */
+)
+{
+ Word16 i, is_planar;
+ IVAS_LSSETUP_CUSTOM_HANDLE hLsSetupCustom;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ hLsSetupCustom = hIvasDec->st_ivas->hLsSetupCustom;
+
+ IF( hLsSetupCustom == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ /* Move Custom LS layout data to the decoder handle */
+
+ /* Loudspeaker azimuths and elevations */
+ hLsSetupCustom->num_spk = hLsCustomData.num_spk;
+
+ mvr2r( hLsCustomData.azimuth, hLsSetupCustom->ls_azimuth, hLsCustomData.num_spk );
+ mvr2r( hLsCustomData.elevation, hLsSetupCustom->ls_elevation, hLsCustomData.num_spk );
+
+ /* Set planar flag */
+ is_planar = 1;
+ FOR( i = 0; i < hLsCustomData.num_spk; i++ )
+ {
+ IF( is_planar && hLsSetupCustom->ls_elevation[i] != 0.0f )
+ {
+ is_planar = 0;
+ }
+ }
+ hLsSetupCustom->is_planar_setup = is_planar;
+
+ /* Loudspeaker LFE */
+ hLsSetupCustom->num_lfe = hLsCustomData.num_lfe;
+ mvs2s( hLsCustomData.lfe_idx, hLsSetupCustom->lfe_idx, hLsCustomData.num_lfe );
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetHrtfHandle( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetHrtfHandle(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_HRTF_HANDLE *hHrtfTD /* o : HRTF handle */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHrtfTD == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ *hHrtfTD = hIvasDec->st_ivas->hHrtfTD;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetHrtfCRendHandle( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetHrtfCRendHandle(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_HRTF_CREND_HANDLE *hSetOfHRTF /* o : Set of HRTF handle */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hSetOfHRTF == NULL )
+ {
+ return IVAS_ERR_WRONG_PARAMS;
+ }
+
+ *hSetOfHRTF = hIvasDec->st_ivas->hSetOfHRTF;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetHrtfFastConvHandle( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetHrtfFastConvHandle(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHrtfFastConv == NULL )
+ {
+ return IVAS_ERR_WRONG_PARAMS;
+ }
+
+ *hHrtfFastConv = hIvasDec->st_ivas->hHrtfFastConv;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetHrtfParamBinHandle( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetHrtfParamBinHandle(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_DEC_HRTF_PARAMBIN_HANDLE *hHrtfParambin /* o : Parametric binauralizer HRTF handle */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHrtfParambin == NULL )
+ {
+ return IVAS_ERR_WRONG_PARAMS;
+ }
+
+ *hHrtfParambin = hIvasDec->st_ivas->hHrtfParambin;
+
+ return IVAS_ERR_OK;
+}
+
+/*---------------------------------------------------------------------*
+ * copyRendererConfigStruct( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static ivas_error copyRendererConfigStruct(
+ RENDER_CONFIG_HANDLE hRCin,
+ IVAS_RENDER_CONFIG_HANDLE hRCout )
+{
+ IF( hRCin == NULL || hRCout == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ hRCout->roomAcoustics.override = hRCin->roomAcoustics.override;
+ hRCout->roomAcoustics.nBands = hRCin->roomAcoustics.nBands;
+ hRCout->roomAcoustics.acousticPreDelay = hRCin->roomAcoustics.acousticPreDelay;
+ hRCout->roomAcoustics.inputPreDelay = hRCin->roomAcoustics.inputPreDelay;
+
+ mvr2r( hRCin->roomAcoustics.pFc_input, hRCout->roomAcoustics.pFc_input, CLDFB_NO_CHANNELS_MAX );
+ mvr2r( hRCin->roomAcoustics.pAcoustic_rt60, hRCout->roomAcoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX );
+ mvr2r( hRCin->roomAcoustics.pAcoustic_dsr, hRCout->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX );
+ mvr2r( hRCin->directivity, hRCout->directivity, 3 * MAX_NUM_OBJECTS );
+ hRCout->roomAcoustics.use_er = hRCin->roomAcoustics.use_er;
+ hRCout->roomAcoustics.lowComplexity = hRCin->roomAcoustics.lowComplexity;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetRenderConfig( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetRenderConfig(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_RENDER_CONFIG_HANDLE hRCout /* o : Render configuration handle */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hRenderConfig == NULL || hRCout == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ return copyRendererConfigStruct( hIvasDec->st_ivas->hRenderConfig, hRCout );
+}
+
+/*! r: error code*/
+ivas_error IVAS_DEC_GetDefaultRenderConfig(
+ IVAS_RENDER_CONFIG_HANDLE hRCout /* o : Render config handle */
+)
+{
+ RENDER_CONFIG_DATA RCin;
+ RENDER_CONFIG_HANDLE hRCin = &RCin;
+ ivas_error error;
+
+ IF( ( error = ivas_render_config_init_from_rom( &hRCin ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ return copyRendererConfigStruct( hRCin, hRCout );
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_FeedRenderConfig( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_FeedRenderConfig(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const IVAS_RENDER_CONFIG_DATA renderConfig /* i : Render configuration struct */
+)
+{
+ RENDER_CONFIG_HANDLE hRenderConfig;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hRenderConfig == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ hRenderConfig = hIvasDec->st_ivas->hRenderConfig;
+ hRenderConfig->roomAcoustics.override = renderConfig.roomAcoustics.override;
+ hRenderConfig->roomAcoustics.nBands = renderConfig.roomAcoustics.nBands;
+ hRenderConfig->roomAcoustics.acousticPreDelay = renderConfig.roomAcoustics.acousticPreDelay;
+ hRenderConfig->roomAcoustics.inputPreDelay = renderConfig.roomAcoustics.inputPreDelay;
+
+ hRenderConfig->roomAcoustics.use_er = 0;
+ IF( EQ_16( renderConfig.roomAcoustics.use_er, 1 ) )
+ {
+ hRenderConfig->roomAcoustics.use_er = renderConfig.roomAcoustics.use_er;
+ hRenderConfig->roomAcoustics.lowComplexity = renderConfig.roomAcoustics.lowComplexity;
+ hRenderConfig->roomAcoustics.dimensions = renderConfig.roomAcoustics.dimensions;
+ hRenderConfig->roomAcoustics.ListenerOrigin = renderConfig.roomAcoustics.ListenerOrigin;
+
+ mvr2r( renderConfig.roomAcoustics.AbsCoeff, hRenderConfig->roomAcoustics.AbsCoeff, IVAS_ROOM_ABS_COEFF );
+ }
+
+ mvr2r( renderConfig.roomAcoustics.pFc_input, hRenderConfig->roomAcoustics.pFc_input, CLDFB_NO_CHANNELS_MAX );
+ mvr2r( renderConfig.roomAcoustics.pAcoustic_rt60, hRenderConfig->roomAcoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX );
+ mvr2r( renderConfig.roomAcoustics.pAcoustic_dsr, hRenderConfig->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX );
+
+ mvr2r( renderConfig.directivity, hRenderConfig->directivity, 3 * MAX_NUM_OBJECTS );
+
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetDelay( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetDelay(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *nSamples, /* o : decoder delay in samples */
+ Word32 *timeScale /* o : time scale of the delay, equal to decoder output sampling rate */
+)
+{
+ Decoder_Struct *st_ivas;
+ DECODER_CONFIG_HANDLE hDecoderConfig;
+ Word32 out_fs_fx;
+
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || nSamples == NULL || timeScale == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ IF( !hIvasDec->hasDecodedFirstGoodFrame )
+ {
+ /* Delay depends on IVAS format, which is unknown until first frame has been decoded */
+ return IVAS_ERR_WAITING_FOR_BITSTREAM;
+ }
+
+ st_ivas = hIvasDec->st_ivas;
+ hDecoderConfig = st_ivas->hDecoderConfig;
+
+ out_fs_fx = ( hDecoderConfig->output_Fs != 48000 ) ? ( ( hDecoderConfig->output_Fs != 32000 ) ? FS_16K_IN_NS_Q31 : FS_32K_IN_NS_Q31 ) : FS_48K_IN_NS_Q31;
+
+ nSamples[1] = NS2SA_fx2( hDecoderConfig->output_Fs, get_delay( DEC, hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->cldfbAnaDec[0] ) );
+ nSamples[2] = (Word16) W_round64_L( W_mult0_32_32( L_shl( st_ivas->binaural_latency_ns, 1 ), out_fs_fx ) );
+ nSamples[0] = add( nSamples[1], nSamples[2] );
+
+ IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) )
+ {
+ /* note: in MASA, all delay is compensated at the decoder by default, so subtract the encoder delay for print-out */
+ nSamples[1] = sub( nSamples[1], NS2SA_fx2( hDecoderConfig->output_Fs, IVAS_ENC_DELAY_NS ) );
+ }
+
+ *timeScale = hDecoderConfig->output_Fs;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_HasDecodedFirstGoodFrame( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_HasDecodedFirstGoodFrame(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ bool *hasDecodedFirstGoodFrame /* o : flag indicating if the decoder has decoded a good frame since it was configured */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hasDecodedFirstGoodFrame == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ *hasDecodedFirstGoodFrame = hIvasDec->hasDecodedFirstGoodFrame;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetPcmFrameSize( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetPcmFrameSize(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word32 *pcmFrameSize /* o : total size of the PCM output frame. This takes into account the number of output channels */
+)
+{
+ IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || pcmFrameSize == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ IF( hIvasDec->hasDecodedFirstGoodFrame )
+ {
+ *pcmFrameSize = hIvasDec->st_ivas->hDecoderConfig->nchan_out * hIvasDec->st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC;
+ }
+ ELSE
+ {
+ *pcmFrameSize = 0;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * isSidFrame( )
+ *
+ * Check if a frame contains a SID
+ *---------------------------------------------------------------------*/
+
+static bool isSidFrame(
+ const UWord16 size )
+{
+ IF( EQ_16( size, ( SID_1k75 / FRAMES_PER_SEC ) ) )
+ {
+ return true; /* AMR-WB SID */
+ }
+ ELSE IF( EQ_16( size, ( SID_2k40 / FRAMES_PER_SEC ) ) )
+ {
+ return true; /* EVS SID */
+ }
+ ELSE IF( EQ_16( size, ( IVAS_SID_5k2 / FRAMES_PER_SEC ) ) )
+ {
+ return true; /* IVAS SID */
+ }
+
+ return false;
+}
+
+static void bsCompactToSerial( const UWord8 *compact, UWord16 *serial, UWord16 num_bits )
+{
+/* Bitstream conversion is not counted towards complexity and memory usage */
+#define WMC_TOOL_SKIP
+ UWord32 i;
+ UWord8 byte = 0;
+ const UWord8 mask = 0x80;
+
+ FOR( i = 0; i < num_bits; ++i )
+ {
+ IF( EQ_16( ( i % 8 ), 0 ) )
+ {
+ byte = compact[L_shr( i, 3 )];
+ }
+
+ serial[i] = shr( s_and( byte, mask ), 7 );
+
+ byte = (UWord8) shl( byte, 1 );
+ }
+
+ /* Add 4 padding bytes required by core coder */
+ FOR( i = 0; i < 4 * 8; ++i )
+ {
+ serial[num_bits + i] = 0;
+ }
+#undef WMC_TOOL_SKIP
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_VoIP_FeedFrame( )
+ *
+ * Feed RTP packet into internal jitter buffer
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_VoIP_FeedFrame(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord8 *au, /* i : buffer containing input access unit */
+ const UWord16 auSize, /* i : size of the access unit */
+ const UWord16 rtpSequenceNumber, /* i : RTP sequence number (16 bits) */
+ const UWord32 rtpTimeStamp, /* i : RTP timestamp (32 bits) */
+ const UWord32 rcvTime_ms, /* i : receive time of the RTP packet in milliseconds */
+ const bool qBit /* i : Q bit for AMR-WB IO */
+)
+{
+ JB4_DATAUNIT_HANDLE dataUnit;
+ Word16 partialCopyFrameType, partialCopyOffset;
+ Word16 result;
+
+ IF( EQ_16( auSize, 0 ) )
+ {
+ return IVAS_ERR_OK; /* ignore empty/NO_DATA frame - shouldn't be transmitted in RTP */
+ }
+ IF( GT_16( shr( add( auSize, 7 ), 3 ), (Word16) MAX_AU_SIZE ) )
+ {
+ return IVAS_ERR_INVALID_BITSTREAM;
+ }
+
+ /* check if frame contains a partial copy and get its offset */
+ evs_dec_previewFrame_float( au, auSize, &partialCopyFrameType, &partialCopyOffset );
+
+ /* create data unit for primary copy in the frame */
+ dataUnit = JB4_AllocDataUnit( hIvasDec->hVoIP->hJBM );
+ mvc2c( au, dataUnit->data, shr( add( auSize, 7 ), 3 ) );
+ dataUnit->dataSize = auSize;
+ dataUnit->duration = 20;
+ dataUnit->sequenceNumber = rtpSequenceNumber;
+ dataUnit->silenceIndicator = isSidFrame( dataUnit->dataSize );
+ dataUnit->timeScale = 1000;
+ dataUnit->rcvTime = rcvTime_ms;
+ dataUnit->timeStamp = rtpTimeStamp;
+ dataUnit->partial_frame = 0;
+ dataUnit->partialCopyOffset = partialCopyOffset;
+ dataUnit->qBit = qBit;
+
+ /* add the frame to the JBM */
+ result = JB4_PushDataUnit( hIvasDec->hVoIP->hJBM, dataUnit, rcvTime_ms );
+ IF( NE_16( result, 0 ) )
+ {
+ return IVAS_ERR_UNKNOWN;
+ }
+
+ IF( NE_16( partialCopyFrameType, RF_NO_DATA ) && NE_16( partialCopyOffset, 0 ) )
+ {
+ /* create data unit for partial copy in the frame */
+ dataUnit = JB4_AllocDataUnit( hIvasDec->hVoIP->hJBM );
+ mvc2c( au, dataUnit->data, shr( add( auSize, 7 ), 3 ) );
+ dataUnit->dataSize = auSize;
+ dataUnit->duration = 20;
+ dataUnit->sequenceNumber = rtpSequenceNumber;
+ dataUnit->silenceIndicator = 0; /* there are no partial copies for SID frames */
+ dataUnit->timeScale = 1000;
+ dataUnit->rcvTime = rcvTime_ms;
+ dataUnit->timeStamp = L_sub( rtpTimeStamp, partialCopyOffset * dataUnit->duration );
+ dataUnit->partial_frame = 1;
+ dataUnit->partialCopyOffset = partialCopyOffset;
+ dataUnit->qBit = qBit;
+
+ /* add the frame to the JBM */
+ result = JB4_PushDataUnit( hIvasDec->hVoIP->hJBM, dataUnit, rcvTime_ms );
+ IF( NE_16( result, 0 ) )
+ {
+ return IVAS_ERR_UNKNOWN;
+ }
+ }
+
+ return IVAS_ERR_OK;
+}
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_VoIP_SetScale( )
+ *
+ * Set the TSM scale
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_VoIP_SetScale(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 maxScaling, /* i : max allowed absolute difference in samples from the default 20ms frame size */
+ const Word16 scale /* i : TSM scale to set in percent of the default frame size */
+)
+{
+ ivas_error error;
+
+ error = IVAS_ERR_OK;
+
+ IF( EQ_16( hIvasDec->st_ivas->hDecoderConfig->Opt_tsm, false ) )
+ {
+ return IVAS_ERR_TSM_NOT_ENABLED;
+ }
+ ELSE
+ {
+ hIvasDec->tsm_scale = scale;
+ hIvasDec->tsm_max_scaling = maxScaling;
+ }
+
+ return error;
+}
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_VoIP_SetScale( )
+ *
+ * Set the TSM scale
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_TSM_SetQuality(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const float quality /* i : target TSM quality */
+)
+{
+ ivas_error error;
+
+ error = IVAS_ERR_OK;
+
+ IF( EQ_16( hIvasDec->st_ivas->hDecoderConfig->Opt_tsm, false ) )
+ {
+ return IVAS_ERR_TSM_NOT_ENABLED;
+ }
+ ELSE
+ {
+ hIvasDec->tsm_quality = quality;
+ }
+
+ return error;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_VoIP_GetSamples( )
+ *
+ * Main function to decode one frame in VoIP
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_VoIP_GetSamples(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ UWord16 nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */
+ Word16 *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */
+ const UWord32 systemTimestamp_ms /* i : current system timestamp */
+#ifdef SUPPORT_JBM_TRACEFILE
+ ,
+ JbmTraceFileWriterFn jbmWriterFn,
+ void *jbmWriter
+#endif
+)
+{
+ Decoder_Struct *st_ivas;
+ DECODER_CONFIG_HANDLE hDecoderConfig;
+ IVAS_DEC_VOIP *hVoIP;
+ UWord32 extBufferedTime_ms, scale, maxScaling;
+ JB4_DATAUNIT_HANDLE dataUnit;
+ UWord16 extBufferedSamples;
+ Word16 timeScalingDone;
+ Word16 result;
+ ivas_error error;
+ Word16 nSamplesRendered;
+ UWord8 nOutChannels;
+
+ st_ivas = hIvasDec->st_ivas;
+ hDecoderConfig = st_ivas->hDecoderConfig;
+ hVoIP = hIvasDec->hVoIP;
+ timeScalingDone = 0;
+ nOutChannels = (UWord8) st_ivas->hDecoderConfig->nchan_out;
+ nSamplesRendered = 0;
+
+ IF( EQ_16( nSamplesPerChannel, 0 ) )
+ {
+ return IVAS_ERR_WRONG_PARAMS;
+ }
+
+ /* make sure that the FIFO after decoder/scaler contains at least one sound card frame (i.e. 20ms) */
+ WHILE( LT_16( nSamplesRendered, nSamplesPerChannel ) )
+ {
+ IF( EQ_16( hIvasDec->nSamplesAvailableNext, 0 ) )
+ {
+ Word16 nSamplesBuffered;
+ nSamplesBuffered = 0;
+ IF( hIvasDec->hasBeenFedFirstGoodFrame )
+ {
+ IF( ( error = IVAS_DEC_GetBufferedNumberOfSamples( hIvasDec, &nSamplesBuffered ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+ extBufferedSamples = add( nSamplesRendered, nSamplesBuffered );
+ extBufferedTime_ms = extBufferedSamples * 1000 / hDecoderConfig->output_Fs;
+ dataUnit = NULL;
+
+ /* pop one access unit from the jitter buffer */
+ result = JB4_PopDataUnit( hVoIP->hJBM, systemTimestamp_ms, extBufferedTime_ms, &dataUnit, &scale, &maxScaling );
+ IF( NE_16( result, 0 ) )
+ {
+ return IVAS_ERR_UNKNOWN;
+ }
+ maxScaling = maxScaling * hDecoderConfig->output_Fs / 1000;
+
+ /* avoid time scaling multiple times in one sound card slot */
+ IF( NE_32( scale, 100U ) )
+ {
+ IF( timeScalingDone )
+ {
+ scale = 100;
+ }
+ ELSE
+ {
+ timeScalingDone = 1;
+ }
+ }
+
+ /* limit scale to range supported by time scaler */
+ IF( LT_32( scale, APA_MIN_SCALE ) )
+ {
+ scale = APA_MIN_SCALE;
+ }
+ ELSE IF( GT_32( scale, APA_MAX_SCALE ) )
+ {
+ scale = APA_MAX_SCALE;
+ }
+
+ IF( ( error = IVAS_DEC_VoIP_SetScale( hIvasDec, (Word16) maxScaling, (Word16) scale ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ /* copy bitstream into decoder state */
+ IF( dataUnit )
+ {
+ hIvasDec->hVoIP->hCurrentDataUnit = dataUnit;
+
+ bsCompactToSerial( dataUnit->data, hIvasDec->hVoIP->bs_conversion_buf, dataUnit->dataSize );
+
+
+ IF( ( error = IVAS_DEC_FeedFrame_Serial( hIvasDec, hIvasDec->hVoIP->bs_conversion_buf, dataUnit->dataSize, 0 ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+ ELSE IF( hIvasDec->hasDecodedFirstGoodFrame )
+ {
+ /* Decoder has been initialized with first good frame - do PLC */
+ IF( ( error = IVAS_DEC_FeedFrame_Serial( hIvasDec, hIvasDec->hVoIP->bs_conversion_buf, 0, 1 ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+#ifdef SUPPORT_JBM_TRACEFILE
+ /* jbmWriterFn and jbmWriter may be NULL if tracefile writing was not requested on CLI */
+ IF( jbmWriterFn != NULL && jbmWriter != NULL )
+ {
+ /* write JBM trace data entry */
+ store_JbmData( hVoIP, dataUnit, systemTimestamp_ms, extBufferedSamples, hDecoderConfig->output_Fs );
+ IF( ( jbmWriterFn( &hVoIP->JbmTraceData, jbmWriter ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "\nError writing JBM Trace data to file\n" );
+ return IVAS_ERR_UNKNOWN;
+ }
+ }
+#endif
+ IF( dataUnit )
+ {
+ IF( NE_16( dataUnit->partial_frame, 0 ) )
+ {
+ hVoIP->lastDecodedWasActive = 1;
+ }
+ ELSE
+ {
+ hVoIP->lastDecodedWasActive = !dataUnit->silenceIndicator;
+ }
+
+ /* data unit memory is no longer used */
+ JB4_FreeDataUnit( hVoIP->hJBM, dataUnit );
+ }
+
+ IF( !hIvasDec->hasBeenFedFirstGoodFrame )
+ {
+ hIvasDec->nSamplesAvailableNext = hIvasDec->nSamplesFrame;
+ hIvasDec->nSamplesRendered = 0;
+ }
+ }
+
+ /* decode */
+ IF( !hIvasDec->hasBeenFedFirstGoodFrame )
+ {
+ /* codec mode to use not known yet - simply output silence */
+ /* directly set output zero */
+ Word16 nSamplesToZero = min( nSamplesPerChannel, hIvasDec->nSamplesAvailableNext );
+ set_s( pcmBuf + nSamplesRendered * nOutChannels, 0, nSamplesToZero * nOutChannels );
+ nSamplesRendered = add( nSamplesRendered, nSamplesToZero );
+ hIvasDec->nSamplesRendered = add( hIvasDec->nSamplesRendered, nSamplesToZero );
+ hIvasDec->nSamplesAvailableNext = sub( hIvasDec->nSamplesAvailableNext, nSamplesToZero );
+ }
+ ELSE
+ {
+ Word16 nSamplesToRender, nSamplesRendered_loop;
+ bool tmp;
+ nSamplesToRender = sub( nSamplesPerChannel, nSamplesRendered );
+
+ /* render IVAS frames directly to the output buffer */
+ IF( ( error = IVAS_DEC_GetSamples( hIvasDec, nSamplesToRender, pcmBuf + nSamplesRendered * nOutChannels, &nSamplesRendered_loop, &tmp ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ nSamplesRendered = add( nSamplesRendered, nSamplesRendered_loop );
+ }
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_VoIP_Flush( )
+ *
+ * Function to flush remaining audio in VoIP
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_Flush(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */
+ Word16 *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */
+ Word16 *nSamplesFlushed /* o : number of samples flushed */
+)
+{
+ ivas_error error;
+ UWord16 nSamplesToRender;
+ UWord16 nSamplesFlushedLocal;
+
+ *nSamplesFlushed = s_min( nSamplesPerChannel, hIvasDec->nSamplesAvailableNext );
+
+ nSamplesToRender = (UWord16) *nSamplesFlushed;
+
+ /* render IVAS frames */
+ error = IVAS_DEC_GetRenderedSamples( hIvasDec, nSamplesToRender, &nSamplesFlushedLocal, &hIvasDec->nSamplesAvailableNext, pcmBuf );
+
+ return error;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_VoIP_IsEmpty( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+bool IVAS_DEC_VoIP_IsEmpty(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const Word16 nSamplesAsked )
+{
+ return ( EQ_16( JB4_bufferedDataUnits( hIvasDec->hVoIP->hJBM ), 0 ) && LT_16( hIvasDec->nSamplesAvailableNext, nSamplesAsked ) );
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_VoIP_Get_CA_offset( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_VoIP_Get_CA_offset(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ Word16 *optimum_offset,
+ Word16 *FEC_hi )
+{
+ IF( ( hIvasDec == NULL || hIvasDec->hVoIP == NULL || hIvasDec->hVoIP->hJBM == NULL ) )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ *optimum_offset = JB4_getFECoffset( hIvasDec->hVoIP->hJBM );
+ *FEC_hi = JB4_FECoffset( hIvasDec->hVoIP->hJBM );
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_Close_VoIP( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static void IVAS_DEC_Close_VoIP(
+ IVAS_DEC_VOIP *hVoIP /* i/o: IVAS decoder handle */
+)
+{
+ JB4_Destroy( &hVoIP->hJBM );
+
+ IF( hVoIP->bs_conversion_buf != NULL )
+ {
+#define WMC_TOOL_SKIP
+ /* Bitstream conversion is not counted towards complexity and memory usage */
+ free( hVoIP->bs_conversion_buf );
+#undef WMC_TOOL_SKIP
+ }
+
+ free( hVoIP );
+
+ return;
+}
+
+
+#ifdef SUPPORT_JBM_TRACEFILE
+/*---------------------------------------------------------------------*
+ * store_JbmData()
+ *
+ * Store JBM trace data entry
+ *---------------------------------------------------------------------*/
+
+static void store_JbmData(
+ IVAS_DEC_VOIP *hVoIP,
+ JB4_DATAUNIT_HANDLE dataUnit,
+ const UWord32 systemTimestamp_ms,
+ const UWord16 extBufferedSamples,
+ const Word32 output_Fs )
+{
+ IVAS_JBM_TRACE_DATA *JbmTraceData;
+
+ IF( hVoIP == NULL )
+ {
+ return;
+ }
+
+ JbmTraceData = &hVoIP->JbmTraceData;
+
+ JbmTraceData->systemTimestamp_ms = systemTimestamp_ms;
+ JbmTraceData->extBufferedSamples = extBufferedSamples;
+ JbmTraceData->lastDecodedWasActive = hVoIP->lastDecodedWasActive;
+ JbmTraceData->output_Fs = output_Fs;
+ JbmTraceData->dataUnit_flag = dataUnit != NULL;
+ IF( dataUnit != NULL )
+ {
+ JbmTraceData->sequenceNumber = dataUnit->sequenceNumber;
+ JbmTraceData->timeStamp = dataUnit->timeStamp;
+ JbmTraceData->rcvTime = dataUnit->rcvTime;
+ JbmTraceData->partial_frame = dataUnit->partial_frame;
+ JbmTraceData->partialCopyOffset = dataUnit->partialCopyOffset;
+ }
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetJbmData()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_GetJbmData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_JBM_TRACE_DATA *JbmTraceData /* o : JBM Trace data */
+
+)
+{
+ IF( hIvasDec->hVoIP == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ *JbmTraceData = hIvasDec->hVoIP->JbmTraceData;
+
+ return IVAS_ERR_OK;
+}
+
+#endif
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_GetErrorMessage( )
+ *
+ * Maps error codes to error description strings
+ *---------------------------------------------------------------------*/
+
+const char *IVAS_DEC_GetErrorMessage(
+ ivas_error error /* i : decoder error code enum */
+)
+{
+ return ivas_error_to_string( error );
+}
+
+
+/*---------------------------------------------------------------------*
+ * get_channel_config()
+ *
+ * Gets a str related to input config
+ *---------------------------------------------------------------------*/
+
+static ivas_error get_channel_config(
+ AUDIO_CONFIG config,
+ Word8 *str )
+{
+ IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_MONO ) )
+ {
+ strcpy( (char *) str, "Mono" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_STEREO ) )
+ {
+ strcpy( (char *) str, "Stereo" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_5_1 ) )
+ {
+ strcpy( (char *) str, "Multichannel 5.1 (CICP6)" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_7_1 ) )
+ {
+ strcpy( (char *) str, "Multichannel 7.1 (CICP12)" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_5_1_2 ) )
+ {
+ strcpy( (char *) str, "Multichannel 5.1+2 (CICP14)" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_5_1_4 ) )
+ {
+ strcpy( (char *) str, "Multichannel 5.1+4 (CICP16)" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_7_1_4 ) )
+ {
+ strcpy( (char *) str, "Multichannel 7.1+4 (CICP19)" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
+ {
+ strcpy( (char *) str, "Multichannel (custom loudspeaker layout)" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_FOA ) )
+ {
+ strcpy( (char *) str, "Ambisonics: First Order (FOA)" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_HOA2 ) )
+ {
+ strcpy( (char *) str, "Ambisonics: Second Order (HOA2)" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_HOA3 ) )
+ {
+ strcpy( (char *) str, "Ambisonics: Third Order (HOA3)" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_BINAURAL ) )
+ {
+ strcpy( (char *) str, "Binaural: no room" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) )
+ {
+ strcpy( (char *) str, "Binaural: room with impulse responses" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
+ {
+ strcpy( (char *) str, "Binaural: room with reverb" );
+ }
+ ELSE IF( EQ_16( (Word16) config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
+ {
+ strcpy( (char *) str, "External renderer" );
+ }
+ ELSE
+ {
+ return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Error: Incorrect Input/Output Configuration" );
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * printConfigInfo_dec( )
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static ivas_error printConfigInfo_dec(
+ Decoder_Struct *st_ivas,
+ const Word16 bitstreamformat,
+ const bool Opt_VOIP,
+ const bool quietModeEnabled )
+{
+ ivas_error error;
+ Word8 config_str[50];
+ AUDIO_CONFIG output_config;
+
+ /*-----------------------------------------------------------------*
+ * Print info on screen
+ *-----------------------------------------------------------------*/
+
+ fprintf( stdout, "\n" );
+
+ /*-----------------------------------------------------------------*
+ * Print output sampling frequency
+ *-----------------------------------------------------------------*/
+
+ fprintf( stdout, "Output sampling rate: %d Hz\n", st_ivas->hDecoderConfig->output_Fs );
+
+ /*-----------------------------------------------------------------*
+ * Print bitrate
+ *-----------------------------------------------------------------*/
+
+ IF( !quietModeEnabled )
+ {
+ IF( !Opt_VOIP )
+ {
+ fprintf( stdout, "Bitrate: %.2f kbps\n", (float) st_ivas->hDecoderConfig->ivas_total_brate / 1000 );
+
+ IF( LE_32( st_ivas->hDecoderConfig->ivas_total_brate, 0 ) )
+ {
+ IF( EQ_16( bitstreamformat, G192 ) )
+ {
+ fprintf( stdout, "Active Bitrate not identified in bitstream file \n" );
+ }
+ ELSE /* MIME */
+ {
+ fprintf( stdout, "Active Bitrate not identified from first MIME frame \n" );
+ }
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Print output configuration
+ *-----------------------------------------------------------------*/
+
+ IF( EQ_16( (Word16) st_ivas->ivas_format, MONO_FORMAT ) )
+ {
+ IF( st_ivas->hDecoderConfig->Opt_non_diegetic_pan )
+ {
+ fprintf( stdout, "Output configuration: mono EVS bit-exact decoding to stereo\n" );
+ fprintf( stdout, "Non-diegetic panning: %.2f\n", st_ivas->hDecoderConfig->non_diegetic_pan_gain * 90.f );
+ }
+ ELSE
+ {
+ fprintf( stdout, "Output configuration: mono EVS bit-exact decoding\n" );
+ }
+ }
+ ELSE
+ {
+ IF( !quietModeEnabled )
+ {
+ IF( EQ_16( (Word16) st_ivas->ivas_format, STEREO_FORMAT ) )
+ {
+ fprintf( stdout, "Input configuration: Stereo\n" );
+ }
+ ELSE IF( EQ_16( (Word16) st_ivas->ivas_format, ISM_FORMAT ) )
+ {
+ IF( EQ_16( (Word16) st_ivas->ism_mode, ISM_MODE_PARAM ) )
+ {
+ fprintf( stdout, "Input configuration: ISM (ParamISM): 2 transport channels\n" );
+ }
+ ELSE
+ {
+ fprintf( stdout, "Input configuration: ISM: %d transport channel(s)\n", st_ivas->nchan_transport );
+ }
+ }
+ ELSE IF( EQ_16( (Word16) st_ivas->ivas_format, SBA_FORMAT ) )
+ {
+ fprintf( stdout, "Input configuration: Scene Based Audio, Ambisonic order %i%s, %d transport channel(s)\n", st_ivas->sba_order, st_ivas->sba_planar ? " (Planar)" : "", st_ivas->nchan_transport );
+ }
+ ELSE IF( EQ_16( (Word16) st_ivas->ivas_format, SBA_ISM_FORMAT ) )
+ {
+ fprintf( stdout, "Input configuration: Combined Scene Based Audio, Ambisonic order %i, with %d Objects \n", st_ivas->sba_order, st_ivas->nchan_ism );
+ }
+ ELSE IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) )
+ {
+ fprintf( stdout, "Input configuration: MASA - %d channel(s)\n", st_ivas->nchan_transport );
+ }
+ ELSE IF( EQ_16( (Word16) st_ivas->ivas_format, MC_FORMAT ) )
+ {
+ IF( ( error = get_channel_config( st_ivas->transport_config, &config_str[0] ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ fprintf( stdout, "Input configuration: %s\n", config_str );
+ }
+ ELSE IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) )
+ {
+ fprintf( stdout, "Input configuration: combined ISM and MASA (%i ISM stream(s)) \n", st_ivas->nchan_ism );
+ }
+ }
+
+ output_config = st_ivas->hDecoderConfig->output_config;
+ get_channel_config( output_config, &config_str[0] );
+ fprintf( stdout, "Output configuration: %s\n", config_str );
+
+ IF( ( EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) )
+ {
+ fprintf( stdout, "Render framesize: %dms\n", get_render_frame_size_ms( st_ivas->hDecoderConfig->render_framesize ) );
+ }
+ IF( st_ivas->hDecoderConfig->Opt_HRTF_binary )
+ {
+ fprintf( stdout, "HRIR/BRIR file: ON\n" );
+ }
+
+ IF( st_ivas->hDecoderConfig->Opt_RendConfigCustom )
+ {
+ fprintf( stdout, "Renderer config. file: ON\n" );
+ }
+
+ IF( st_ivas->hDecoderConfig->Opt_Headrotation )
+ {
+ fprintf( stdout, "Head rotation: ON\n" );
+ }
+
+ IF( st_ivas->hDecoderConfig->Opt_ExternalOrientation )
+ {
+ fprintf( stdout, "External orientation: ON\n" );
+ }
+
+ IF( NE_16( (Word16) st_ivas->hDecoderConfig->orientation_tracking, IVAS_HEAD_ORIENT_TRK_NONE ) )
+ {
+ SWITCH( st_ivas->hDecoderConfig->orientation_tracking )
+ {
+ case IVAS_HEAD_ORIENT_TRK_AVG:
+ fprintf( stdout, "Orientation tracking: AVG\n" );
+ BREAK;
+ case IVAS_HEAD_ORIENT_TRK_REF:
+ fprintf( stdout, "Orientation tracking: REF\n" );
+ BREAK;
+ case IVAS_HEAD_ORIENT_TRK_REF_VEC:
+ fprintf( stdout, "Orientation tracking: REF_VEC\n" );
+ BREAK;
+ case IVAS_HEAD_ORIENT_TRK_REF_VEC_LEV:
+ fprintf( stdout, "Orientation tracking: REF_VEC_LEV\n" );
+ BREAK;
+ default:
+ BREAK;
+ }
+ }
+
+ IF( st_ivas->hDecoderConfig->Opt_non_diegetic_pan )
+ {
+ fprintf( stdout, "Non-diegetic panning: %.2f\n", st_ivas->hDecoderConfig->non_diegetic_pan_gain * 90.f );
+ }
+
+ IF( st_ivas->hDecoderConfig->Opt_dpid_on )
+ {
+ fprintf( stdout, "Directivity pattern: ON\n" );
+ }
+
+ IF( st_ivas->hDecoderConfig->Opt_aeid_on )
+ {
+ fprintf( stdout, "Acoustic environment ID:ON\n" );
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Print TSM mode info
+ *-----------------------------------------------------------------*/
+
+ IF( st_ivas->hDecoderConfig->Opt_tsm )
+ {
+ fprintf( stdout, "TSM mode: ON\n" );
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_PrintConfig( )
+ *
+ * Print decoder set-up info
+ *---------------------------------------------------------------------*/
+
+void IVAS_DEC_PrintConfig(
+ const IVAS_DEC_HANDLE hIvasDec,
+ const bool quietModeEnabled,
+ const bool voipMode )
+{
+ printConfigInfo_dec( hIvasDec->st_ivas, hIvasDec->bitstreamformat, voipMode, quietModeEnabled );
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_PrintDisclaimer( )
+ *
+ * Print IVAS disclaimer to console
+ *---------------------------------------------------------------------*/
+
+void IVAS_DEC_PrintDisclaimer( void )
+{
+ print_disclaimer( stderr );
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * evs_dec_main( )
+ *
+ * EVS codec main decoder fucntion
+ *---------------------------------------------------------------------*/
+
+static ivas_error evs_dec_main(
+ Decoder_Struct *st_ivas,
+ const Word16 nOutSamples,
+ float *floatBuf,
+ Word16 *pcmBuf )
+{
+ DEC_CORE_HANDLE *hCoreCoder;
+ float mixer_left, mixer_rigth;
+ float *p_output[MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN];
+ Word16 ch;
+ ivas_error error;
+
+ hCoreCoder = st_ivas->hSCE[0]->hCoreCoder;
+ hCoreCoder[0]->total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
+ hCoreCoder[0]->total_num_bits = st_ivas->num_bits;
+ hCoreCoder[0]->output_frame_fx = extract_l( Mult_32_16( hCoreCoder[0]->output_Fs, 0x0290 ) );
+ mdct_switching_dec( hCoreCoder[0] );
+
+ FOR( ch = 0; ch < MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN; ch++ )
+ {
+ p_output[ch] = st_ivas->p_output_f[ch];
+ }
+#ifndef EVS_FLOAT
+ Word16 output_16[L_FRAME48k];
+#endif // !EVS_FLOAT
+
+ /* run the main EVS decoding routine */
+ IF( EQ_16( hCoreCoder[0]->codec_mode, MODE1 ) )
+ {
+ IF( hCoreCoder[0]->Opt_AMR_WB )
+ {
+#ifdef EVS_FLOAT
+ IF( ( error = amr_wb_dec_flt( hCoreCoder[0], st_ivas->mem_hp20_out[0], p_output[0] ) ) != IVAS_ERR_OK )
+#else
+ IF( ( error = amr_wb_dec_fx( output_16, hCoreCoder[0] ) ) != IVAS_ERR_OK )
+#endif
+ {
+ return error;
+ }
+ }
+ ELSE
+ {
+#ifdef EVS_FLOAT
+ IF( ( error = evs_dec_flt( hCoreCoder[0], st_ivas->mem_hp20_out[0], p_output[0], FRAMEMODE_NORMAL ) ) != IVAS_ERR_OK )
+#else
+ IF( ( error = evs_dec_fx( hCoreCoder[0], output_16, FRAMEMODE_NORMAL ) ) != IVAS_ERR_OK )
+#endif
+ {
+ return error;
+ }
+ }
+ }
+ ELSE
+ {
+ IF( EQ_16( hCoreCoder[0]->bfi, 0 ) )
+ {
+#ifdef EVS_FLOAT
+ IF( ( error = evs_dec_flt( hCoreCoder[0], st_ivas->mem_hp20_out[0], p_output[0], FRAMEMODE_NORMAL ) ) != IVAS_ERR_OK )
+#else
+ IF( ( error = evs_dec_fx( hCoreCoder[0], output_16, FRAMEMODE_NORMAL ) ) != IVAS_ERR_OK )
+#endif
+ {
+ return error;
+ }
+ }
+ ELSE IF( EQ_16( hCoreCoder[0]->bfi, 2 ) )
+ {
+#ifdef EVS_FLOAT
+ IF( ( error = evs_dec_flt( hCoreCoder[0], st_ivas->mem_hp20_out[0], p_output[0], FRAMEMODE_FUTURE ) ) != IVAS_ERR_OK )
+#else
+ IF( ( error = evs_dec_fx( hCoreCoder[0], output_16, FRAMEMODE_FUTURE ) ) != IVAS_ERR_OK )
+#endif
+ {
+ return error;
+ }
+ }
+ ELSE
+ {
+#ifdef EVS_FLOAT
+ IF( ( error = evs_dec_flt( hCoreCoder[0], st_ivas->mem_hp20_out[0], p_output[0], FRAMEMODE_MISSING ) ) != IVAS_ERR_OK )
+#else
+ IF( ( error = evs_dec_fx( hCoreCoder[0], output_16, FRAMEMODE_MISSING ) ) != IVAS_ERR_OK )
+#endif
+ {
+ return error;
+ }
+ }
+ }
+
+ st_ivas->BER_detect = hCoreCoder[0]->BER_detect;
+ IF( EQ_16( st_ivas->renderer_type, RENDERER_NON_DIEGETIC_DOWNMIX ) )
+ {
+ mixer_left = ( st_ivas->hDecoderConfig->non_diegetic_pan_gain + 1.f ) * 0.5f;
+ mixer_rigth = 1.f - mixer_left;
+ v_multc( p_output[0], mixer_rigth, p_output[1], nOutSamples );
+ v_multc( p_output[0], mixer_left, p_output[0], nOutSamples );
+ }
+#ifndef EVS_FLOAT
+ FOR( Word16 i = 0; i < nOutSamples; i++ )
+ {
+ p_output[0][i] = output_16[i];
+ }
+#endif
+ IF( !st_ivas->hDecoderConfig->Opt_tsm )
+ {
+ ivas_jbm_dec_copy_tc_no_tsm( st_ivas, p_output, nOutSamples );
+ }
+ ELSE IF( floatBuf != NULL )
+ {
+ /* BE workaround */
+ Word16 pcm_buf_local[L_FRAME48k * MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN];
+
+ /* convert 'float' output data to 'short' */
+ ivas_syn_output( p_output, nOutSamples, st_ivas->hDecoderConfig->nchan_out, pcm_buf_local );
+ mvs2r( pcm_buf_local, floatBuf, nOutSamples * st_ivas->hDecoderConfig->nchan_out );
+ }
+ ELSE
+ {
+ ivas_syn_output( p_output, nOutSamples, st_ivas->hDecoderConfig->nchan_out, pcmBuf );
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * input_format_API_to_internal()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static ivas_error input_format_API_to_internal(
+ IVAS_DEC_INPUT_FORMAT input_format,
+ Word16 *bitstream_format_internal,
+ Word16 *sdp_hf_only,
+ const bool is_voip_enabled )
+{
+ SWITCH( input_format )
+ {
+ case IVAS_DEC_INPUT_FORMAT_G192:
+ *bitstream_format_internal = is_voip_enabled ? VOIP_G192_RTP : G192;
+ *sdp_hf_only = 0;
+ BREAK;
+ case IVAS_DEC_INPUT_FORMAT_MIME:
+ *bitstream_format_internal = MIME;
+ *sdp_hf_only = 0;
+ BREAK;
+ case IVAS_DEC_INPUT_FORMAT_RTPDUMP:
+ assert( is_voip_enabled && "RTP dump only supported in VoIP mode" );
+ *bitstream_format_internal = VOIP_RTPDUMP;
+ *sdp_hf_only = 0;
+ BREAK;
+ case IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF:
+ assert( is_voip_enabled && "RTP dump only supported in VoIP mode" );
+ *bitstream_format_internal = VOIP_RTPDUMP;
+ *sdp_hf_only = 1;
+ BREAK;
+ default:
+ return IVAS_ERR_INVALID_BITSTREAM;
+ BREAK;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_VoIP_reconfigure()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static ivas_error IVAS_DEC_VoIP_reconfigure(
+ IVAS_DEC_HANDLE hIvasDec,
+ const UWord16 nTransportChannels,
+ const UWord16 l_ts )
+{
+ Word16 apa_buffer_size;
+
+ apa_buffer_size = hIvasDec->nSamplesFrame;
+
+ IF( hIvasDec->apaExecBuffer == NULL )
+ {
+ DECODER_CONFIG_HANDLE hDecoderConfig;
+
+ IF( hIvasDec->st_ivas->hDecoderConfig->Opt_tsm )
+ {
+ UWord16 wss, css;
+ float startQuality;
+
+ startQuality = hIvasDec->tsm_quality;
+ apa_buffer_size = APA_BUF_PER_CHANNEL;
+
+ /* get current renderer type*/
+ hDecoderConfig = hIvasDec->st_ivas->hDecoderConfig;
+
+ IF( EQ_32( hDecoderConfig->output_Fs, 8000 ) )
+ {
+ wss = 1;
+ css = 1;
+ }
+ ELSE IF( EQ_32( hDecoderConfig->output_Fs, 16000 ) )
+ {
+ wss = 2;
+ css = 1;
+ }
+ ELSE IF( EQ_32( hDecoderConfig->output_Fs, 32000 ) )
+ {
+ wss = 4;
+ css = 2;
+ }
+ ELSE IF( EQ_32( hDecoderConfig->output_Fs, 48000 ) )
+ {
+ wss = 6;
+ css = 3;
+ }
+ ELSE
+ {
+ return IVAS_ERR_INIT_ERROR;
+ }
+
+ IF( NE_32( (Word32) apa_init( &hIvasDec->hTimeScaler, nTransportChannels ), IVAS_ERR_OK ) ||
+ NE_16( (Word16) apa_set_rate( hIvasDec->hTimeScaler, hDecoderConfig->output_Fs ), 0 ) ||
+ NE_16( (Word16) apa_set_complexity_options( hIvasDec->hTimeScaler, wss, css ), 0 ) ||
+ NE_16( (Word16) apa_set_quality( hIvasDec->hTimeScaler, startQuality, 4, 4 ), 0 ) ||
+ NE_16( (Word16) apa_set_renderer_granularity( hIvasDec->hTimeScaler, l_ts ), 0 ) )
+ {
+ return IVAS_ERR_INIT_ERROR;
+ }
+
+ IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) )
+ {
+ IF( NE_16( (Word16) apa_set_evs_compat_mode( hIvasDec->hTimeScaler, true ), 0 ) )
+ {
+ return IVAS_ERR_INIT_ERROR;
+ }
+ }
+
+ IF( ( hIvasDec->apaExecBuffer = malloc( sizeof( float ) * apa_buffer_size * nTransportChannels ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" );
+ }
+
+ set_zero( hIvasDec->apaExecBuffer, apa_buffer_size * nTransportChannels );
+ }
+ }
+ ELSE
+ {
+ IF( hIvasDec->st_ivas->hDecoderConfig->Opt_tsm )
+ {
+ IF( NE_16( (Word16) apa_reconfigure( hIvasDec->hTimeScaler, nTransportChannels, l_ts ), 0 ) )
+ {
+ return IVAS_ERR_INIT_ERROR;
+ }
+ apa_buffer_size = APA_BUF_PER_CHANNEL;
+ free( hIvasDec->apaExecBuffer );
+ IF( ( hIvasDec->apaExecBuffer = malloc( sizeof( float ) * apa_buffer_size * nTransportChannels ) ) == NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" );
+ }
+ set_zero( hIvasDec->apaExecBuffer, apa_buffer_size * nTransportChannels );
+ }
+ /* realloc apa_exe_buffer */
+ }
+
+ hIvasDec->nTransportChannelsOld = nTransportChannels;
+
+ return IVAS_ERR_OK;
+}
+#endif // IVAS_FLOAT_FIXED