| /* |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| /* |
| * isacfix.c |
| * |
| * This C file contains the functions for the ISAC API |
| * |
| */ |
| |
| #include "webrtc/modules/audio_coding/codecs/isac/fix/include/isacfix.h" |
| |
| #include <stdlib.h> |
| |
| #include "webrtc/rtc_base/checks.h" |
| #include "webrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h" |
| #include "webrtc/modules/audio_coding/codecs/isac/fix/source/codec.h" |
| #include "webrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h" |
| #include "webrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h" |
| #include "webrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h" |
| #include "webrtc/modules/audio_coding/codecs/isac/fix/source/structs.h" |
| #include "webrtc/system_wrappers/include/cpu_features_wrapper.h" |
| |
| // Declare function pointers. |
| FilterMaLoopFix WebRtcIsacfix_FilterMaLoopFix; |
| Spec2Time WebRtcIsacfix_Spec2Time; |
| Time2Spec WebRtcIsacfix_Time2Spec; |
| MatrixProduct1 WebRtcIsacfix_MatrixProduct1; |
| MatrixProduct2 WebRtcIsacfix_MatrixProduct2; |
| |
| /* This method assumes that |stream_size_bytes| is in valid range, |
| * i.e. >= 0 && <= STREAM_MAXW16_60MS |
| */ |
| static void InitializeDecoderBitstream(size_t stream_size_bytes, |
| Bitstr_dec* bitstream) { |
| bitstream->W_upper = 0xFFFFFFFF; |
| bitstream->streamval = 0; |
| bitstream->stream_index = 0; |
| bitstream->full = 1; |
| bitstream->stream_size = (stream_size_bytes + 1) >> 1; |
| memset(bitstream->stream, 0, sizeof(bitstream->stream)); |
| } |
| |
| /************************************************************************** |
| * WebRtcIsacfix_AssignSize(...) |
| * |
| * Functions used when malloc is not allowed |
| * Returns number of bytes needed to allocate for iSAC struct. |
| * |
| */ |
| |
| int16_t WebRtcIsacfix_AssignSize(int *sizeinbytes) { |
| *sizeinbytes=sizeof(ISACFIX_SubStruct)*2/sizeof(int16_t); |
| return(0); |
| } |
| |
| /*************************************************************************** |
| * WebRtcIsacfix_Assign(...) |
| * |
| * Functions used when malloc is not allowed |
| * Place struct at given address |
| * |
| * If successful, Return 0, else Return -1 |
| */ |
| |
| int16_t WebRtcIsacfix_Assign(ISACFIX_MainStruct **inst, void *ISACFIX_inst_Addr) { |
| if (ISACFIX_inst_Addr!=NULL) { |
| ISACFIX_SubStruct* self = ISACFIX_inst_Addr; |
| *inst = (ISACFIX_MainStruct*)self; |
| self->errorcode = 0; |
| self->initflag = 0; |
| self->ISACenc_obj.SaveEnc_ptr = NULL; |
| WebRtcIsacfix_InitBandwidthEstimator(&self->bwestimator_obj); |
| return(0); |
| } else { |
| return(-1); |
| } |
| } |
| |
| |
| #ifndef ISACFIX_NO_DYNAMIC_MEM |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_Create(...) |
| * |
| * This function creates a ISAC instance, which will contain the state |
| * information for one coding/decoding channel. |
| * |
| * Input: |
| * - *ISAC_main_inst : a pointer to the coder instance. |
| * |
| * Return value : 0 - Ok |
| * -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_Create(ISACFIX_MainStruct **ISAC_main_inst) |
| { |
| ISACFIX_SubStruct *tempo; |
| tempo = malloc(1 * sizeof(ISACFIX_SubStruct)); |
| *ISAC_main_inst = (ISACFIX_MainStruct *)tempo; |
| if (*ISAC_main_inst!=NULL) { |
| (*(ISACFIX_SubStruct**)ISAC_main_inst)->errorcode = 0; |
| (*(ISACFIX_SubStruct**)ISAC_main_inst)->initflag = 0; |
| (*(ISACFIX_SubStruct**)ISAC_main_inst)->ISACenc_obj.SaveEnc_ptr = NULL; |
| WebRtcSpl_Init(); |
| WebRtcIsacfix_InitBandwidthEstimator(&tempo->bwestimator_obj); |
| return(0); |
| } else { |
| return(-1); |
| } |
| } |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_CreateInternal(...) |
| * |
| * This function creates the memory that is used to store data in the encoder |
| * |
| * Input: |
| * - *ISAC_main_inst : a pointer to the coder instance. |
| * |
| * Return value : 0 - Ok |
| * -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_CreateInternal(ISACFIX_MainStruct *ISAC_main_inst) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* Allocate memory for storing encoder data */ |
| ISAC_inst->ISACenc_obj.SaveEnc_ptr = malloc(1 * sizeof(IsacSaveEncoderData)); |
| |
| if (ISAC_inst->ISACenc_obj.SaveEnc_ptr!=NULL) { |
| return(0); |
| } else { |
| return(-1); |
| } |
| } |
| |
| |
| #endif |
| |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_Free(...) |
| * |
| * This function frees the ISAC instance created at the beginning. |
| * |
| * Input: |
| * - ISAC_main_inst : a ISAC instance. |
| * |
| * Return value : 0 - Ok |
| * -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_Free(ISACFIX_MainStruct *ISAC_main_inst) |
| { |
| free(ISAC_main_inst); |
| return(0); |
| } |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_FreeInternal(...) |
| * |
| * This function frees the internal memory for storing encoder data. |
| * |
| * Input: |
| * - ISAC_main_inst : a ISAC instance. |
| * |
| * Return value : 0 - Ok |
| * -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_FreeInternal(ISACFIX_MainStruct *ISAC_main_inst) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* Release memory */ |
| free(ISAC_inst->ISACenc_obj.SaveEnc_ptr); |
| |
| return(0); |
| } |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_InitNeon(...) |
| * |
| * This function initializes function pointers for ARM Neon platform. |
| */ |
| |
| #if defined(WEBRTC_HAS_NEON) |
| static void WebRtcIsacfix_InitNeon(void) { |
| WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrNeon; |
| WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopNeon; |
| WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeNeon; |
| WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecNeon; |
| WebRtcIsacfix_AllpassFilter2FixDec16 = |
| WebRtcIsacfix_AllpassFilter2FixDec16Neon; |
| WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1Neon; |
| WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2Neon; |
| } |
| #endif |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_InitMIPS(...) |
| * |
| * This function initializes function pointers for MIPS platform. |
| */ |
| |
| #if defined(MIPS32_LE) |
| static void WebRtcIsacfix_InitMIPS(void) { |
| WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrMIPS; |
| WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopMIPS; |
| WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeMIPS; |
| WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecMIPS; |
| WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1MIPS; |
| WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2MIPS; |
| #if defined(MIPS_DSP_R1_LE) |
| WebRtcIsacfix_AllpassFilter2FixDec16 = |
| WebRtcIsacfix_AllpassFilter2FixDec16MIPS; |
| WebRtcIsacfix_HighpassFilterFixDec32 = |
| WebRtcIsacfix_HighpassFilterFixDec32MIPS; |
| #endif |
| #if defined(MIPS_DSP_R2_LE) |
| WebRtcIsacfix_CalculateResidualEnergy = |
| WebRtcIsacfix_CalculateResidualEnergyMIPS; |
| #endif |
| } |
| #endif |
| |
| static void InitFunctionPointers(void) { |
| WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrC; |
| WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopC; |
| WebRtcIsacfix_CalculateResidualEnergy = |
| WebRtcIsacfix_CalculateResidualEnergyC; |
| WebRtcIsacfix_AllpassFilter2FixDec16 = WebRtcIsacfix_AllpassFilter2FixDec16C; |
| WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C; |
| WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecC; |
| WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeC; |
| WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1C; |
| WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2C; |
| |
| #if defined(WEBRTC_HAS_NEON) |
| WebRtcIsacfix_InitNeon(); |
| #endif |
| |
| #if defined(MIPS32_LE) |
| WebRtcIsacfix_InitMIPS(); |
| #endif |
| } |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_EncoderInit(...) |
| * |
| * This function initializes a ISAC instance prior to the encoder calls. |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - CodingMode : 0 -> Bit rate and frame length are automatically |
| * adjusted to available bandwidth on |
| * transmission channel. |
| * 1 -> User sets a frame length and a target bit |
| * rate which is taken as the maximum short-term |
| * average bit rate. |
| * |
| * Return value : 0 - Ok |
| * -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst, |
| int16_t CodingMode) |
| { |
| int k; |
| int16_t statusInit; |
| ISACFIX_SubStruct *ISAC_inst; |
| |
| statusInit = 0; |
| /* typecast pointer to rela structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* flag encoder init */ |
| ISAC_inst->initflag |= 2; |
| |
| if (CodingMode == 0) |
| /* Adaptive mode */ |
| ISAC_inst->ISACenc_obj.new_framelength = INITIAL_FRAMESAMPLES; |
| else if (CodingMode == 1) |
| /* Instantaneous mode */ |
| ISAC_inst->ISACenc_obj.new_framelength = 480; /* default for I-mode */ |
| else { |
| ISAC_inst->errorcode = ISAC_DISALLOWED_CODING_MODE; |
| statusInit = -1; |
| } |
| |
| ISAC_inst->CodingMode = CodingMode; |
| |
| WebRtcIsacfix_InitMaskingEnc(&ISAC_inst->ISACenc_obj.maskfiltstr_obj); |
| WebRtcIsacfix_InitPreFilterbank(&ISAC_inst->ISACenc_obj.prefiltbankstr_obj); |
| WebRtcIsacfix_InitPitchFilter(&ISAC_inst->ISACenc_obj.pitchfiltstr_obj); |
| WebRtcIsacfix_InitPitchAnalysis(&ISAC_inst->ISACenc_obj.pitchanalysisstr_obj); |
| |
| WebRtcIsacfix_InitRateModel(&ISAC_inst->ISACenc_obj.rate_data_obj); |
| |
| |
| ISAC_inst->ISACenc_obj.buffer_index = 0; |
| ISAC_inst->ISACenc_obj.frame_nb = 0; |
| ISAC_inst->ISACenc_obj.BottleNeck = 32000; /* default for I-mode */ |
| ISAC_inst->ISACenc_obj.MaxDelay = 10; /* default for I-mode */ |
| ISAC_inst->ISACenc_obj.current_framesamples = 0; |
| ISAC_inst->ISACenc_obj.s2nr = 0; |
| ISAC_inst->ISACenc_obj.MaxBits = 0; |
| ISAC_inst->ISACenc_obj.bitstr_seed = 4447; |
| ISAC_inst->ISACenc_obj.payloadLimitBytes30 = STREAM_MAXW16_30MS << 1; |
| ISAC_inst->ISACenc_obj.payloadLimitBytes60 = STREAM_MAXW16_60MS << 1; |
| ISAC_inst->ISACenc_obj.maxPayloadBytes = STREAM_MAXW16_60MS << 1; |
| ISAC_inst->ISACenc_obj.maxRateInBytes = STREAM_MAXW16_30MS << 1; |
| ISAC_inst->ISACenc_obj.enforceFrameSize = 0; |
| |
| /* Init the bistream data area to zero */ |
| for (k=0; k<STREAM_MAXW16_60MS; k++){ |
| ISAC_inst->ISACenc_obj.bitstr_obj.stream[k] = 0; |
| } |
| |
| #ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED |
| WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACenc_obj.interpolatorstr_obj); |
| #endif |
| |
| InitFunctionPointers(); |
| |
| return statusInit; |
| } |
| |
| /* Read the given number of bytes of big-endian 16-bit integers from |src| and |
| write them to |dest| in host endian. If |nbytes| is odd, the number of |
| output elements is rounded up, and the least significant byte of the last |
| element is set to 0. */ |
| static void read_be16(const uint8_t* src, size_t nbytes, uint16_t* dest) { |
| size_t i; |
| for (i = 0; i < nbytes / 2; ++i) |
| dest[i] = src[2 * i] << 8 | src[2 * i + 1]; |
| if (nbytes % 2 == 1) |
| dest[nbytes / 2] = src[nbytes - 1] << 8; |
| } |
| |
| /* Read the given number of bytes of host-endian 16-bit integers from |src| and |
| write them to |dest| in big endian. If |nbytes| is odd, the number of source |
| elements is rounded up (but only the most significant byte of the last |
| element is used), and the number of output bytes written will be |
| nbytes + 1. */ |
| static void write_be16(const uint16_t* src, size_t nbytes, uint8_t* dest) { |
| size_t i; |
| for (i = 0; i < nbytes / 2; ++i) { |
| dest[2 * i] = src[i] >> 8; |
| dest[2 * i + 1] = src[i]; |
| } |
| if (nbytes % 2 == 1) { |
| dest[nbytes - 1] = src[nbytes / 2] >> 8; |
| dest[nbytes] = 0; |
| } |
| } |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_Encode(...) |
| * |
| * This function encodes 10ms frame(s) and inserts it into a package. |
| * Input speech length has to be 160 samples (10ms). The encoder buffers those |
| * 10ms frames until it reaches the chosen Framesize (480 or 960 samples |
| * corresponding to 30 or 60 ms frames), and then proceeds to the encoding. |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - speechIn : input speech vector. |
| * |
| * Output: |
| * - encoded : the encoded data vector |
| * |
| * Return value: |
| * : >0 - Length (in bytes) of coded data |
| * : 0 - The buffer didn't reach the chosen framesize |
| * so it keeps buffering speech samples. |
| * : -1 - Error |
| */ |
| |
| int WebRtcIsacfix_Encode(ISACFIX_MainStruct *ISAC_main_inst, |
| const int16_t *speechIn, |
| uint8_t* encoded) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| int stream_len; |
| |
| /* typecast pointer to rela structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| |
| /* check if encoder initiated */ |
| if ((ISAC_inst->initflag & 2) != 2) { |
| ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED; |
| return (-1); |
| } |
| |
| stream_len = WebRtcIsacfix_EncodeImpl((int16_t*)speechIn, |
| &ISAC_inst->ISACenc_obj, |
| &ISAC_inst->bwestimator_obj, |
| ISAC_inst->CodingMode); |
| if (stream_len<0) { |
| ISAC_inst->errorcode = -(int16_t)stream_len; |
| return -1; |
| } |
| |
| write_be16(ISAC_inst->ISACenc_obj.bitstr_obj.stream, (size_t)stream_len, |
| encoded); |
| return stream_len; |
| |
| } |
| |
| |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_EncodeNb(...) |
| * |
| * This function encodes 10ms narrow band (8 kHz sampling) frame(s) and inserts |
| * it into a package. Input speech length has to be 80 samples (10ms). The encoder |
| * interpolates into wide-band (16 kHz sampling) buffers those |
| * 10ms frames until it reaches the chosen Framesize (480 or 960 wide-band samples |
| * corresponding to 30 or 60 ms frames), and then proceeds to the encoding. |
| * |
| * The function is enabled if WEBRTC_ISAC_FIX_NB_CALLS_ENABLED is defined |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - speechIn : input speech vector. |
| * |
| * Output: |
| * - encoded : the encoded data vector |
| * |
| * Return value: |
| * : >0 - Length (in bytes) of coded data |
| * : 0 - The buffer didn't reach the chosen framesize |
| * so it keeps buffering speech samples. |
| * : -1 - Error |
| */ |
| #ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED |
| int16_t WebRtcIsacfix_EncodeNb(ISACFIX_MainStruct *ISAC_main_inst, |
| const int16_t *speechIn, |
| int16_t *encoded) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| int16_t stream_len; |
| int16_t speechInWB[FRAMESAMPLES_10ms]; |
| int16_t Vector_Word16_1[FRAMESAMPLES_10ms/2]; |
| int16_t Vector_Word16_2[FRAMESAMPLES_10ms/2]; |
| |
| int k; |
| |
| |
| /* typecast pointer to rela structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| |
| /* check if encoder initiated */ |
| if ((ISAC_inst->initflag & 2) != 2) { |
| ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED; |
| return (-1); |
| } |
| |
| |
| /* Oversample to WB */ |
| |
| /* Form polyphase signals, and compensate for DC offset */ |
| for (k=0;k<FRAMESAMPLES_10ms/2;k++) { |
| Vector_Word16_1[k] = speechIn[k] + 1; |
| Vector_Word16_2[k] = speechIn[k]; |
| } |
| WebRtcIsacfix_FilterAndCombine2(Vector_Word16_1, Vector_Word16_2, speechInWB, &ISAC_inst->ISACenc_obj.interpolatorstr_obj, FRAMESAMPLES_10ms); |
| |
| |
| /* Encode WB signal */ |
| stream_len = WebRtcIsacfix_EncodeImpl((int16_t*)speechInWB, |
| &ISAC_inst->ISACenc_obj, |
| &ISAC_inst->bwestimator_obj, |
| ISAC_inst->CodingMode); |
| if (stream_len<0) { |
| ISAC_inst->errorcode = - stream_len; |
| return -1; |
| } |
| |
| write_be16(ISAC_inst->ISACenc_obj.bitstr_obj.stream, |
| stream_len, |
| (uint8_t*)encoded); |
| return stream_len; |
| } |
| #endif /* WEBRTC_ISAC_FIX_NB_CALLS_ENABLED */ |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_GetNewBitStream(...) |
| * |
| * This function returns encoded data, with the recieved bwe-index in the |
| * stream. It should always return a complete packet, i.e. only called once |
| * even for 60 msec frames |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - bweIndex : index of bandwidth estimate to put in new bitstream |
| * |
| * Output: |
| * - encoded : the encoded data vector |
| * |
| * Return value: |
| * : >0 - Length (in bytes) of coded data |
| * : -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_GetNewBitStream(ISACFIX_MainStruct *ISAC_main_inst, |
| int16_t bweIndex, |
| float scale, |
| uint8_t* encoded) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| int16_t stream_len; |
| |
| /* typecast pointer to rela structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| |
| /* check if encoder initiated */ |
| if ((ISAC_inst->initflag & 2) != 2) { |
| ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED; |
| return (-1); |
| } |
| |
| stream_len = WebRtcIsacfix_EncodeStoredData(&ISAC_inst->ISACenc_obj, |
| bweIndex, |
| scale); |
| if (stream_len<0) { |
| ISAC_inst->errorcode = - stream_len; |
| return -1; |
| } |
| |
| write_be16(ISAC_inst->ISACenc_obj.bitstr_obj.stream, stream_len, encoded); |
| return stream_len; |
| } |
| |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_DecoderInit(...) |
| * |
| * This function initializes a ISAC instance prior to the decoder calls. |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| */ |
| |
| void WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct *ISAC_main_inst) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| |
| InitFunctionPointers(); |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* flag decoder init */ |
| ISAC_inst->initflag |= 1; |
| |
| WebRtcIsacfix_InitMaskingDec(&ISAC_inst->ISACdec_obj.maskfiltstr_obj); |
| WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACdec_obj.postfiltbankstr_obj); |
| WebRtcIsacfix_InitPitchFilter(&ISAC_inst->ISACdec_obj.pitchfiltstr_obj); |
| |
| /* TS */ |
| WebRtcIsacfix_InitPlc( &ISAC_inst->ISACdec_obj.plcstr_obj ); |
| |
| |
| #ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED |
| WebRtcIsacfix_InitPreFilterbank(&ISAC_inst->ISACdec_obj.decimatorstr_obj); |
| #endif |
| } |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_UpdateBwEstimate1(...) |
| * |
| * This function updates the estimate of the bandwidth. |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - encoded : encoded ISAC frame(s). |
| * - packet_size : size of the packet. |
| * - rtp_seq_number : the RTP number of the packet. |
| * - arr_ts : the arrival time of the packet (from NetEq) |
| * in samples. |
| * |
| * Return value : 0 - Ok |
| * -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct *ISAC_main_inst, |
| const uint8_t* encoded, |
| size_t packet_size, |
| uint16_t rtp_seq_number, |
| uint32_t arr_ts) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| Bitstr_dec streamdata; |
| int16_t err; |
| const size_t kRequiredEncodedLenBytes = 10; |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* Sanity check of packet length */ |
| if (packet_size == 0) { |
| /* return error code if the packet length is null or less */ |
| ISAC_inst->errorcode = ISAC_EMPTY_PACKET; |
| return -1; |
| } else if (packet_size > (STREAM_MAXW16<<1)) { |
| /* return error code if length of stream is too long */ |
| ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH; |
| return -1; |
| } |
| |
| /* check if decoder initiated */ |
| if ((ISAC_inst->initflag & 1) != 1) { |
| ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED; |
| return (-1); |
| } |
| |
| InitializeDecoderBitstream(packet_size, &streamdata); |
| |
| read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream); |
| |
| err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj, |
| &streamdata, |
| packet_size, |
| rtp_seq_number, |
| 0, |
| arr_ts); |
| |
| |
| if (err < 0) |
| { |
| /* return error code if something went wrong */ |
| ISAC_inst->errorcode = -err; |
| return -1; |
| } |
| |
| |
| return 0; |
| } |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_UpdateBwEstimate(...) |
| * |
| * This function updates the estimate of the bandwidth. |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - encoded : encoded ISAC frame(s). |
| * - packet_size : size of the packet. |
| * - rtp_seq_number : the RTP number of the packet. |
| * - send_ts : Send Time Stamp from RTP header |
| * - arr_ts : the arrival time of the packet (from NetEq) |
| * in samples. |
| * |
| * Return value : 0 - Ok |
| * -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst, |
| const uint8_t* encoded, |
| size_t packet_size, |
| uint16_t rtp_seq_number, |
| uint32_t send_ts, |
| uint32_t arr_ts) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| Bitstr_dec streamdata; |
| int16_t err; |
| const size_t kRequiredEncodedLenBytes = 10; |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* Sanity check of packet length */ |
| if (packet_size == 0) { |
| /* return error code if the packet length is null or less */ |
| ISAC_inst->errorcode = ISAC_EMPTY_PACKET; |
| return -1; |
| } else if (packet_size < kRequiredEncodedLenBytes) { |
| ISAC_inst->errorcode = ISAC_PACKET_TOO_SHORT; |
| return -1; |
| } else if (packet_size > (STREAM_MAXW16<<1)) { |
| /* return error code if length of stream is too long */ |
| ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH; |
| return -1; |
| } |
| |
| /* check if decoder initiated */ |
| if ((ISAC_inst->initflag & 1) != 1) { |
| ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED; |
| return (-1); |
| } |
| |
| InitializeDecoderBitstream(packet_size, &streamdata); |
| |
| read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream); |
| |
| err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj, |
| &streamdata, |
| packet_size, |
| rtp_seq_number, |
| send_ts, |
| arr_ts); |
| |
| if (err < 0) |
| { |
| /* return error code if something went wrong */ |
| ISAC_inst->errorcode = -err; |
| return -1; |
| } |
| |
| |
| return 0; |
| } |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_Decode(...) |
| * |
| * This function decodes a ISAC frame. Output speech length |
| * will be a multiple of 480 samples: 480 or 960 samples, |
| * depending on the framesize (30 or 60 ms). |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - encoded : encoded ISAC frame(s) |
| * - len : bytes in encoded vector |
| * |
| * Output: |
| * - decoded : The decoded vector |
| * |
| * Return value : >0 - number of samples in decoded vector |
| * -1 - Error |
| */ |
| |
| |
| int WebRtcIsacfix_Decode(ISACFIX_MainStruct* ISAC_main_inst, |
| const uint8_t* encoded, |
| size_t len, |
| int16_t* decoded, |
| int16_t* speechType) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| /* number of samples (480 or 960), output from decoder */ |
| /* that were actually used in the encoder/decoder (determined on the fly) */ |
| size_t number_of_samples; |
| int declen_int = 0; |
| size_t declen; |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* check if decoder initiated */ |
| if ((ISAC_inst->initflag & 1) != 1) { |
| ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED; |
| return (-1); |
| } |
| |
| /* Sanity check of packet length */ |
| if (len == 0) { |
| /* return error code if the packet length is null or less */ |
| ISAC_inst->errorcode = ISAC_EMPTY_PACKET; |
| return -1; |
| } else if (len > (STREAM_MAXW16<<1)) { |
| /* return error code if length of stream is too long */ |
| ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH; |
| return -1; |
| } |
| |
| InitializeDecoderBitstream(len, &ISAC_inst->ISACdec_obj.bitstr_obj); |
| |
| read_be16(encoded, len, ISAC_inst->ISACdec_obj.bitstr_obj.stream); |
| |
| /* added for NetEq purposes (VAD/DTX related) */ |
| *speechType=1; |
| |
| declen_int = WebRtcIsacfix_DecodeImpl(decoded, &ISAC_inst->ISACdec_obj, |
| &number_of_samples); |
| if (declen_int < 0) { |
| /* Some error inside the decoder */ |
| ISAC_inst->errorcode = -(int16_t)declen_int; |
| memset(decoded, 0, sizeof(int16_t) * MAX_FRAMESAMPLES); |
| return -1; |
| } |
| declen = (size_t)declen_int; |
| |
| /* error check */ |
| |
| if (declen & 1) { |
| if (len != declen && |
| len != declen + |
| ((ISAC_inst->ISACdec_obj.bitstr_obj.stream[declen >> 1]) & 0xFF)) { |
| ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH; |
| memset(decoded, 0, sizeof(int16_t) * number_of_samples); |
| return -1; |
| } |
| } else { |
| if (len != declen && |
| len != declen + |
| ((ISAC_inst->ISACdec_obj.bitstr_obj.stream[declen >> 1]) >> 8)) { |
| ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH; |
| memset(decoded, 0, sizeof(int16_t) * number_of_samples); |
| return -1; |
| } |
| } |
| |
| return (int)number_of_samples; |
| } |
| |
| |
| |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_DecodeNb(...) |
| * |
| * This function decodes a ISAC frame in narrow-band (8 kHz sampling). |
| * Output speech length will be a multiple of 240 samples: 240 or 480 samples, |
| * depending on the framesize (30 or 60 ms). |
| * |
| * The function is enabled if WEBRTC_ISAC_FIX_NB_CALLS_ENABLED is defined |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - encoded : encoded ISAC frame(s) |
| * - len : bytes in encoded vector |
| * |
| * Output: |
| * - decoded : The decoded vector |
| * |
| * Return value : >0 - number of samples in decoded vector |
| * -1 - Error |
| */ |
| |
| #ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED |
| int WebRtcIsacfix_DecodeNb(ISACFIX_MainStruct* ISAC_main_inst, |
| const uint16_t* encoded, |
| size_t len, |
| int16_t* decoded, |
| int16_t* speechType) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| /* twice the number of samples (480 or 960), output from decoder */ |
| /* that were actually used in the encoder/decoder (determined on the fly) */ |
| size_t number_of_samples; |
| int declen_int = 0; |
| size_t declen; |
| int16_t dummy[FRAMESAMPLES/2]; |
| |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* check if decoder initiated */ |
| if ((ISAC_inst->initflag & 1) != 1) { |
| ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED; |
| return (-1); |
| } |
| |
| if (len == 0) { |
| /* return error code if the packet length is null or less */ |
| ISAC_inst->errorcode = ISAC_EMPTY_PACKET; |
| return -1; |
| } else if (len > (STREAM_MAXW16<<1)) { |
| /* return error code if length of stream is too long */ |
| ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH; |
| return -1; |
| } |
| |
| InitializeDecoderBitstream(len, &ISAC_inst->ISACdec_obj.bitstr_obj); |
| |
| read_be16(encoded, len, ISAC_inst->ISACdec_obj.bitstr_obj.stream); |
| |
| /* added for NetEq purposes (VAD/DTX related) */ |
| *speechType=1; |
| |
| declen_int = WebRtcIsacfix_DecodeImpl(decoded, &ISAC_inst->ISACdec_obj, |
| &number_of_samples); |
| if (declen_int < 0) { |
| /* Some error inside the decoder */ |
| ISAC_inst->errorcode = -(int16_t)declen_int; |
| memset(decoded, 0, sizeof(int16_t) * FRAMESAMPLES); |
| return -1; |
| } |
| declen = (size_t)declen_int; |
| |
| /* error check */ |
| |
| if (declen & 1) { |
| if (len != declen && |
| len != declen + |
| ((ISAC_inst->ISACdec_obj.bitstr_obj.stream[declen >> 1]) & 0xFF)) { |
| ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH; |
| memset(decoded, 0, sizeof(int16_t) * number_of_samples); |
| return -1; |
| } |
| } else { |
| if (len != declen && |
| len != declen + |
| ((ISAC_inst->ISACdec_obj.bitstr_obj.stream[declen >>1]) >> 8)) { |
| ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH; |
| memset(decoded, 0, sizeof(int16_t) * number_of_samples); |
| return -1; |
| } |
| } |
| |
| WebRtcIsacfix_SplitAndFilter2(decoded, decoded, dummy, &ISAC_inst->ISACdec_obj.decimatorstr_obj); |
| |
| if (number_of_samples>FRAMESAMPLES) { |
| WebRtcIsacfix_SplitAndFilter2(decoded + FRAMESAMPLES, decoded + FRAMESAMPLES/2, |
| dummy, &ISAC_inst->ISACdec_obj.decimatorstr_obj); |
| } |
| |
| return (int)(number_of_samples / 2); |
| } |
| #endif /* WEBRTC_ISAC_FIX_NB_CALLS_ENABLED */ |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_DecodePlcNb(...) |
| * |
| * This function conducts PLC for ISAC frame(s) in narrow-band (8kHz sampling). |
| * Output speech length will be "240*noOfLostFrames" samples |
| * that is equevalent of "30*noOfLostFrames" millisecond. |
| * |
| * The function is enabled if WEBRTC_ISAC_FIX_NB_CALLS_ENABLED is defined |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - noOfLostFrames : Number of PLC frames (240 sample=30ms) to produce |
| * |
| * Output: |
| * - decoded : The decoded vector |
| * |
| * Return value : Number of samples in decoded PLC vector |
| */ |
| |
| #ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED |
| size_t WebRtcIsacfix_DecodePlcNb(ISACFIX_MainStruct* ISAC_main_inst, |
| int16_t* decoded, |
| size_t noOfLostFrames ) |
| { |
| size_t no_of_samples, declen, k; |
| int16_t outframeNB[FRAMESAMPLES]; |
| int16_t outframeWB[FRAMESAMPLES]; |
| int16_t dummy[FRAMESAMPLES/2]; |
| |
| |
| ISACFIX_SubStruct *ISAC_inst; |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* Limit number of frames to two = 60 msec. Otherwise we exceed data vectors */ |
| if (noOfLostFrames > 2){ |
| noOfLostFrames = 2; |
| } |
| |
| k = 0; |
| declen = 0; |
| while( noOfLostFrames > 0 ) |
| { |
| WebRtcIsacfix_DecodePlcImpl(outframeWB, &ISAC_inst->ISACdec_obj, |
| &no_of_samples); |
| |
| WebRtcIsacfix_SplitAndFilter2(outframeWB, &(outframeNB[k*240]), dummy, &ISAC_inst->ISACdec_obj.decimatorstr_obj); |
| |
| declen += no_of_samples; |
| noOfLostFrames--; |
| k++; |
| } |
| |
| declen>>=1; |
| |
| for (k=0;k<declen;k++) { |
| decoded[k] = outframeNB[k]; |
| } |
| |
| return declen; |
| } |
| #endif /* WEBRTC_ISAC_FIX_NB_CALLS_ENABLED */ |
| |
| |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_DecodePlc(...) |
| * |
| * This function conducts PLC for ISAC frame(s) in wide-band (16kHz sampling). |
| * Output speech length will be "480*noOfLostFrames" samples |
| * that is equevalent of "30*noOfLostFrames" millisecond. |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - noOfLostFrames : Number of PLC frames (480sample = 30ms) |
| * to produce |
| * |
| * Output: |
| * - decoded : The decoded vector |
| * |
| * Return value : Number of samples in decoded PLC vector |
| */ |
| |
| size_t WebRtcIsacfix_DecodePlc(ISACFIX_MainStruct* ISAC_main_inst, |
| int16_t* decoded, |
| size_t noOfLostFrames) |
| { |
| |
| size_t no_of_samples, declen, k; |
| int16_t outframe16[MAX_FRAMESAMPLES]; |
| |
| ISACFIX_SubStruct *ISAC_inst; |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* Limit number of frames to two = 60 msec. Otherwise we exceed data vectors */ |
| if (noOfLostFrames > 2) { |
| noOfLostFrames = 2; |
| } |
| k = 0; |
| declen = 0; |
| while( noOfLostFrames > 0 ) |
| { |
| WebRtcIsacfix_DecodePlcImpl(&(outframe16[k*480]), &ISAC_inst->ISACdec_obj, |
| &no_of_samples); |
| declen += no_of_samples; |
| noOfLostFrames--; |
| k++; |
| } |
| |
| for (k=0;k<declen;k++) { |
| decoded[k] = outframe16[k]; |
| } |
| |
| return declen; |
| } |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_Control(...) |
| * |
| * This function sets the limit on the short-term average bit rate and the |
| * frame length. Should be used only in Instantaneous mode. |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - rate : limit on the short-term average bit rate, |
| * in bits/second (between 10000 and 32000) |
| * - framesize : number of milliseconds per frame (30 or 60) |
| * |
| * Return value : 0 - ok |
| * -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_Control(ISACFIX_MainStruct *ISAC_main_inst, |
| int16_t rate, |
| int framesize) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| if (ISAC_inst->CodingMode == 0) |
| { |
| /* in adaptive mode */ |
| ISAC_inst->errorcode = ISAC_MODE_MISMATCH; |
| return -1; |
| } |
| |
| |
| if (rate >= 10000 && rate <= 32000) |
| ISAC_inst->ISACenc_obj.BottleNeck = rate; |
| else { |
| ISAC_inst->errorcode = ISAC_DISALLOWED_BOTTLENECK; |
| return -1; |
| } |
| |
| |
| |
| if (framesize == 30 || framesize == 60) |
| ISAC_inst->ISACenc_obj.new_framelength = (int16_t)((FS/1000) * framesize); |
| else { |
| ISAC_inst->errorcode = ISAC_DISALLOWED_FRAME_LENGTH; |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| void WebRtcIsacfix_SetInitialBweBottleneck(ISACFIX_MainStruct* ISAC_main_inst, |
| int bottleneck_bits_per_second) { |
| ISACFIX_SubStruct* inst = (ISACFIX_SubStruct*)ISAC_main_inst; |
| RTC_DCHECK_GE(bottleneck_bits_per_second, 10000); |
| RTC_DCHECK_LE(bottleneck_bits_per_second, 32000); |
| inst->bwestimator_obj.sendBwAvg = ((uint32_t)bottleneck_bits_per_second) << 7; |
| } |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_ControlBwe(...) |
| * |
| * This function sets the initial values of bottleneck and frame-size if |
| * iSAC is used in channel-adaptive mode. Through this API, users can |
| * enforce a frame-size for all values of bottleneck. Then iSAC will not |
| * automatically change the frame-size. |
| * |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance. |
| * - rateBPS : initial value of bottleneck in bits/second |
| * 10000 <= rateBPS <= 32000 is accepted |
| * For default bottleneck set rateBPS = 0 |
| * - frameSizeMs : number of milliseconds per frame (30 or 60) |
| * - enforceFrameSize : 1 to enforce the given frame-size through out |
| * the adaptation process, 0 to let iSAC change |
| * the frame-size if required. |
| * |
| * Return value : 0 - ok |
| * -1 - Error |
| */ |
| |
| int16_t WebRtcIsacfix_ControlBwe(ISACFIX_MainStruct *ISAC_main_inst, |
| int16_t rateBPS, |
| int frameSizeMs, |
| int16_t enforceFrameSize) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| /* Typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* check if encoder initiated */ |
| if ((ISAC_inst->initflag & 2) != 2) { |
| ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED; |
| return (-1); |
| } |
| |
| /* Check that we are in channel-adaptive mode, otherwise, return -1 */ |
| if (ISAC_inst->CodingMode != 0) { |
| ISAC_inst->errorcode = ISAC_MODE_MISMATCH; |
| return (-1); |
| } |
| |
| /* Set struct variable if enforceFrameSize is set. ISAC will then keep the */ |
| /* chosen frame size. */ |
| ISAC_inst->ISACenc_obj.enforceFrameSize = (enforceFrameSize != 0)? 1:0; |
| |
| /* Set initial rate, if value between 10000 and 32000, */ |
| /* if rateBPS is 0, keep the default initial bottleneck value (15000) */ |
| if ((rateBPS >= 10000) && (rateBPS <= 32000)) { |
| ISAC_inst->bwestimator_obj.sendBwAvg = (((uint32_t)rateBPS) << 7); |
| } else if (rateBPS != 0) { |
| ISAC_inst->errorcode = ISAC_DISALLOWED_BOTTLENECK; |
| return -1; |
| } |
| |
| /* Set initial framesize. If enforceFrameSize is set the frame size will not change */ |
| if ((frameSizeMs == 30) || (frameSizeMs == 60)) { |
| ISAC_inst->ISACenc_obj.new_framelength = (int16_t)((FS/1000) * frameSizeMs); |
| } else { |
| ISAC_inst->errorcode = ISAC_DISALLOWED_FRAME_LENGTH; |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_GetDownLinkBwIndex(...) |
| * |
| * This function returns index representing the Bandwidth estimate from |
| * other side to this side. |
| * |
| * Input: |
| * - ISAC_main_inst: iSAC struct |
| * |
| * Output: |
| * - rateIndex : Bandwidth estimate to transmit to other side. |
| * |
| */ |
| |
| int16_t WebRtcIsacfix_GetDownLinkBwIndex(ISACFIX_MainStruct* ISAC_main_inst, |
| int16_t* rateIndex) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* Call function to get Bandwidth Estimate */ |
| *rateIndex = WebRtcIsacfix_GetDownlinkBwIndexImpl(&ISAC_inst->bwestimator_obj); |
| |
| return 0; |
| } |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_UpdateUplinkBw(...) |
| * |
| * This function takes an index representing the Bandwidth estimate from |
| * this side to other side and updates BWE. |
| * |
| * Input: |
| * - ISAC_main_inst: iSAC struct |
| * - rateIndex : Bandwidth estimate from other side. |
| * |
| */ |
| |
| int16_t WebRtcIsacfix_UpdateUplinkBw(ISACFIX_MainStruct* ISAC_main_inst, |
| int16_t rateIndex) |
| { |
| int16_t err = 0; |
| ISACFIX_SubStruct *ISAC_inst; |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| /* Call function to update BWE with received Bandwidth Estimate */ |
| err = WebRtcIsacfix_UpdateUplinkBwRec(&ISAC_inst->bwestimator_obj, rateIndex); |
| if (err < 0) { |
| ISAC_inst->errorcode = -err; |
| return (-1); |
| } |
| |
| return 0; |
| } |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_ReadFrameLen(...) |
| * |
| * This function returns the length of the frame represented in the packet. |
| * |
| * Input: |
| * - encoded : Encoded bitstream |
| * |
| * Output: |
| * - frameLength : Length of frame in packet (in samples) |
| * |
| */ |
| |
| int16_t WebRtcIsacfix_ReadFrameLen(const uint8_t* encoded, |
| size_t encoded_len_bytes, |
| size_t* frameLength) |
| { |
| Bitstr_dec streamdata; |
| int16_t err; |
| const size_t kRequiredEncodedLenBytes = 10; |
| |
| if (encoded_len_bytes < kRequiredEncodedLenBytes) { |
| return -1; |
| } |
| |
| InitializeDecoderBitstream(encoded_len_bytes, &streamdata); |
| |
| read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream); |
| |
| /* decode frame length */ |
| err = WebRtcIsacfix_DecodeFrameLen(&streamdata, frameLength); |
| if (err<0) // error check |
| return err; |
| |
| return 0; |
| } |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_ReadBwIndex(...) |
| * |
| * This function returns the index of the Bandwidth estimate from the bitstream. |
| * |
| * Input: |
| * - encoded : Encoded bitstream |
| * |
| * Output: |
| * - frameLength : Length of frame in packet (in samples) |
| * - rateIndex : Bandwidth estimate in bitstream |
| * |
| */ |
| |
| int16_t WebRtcIsacfix_ReadBwIndex(const uint8_t* encoded, |
| size_t encoded_len_bytes, |
| int16_t* rateIndex) |
| { |
| Bitstr_dec streamdata; |
| int16_t err; |
| const size_t kRequiredEncodedLenBytes = 10; |
| |
| if (encoded_len_bytes < kRequiredEncodedLenBytes) { |
| return -1; |
| } |
| |
| InitializeDecoderBitstream(encoded_len_bytes, &streamdata); |
| |
| read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream); |
| |
| /* decode frame length, needed to get to the rateIndex in the bitstream */ |
| size_t frameLength; |
| err = WebRtcIsacfix_DecodeFrameLen(&streamdata, &frameLength); |
| if (err<0) // error check |
| return err; |
| |
| /* decode BW estimation */ |
| err = WebRtcIsacfix_DecodeSendBandwidth(&streamdata, rateIndex); |
| if (err<0) // error check |
| return err; |
| |
| return 0; |
| } |
| |
| |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_GetErrorCode(...) |
| * |
| * This function can be used to check the error code of an iSAC instance. When |
| * a function returns -1 a error code will be set for that instance. The |
| * function below extract the code of the last error that occured in the |
| * specified instance. |
| * |
| * Input: |
| * - ISAC_main_inst : ISAC instance |
| * |
| * Return value : Error code |
| */ |
| |
| int16_t WebRtcIsacfix_GetErrorCode(ISACFIX_MainStruct *ISAC_main_inst) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| return ISAC_inst->errorcode; |
| } |
| |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_GetUplinkBw(...) |
| * |
| * This function returns the inst quantized iSAC send bitrate |
| * |
| * Input: |
| * - ISAC_main_inst : iSAC instance |
| * |
| * Return value : bitrate |
| */ |
| |
| int32_t WebRtcIsacfix_GetUplinkBw(ISACFIX_MainStruct *ISAC_main_inst) |
| { |
| ISACFIX_SubStruct *ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| BwEstimatorstr * bw = (BwEstimatorstr*)&(ISAC_inst->bwestimator_obj); |
| |
| return (int32_t) WebRtcIsacfix_GetUplinkBandwidth(bw); |
| } |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_GetNewFrameLen(...) |
| * |
| * This function return the next frame length (in samples) of iSAC. |
| * |
| * Input: |
| * - ISAC_main_inst : iSAC instance |
| * |
| * Return value : frame lenght in samples |
| */ |
| |
| int16_t WebRtcIsacfix_GetNewFrameLen(ISACFIX_MainStruct *ISAC_main_inst) |
| { |
| ISACFIX_SubStruct *ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| return ISAC_inst->ISACenc_obj.new_framelength; |
| } |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_SetMaxPayloadSize(...) |
| * |
| * This function sets a limit for the maximum payload size of iSAC. The same |
| * value is used both for 30 and 60 msec packets. |
| * The absolute max will be valid until next time the function is called. |
| * NOTE! This function may override the function WebRtcIsacfix_SetMaxRate() |
| * |
| * Input: |
| * - ISAC_main_inst : iSAC instance |
| * - maxPayloadBytes : maximum size of the payload in bytes |
| * valid values are between 100 and 400 bytes |
| * |
| * |
| * Return value : 0 if sucessful |
| * -1 if error happens |
| */ |
| |
| int16_t WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_MainStruct *ISAC_main_inst, |
| int16_t maxPayloadBytes) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| if((maxPayloadBytes < 100) || (maxPayloadBytes > 400)) |
| { |
| /* maxPayloadBytes is out of valid range */ |
| return -1; |
| } |
| else |
| { |
| /* Set new absolute max, which will not change unless this function |
| is called again with a new value */ |
| ISAC_inst->ISACenc_obj.maxPayloadBytes = maxPayloadBytes; |
| |
| /* Set new maximum values for 30 and 60 msec packets */ |
| if (maxPayloadBytes < ISAC_inst->ISACenc_obj.maxRateInBytes) { |
| ISAC_inst->ISACenc_obj.payloadLimitBytes30 = maxPayloadBytes; |
| } else { |
| ISAC_inst->ISACenc_obj.payloadLimitBytes30 = ISAC_inst->ISACenc_obj.maxRateInBytes; |
| } |
| |
| if ( maxPayloadBytes < (ISAC_inst->ISACenc_obj.maxRateInBytes << 1)) { |
| ISAC_inst->ISACenc_obj.payloadLimitBytes60 = maxPayloadBytes; |
| } else { |
| ISAC_inst->ISACenc_obj.payloadLimitBytes60 = (ISAC_inst->ISACenc_obj.maxRateInBytes << 1); |
| } |
| } |
| return 0; |
| } |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_SetMaxRate(...) |
| * |
| * This function sets the maximum rate which the codec may not exceed for a |
| * singel packet. The maximum rate is set in bits per second. |
| * The codec has an absolute maximum rate of 53400 bits per second (200 bytes |
| * per 30 msec). |
| * It is possible to set a maximum rate between 32000 and 53400 bits per second. |
| * |
| * The rate limit is valid until next time the function is called. |
| * |
| * NOTE! Packet size will never go above the value set if calling |
| * WebRtcIsacfix_SetMaxPayloadSize() (default max packet size is 400 bytes). |
| * |
| * Input: |
| * - ISAC_main_inst : iSAC instance |
| * - maxRateInBytes : maximum rate in bits per second, |
| * valid values are 32000 to 53400 bits |
| * |
| * Return value : 0 if sucessful |
| * -1 if error happens |
| */ |
| |
| int16_t WebRtcIsacfix_SetMaxRate(ISACFIX_MainStruct *ISAC_main_inst, |
| int32_t maxRate) |
| { |
| ISACFIX_SubStruct *ISAC_inst; |
| int16_t maxRateInBytes; |
| |
| /* typecast pointer to real structure */ |
| ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; |
| |
| if((maxRate < 32000) || (maxRate > 53400)) |
| { |
| /* maxRate is out of valid range */ |
| return -1; |
| } |
| else |
| { |
| /* Calculate maximum number of bytes per 30 msec packets for the given |
| maximum rate. Multiply with 30/1000 to get number of bits per 30 msec, |
| divide by 8 to get number of bytes per 30 msec: |
| maxRateInBytes = floor((maxRate * 30/1000) / 8); */ |
| maxRateInBytes = (int16_t)( WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_MUL(maxRate, 3), 800) ); |
| |
| /* Store the value for usage in the WebRtcIsacfix_SetMaxPayloadSize-function */ |
| ISAC_inst->ISACenc_obj.maxRateInBytes = maxRateInBytes; |
| |
| /* For 30 msec packets: if the new limit is below the maximum |
| payload size, set a new limit */ |
| if (maxRateInBytes < ISAC_inst->ISACenc_obj.maxPayloadBytes) { |
| ISAC_inst->ISACenc_obj.payloadLimitBytes30 = maxRateInBytes; |
| } else { |
| ISAC_inst->ISACenc_obj.payloadLimitBytes30 = ISAC_inst->ISACenc_obj.maxPayloadBytes; |
| } |
| |
| /* For 60 msec packets: if the new limit (times 2) is below the |
| maximum payload size, set a new limit */ |
| if ( (maxRateInBytes << 1) < ISAC_inst->ISACenc_obj.maxPayloadBytes) { |
| ISAC_inst->ISACenc_obj.payloadLimitBytes60 = (maxRateInBytes << 1); |
| } else { |
| ISAC_inst->ISACenc_obj.payloadLimitBytes60 = ISAC_inst->ISACenc_obj.maxPayloadBytes; |
| } |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| /**************************************************************************** |
| * WebRtcIsacfix_version(...) |
| * |
| * This function returns the version number. |
| * |
| * Output: |
| * - version : Pointer to character string |
| * |
| */ |
| |
| void WebRtcIsacfix_version(char *version) |
| { |
| strcpy(version, "3.6.0"); |
| } |
| |
| void WebRtcIsacfix_GetBandwidthInfo(ISACFIX_MainStruct* ISAC_main_inst, |
| IsacBandwidthInfo* bwinfo) { |
| ISACFIX_SubStruct* inst = (ISACFIX_SubStruct*)ISAC_main_inst; |
| RTC_DCHECK_NE(0, inst->initflag & 1); // Decoder initialized. |
| WebRtcIsacfixBw_GetBandwidthInfo(&inst->bwestimator_obj, bwinfo); |
| } |
| |
| void WebRtcIsacfix_SetBandwidthInfo(ISACFIX_MainStruct* ISAC_main_inst, |
| const IsacBandwidthInfo* bwinfo) { |
| ISACFIX_SubStruct* inst = (ISACFIX_SubStruct*)ISAC_main_inst; |
| RTC_DCHECK_NE(0, inst->initflag & 2); // Encoder initialized. |
| WebRtcIsacfixBw_SetBandwidthInfo(&inst->bwestimator_obj, bwinfo); |
| } |