G726Codec.java
3.25 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
102
103
104
105
106
107
108
package cn.org.hentai.jtt1078.codec;
import cn.org.hentai.jtt1078.codec.g726.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class G726Codec extends AudioCodec {
// pcm采样率
private static final int PCM_SAMPLE = 8000;
// pcm采样点
private static final int PCM_POINT = 320;
// 音频通道数
private static final int CHANNEL = 1;
// 码率
private static final int G726_BIT_RATE_16000 = 16000;
private static final int G726_BIT_RATE_24000 = 24000;
private static final int G726_BIT_RATE_32000 = 32000;
private static final int G726_BIT_RATE_40000 = 40000;
@Override
public byte[] toPCM(byte[] data) {
int pos = 0;
// 如果前四字节是00 01 52 00,则是海思头,需要去掉
if (data[0] == 0x00 && data[1] == 0x01 && (data[2] & 0xff) == (data.length - 4) / 2 && data[3] == 0x00) {
pos = 4;
}
int length = data.length - pos;
int point = PCM_POINT;
// 计算G726的码率
int rateBit = length * 8 * PCM_SAMPLE/point;
G726 g726 = null;
// 码率
if (rateBit == G726_BIT_RATE_40000) {
g726 = new G726_40();
}
else if (rateBit == G726_BIT_RATE_32000) {
g726 = new G726_32();
}
else if (rateBit == G726_BIT_RATE_24000) {
g726 = new G726_24();
}
else if (rateBit == G726_BIT_RATE_16000) {
g726 = new G726_16();
}
else {
return null;
}
int pcmSize = point * CHANNEL * 2;
byte[] pcm = new byte[pcmSize];
int ret = g726.decode(data,pos,length,G726.AUDIO_ENCODING_LINEAR,pcm,0);
if (ret < 0) {
return null;
}
return pcm;
}
@Override
public byte[] fromPCM(byte[] data) {
// TODO:
return new byte[0];
}
private static void readWrite(String in,String out,int size) throws Exception {
FileInputStream f = new FileInputStream(in);
FileOutputStream o = new FileOutputStream(out);
int len = -1;
byte[] buff = new byte[size];
G726Codec g726Codec = new G726Codec();
int index = 0;
while ((len = f.read(buff,index,buff.length)) > -1) {
o.write(g726Codec.toPCM(buff));
}
}
// mac下在终端中输入 /Applications/VLC.app/Contents/MacOS/VLC --demux=rawaud --rawaud-channels 1 --rawaud-samplerate 8000 ${path}
// 修改${path} 的值为pcm路径,即可播放转码后的pcm文件
public static void main(String[] args) throws Exception {
readWrite(Thread.currentThread().getContextClassLoader().getResource("g726/in_40.g726").getPath(),
"/Users/tmyam/Downloads/out_40.pcm",200);
readWrite(Thread.currentThread().getContextClassLoader().getResource("g726/in_32.g726").getPath(),
"/Users/tmyam/Downloads/out_32.pcm",160);
readWrite(Thread.currentThread().getContextClassLoader().getResource("g726/in_24.g726").getPath(),
"/Users/tmyam/Downloads/out_24.pcm",120);
readWrite(Thread.currentThread().getContextClassLoader().getResource("g726/in_16.g726").getPath(),
"/Users/tmyam/Downloads/out_16.pcm",80);
}
}