GSMAMR语音编码器

GSMAMR语音编码器

一、GSMAMR Codec 简介

数字蜂窝系统自适应多码率语音传输编解码器(Adaptive Multi-Rate Speech Codec:AMR)是欧洲电信标准化协会(ETSI)下属的SMG11Special Mobile Group11)为GSM系统所定制的语音编解码标准,其目的是在半速率信道容量的情况下得到有线语音编解码质量。 AMR作为第四代GSM语音编解码标准,提供了一种自适应的解决方法来跟踪快速变化的无线信道情况和本地流量情况。现今的GSM语音和信道编码器工作在固定码率上,这些码率在设计阶段就已经选定,是理想信道性能和信道误码鲁棒性的一个折衷。另一方面,AMR编码器实时根据信道类型(全速率或半速率)选择多种码率中的一种,从而达到语音编码和信道编码的最优组合以满足瞬时的无线信道条件和本地容量需求。AMR提供了从4.75kbits/s12.2kbits/s的多种码率选择。AMR凭借其优异的性能成为UMTSITU第三代系统候选编码。

二、GSMAMR Codec 编码方法

       GSMAMR Codec适用于对每秒8000次采样,16位,单声道音频数据进行编码。在16位的采样精度下,每一个采样值都是16位的半字,并且线性连续存放。GSMAMR Codec每次对一帧数据(160个采样值)进行编码,根据不同的编码速率,产生编码后的内容长度不同,详见表一。

速率

编码后长度()

编码后长度(字节)

4.75 kbps

95

12

5.15 kbps

103

13

5.9 kbps

118

15

6.7 kbps

134

17

7.4 kbps

148

19

7.95 kbps

159

20

10.2 kbps

204

26

12.2 kbps  (GSM EFR)

244

31

表一

 

对一帧语音数据编码后,可以形成相应的一个GSMAMR数据帧,如下图:

Frame Type (16 bit)

Speech Rate (16 bit)

Speech Content( n*8 bit)

       Frame Type占一个半字,十六位,表示帧类型。

帧类型

NON_SPEECH

-1

SPEECH_GOOD

0

SPEECH_DEGRADED

1

ONSET

2

SPEECH_BAD

3

SID_FIRST

4

SID_UPDATE

5

SID_BAD

6

NO_DATA

7

N_FRAMETYPES

8

       Speech Rate占一个半字,十六位,表示编码速率。

编码速率

RATE_UNDEFINED

-1

RATE_4750

0

RATE_5150

1

RATE_5900

2

RATE_6700

3

RATE_7400

4

RATE_7950

5

RATE_10200

6

RATE_12200

7

RATE_DTX

8

       Speech Content长度由Frame TypeSpeech Rate决定,详见表一。

三、GSMAMR Codec代码分析

       AMR Codec API相关源文件一共有八个,如下表:

             

文件名

功能

bitpack.c

位流打包/解包函数

encgsmamr.c

GSMAMR编码函数

decgsmamr.c

GSMAMR解码函数

dtx_util.c

DTX函数

gain_util.c

增益函数

tab_util.c

GSMAMR编码参数表

util.c

辅助函数

owngsmamr.h

常量定义,类型定义和内联函数定义

       其中encgsmamr.cdecgsmamr.c为主要文件,面向程序员的函数主要有如下几个:

 

 

编码类:

======================================================================

       APIGSMAMR_Status   apiGSMAMREncoder_GetSize

         (GSMAMREncoder_Obj* encoderObj, unsigned int *pCodecSize)

              功能:取得GSMAMR编码对象的大小。

 

       参数定义:

              GSMAMREncoder_Obj* encoderObj

                     GSMAMR编码对象指针。

              unsigned int *pCodecSize

                     存放GSMAMR编码对象的大小的整型数指针。

 

       代码分析:

GSMAMREncoder_Obj 定义如下:

struct _GSMAMREncoder_Obj {

   GSMAMRCoder_Obj   objPrm;

/* preprocess state */

   char   *preProc;    /* High pass pre processing filter memory */

   Encoder_State   cod_amr_state;

   GSMAMR_Rate_t   rate;    /* encode rate */

};

