微信公众号:Android疯子
在前三篇得基础上,这次研究了组播功能。非常感谢https://blog.csdn.net/jspping/article/details/64438515得贡献!
组播也就是通过MulticastSocket来进行开发,与DatagramSocket比较相类似,这次依然是用两个线程进行实现,发送线程MultiSendThread和接收线程MultiReceiveThread。废话不多说,开始码:
(一)MultiSendThread:
(1)初始化MuticastSocket
1// 侦听的端口
2try {
3 multicastSocket = new MulticastSocket(8082);
4 // 使用D类地址,该地址为发起组播的那个ip段,即侦听10001的套接字
5 address = InetAddress.getByName("239.0.0.1");
6} catch (IOException e) {
7 e.printStackTrace();
8}
(2)初始化AudioRecord
1protected LinkedList<byte[]> mRecordQueue;
2int minBufferSize;
3private static AcousticEchoCanceler aec;
4private static AutomaticGainControl agc;
5private static NoiseSuppressor nc;
6AudioRecord audioRec;
7byte[] buffer;
8
9@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
10private void initAudio() {
11 //播放的采样频率 和录制的采样频率一样
12 int sampleRate = 44100;
13 //和录制的一样的
14 int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
15 //录音用输入单声道 播放用输出单声道
16 int channelConfig = AudioFormat.CHANNEL_IN_MONO;
17
18 minBufferSize = AudioRecord.getMinBufferSize(
19 sampleRate,
20 channelConfig, AudioFormat.ENCODING_PCM_16BIT);
21 System.out.println("****RecordMinBufferSize = " + minBufferSize);
22 audioRec = new AudioRecord(
23 MediaRecorder.AudioSource.MIC,
24 sampleRate,
25 channelConfig,
26 audioFormat,
27 minBufferSize);
28 buffer = new byte[minBufferSize];
29
30 if (audioRec == null) {
31 return;
32 }
33 //声学回声消除器 AcousticEchoCanceler 消除了从远程捕捉到音频信号上的信号的作用
34 if (AcousticEchoCanceler.isAvailable()) {
35 aec = AcousticEchoCanceler.create(audioRec.getAudioSessionId());
36 if (aec != null) {
37 aec.setEnabled(true);
38 }
39 }
40
41 //自动增益控制 AutomaticGainControl 自动恢复正常捕获的信号输出
42 if (AutomaticGainControl.isAvailable()) {
43 agc = AutomaticGainControl.create(audioRec.getAudioSessionId());
44 if (agc != null) {
45 agc.setEnabled(true);
46 }
47 }
48
49 //噪声抑制器 NoiseSuppressor 可以消除被捕获信号的背景噪音
50 if (NoiseSuppressor.isAvailable()) {
51 nc = NoiseSuppressor.create(audioRec.getAudioSessionId());
52 if (nc != null) {
53 nc.setEnabled(true);
54 }
55 }
56 mRecordQueue = new LinkedList<byte[]>();
57}
(3)开始录制,并实时发送出去
1@Override
2public void run() {
3 if (multicastSocket == null)
4 return;
5 try {
6 audioRec.startRecording();
7 while (true) {
8 try {
9 byte[] bytes_pkg = buffer.clone();
10 if (mRecordQueue.size() >= 2) {
11 int length = audioRec.read(buffer, 0, minBufferSize);
12 // 组报
13 DatagramPacket datagramPacket = new DatagramPacket(buffer, length);
14 // 向组播ID,即接收group /239.0.0.1 端口 10001
15 datagramPacket.setAddress(address);
16 // 发送的端口号
17 datagramPacket.setPort(10001);
18 System.out.println("AudioRTwritePacket = " + datagramPacket.getData().toString());
19
20 multicastSocket.send(datagramPacket);
21 }
22 mRecordQueue.add(bytes_pkg);
23 } catch (Exception e) {
24 // TODO Auto-generated catch block
25 e.printStackTrace();
26 }
27 }
28 } catch (Exception e) {
29 e.printStackTrace();
30 }
31}
(二)MultiReceiveThread
(1)初始化MulticastSocket
1// 接收数据时需要指定监听的端口号
2try {
3 multicastSocket = new MulticastSocket(10001);
4 // 创建组播ID地址
5 InetAddress address = InetAddress.getByName("239.0.0.1");
6 // 加入地址
7 multicastSocket.joinGroup(address);
8} catch (IOException e) {
9 e.printStackTrace();
10}
(2)初始化AudioTrack
1byte[] buffer;
2AudioTrack audioTrk;
3
4private void initAudioTracker() {
5 //扬声器播放
6 int streamType = AudioManager.STREAM_MUSIC;
7 //播放的采样频率 和录制的采样频率一样
8 int sampleRate = 44100;
9 //和录制的一样的
10 int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
11 //流模式
12 int mode = AudioTrack.MODE_STREAM;
13 //录音用输入单声道 播放用输出单声道
14 int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
15 int recBufSize = AudioTrack.getMinBufferSize(
16 sampleRate,
17 channelConfig,
18 audioFormat);
19 System.out.println("****playRecBufSize = " + recBufSize);
20 audioTrk = new AudioTrack(
21 streamType,
22 sampleRate,
23 channelConfig,
24 audioFormat,
25 recBufSize,
26 mode);
27 audioTrk.setStereoVolume(AudioTrack.getMaxVolume(),
28 AudioTrack.getMaxVolume());
29 buffer = new byte[recBufSize];
30
31}
(3)开始接收,并进行实时播放
1@Override
2public void run() {
3 if (multicastSocket == null)
4 return;
5 //从文件流读数据
6 audioTrk.play();
7 // 包长
8 while (true) {
9 try {
10 // 数据报
11 DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
12 // 接收数据,同样会进入阻塞状态
13 multicastSocket.receive(datagramPacket);
14 audioTrk.write(datagramPacket.getData(), 0, datagramPacket.getLength());
15 } catch (IOException e) {
16 // TODO Auto-generated catch block
17 e.printStackTrace();
18 }
19 }
20
21}
(三)开始测试
1MultiSendThread multiSendThread;
2MultiReceiverThread multiReceiverThread;
3
4@OnClick({R.id.btnSend, R.id.btnReceive})
5public void onViewClicked(View view) {
6 switch (view.getId()) {
7 case R.id.btnSend:
8 if (multiSendThread == null) {
9 multiSendThread = new MultiSendThread();
10 }
11 new Thread(multiSendThread).start();
12 break;
13 case R.id.btnReceive:
14 if (multiReceiverThread == null) {
15 multiReceiverThread = new MultiReceiverThread();
16 }
17 new Thread(multiReceiverThread).start();
18 break;
19 }
20}