G711编码的声音清晰度好,语音自然度高,但压缩效率低,数据量大常在32Kbps以上。常用于电话语音(推荐使用64Kbps),sampling rate为8K,压缩率为2,即把S16格式的数据压缩为8bit,分为a-law和u-law。
a-law也叫g711a,输入的是13位(其实是S16的高13位),使用在欧洲和其他地区,这种格式是经过特别设计的,便于数字设备进行快速运算。
运算过程如下:
(1) 取符号位并取反得到s,
(2) 获取强度位eee,获取方法如图所示
(3) 获取高位样本位wxyz
(4) 组合为seeewxyz,将seeewxyz逢偶数为取补数,编码完毕

示例:
输入pcm数据为3210,二进制对应为(0000 1100 1000 1010)
二进制变换下排列组合方式(0 0001 1001 0001010)
(1) 获取符号位最高位为0,取反,s=1
(2) 获取强度位0001,查表,编码制应该是eee=100
(3) 获取高位样本wxyz=1001
(4) 组合为11001001,逢偶数为取反为10011100
编码完毕。
u-law也叫g711u,使用在北美和日本,输入的是14位,编码算法就是查表,没啥复杂算法,就是基础值+平均偏移值,具体示例如下:
pcm=2345
(1)取得范围值
+4062 to +2015 in 16 intervals of 128 |
(2)得到基础值0x90,
(3)间隔数128,
(4)区间基本值4062,
(5)当前值2345和区间基本值差异4062-2345=1717,
(6)偏移值=1717/间隔数=1717/128,取整得到13,
(7)输出为0x90+13=0x9D

