前段時(shí)間在做攝像頭想關(guān)的項(xiàng)目的時(shí)候,在播放卡錄得時(shí)候,攝像頭返回來的數(shù)據(jù)的時(shí)候,發(fā)現(xiàn)返回來的音頻的格式是將pcm編碼成G711A的數(shù)據(jù)。所以只能將G711A轉(zhuǎn)換為pcm,然后在進(jìn)行播放。于是,就瘋狂的在網(wǎng)上找資料。
但是,并沒有找到G711A轉(zhuǎn)pcm的相關(guān)資料。
于是,就開始研究編碼格式.
先補(bǔ)充一下pcm和G711的編碼方式
1)pcm
PCM是一種編碼格式,pcm是裸流。
所以,pcm我們直接就能夠就行播放
2)G711
在開始講G711A轉(zhuǎn)為pcm的時(shí)候,我們先了解一下pcm是怎么被轉(zhuǎn)換為G711的。
以下的相互轉(zhuǎn)換,都會(huì)用到一個(gè)三方庫。

屏幕快照 2018-06-21 下午3.35.29.png
1)pcm-> G711
從上面的編碼原理可以知道,pcm轉(zhuǎn)G711是進(jìn)行了壓縮轉(zhuǎn)換。
起壓縮率為1:2, 即把16位數(shù)據(jù)壓縮成8位
NSUInteger datalength = [inputData length];
Byte *byteData = (Byte *)[inputData bytes];
short *pPcm = (short *)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++) {
G711Buff[i] = linear2alaw(pPcm[i]);
}
outlen = i;
Byte *sendbuff = (Byte *)G711Buff;
NSData * sendData = [[NSData alloc]initWithBytes:sendbuff length:len];
2)G711A->pcm
因?yàn)槲覀冎纏cm轉(zhuǎn)G711是將pcm進(jìn)行了壓縮,那么G711轉(zhuǎn)pcm我們就需要將G711重新編碼后,長度會(huì)增加會(huì)原來的兩倍。
我收到的數(shù)據(jù)是char類型的buffer數(shù)據(jù)
dataPtr:(const char *)data_ptr
遍歷收到的數(shù)據(jù),解析每個(gè)字節(jié)
short * pcmOuT = (short *)(malloc(dataLen*2));//因?yàn)檗D(zhuǎn)換后長度為原來的兩倍,所以申請(qǐng)一個(gè)數(shù)據(jù)長度兩倍的數(shù)組
for (int i =0; i<dataLen; i++) {
pcmOuT[i] = (int16_t)alaw2linear(data_ptr[i]);
}
這樣解析出來的數(shù)據(jù)就是pcm。可以截止播放.
G711U轉(zhuǎn)pcm也是類似的做法