G711规定了如何将128kbps的raw pcm信号转为64kbps的g711u/g711a音频信号。本文在前人的基础上封装了G711的编解码算法,有两种实现(基于算法和基于查表),查表的速度更快(源码下载)。
#ifndef _G711_H_
#define _G711_H_
/***********************************************************
** Author:kaychan
** Data:2019-11-21
** Mail:1203375695@qq.com
** Explain:a g711 codec use lookup table and algorithm
***********************************************************/
// base on lookup table
int g711a_encode(unsigned char *odata, short *idata, int ilen);
int g711u_encode(unsigned char *odata, short *idata, int ilen);
int g711a_decode(short *odata, unsigned char *idata, int ilen);
int g711u_decode(short *odata, unsigned char *idata, int ilen);
// base on algorithm
int g711a_encode2(unsigned char g711_data[], const short amp[], int len);
int g711u_encode2(unsigned char g711_data[], const short amp[], int len);
int g711a_decode2(short amp[], const unsigned char g711a_data[], int g711a_bytes);
int g711u_decode2(short amp[], const unsigned char g711u_data[], int g711u_bytes);
#endif
AvG711类封装
基于上述封装G711音频编解码类AvG711
AvG711.h
#ifndef _AV_G711_H_
#define _AV_G711_H_
/***********************************************************
** Author:kaychan
** Data:2019-11-21
** Mail:1203375695@qq.com
** Explain:a g711 codec class
***********************************************************/
typedef enum AvG711Fmt_E {
AvG711Fmt_Alaw = 0,
AvG711Fmt_Ulaw = 1,
}AvG711Fmt;
class AvG711 {
public:
AvG711(AvG711Fmt fmt = AvG711Fmt_Alaw);
~AvG711();
int encode(unsigned char **odata, unsigned char *idata, int ilen);
int encode(const char *g711_file, const char *pcm_file);
int decode(unsigned char **odata, unsigned char *idata, int ilen);
int decode(const char *pcm_file, const char *g711_file);
void free_output_data(unsigned char *odata);
private:
AvG711Fmt fmt_;
};
#endif
AvG711.cpp
#include "AvG711.h"
#include "g711.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
AvG711::AvG711(AvG711Fmt fmt) {
fmt_ = fmt;
}
AvG711::~AvG711() {
}
int AvG711::encode(unsigned char **odata, unsigned char *idata, int ilen) {
if (ilen > 0) {
int olen = ilen / 2;
*odata = (unsigned char *)malloc(sizeof(unsigned char) * olen);
if (*odata) {
if(fmt_ == AvG711Fmt_Alaw)
return g711a_encode(*odata, (short *)idata, ilen);
else if(fmt_ == AvG711Fmt_Ulaw)
return g711u_encode(*odata, (short *)idata, ilen);
}
}
return -1;
}
int AvG711::encode(const char *g711_file, const char *pcm_file) {
FILE *ifile = fopen(pcm_file, "rb");
FILE *ofile = fopen(g711_file, "wb");
if (ifile && ofile) {
int r = -1;
do {
unsigned char ibuf[160];
r = fread(ibuf, 1, 160, ifile);
if (r > 0) {
unsigned char *obuf;
int olen = encode(&obuf, ibuf, r);
fwrite(obuf, 1, olen, ofile);
free_output_data(obuf);
memset(ibuf, 0, sizeof(ibuf));
}
} while (r > 0);
fclose(ifile);
fclose(ofile);
return 0;
}
return -1;
}
int AvG711::decode(unsigned char **odata, unsigned char *idata, int ilen) {
if (ilen > 0) {
int olen = ilen * 2;
*odata = (unsigned char *)malloc(sizeof(unsigned char) * olen);
if (*odata) {
if (fmt_ == AvG711Fmt_Alaw)
return g711a_decode((short *)(*odata), idata, ilen);
else if (fmt_ == AvG711Fmt_Ulaw)
return g711u_decode((short *)(*odata), idata, ilen);
}
}
return -1;
}
int AvG711::decode(const char *pcm_file, const char *g711_file) {
FILE *ifile = fopen(g711_file, "rb");
FILE *ofile = fopen(pcm_file, "wb");
if (ifile && ofile) {
int r = -1;
do {
unsigned char ibuf[80];
r = fread(ibuf, 1, 80, ifile);
if (r > 0) {
unsigned char *obuf;
int olen = decode(&obuf, ibuf, r);
fwrite(obuf, 1, olen, ofile);
free_output_data(obuf);
memset(ibuf, 0, sizeof(ibuf));
}
} while (r > 0);
fclose(ifile);
fclose(ofile);
return 0;
}
return -1;
}
void AvG711::free_output_data(unsigned char *odata) {
free(odata);
}
调用实例
AvG711 g711a(AvG711Fmt_Alaw);
g711a.encode("g711a.g711", "xxx.pcm"); // pcm->pcma
g711a.decode("xxx.pcm", "g711a.g711"); // pcma->pcm
AvG711 g711u(AvG711Fmt_Ulaw);
g711u.encode("g711u.g711", "xxx.pcm"); // pcm->pcmu
g711u.decode("xxx.pcm", "g711u.g711"); // pcmu->pcm