Code如下
-
#include <stdio.h>
-
-
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
-
#define QUANT_MASK (0xf) /* Quantization field mask. */
-
#define NSEGS (8) /* Number of A-law segments. */
-
#define SEG_SHIFT (4) /* Left shift for segment number. */
-
#define SEG_MASK (0x70) /* Segment field mask. */
-
#define BIAS (0x84) /* Bias for linear code. */
-
#define CLIP 8159
-
-
#define G711_A_LAW (0)
-
#define G711_MU_LAW (1)
-
#define DATA_LEN (16)
-
-
static
short seg_aend[
8] = {
-
0x1F,
0x3F,
0x7F,
0xFF,
-
0x1FF,
0x3FF,
0x7FF,
0xFFF
-
};
-
-
static
short seg_uend[
8] = {
-
0x3F,
0x7F,
0xFF,
0x1FF,
-
0x3FF,
0x7FF,
0xFFF,
0x1FFF
-
};
-
-
unsigned
char _u2a[
128] = {
-
/* u- to A-law conversions */
-
1,
1,
2,
2,
3,
3,
4,
4,
-
5,
5,
6,
6,
7,
7,
8,
8,
-
9,
10,
11,
12,
13,
14,
15,
16,
-
17,
18,
19,
20,
21,
22,
23,
24,
-
25,
27,
29,
31,
33,
34,
35,
36,
-
37,
38,
39,
40,
41,
42,
43,
44,
-
46,
48,
49,
50,
51,
52,
53,
54,
-
55,
56,
57,
58,
59,
60,
61,
62,
-
64,
65,
66,
67,
68,
69,
70,
71,
-
72,
73,
74,
75,
76,
77,
78,
79,
-
81,
82,
83,
84,
85,
86,
87,
88,
-
89,
90,
91,
92,
93,
94,
95,
96,
-
97,
98,
99,
100,
101,
102,
103,
104,
-
105,
106,
107,
108,
109,
110,
111,
112,
-
113,
114,
115,
116,
117,
118,
119,
120,
-
121,
122,
123,
124,
125,
126,
127,
128
-
};
-
-
unsigned
char _a2u[
128] = {
-
/* A- to u-law conversions */
-
1,
3,
5,
7,
9,
11,
13,
15,
-
16,
17,
18,
19,
20,
21,
22,
23,
-
24,
25,
26,
27,
28,
29,
30,
31,
-
32,
32,
33,
33,
34,
34,
35,
35,
-
36,
37,
38,
39,
40,
41,
42,
43,
-
44,
45,
46,
47,
48,
48,
49,
49,
-
50,
51,
52,
53,
54,
55,
56,
57,
-
58,
59,
60,
61,
62,
63,
64,
64,
-
65,
66,
67,
68,
69,
70,
71,
72,
-
73,
74,
75,
76,
77,
78,
79,
79,
-
80,
81,
82,
83,
84,
85,
86,
87,
-
88,
89,
90,
91,
92,
93,
94,
95,
-
96,
97,
98,
99,
100,
101,
102,
103,
-
104,
105,
106,
107,
108,
109,
110,
111,
-
112,
113,
114,
115,
116,
117,
118,
119,
-
120,
121,
122,
123,
124,
125,
126,
127
-
};
-
-
static short search(int val, short *table, int size)
-
{
-
int i;
-
for (i =
0; i < size; i++) {
-
if (val <= *table++)
-
return (i);
-
-
}
-
return (size);
-
}
-
-
/*
-
* linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
-
*
-
* linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
-
*
-
*Linear Input CodeCompressed Code
-
*---------------------------------------
-
*0000000wxyza000wxyz
-
*0000001wxyza001wxyz
-
*000001wxyzab010wxyz
-
*00001wxyzabc011wxyz
-
*0001wxyzabcd100wxyz
-
*001wxyzabcde101wxyz
-
*01wxyzabcdef110wxyz
-
*1wxyzabcdefg111wxyz
-
*
-
* For further information see John C. Bellamy's Digital Telephony, 1982,
-
* John Wiley & Sons, pps 98-111 and 472-476.
-
*/
-
unsigned char linear2alaw(int pcm_val)/* 2's complement (16-bit range) */
-
{
-
-
int mask;
-
int seg;
-
unsigned
char aval;
-
-
pcm_val = pcm_val >>
3;
-
-
if (pcm_val >=
0) {
-
mask =
0xD5;
/* sign (7th) bit = 1 */
-
}
else {
-
mask =
0x55;
/* sign bit = 0 */
-
pcm_val = -pcm_val -
1;
-
}
-
-
/* Convert the scaled magnitude to segment number. */
-
seg = search(pcm_val, seg_aend,
8);
-
-
/* Combine the sign, segment, and quantization bits. */
-
-
if (seg >=
8)
/* out of range, return maximum value. */
-
return (
unsigned
char) (
0x7F ^ mask);
-
else {
-
aval = (
unsigned
char) seg << SEG_SHIFT;
-
if (seg <
2)
-
aval |= (pcm_val >>
1) & QUANT_MASK;
-
else
-
aval |= (pcm_val >> seg) & QUANT_MASK;
-
return (aval ^ mask);
-
}
-
-
}
-
-
/*
-
* alaw2linear() - Convert an A-law value to 16-bit linear PCM
-
*
-
*/
-
int alaw2linear(unsigned char a_val)
-
{
-
-
int t;
-
int seg;
-
-
a_val ^=
0x55;
-
-
t = (a_val & QUANT_MASK) <<
4;
-
seg = ((
unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
-
switch (seg) {
-
case
0:
-
t +=
8;
-
break;
-
case
1:
-
t +=
0x108;
-
break;
-
default:
-
t +=
0x108;
-
t <<= seg -
1;
-
-
}
-
return ((a_val & SIGN_BIT) ? t : -t);
-
}
-
-
-
/*
-
* linear2ulaw() - Convert a linear PCM value to u-law
-
*
-
* In order to simplify the encoding process, the original linear magnitude
-
* is biased by adding 33 which shifts the encoding range from (0 - 8158) to
-
* (33 - 8191). The result can be seen in the following encoding table:
-
*
-
*Biased Linear Input CodeCompressed Code
-
*---------------------------------------
-
*00000001wxyza000wxyz
-
*0000001wxyzab001wxyz
-
*000001wxyzabc010wxyz
-
*00001wxyzabcd011wxyz
-
*0001wxyzabcde100wxyz
-
*001wxyzabcdef101wxyz
-
*01wxyzabcdefg110wxyz
-
*1wxyzabcdefgh111wxyz
-
*
-
* Each biased linear code has a leading 1 which identifies the segment
-
* number. The value of the segment number is equal to 7 minus the number
-
* of leading 0's. The quantization interval is directly available as the
-
* four bits wxyz. * The trailing bits (a - h) are ignored.
-
*
-
* Ordinarily the complement of the resulting code word is used for
-
* transmission, and so the code word is complemented before it is returned.
-
*
-
* For further information see John C. Bellamy's Digital Telephony, 1982,
-
* John Wiley & Sons, pps 98-111 and 472-476.
-
*/
-
unsigned char linear2ulaw(short pcm_val)/* 2's complement (16-bit range) */
-
{
-
short mask;
-
short seg;
-
unsigned
char uval;
-
-
/* Get the sign and the magnitude of the value. */
-
pcm_val = pcm_val >>
2;
-
if (pcm_val <
0) {
-
pcm_val = -pcm_val;
-
mask =
0x7F;
-
}
else {
-
mask =
0xFF;
-
}
-
if (pcm_val > CLIP)
-
pcm_val = CLIP;
/* clip the magnitude */
-
pcm_val += (BIAS >>
2);
-
-
/* Convert the scaled magnitude to segment number. */
-
seg = search(pcm_val, seg_uend,
8);
-
-
/*
-
* Combine the sign, segment, quantization bits;
-
* and complement the code word.
-
*/
-
if (seg >=
8)
/* out of range, return maximum value. */
-
return (
unsigned
char) (
0x7F ^ mask);
-
else {
-
-
uval = (
unsigned
char) (seg <<
4) | ((pcm_val >> (seg +
1)) &
0xF);
-
return (uval ^ mask);
-
}
-
}
-
-
/*
-
* ulaw2linear() - Convert a u-law value to 16-bit linear PCM
-
*
-
* First, a biased linear code is derived from the code word. An unbiased
-
* output can then be obtained by subtracting 33 from the biased code.
-
*
-
* Note that this function expects to be passed the complement of the
-
* original code word. This is in keeping with ISDN conventions.
-
*/
-
short ulaw2linear(unsigned char u_val)
-
{
-
short t;
-
-
/* Complement to obtain normal u-law value. */
-
u_val = ~u_val;
-
-
/*
-
* Extract and bias the quantization bits. Then
-
* shift up by the segment number and subtract out the bias.
-
*/
-
t = ((u_val & QUANT_MASK) <<
3) + BIAS;
-
t <<= ((
unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
-
return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
-
}
-
-
/* A-law to u-law conversion */
-
unsigned char alaw2ulaw(unsigned char aval)
-
{
-
aval &=
0xff;
-
return (
unsigned
char) ((aval &
0x80) ? (
0xFF ^ _a2u[aval ^
0xD5]) :
-
(
0x7F ^ _a2u[aval ^
0x55]));
-
}
-
-
/* u-law to A-law conversion */
-
unsigned char ulaw2alaw(unsigned char uval)
-
{
-
uval &=
0xff;
-
return (
unsigned
char) ((uval &
0x80) ? (
0xD5 ^ (_u2a[
0xFF ^ uval] -
1)) :
-
(
unsigned
char) (
0x55 ^ (_u2a[
0x7F ^ uval] -
1)));
-
}
-
-
int encode(char *a_psrc, char *a_pdst, int in_data_len, unsigned char type)
-
{
-
-
int i;
-
short *psrc = (
short *)a_psrc;
-
int out_data_len = in_data_len /
sizeof(
short);
-
-
if (a_psrc ==
NULL || a_pdst ==
NULL) {
-
return (
-1);
-
}
-
-
if (in_data_len <=
0) {
-
return (
-1);
-
}
-
-
-
if (type == G711_A_LAW) {
-
for (i =
0; i < out_data_len; i++) {
-
a_pdst[i] = (
char)linear2alaw(psrc[i]);
-
}
-
}
else {
-
for (i =
0; i < out_data_len; i++) {
-
a_pdst[i] = (
char)linear2ulaw(psrc[i]);
-
}
-
}
-
return (i);
-
}
-
-
int decode(char *a_psrc, char *a_pdst, int in_data_len, unsigned char type)
-
{
-
-
int i;
-
short *pdst = (
short *)a_pdst;
-
int out_data_len = in_data_len /
sizeof(
char);
-
-
if (a_psrc ==
NULL || a_pdst ==
NULL) {
-
return (
-1);
-
}
-
-
if (type == G711_A_LAW) {
-
for (i =
0; i < out_data_len; i++) {
-
pdst[i] = (
short)alaw2linear((
unsigned
char)a_psrc[i]);
-
}
-
}
else {
-
for (i =
0; i < out_data_len; i++) {
-
pdst[i] = (
short)ulaw2linear((
unsigned
char)a_psrc[i]);
-
}
-
}
-
-
return (i *
sizeof(
short));
-
}
-
-
int main(int argc, char **argv)
-
{
-
int i =
0;
-
int n =
0;
-
unsigned
short pcm_buf[DATA_LEN] = {
0};
/*store linear pcm data*/
-
unsigned
short pcm_buf2[DATA_LEN] = {
0};
/*store linear pcm data*/
-
unsigned
char g711_buf[DATA_LEN] = {
0};
-
-
FILE * fp_in = fopen(
"input.wav",
"r");
-
FILE * fp_out = fopen(
"pcm.g711_alaw",
"w");
-
FILE * fp_out_pcm = fopen(
"pcm2.wav",
"w");
-
-
unsigned
char header[
128] = {
0 };
-
fread(header,
1,
0x2c, fp_in);
-
fwrite(header,
1,
0x2c, fp_out_pcm);
-
-
while (DATA_LEN *
2 == fread(pcm_buf,
1, DATA_LEN *
2, fp_in)) {
-
-
printf(
"encode %d was trans\n",
-
encode(pcm_buf, g711_buf,
sizeof(pcm_buf), G711_A_LAW));
-
-
fwrite(g711_buf,
1, DATA_LEN, fp_out);
-
-
printf(
"decode %d was trans\n",
-
decode(g711_buf, pcm_buf2,
sizeof(g711_buf), G711_A_LAW));
-
-
fwrite(pcm_buf2,
1, DATA_LEN*
2, fp_out_pcm);
-
}
-
-
fclose(fp_in);
-
fclose(fp_out);
-
fclose(fp_out_pcm);
-
return
0;
-
}