app-starlock/lib/tools/G711Tool.dart

274 lines
7.0 KiB
Dart
Raw Normal View History

2025-04-02 17:36:27 +08:00
/**
* G711Tool - G.711
*
* G.711ITU-T标准
* A-lawμ-law
*
* PCM线性音频数据与G.711 A-law/μ-law格式之间的转换功能
* 16线PCM样本压缩为8位
*/
class G711Tool {
// 常量定义
static const int SIGN_BIT = 0x80; // A-law字节的符号位
static const int QUANT_MASK = 0xf; // 量化字段掩码
static const int NSEGS = 8; // A-law段数
static const int SEG_SHIFT = 4; // 段号左移位数
static const int SEG_MASK = 0x70; // 段字段掩码
static const int BIAS = 0x84; // 线性编码的偏置值
// 查找表
/**
* μ-law到A-law的转换表
* 线PCM
*/
static final List<int> _u2a = [
// 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
];
/**
* A-law到μ-law的转换表
* 线PCM
*/
static final List<int> _a2u = [
// 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
];
/**
*
* PCM值应该映射到哪个段
*
*/
static final List<int> _segEnd = [
0xFF,
0x1FF,
0x3FF,
0x7FF,
0xFFF,
0x1FFF,
0x3FFF,
0x7FFF
];
/**
*
*
* @param val
* @param table
* @param size
* @return
*/
static int _search(int val, List<int> table, int size) {
for (int i = 0; i < size; i++) {
if (val <= table[i]) return i;
}
return size;
}
/**
* 线PCM值转换为A-law编码值
*
* :
* 1.
* 2.
* 3.
* 4. A-law值
*
* @param pcmVal 16线PCM值
* @return 8A-law编码值
*/
static int _linear2alaw(int pcmVal) {
int mask;
int seg;
int aval;
if (pcmVal >= 0) {
mask = 0xD5; // sign (7th) bit = 1
} else {
mask = 0x55; // sign bit = 0
pcmVal = -pcmVal - 1;
if (pcmVal < 0) pcmVal = 32767;
}
seg = _search(pcmVal, _segEnd, 8);
if (seg >= 8) return 0x7F ^ mask;
aval = seg << SEG_SHIFT;
if (seg < 2) {
aval |= (pcmVal >> 4) & QUANT_MASK;
} else {
aval |= (pcmVal >> (seg + 3)) & QUANT_MASK;
}
return aval ^ mask;
}
/**
* A-law编码值转换为线性PCM值
*
* :
* 1.
* 2.
* 3. 线
* 4.
*
* @param aVal 8A-law编码值
* @return 16线PCM值
*/
static int _alaw2linear(int aVal) {
int t;
int seg;
aVal ^= 0x55;
t = (aVal & QUANT_MASK) << 4;
seg = (aVal & SEG_MASK) >> SEG_SHIFT;
switch (seg) {
case 0:
t += 8;
break;
case 1:
t += 0x108;
break;
default:
t += 0x108;
t <<= seg - 1;
}
return (aVal & SIGN_BIT) != 0 ? t : -t;
}
/**
* 线PCM值转换为μ-law编码值
*
* A-law类似使
*
* @param pcmVal 16线PCM值
* @return 8μ-law编码值
*/
static int _linear2ulaw(int pcmVal) {
int mask;
int seg;
int uval;
if (pcmVal < 0) {
pcmVal = BIAS - pcmVal;
mask = 0x7F;
} else {
pcmVal += BIAS;
mask = 0xFF;
}
seg = _search(pcmVal, _segEnd, 8);
if (seg >= 8) return 0x7F ^ mask;
uval = (seg << 4) | ((pcmVal >> (seg + 3)) & 0xF);
return uval ^ mask;
}
/**
* μ-law编码值转换为线性PCM值
*
* @param uVal 8μ-law编码值
* @return 16线PCM值
*/
static int _ulaw2linear(int uVal) {
uVal = ~uVal;
int t = ((uVal & QUANT_MASK) << 3) + BIAS;
t <<= (uVal & SEG_MASK) >> SEG_SHIFT;
return (uVal & SIGN_BIT) != 0 ? (BIAS - t) : (t - BIAS);
}
/**
* A-law编码值转换为μ-law编码值
*
* 使
*
* @param aval 8A-law编码值
* @return 8μ-law编码值
*/
static int alaw2ulaw(int aval) {
aval &= 0xff;
return (aval & 0x80) != 0
? (0xFF ^ _a2u[aval ^ 0xD5])
: (0x7F ^ _a2u[aval ^ 0x55]);
}
/**
* μ-law编码值转换为A-law编码值
*
* 使
*
* @param uval 8μ-law编码值
* @return 8A-law编码值
*/
static int ulaw2alaw(int uval) {
uval &= 0xff;
return (uval & 0x80) != 0
? (0xD5 ^ (_u2a[0xFF ^ uval] - 1))
: (0x55 ^ (_u2a[0x7F ^ uval] - 1));
}
/**
* PCM数据编码为G.711
*
* @param pcm PCM数据
* @param lawFlag : 0A-law, 1μ-law
* @return G.711
*/
static List<int> encode(List<int> pcm, int lawFlag) {
List<int> code = List<int>.filled(pcm.length, 0);
if (lawFlag == 0) {
for (int i = 0; i < pcm.length; i++) {
code[i] = _linear2alaw(pcm[i]);
}
} else {
for (int i = 0; i < pcm.length; i++) {
code[i] = _linear2ulaw(pcm[i]);
}
}
return code;
}
/**
* G.711PCM格式
*
* @param code G.711
* @param lawFlag : 0A-law, 1μ-law
* @return PCM数据
*/
static List<int> decode(List<int> code, int lawFlag) {
List<int> pcm = List<int>.filled(code.length, 0);
if (lawFlag == 0) {
for (int i = 0; i < code.length; i++) {
pcm[i] = _alaw2linear(code[i]);
}
} else {
for (int i = 0; i < code.length; i++) {
pcm[i] = _ulaw2linear(code[i]);
}
}
return pcm;
}
}