一、概述
G.711是國際電信聯盟(ITU)為語音通信和錄音等應用而制定的音頻編解碼標準。該標準主要用於傳輸純語音信息,包括電話、對講機等,不支持音頻信號的壓縮。G.711採用時域抽樣,將模擬音頻採樣率從8kHz上升至16kHz,保證傳輸音頻質量。
二、G.711編解碼原理
G.711有兩種編解碼方式,分別為u-law(μ-law)和A-law。這兩種編碼方式是根據編碼器的壓縮特性進行選擇的。
1. u-law編碼
short linear2ulaw(int pcm_val)
{
int mask;
int seg;
unsigned char uval;
pcm_val = pcm_val >> 2;
if (pcm_val 0x3FFF) {
pcm_val = 0x3FFF;
}
pcm_val += 0x20;
seg = compand[pcm_val>>6];
uval = (unsigned char)(seg | ((pcm_val >>(seg + 1)) & 0x0F));
return (short)(uval ^ mask);
}
2. A-law編碼
short 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;
}
if (pcm_val 0x7FF) {
pcm_val = 0x7FF;
}
pcm_val >>= 4;
seg = search(pcm_val, seg_end, 8);
if (seg >= 8) {
return (short)(0x7F ^ mask);
} else {
aval = (unsigned char)(seg <> (seg + 1) & 0x0F));
return (short)(aval ^ mask);
}
}
三、G.711編碼器的實現
以下代碼展示了一個簡單的G.711編碼器實現:
public class G711Encoder {
static final int ZEROTRAP = 1;
static final int BIAS = 0x84;
static final int CLIP = 8159;
private static byte[] _law2linear;
/**
* 靜態塊,初始化_law2linear表
*/
static {
_law2linear = new byte[1024];
for (int i = 0; i < 256; i++) {
int x = i ^ 0x55;
x <<= 7;
short t = (short) x;
if ((x & 0x8000) != 0) {
t = (short) (0x7fff - (x & 0x7fff));
}
t -= BIAS <>> 8);
_law2linear[i + 256] = (byte) (t & 0xff);
x = (i & 0x7f) << 8;
t = (short) x;
if ((x & 0x8000) != 0) {
t = (short) (0x7fff - (x & 0x7fff));
}
t -= (BIAS <>> 8);
_law2linear[i + 768] = (byte) (t & 0xff);
}
}
/**
* 編碼PCM到G.711
*
* @param pcm 輸入PCM數據
* @return 返回G.711編碼後的數據
*/
public byte[] encode(byte[] pcm) {
byte[] g711 = new byte[pcm.length / 2];
int idx, x;
for (int i = 0, s = 0; i < pcm.length; i += 2) {
idx = ((pcm[i + 1] & 0xff) << 8) | (pcm[i] & 0xff);
if (idx 32767) {
idx = 32767;
}
x = _law2linear[idx];
if (pcm[i + 1] < 0) {
x = -x;
}
x += 0x80;
if (x 0xFF) {
x = 0xFF;
}
g711[s++] = (byte) x;
}
return g711;
}
}
四、G.711解碼器的實現
以下代碼展示了一個簡單的G.711解碼器實現:
public class G711Decoder {
static final int ZEROTRAP = 1;
static final int BIAS = 0x84;
static final int CLIP = 8159;
private static short[] _linear2law;
/**
* 靜態塊,初始化_linear2law表
*/
static {
int[] seg_end = {0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
_linear2law = new short[65536];
for (int i = 0; i < 65536; i++) {
short sign = 0;
if (i < 0) {
i = -i;
sign = 0x80;
}
int exponent = search(i, seg_end, 8) <> (exponent + 3)) & 0x0F;
_linear2law[i] = (short) (sign | exponent | mantissa);
}
}
/**
* 解碼G.711到PCM
*
* @param g711 輸入G.711數據
* @return 返回PCM解碼後的數據
*/
public byte[] decode(byte[] g711) {
byte[] pcm = new byte[g711.length * 2];
int idx, sign, x;
for (int i = 0, s = 0; i < g711.length; i++, s += 2) {
sign = (g711[i] & 0x80) != 0 ? (byte) 0x00FF : 0;
idx = ((g711[i] ^ sign) & 0xff);
x = _linear2law[idx] + BIAS <> 8);
}
return pcm;
}
}
五、應用舉例
G.711主要在電話語音通信、對講機等領域中得到廣泛使用。以下是一個Java語言中使用G.711編解碼的例子:
public class G711Example {
public static void main(String[] args) {
short[] pcmData = new short[]{0, 100, 200, 300, 400, 500};
G711Encoder encoder = new G711Encoder();
G711Decoder decoder = new G711Decoder();
byte[] g711Data = encoder.encode(ArrayUtils.toBytes(pcmData)); // PCM -> G.711
short[] pcmData2 = ArrayUtils.toShorts(decoder.decode(g711Data)); // G.711 -> PCM
System.out.println(Arrays.toString(pcmData));
System.out.println(Bytes.toHexString(g711Data, "", " ", ""));
System.out.println(Arrays.toString(pcmData2));
}
}
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/275624.html
微信掃一掃
支付寶掃一掃