GSMAMREncoder_Obj结构体中的GSMAMRCoder_Obj 定义如下:

typedef struct _GSMAMRCoder_Obj{

   int   objSize;

   int   key;

   int   mode;    /* encoder mode's */

   GSMAMRCodec_Type   codecType;

}GSMAMRCoder_Obj;

其中成员变量objSize 即为GSMAMR编码对象的大小,这个变量在函数apiGSMAMREncoder_Init中进行初始化。

 


======================================================================

       APIGSMAMR_Status   apiGSMAMREncoder_Alloc

         (const GSMAMREnc_Params *gsm_Params, unsigned int *pSizeTab)

              功能:计算GSMAMR编码对象需要分配多少内存区域。

 

       参数定义:

              const GSMAMREnc_Params *gsm_Params

                     GSMAMR编码参数指针。

unsigned int *pSizeTab

       存放GSMAMR编码对象所需内存区域的大小。

 

       代码分析:

              GSMAMR编码参数结构体定义如下:

typedef struct _GSMAMREnc_Params{

   GSMAMRCodec_Type codecType;

   int mode;

}GSMAMREnc_Params;

              GSMAMRCodec_Type为一个枚举类型,表示编码器类型是GSMAMR

typedef enum _GSMAMRCodec_Type{

   GSMAMR_CODEC=0

}GSMAMRCodec_Type;

              mode表示GSMAMR编码器的编码模式

typedef enum _GSMAMREncode_Mode{

   GSMAMREncode_DefaultMode=0,   /*缺省模式*/

   GSMAMREncode_VAD1_Enabled,   /*VAD1模式*/

   GSMAMREncode_VAD2_Enabled   /*VAD2模式*/

}GSMAMREncode_Mode;

 


======================================================================

       APIGSMAMR_Status   apiGSMAMREncoder_Init

         (GSMAMREncoder_Obj* encoderObj, unsigned int mode)

              功能:初始化GSMAMR编码对象

 

       参数定义:

              GSMAMREncoder_Obj* encoderObj

                     GSMAMR编码对象指针。

              unsigned int mode

                     GSMAMR编码模式,参照如下定义

       代码分析:

              编码模式为如下三种之一:

typedef enum _GSMAMREncode_Mode{

   GSMAMREncode_DefaultMode=0,   /*缺省模式*/

   GSMAMREncode_VAD1_Enabled,   /*VAD1模式*/

   GSMAMREncode_VAD2_Enabled   /*VAD2模式*/

}GSMAMREncode_Mode;

 


======================================================================

       APIGSMAMR_Status   apiGSMAMREncode

         (GSMAMREncoder_Obj* encoderObj,const short* src,  GSMAMR_Rate_t rate,

          unsigned char* dst, int *pVad )

              功能:GSMAMR编码

      

参数定义及分析:

              GSMAMREncoder_Obj* encoderObj

                     GSMAMR编码对象指针。

              const short* src

需要进行编码的内容的指针,由于GSMAMR一次对160个采样进行编码(在8000Hz的采样率下是20ms长的语音内容),所以指针长度为160

              GSMAMR_Rate_t rate

                     采用的编码速率,参照如下定义

typedef enum {

    GSMAMR_RATE_UNDEFINED = -1,

    GSMAMR_RATE_4750 = 0,  /* MR475  4.75 kbps  */

    GSMAMR_RATE_5150,      /* MR515  5.15 kbps  */

    GSMAMR_RATE_5900,      /* MR59   5.9  kbps  */

    GSMAMR_RATE_6700,      /* MR67   6.7  kbps  */

    GSMAMR_RATE_7400,      /* MR74   7.4  kbps  */

    GSMAMR_RATE_7950,      /* MR795  7.95 kbps  */

    GSMAMR_RATE_10200,     /* MR102 10.2  kbps  */

    GSMAMR_RATE_12200,     /* MR122 12.2  kbps  (GSM EFR) */

    GSMAMR_RATE_DTX        /* MRDTX Discontinuous TX mode */

} GSMAMR_Rate_t;

              unsigned char* dst

                     存放编码后的数据。

              int *pVad

                     返回编码的这一个数据帧是否有效,如果有效,返回1,否则返回0

 

 

 

 

 

 

 

 

 

 

 

