G.711是一種由國際電信聯(lián)盟(ITU-T)制定的音頻編碼方式焦除,又稱為ITU-T G.711凳谦。
它是國際電信聯(lián)盟ITU-T定制出來的一套語音壓縮標(biāo)準(zhǔn)鸠踪,它代表了對數(shù)PCM(logarithmic pulse-code modulation)抽樣標(biāo)準(zhǔn)媒楼,主要用于電話掀宋。它主要用脈沖編碼調(diào)制對音頻采樣天梧,采樣率為8k每秒盔性。它利用一個 64Kbps 未壓縮通道傳輸語音訊號。 起壓縮率為1:2呢岗, 即把16位數(shù)據(jù)壓縮成8位冕香。G.711是主流的波形聲音編解碼器。
G.711 標(biāo)準(zhǔn)下主要有兩種壓縮算法后豫。
一種是μ-law algorithm (又稱often u-law, ulaw, mu-law)悉尾,主要運用于北美和日本;
另一種是A-law algorithm挫酿,主要運用于歐洲和世界其他地區(qū)构眯。其中,后者是特別設(shè)計用來方便計算機(jī)處理的早龟。
G711A(A-LAW)壓縮算法
(1)取符號位并取反得到s
(2)獲取強(qiáng)度位eee惫霸,獲取方法如圖所示
(3)獲取高位樣本位wxyz
(4)組合為seeewxyz猫缭,將seeewxyz逢偶數(shù)為取補(bǔ)數(shù),編碼完畢
例:
輸入pcm數(shù)據(jù)為1234它褪,二進(jìn)制對應(yīng)為(0000 0100 1101 0010)
二進(jìn)制變換下排列組合方式(0 00001 0011 010010)
(1)獲取符號位最高位為0饵骨,取反,s=1
(2)獲取強(qiáng)度位00001茫打,查表居触,編碼制應(yīng)該是eee=011
(3)獲取高位樣本wxyz=0011
(4)組合為10110011,逢偶數(shù)為取反為11100110
編碼完畢老赤。
G711U(U-LAW)壓縮算法
通過查表轮洋,計算出:基礎(chǔ)值+平均偏移值
例:
輸入pcm數(shù)據(jù)為1234
(1)取得范圍值,查表得+2014 to +991 in 16 intervals of 64
(2)得到基礎(chǔ)值為0xA0
(3)得到間隔數(shù)為64
(4)得到區(qū)間基本值2014
(5)當(dāng)前值1234和區(qū)間基本值差異2014-1234=780
(6)偏移值=780/間隔數(shù)=780/64抬旺,取整得到12
(7)輸出為0xA0+12=0xAC
編碼完畢弊予。
code如下
#import <Foundation/Foundation.h>
@interface EncoderG711 : NSObject
- (unsigned char)linear2alaw:(int)pcm_val;
- (unsigned char)linear2ulaw:(int)pcm_val;
@end
#import "EncoderG711.h"
#define QUANT_MASK (0xf)
#define SEG_SHIFT (4)
#define BIAS (0x84)
@implementation EncoderG711
static short seg_end[8] = {0xFF,0x1FF,0x3FF,0x7FF,0xFFF,0x1FFF,0x3FFF,0x7FFF};
static int search(int val,short *table,int size)
{
int i;
for (i = 0; i < size; i++) {
if (val <= *table++)
return (i);
}
return (size);
}
- (unsigned char)linear2alaw:(int)pcm_val
{
int mask;
int seg;
unsigned char aval;
if (pcm_val >= 0) {
mask = 0xD5;
} else {
mask = 0x55;
pcm_val = -pcm_val - 8;
}
seg = search(pcm_val, seg_end, 8);
if (seg >= 8)
return (0x7F ^ mask);
else {
aval = seg << SEG_SHIFT;
if (seg < 2)
aval |= (pcm_val >> 4) & QUANT_MASK;
else
aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
return (aval ^ mask);
}
}
- (unsigned char)linear2ulaw:(int)pcm_val
{
int mask;
int seg;
unsigned char uval;
if (pcm_val < 0) {
pcm_val = BIAS - pcm_val;
mask = 0x7F;
} else {
pcm_val += BIAS;
mask = 0xFF;
}
seg = search(pcm_val, seg_end, 8);
if (seg >= 8)
return (0x7F ^ mask);
else {
uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
return (uval ^ mask);
}
}
@end
- (NSData *)encodeG711:(NSData *)data {
NSUInteger datalength = [data length];
Byte *byteData = (Byte *)[data bytes];
short *pPcm = (short *)byteData;
free(byteData);
int outlen = 0;
int len =(int)datalength/2;
Byte *G711Buff = (Byte *)malloc(len);
memset(G711Buff,0,len);
int i;
for (i=0; i<len; i++) {
if (_type==G711A) {
G711Buff[i] = [_g711 linear2alaw:pPcm[i]];
}
else if (_type==G711U) {
G711Buff[i] = [_g711 linear2ulaw:pPcm[i]];
}
}
outlen = i;
Byte *sendbuff = (Byte *)G711Buff;
NSData *sendData = [[NSData alloc] initWithBytes:sendbuff length:len];
free(G711Buff);
return sendData;
}
G711A/G711U解碼請參考這篇:iOS G711解碼