(四)Android基于UDP的多客户端语音通信
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(四)Android基于UDP的多客户端语音通信相关的知识,希望对你有一定的参考价值。
参考技术A 在前三篇得基础上,这次研究了组播功能。非常感谢https://blog.csdn.net/jspping/article/details/64438515得贡献!组播也就是通过MulticastSocket来进行开发,与DatagramSocket比较相类似,这次依然是用两个线程进行实现,发送线程MultiSendThread和接收线程MultiReceiveThread。废话不多说,开始码:
(一)MultiSendThread:
(1)初始化MuticastSocket
// 侦听的端口
try
multicastSocket = new MulticastSocket(8082);
// 使用D类地址,该地址为发起组播的那个ip段,即侦听10001的套接字
address = InetAddress.getByName("239.0.0.1");
catch (IOException e)
e.printStackTrace();
(2)初始化AudioRecord
protected LinkedList<byte[]> mRecordQueue;
int minBufferSize;
private static AcousticEchoCanceler aec;
private static AutomaticGainControl agc;
private static NoiseSuppressor nc;
AudioRecord audioRec;
byte[] buffer;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void initAudio()
//播放的采样频率 和录制的采样频率一样
int sampleRate = 44100;
//和录制的一样的
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
//录音用输入单声道 播放用输出单声道
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
minBufferSize = AudioRecord.getMinBufferSize(
sampleRate,
channelConfig, AudioFormat.ENCODING_PCM_16BIT);
System.out.println("****RecordMinBufferSize = " + minBufferSize);
audioRec = new AudioRecord(
MediaRecorder.Audiosource.MIC,
sampleRate,
channelConfig,
audioFormat,
minBufferSize);
buffer = new byte[minBufferSize];
if (audioRec == null)
return;
//声学回声消除器 AcousticEchoCanceler 消除了从远程捕捉到音频信号上的信号的作用
if (AcousticEchoCanceler.isAvailable())
aec = AcousticEchoCanceler.create(audioRec.getAudioSessionId());
if (aec != null)
aec.setEnabled(true);
//自动增益控制 AutomaticGainControl 自动恢复正常捕获的信号输出
if (AutomaticGainControl.isAvailable())
agc = AutomaticGainControl.create(audioRec.getAudioSessionId());
if (agc != null)
agc.setEnabled(true);
//噪声抑制器 NoiseSuppressor 可以消除被捕获信号的背景噪音
if (NoiseSuppressor.isAvailable())
nc = NoiseSuppressor.create(audioRec.getAudioSessionId());
if (nc != null)
nc.setEnabled(true);
mRecordQueue = new LinkedList<byte[]>();
(3)开始录制,并实时发送出去
@Override
public void run()
if (multicastSocket == null)
return;
try
audioRec.startRecording();
while (true)
try
byte[] bytes_pkg = buffer.clone();
if (mRecordQueue.size() >= 2)
int length = audioRec.read(buffer, 0, minBufferSize);
// 组报
DatagramPacket datagramPacket = new DatagramPacket(buffer, length);
// 向组播ID,即接收group /239.0.0.1 端口 10001
datagramPacket.setAddress(address);
// 发送的端口号
datagramPacket.setPort(10001);
System.out.println("AudioRTwritePacket = " + datagramPacket.getData().toString());
multicastSocket.send(datagramPacket);
mRecordQueue.add(bytes_pkg);
catch (Exception e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (Exception e)
e.printStackTrace();
(二)MultiReceiveThread
(1)初始化MulticastSocket
// 接收数据时需要指定监听的端口号
try
multicastSocket = new MulticastSocket(10001);
// 创建组播ID地址
InetAddress address = InetAddress.getByName("239.0.0.1");
// 加入地址
multicastSocket.joinGroup(address);
catch (IOException e)
e.printStackTrace();
(2)初始化AudioTrack
byte[] buffer;
AudioTrack audioTrk;
private void initAudioTracker()
//扬声器播放
int streamType = AudioManager.STREAM_MUSIC;
//播放的采样频率 和录制的采样频率一样
int sampleRate = 44100;
//和录制的一样的
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
//流模式
int mode = AudioTrack.MODE_STREAM;
//录音用输入单声道 播放用输出单声道
int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
int recBufSize = AudioTrack.getMinBufferSize(
sampleRate,
channelConfig,
audioFormat);
System.out.println("****playRecBufSize = " + recBufSize);
audioTrk = new AudioTrack(
streamType,
sampleRate,
channelConfig,
audioFormat,
recBufSize,
mode);
audioTrk.setStereoVolume(AudioTrack.getMaxVolume(),
AudioTrack.getMaxVolume());
buffer = new byte[recBufSize];
(3)开始接收,并进行实时播放
@Override
public void run()
if (multicastSocket == null)
return;
//从文件流读数据
audioTrk.play();
// 包长
while (true)
try
// 数据报
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
// 接收数据,同样会进入阻塞状态
multicastSocket.receive(datagramPacket);
audioTrk.write(datagramPacket.getData(), 0, datagramPacket.getLength());
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
(三)开始测试
MultiSendThread multiSendThread;
MultiReceiverThread multiReceiverThread;
@OnClick(R.id.btnSend, R.id.btnReceive)
public void onViewClicked(View view)
switch (view.getId())
case R.id.btnSend:
if (multiSendThread == null)
multiSendThread = new MultiSendThread();
new Thread(multiSendThread).start();
break;
case R.id.btnReceive:
if (multiReceiverThread == null)
multiReceiverThread = new MultiReceiverThread();
new Thread(multiReceiverThread).start();
break;
以上是关于(四)Android基于UDP的多客户端语音通信的主要内容,如果未能解决你的问题,请参考以下文章