解码类:

======================================================================

APIGSMAMR_Status   apiGSMAMRDecoder_GetSize

         (GSMAMRDecoder_Obj* decoderObj, unsigned int *pCodecSize)

              功能:取得GSMAMR解码对象的大小。

 

       参数定义:

              GSMAMRDecoder_Obj* decoderObj

                     GSMAMR解码对象指针。

              unsigned int *pCodecSize

                     存放GSMAMR解码对象的大小的整型数指针。

 

       代码分析:

              GSMAMRDecoder_Obj结构体定义如下:

struct _GSMAMRDecoder_Obj {

/* post process state */

   GSMAMRCoder_Obj    objPrm;

   char    *postProc;   /* High pass post processing filter memory */

   Decoder_State    decoder_amrState;

/* postfiltering state */

   Post_FilterState    filt_state;

   GSMAMR_Rate_t    rate;     /* decode rate */

};

GSMAMRDecoder_Obj结构体中的GSMAMRCoder_Obj 定义如下:

typedef struct _GSMAMRCoder_Obj{

   int   objSize;

   int   key;

   int   mode;    /* encoder mode's */

   GSMAMRCodec_Type   codecType;

}GSMAMRCoder_Obj;

其中成员变量objSize 即为GSMAMR解码对象的大小,这个变量在函数apiGSMAMRDecoder_Init中进行初始化。


======================================================================

APIGSMAMR_Status   apiGSMAMRDecoder_Alloc

         (const GSMAMRDec_Params *gsm_Params, unsigned int *pSizeTab)

              功能:计算GSMAMR解码对象需要分配多少内存区域。

 

       参数定义:

              const GSMAMRDec_Params *gsm_Params

                     GSMAMR解码参数指针。

              unsigned int *pSizeTab

       存放GSMAMR解码对象所需内存区域的大小。

 

       代码分析:

              GSMAMR解码参数结构体定义如下:

typedef struct _GSMAMRDec_Params{

   GSMAMRCodec_Type codecType;

   int mode;

}GSMAMRDec_Params;

              GSMAMRCodec_Type为一个枚举类型,表示解码器类型是GSMAMR

typedef enum _GSMAMRCodec_Type{

   GSMAMR_CODEC=0

}GSMAMRCodec_Type;

              mode表示GSMAMR解码器的解码模式

typedef enum _GSMAMRDecode_Mode{

   GSMAMRDecode_DefaultMode=0

}GSMAMRDecode_Mode;


======================================================================

APIGSMAMR_Status   apiGSMAMRDecoder_Init

         (GSMAMRDecoder_Obj* decoderObj, unsigned int mode)

              功能:初始化GSMAMR解码对象

 

       参数定义和分析:

              GSMAMRDecoder_Obj* decoderObj

                     GSMAMR编码对象指针。

              unsigned int mode

                     GSMAMR编码模式,参照如下定义:

typedef enum _GSMAMRDecode_Mode{

   GSMAMRDecode_DefaultMode=0

}GSMAMRDecode_Mode;

 


======================================================================

APIGSMAMR_Status   apiGSMAMRDecode

         (GSMAMRDecoder_Obj* decoderObj,const unsigned char* src,

          GSMAMR_Rate_t rate,RXFrameType rx_type, short* dst)

              功能:GSMAMR解码

 

GSMAMRDecoder_Obj* decoderObj

                     GSMAMR解码对象指针。

const unsigned char* src

需要进行解码的内容的指针,根据编码速率不同,长度不同。

GSMAMR_Rate_t rate

                     采用的解码速率,参照如下定义

