AudioCodecUtil.java
3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package com.genersoft.iot.vmp.jtt1078.util;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.Arrays;
/**
* 音频转换与封包工具 (修复版)
*/
public class AudioCodecUtil {
// G.711A (byte) -> PCM (byte[])
public static byte[] g711aToPcm(byte[] g711Data) {
if (g711Data == null) return new byte[0];
byte[] pcmData = new byte[g711Data.length * 2];
for (int i = 0; i < g711Data.length; i++) {
short s = ALaw.decode(g711Data[i]);
pcmData[2 * i] = (byte) (s & 0xff);
pcmData[2 * i + 1] = (byte) ((s >> 8) & 0xff);
}
return pcmData;
}
// PCM -> G.711A (byte[])
public static byte[] pcmToG711a(byte[] pcmData) {
if (pcmData == null) return new byte[0];
byte[] g711Data = new byte[pcmData.length / 2];
for (int i = 0; i < g711Data.length; i++) {
int low = pcmData[2 * i] & 0xff;
int high = pcmData[2 * i + 1] & 0xff;
short s = (short) (low | (high << 8));
g711Data[i] = ALaw.encode(s);
}
return g711Data;
}
/**
* 【核心修复】更安全的封包逻辑
*/
public static ByteBuf encodeJt1078AudioPacket(String sim, int channel, int sequence, byte[] audioBody) {
// 计算总长度:30字节头 + 音频体长度
int totalLen = 30 + (audioBody != null ? audioBody.length : 0);
// 创建 HeapBuffer
ByteBuf buffer = Unpooled.buffer(totalLen);
// --- 30字节头 ---
buffer.writeInt(0x30316364); // 0-3: Frame Header
buffer.writeByte(0x80); // 4: RTP V=2, P=0, X=0, CC=0
buffer.writeByte(0x88); // 5: M=1, PT=8 (PCMA)
buffer.writeShort(sequence); // 6-7: Sequence
// 8-13: SIM卡号 (BCD)
byte[] bcdSim = str2Bcd(sim);
buffer.writeBytes(bcdSim); // 写入6字节
buffer.writeByte(channel); // 14: Channel
buffer.writeByte(0x30); // 15: DataType (0011 0000 -> 音频I帧)
buffer.writeLong(System.currentTimeMillis()); // 16-23: Timestamp
// 24-27: Intervals
buffer.writeShort(0);
buffer.writeShort(0);
// 28-29: Body Length
int bodyLen = (audioBody != null ? audioBody.length : 0);
buffer.writeShort(bodyLen);
// --- 写入音频数据 ---
if (bodyLen > 0) {
buffer.writeBytes(audioBody);
}
return buffer;
}
/**
* 【修复】更健壮的 BCD 转码
* 确保必须返回 6 字节,不足补0,超过截断
*/
public static byte[] str2Bcd(String asc) {
if (asc == null) return new byte[6];
// 1. 预处理:只保留数字,不足12位补0
String num = asc.replaceAll("[^0-9]", "");
if (num.length() > 12) num = num.substring(0, 12);
else while (num.length() < 12) num = "0" + num; // 左补0
// 2. 转换
byte[] bbt = new byte[6];
char[] chars = num.toCharArray();
for (int p = 0; p < 6; p++) {
int high = chars[2 * p] - '0';
int low = chars[2 * p + 1] - '0';
bbt[p] = (byte) ((high << 4) | low);
}
return bbt;
}
}