音频编解码之G711

音视频应用开发系列文章目录

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值