typedef enum {

    GSMAMR_RATE_UNDEFINED = -1,

    GSMAMR_RATE_4750 = 0,  /* MR475  4.75 kbps  */

    GSMAMR_RATE_5150,      /* MR515  5.15 kbps  */

    GSMAMR_RATE_5900,      /* MR59   5.9  kbps  */

    GSMAMR_RATE_6700,      /* MR67   6.7  kbps  */

    GSMAMR_RATE_7400,      /* MR74   7.4  kbps  */

    GSMAMR_RATE_7950,      /* MR795  7.95 kbps  */

    GSMAMR_RATE_10200,     /* MR102 10.2  kbps  */

    GSMAMR_RATE_12200,     /* MR122 12.2  kbps  (GSM EFR) */

    GSMAMR_RATE_DTX        /* MRDTX Discontinuous TX mode */

} GSMAMR_Rate_t;

RXFrameType rx_type

                     收到的编码数据帧的类型,参照如下定义

typedef enum  {

   RX_NON_SPEECH = -1,

   RX_SPEECH_GOOD = 0,

   RX_SPEECH_DEGRADED,

   RX_ONSET,

   RX_SPEECH_BAD,

   RX_SID_FIRST,

   RX_SID_UPDATE,

   RX_SID_BAD,

   RX_NO_DATA,

   RX_N_FRAMETYPES     /* number of frame types */

}RXFrameType;

short* dst

存放解码后内容的指针,由于GSMAMR一次解码产生160个采样值(在8000Hz的采样率下是20ms长的语音内容),所以指针长度为160

 

 

四、sitsang板上的GSMAMR Codec

       为了在sitsang板上使用GSMAMR Codec,我们将其编成动态库,makefile如下

###########################################################

# Change the definitions according to your system setting #

###########################################################

ifndef IPPROOT

  IPPROOT := /usr/local/ipp/ippxsc30

endif

 

###############################

# DO NOT EDIT BELOW THIS LINE #

###############################

 

# System Specific

INCLSFX=.h

CPPSFX=.c

OBJSFX=.o

EXESFX=

 

# IPP Dependencies

IPPINCLS=-I$(IPPROOT)/include

IPPLIBS=$(IPPROOT)/lib/ippSC_XSC30LNX_r.a

 

# Compiler Specifics

CC=arm-linux-gcc

CFLAGS=-Wall -L.

LIBCFLAGS= $(CFLAGS) -fPIC

CCOPTS=-c -O2

CCDEFS=-D_IPP_PCA -DLINUX32

CCINCLS=-I./include $(IPPINCLS)

 

LNK=arm-linux-ld

LNKOUT=-o

LNKOPTS=

LNKLIBS=$(IPPLIBS)

 

build: prepare_directory build_sharedlib; @echo "Done all"

 

##### api object #####

CPPSRC_API=./src/api/bitpack.c /

        ./src/api/decgsmamr.c /

        ./src/api/dtx_util.c /

        ./src/api/encgsmamr.c /

        ./src/api/gain_util.c /

        ./src/api/tab_util.c /

        ./src/api/util.c

OBJECT_API=$(patsubst %$(CPPSFX), %$(OBJSFX), $(CPPSRC_API))

 

##### ipp object #####

CPPSRC_IPP=./src/_ipp/extra_ipps.c /

        ./src/_ipp/extra_ippsc.c /

        ./src/_ipp/owncts.c

OBJECT_IPP=$(patsubst %$(CPPSFX), %$(OBJSFX), $(CPPSRC_IPP))

 

##### link shared lib #####

OBJECT_SHARED_NAME=libamrcodec.so.1.0.0

OBJECT_SHARED=./lib/$(OBJECT_SHARED_NAME)

SONAME=libamrcodec.so.1

 

build_sharedlib: $(OBJECT_SHARED) ; @echo "Done Sharedlib!!"

 

$(OBJECT_SHARED):$(OBJECT_API) $(OBJECT_IPP)

        $(CC) -shared -Wl,-soname,$(SONAME) -o$@ $(LNKOPTS) $^ $(LNKLIBS)

        cd lib

        ln -sf $(OBJECT_SHARED_NAME) ./lib/libamrcodec.so

        ln -sf $(OBJECT_SHARED_NAME) ./lib/$(SONAME)

        cd ..

 

##### compile shared lib objects all together #####

OBJECTS=$(OBJECT_API) $(OBJECT_IPP)

