Android基于UDP语音对讲系列(四)

微信公众号: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}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stormxiaofeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值