| /* | |
| * 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. | |
| */ | |
| /****************************************************************** | |
| iLBC Speech Coder ANSI-C Source Code | |
| iLBCInterface.c | |
| ******************************************************************/ | |
| #include "modules/audio_coding/codecs/ilbc/ilbc.h" | |
| #include <stdlib.h> | |
| #include "modules/audio_coding/codecs/ilbc/decode.h" | |
| #include "modules/audio_coding/codecs/ilbc/defines.h" | |
| #include "modules/audio_coding/codecs/ilbc/encode.h" | |
| #include "modules/audio_coding/codecs/ilbc/init_decode.h" | |
| #include "modules/audio_coding/codecs/ilbc/init_encode.h" | |
| #include "rtc_base/checks.h" | |
| int16_t WebRtcIlbcfix_EncoderAssign(IlbcEncoderInstance** iLBC_encinst, | |
| int16_t* ILBCENC_inst_Addr, | |
| int16_t* size) { | |
| *iLBC_encinst=(IlbcEncoderInstance*)ILBCENC_inst_Addr; | |
| *size=sizeof(IlbcEncoder)/sizeof(int16_t); | |
| if (*iLBC_encinst!=NULL) { | |
| return(0); | |
| } else { | |
| return(-1); | |
| } | |
| } | |
| int16_t WebRtcIlbcfix_DecoderAssign(IlbcDecoderInstance** iLBC_decinst, | |
| int16_t* ILBCDEC_inst_Addr, | |
| int16_t* size) { | |
| *iLBC_decinst=(IlbcDecoderInstance*)ILBCDEC_inst_Addr; | |
| *size=sizeof(IlbcDecoder)/sizeof(int16_t); | |
| if (*iLBC_decinst!=NULL) { | |
| return(0); | |
| } else { | |
| return(-1); | |
| } | |
| } | |
| int16_t WebRtcIlbcfix_EncoderCreate(IlbcEncoderInstance **iLBC_encinst) { | |
| *iLBC_encinst=(IlbcEncoderInstance*)malloc(sizeof(IlbcEncoder)); | |
| if (*iLBC_encinst!=NULL) { | |
| return(0); | |
| } else { | |
| return(-1); | |
| } | |
| } | |
| int16_t WebRtcIlbcfix_DecoderCreate(IlbcDecoderInstance **iLBC_decinst) { | |
| *iLBC_decinst=(IlbcDecoderInstance*)malloc(sizeof(IlbcDecoder)); | |
| if (*iLBC_decinst!=NULL) { | |
| return(0); | |
| } else { | |
| return(-1); | |
| } | |
| } | |
| int16_t WebRtcIlbcfix_EncoderFree(IlbcEncoderInstance *iLBC_encinst) { | |
| free(iLBC_encinst); | |
| return(0); | |
| } | |
| int16_t WebRtcIlbcfix_DecoderFree(IlbcDecoderInstance *iLBC_decinst) { | |
| free(iLBC_decinst); | |
| return(0); | |
| } | |
| int16_t WebRtcIlbcfix_EncoderInit(IlbcEncoderInstance* iLBCenc_inst, | |
| int16_t mode) { | |
| if ((mode==20)||(mode==30)) { | |
| WebRtcIlbcfix_InitEncode((IlbcEncoder*) iLBCenc_inst, mode); | |
| return(0); | |
| } else { | |
| return(-1); | |
| } | |
| } | |
| int WebRtcIlbcfix_Encode(IlbcEncoderInstance* iLBCenc_inst, | |
| const int16_t* speechIn, | |
| size_t len, | |
| uint8_t* encoded) { | |
| size_t pos = 0; | |
| size_t encpos = 0; | |
| if ((len != ((IlbcEncoder*)iLBCenc_inst)->blockl) && | |
| #ifdef SPLIT_10MS | |
| (len != 80) && | |
| #endif | |
| (len != 2*((IlbcEncoder*)iLBCenc_inst)->blockl) && | |
| (len != 3*((IlbcEncoder*)iLBCenc_inst)->blockl)) | |
| { | |
| /* A maximum of 3 frames/packet is allowed */ | |
| return(-1); | |
| } else { | |
| /* call encoder */ | |
| while (pos<len) { | |
| WebRtcIlbcfix_EncodeImpl((uint16_t*)&encoded[2 * encpos], &speechIn[pos], | |
| (IlbcEncoder*)iLBCenc_inst); | |
| #ifdef SPLIT_10MS | |
| pos += 80; | |
| if(((IlbcEncoder*)iLBCenc_inst)->section == 0) | |
| #else | |
| pos += ((IlbcEncoder*)iLBCenc_inst)->blockl; | |
| #endif | |
| encpos += ((IlbcEncoder*)iLBCenc_inst)->no_of_words; | |
| } | |
| return (int)(encpos*2); | |
| } | |
| } | |
| int16_t WebRtcIlbcfix_DecoderInit(IlbcDecoderInstance* iLBCdec_inst, | |
| int16_t mode) { | |
| if ((mode==20)||(mode==30)) { | |
| WebRtcIlbcfix_InitDecode((IlbcDecoder*) iLBCdec_inst, mode, 1); | |
| return(0); | |
| } else { | |
| return(-1); | |
| } | |
| } | |
| void WebRtcIlbcfix_DecoderInit20Ms(IlbcDecoderInstance* iLBCdec_inst) { | |
| WebRtcIlbcfix_InitDecode((IlbcDecoder*) iLBCdec_inst, 20, 1); | |
| } | |
| void WebRtcIlbcfix_Decoderinit30Ms(IlbcDecoderInstance* iLBCdec_inst) { | |
| WebRtcIlbcfix_InitDecode((IlbcDecoder*) iLBCdec_inst, 30, 1); | |
| } | |
| int WebRtcIlbcfix_Decode(IlbcDecoderInstance* iLBCdec_inst, | |
| const uint8_t* encoded, | |
| size_t len, | |
| int16_t* decoded, | |
| int16_t* speechType) | |
| { | |
| size_t i=0; | |
| /* Allow for automatic switching between the frame sizes | |
| (although you do get some discontinuity) */ | |
| if ((len==((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)|| | |
| (len==2*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)|| | |
| (len==3*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)) { | |
| /* ok, do nothing */ | |
| } else { | |
| /* Test if the mode has changed */ | |
| if (((IlbcDecoder*)iLBCdec_inst)->mode==20) { | |
| if ((len==NO_OF_BYTES_30MS)|| | |
| (len==2*NO_OF_BYTES_30MS)|| | |
| (len==3*NO_OF_BYTES_30MS)) { | |
| WebRtcIlbcfix_InitDecode( | |
| ((IlbcDecoder*)iLBCdec_inst), 30, | |
| ((IlbcDecoder*)iLBCdec_inst)->use_enhancer); | |
| } else { | |
| /* Unsupported frame length */ | |
| return(-1); | |
| } | |
| } else { | |
| if ((len==NO_OF_BYTES_20MS)|| | |
| (len==2*NO_OF_BYTES_20MS)|| | |
| (len==3*NO_OF_BYTES_20MS)) { | |
| WebRtcIlbcfix_InitDecode( | |
| ((IlbcDecoder*)iLBCdec_inst), 20, | |
| ((IlbcDecoder*)iLBCdec_inst)->use_enhancer); | |
| } else { | |
| /* Unsupported frame length */ | |
| return(-1); | |
| } | |
| } | |
| } | |
| while ((i*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)<len) { | |
| if (WebRtcIlbcfix_DecodeImpl( | |
| &decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl], | |
| (const uint16_t*)&encoded | |
| [2 * i * ((IlbcDecoder*)iLBCdec_inst)->no_of_words], | |
| (IlbcDecoder*)iLBCdec_inst, 1) == -1) | |
| return -1; | |
| i++; | |
| } | |
| /* iLBC does not support VAD/CNG yet */ | |
| *speechType=1; | |
| return (int)(i*((IlbcDecoder*)iLBCdec_inst)->blockl); | |
| } | |
| int WebRtcIlbcfix_Decode20Ms(IlbcDecoderInstance* iLBCdec_inst, | |
| const uint8_t* encoded, | |
| size_t len, | |
| int16_t* decoded, | |
| int16_t* speechType) | |
| { | |
| size_t i=0; | |
| if ((len==((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)|| | |
| (len==2*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)|| | |
| (len==3*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)) { | |
| /* ok, do nothing */ | |
| } else { | |
| return(-1); | |
| } | |
| while ((i*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)<len) { | |
| if (!WebRtcIlbcfix_DecodeImpl( | |
| &decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl], | |
| (const uint16_t*)&encoded | |
| [2 * i * ((IlbcDecoder*)iLBCdec_inst)->no_of_words], | |
| (IlbcDecoder*)iLBCdec_inst, 1)) | |
| return -1; | |
| i++; | |
| } | |
| /* iLBC does not support VAD/CNG yet */ | |
| *speechType=1; | |
| return (int)(i*((IlbcDecoder*)iLBCdec_inst)->blockl); | |
| } | |
| int WebRtcIlbcfix_Decode30Ms(IlbcDecoderInstance* iLBCdec_inst, | |
| const uint8_t* encoded, | |
| size_t len, | |
| int16_t* decoded, | |
| int16_t* speechType) | |
| { | |
| size_t i=0; | |
| if ((len==((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)|| | |
| (len==2*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)|| | |
| (len==3*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)) { | |
| /* ok, do nothing */ | |
| } else { | |
| return(-1); | |
| } | |
| while ((i*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)<len) { | |
| if (!WebRtcIlbcfix_DecodeImpl( | |
| &decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl], | |
| (const uint16_t*)&encoded | |
| [2 * i * ((IlbcDecoder*)iLBCdec_inst)->no_of_words], | |
| (IlbcDecoder*)iLBCdec_inst, 1)) | |
| return -1; | |
| i++; | |
| } | |
| /* iLBC does not support VAD/CNG yet */ | |
| *speechType=1; | |
| return (int)(i*((IlbcDecoder*)iLBCdec_inst)->blockl); | |
| } | |
| size_t WebRtcIlbcfix_DecodePlc(IlbcDecoderInstance* iLBCdec_inst, | |
| int16_t* decoded, | |
| size_t noOfLostFrames) { | |
| size_t i; | |
| uint16_t dummy; | |
| for (i=0;i<noOfLostFrames;i++) { | |
| // PLC decoding shouldn't fail, because there is no external input data | |
| // that can be bad. | |
| int result = WebRtcIlbcfix_DecodeImpl( | |
| &decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl], &dummy, | |
| (IlbcDecoder*)iLBCdec_inst, 0); | |
| RTC_CHECK_EQ(result, 0); | |
| } | |
| return (noOfLostFrames*((IlbcDecoder*)iLBCdec_inst)->blockl); | |
| } | |
| size_t WebRtcIlbcfix_NetEqPlc(IlbcDecoderInstance* iLBCdec_inst, | |
| int16_t* decoded, | |
| size_t noOfLostFrames) { | |
| /* Two input parameters not used, but needed for function pointers in NetEQ */ | |
| (void)(decoded = NULL); | |
| (void)(noOfLostFrames = 0); | |
| WebRtcSpl_MemSetW16(((IlbcDecoder*)iLBCdec_inst)->enh_buf, 0, ENH_BUFL); | |
| ((IlbcDecoder*)iLBCdec_inst)->prev_enh_pl = 2; | |
| return (0); | |
| } | |
| void WebRtcIlbcfix_version(char *version) | |
| { | |
| strcpy((char*)version, "1.1.1"); | |
| } |