$(OBJECTS): %$(OBJSFX): %$(CPPSFX)

        $(CC) $(LIBCFLAGS) $(CCINCLS) $(CCDEFS) $(CCOPTS) -o$@ $<

 

prepare_directory: FORCE

        @if test ! -d ./lib; then mkdir ./lib; fi

 

clean: FORCE

        rm -f $(OBJECTS)

 

distclean: clean

        rm -f ./lib/*

 

FORCE:

      

       这样,可以生成libamrcodec.so,如果其他程序需要调用,编译的时候加上-lamrcodec参数即可。

五、GSMAMR Codec 使用方法

编码示例代码:

       我们约定,pSpeechIn指向需要编码的音频内容的内存单元的地址,pEncodedOut指向存放编码后数据帧的内存单元的地址。

       /*定义编码器对象指针*/

       static GSMAMREncoder_Obj *encoder;

      

       /*定义编码模式*/

       static int emode = GSMAMREncode_DefaultMode;

      

       /*定义编码速率*/

       GSMAMR_Rate_t WrkRate = GSMAMR_RATE_12200;

      

       /*编码参数*/

       static GSMAMREnc_Params gsmenc_params;

 

       /*定义临时变量*/

       unsigned int eSize=0,vad;

      

       /*需进行编码的音频内容*/

       short *pSpeechIn;

 

       /*存放编码结果的地址*/

       unsigned char *pEncodedOut;

 

       /*为编码器分配内存空间*/

       gsmenc_params.mode = emode;

       gsmenc_params.codecType = (GSMAMRCodec_Type)0;

       apiGSMAMREncoder_Alloc(&gsmenc_params, &eSize);

       if(!(encoder = (GSMAMREncoder_Obj*)ippsMalloc_8u(eSize))) {

              printf("/nLow memory: %u bytes not allocated/n",eSize);

              exit(1);

       }

 

       /*初始化编码器*/

       apiGSMAMREncoder_Init((GSMAMREncoder_Obj*)encoder,emode);

      

       /*进行编码*/

       apiGSMAMREncode(encoder, pSpeechIn, WrkRate,pEncodedOut+2,&vad);

 

       if(vad)  /*如果编码有效*/

       {

              pEncodedOut[0]=SPEECH_GOOD;    /*Set Frame Type*/

              pEncodedOut[1]=WrkRate;                 /*Set Speech Rate*/

       }

 

 

解码示例代码:

       我们约定,pSpeechOut指向存放解码后音频内容的内存单元的地址,pEncodedIn指需要解码的数据帧的内存单元的地址。

       /*定义解码器对象指针*/

       static GSMAMRDecoder_Obj *decoder;

      

       /*定义解码模式*/

       static int dmode=GSMAMRDecode_DefaultMode;

      

       /*定义解码速率,*/

       GSMAMR_Rate_t WrkRate = GSMAMR_RATE_12200;

 

       /*定义帧类型*/

       RXFrameType rx_type;

      

       /*编码参数*/

       static GSMAMRDec_Params gsmdec_params;

 

       /*定义临时变量*/

       unsigned int eSize=0;

      

       /*需进行解码的音频内容*/

       unsigned char *pEncodedIn;

 

       /*存放解码结果的地址*/

       short *pSpeechOut;

 

 

       /*为解码器分配内存空间*/

       gsmdec_params.mode = dmode;

       gsmdec_params.codecType = (GSMAMRCodec_Type)0;

       apiGSMAMRDecoder_Alloc(&gsmdec_params, &eSize);

       if(!(encoder = (GSMAMRDecoder_Obj*)ippsMalloc_8u(eSize))) {

              printf("/nLow memory: %u bytes not allocated/n",eSize);

              exit(1);

       }

 

       /*初始化解码器*/

       apiGSMAMRDecoder_Init((GSMAMRDecoder_Obj*)decoder,dmode);

      

       /*读取帧信息*/

       rx_type=(RXFrameType)pEncodedIn[0];

       WrkRate=(GSMAMR_Rate_t)pEncodedIn[1];

 

       /*进行编码*/

       apiGSMAMRDecode(decoder,pEncodedIn+2, WrkRate, rx_type, pSpeechOut);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值