之前研究了基于UDP的文字傳輸點(diǎn)擊打開(kāi)鏈接,以及Android端的語(yǔ)音錄制點(diǎn)擊打開(kāi)鏈接,這篇文章就記錄一下Android端局域網(wǎng)內(nèi)的語(yǔ)音傳輸,簡(jiǎn)單的實(shí)現(xiàn)語(yǔ)音對(duì)講,當(dāng)然里面還存在著很多問(wèn)題,包括語(yǔ)音不清晰啊、雜音多啊,不管了,先聽(tīng)見(jiàn)聲音就行了。測(cè)試的時(shí)候兩部手機(jī),上圖:
程序?qū)懥藘蓚€(gè)線程,一個(gè)用于錄制AudioRecordThread,一個(gè)用于播放AudioTrackThread.
(一)錄制與發(fā)送
@Override
public void run() {
if (mSocket == null)
return;
try {
mStartTime = System.currentTimeMillis();
audioRec.startRecording();
while (flag) {
try {
byte[] bytes_pkg = buffer.clone();
if (mRecordQueue.size() >= 2) {
int length = audioRec.read(buffer, 0, minBufferSize);
//獲取音量大小
mVolume = getAudioColum(buffer);
System.out.println(TAG + "= " + mVolume);
Message message = mHandler.obtainMessage();
message.arg1 = (int) mVolume;
mHandler.sendMessage(message);
DatagramPacket writePacket;
InetAddress inet = InetAddress.getByName(inetAddressName);
writePacket = new DatagramPacket(buffer, length, inet, PORT);
writePacket.setLength(length);
System.out.println("AudioRTwritePacket = " + writePacket.getData().toString());
mSocket.send(writePacket);
}
mRecordQueue.add(bytes_pkg);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
audioRec.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
里面包含了獲取音量大小,便于在頁(yè)面上面展示,方法參考了點(diǎn)擊打開(kāi)鏈接
private double getAudioColum(byte[] buffer) {
double sumVolume = 0.0;
double avgVolume = 0.0;
double volume = 0.0;
for (int i = 0; i < buffer.length; i += 2) {
int v1 = buffer[i] & 0xFF;
int v2 = buffer[i + 1] & 0xFF;
int temp = v1 + (v2 << 8);// 小端
if (temp >= 0x8000) {
temp = 0xffff - temp;
}
sumVolume += Math.abs(temp);
}
avgVolume = sumVolume / buffer.length / 2;
volume = Math.log10(1 + avgVolume) * 10;
return volume;
}
(二)接收與播放
@Override
public void run() {
if (mSocket == null)
return;
//從文件流讀數(shù)據(jù)
audioTrk.play();
while (flag) {
DatagramPacket recevPacket;
try {
recevPacket = new DatagramPacket(buffer, 0, buffer.length);
mSocket.receive(recevPacket);
audioTrk.write(recevPacket.getData(), 0, recevPacket.getLength());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
audioTrk.stop();
}
(三)主頁(yè)面 接收按鈕事件
@OnClick({R.id.btn_receive})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn_receive:
if (btnReceive.getText().toString().equals("開(kāi)始接收")) {
btnReceive.setText("停止接收");
try {
if (audioTrackThread == null) {
audioTrackThread = new AudioTrackThread();
}
new Thread(audioTrackThread).start();
} catch (SocketException e) {
e.printStackTrace();
}
} else {
btnReceive.setText("開(kāi)始接收");
audioTrackThread.setFlag(false);
}
break;
}
}
(四)發(fā)送按鈕事件
ivSpeak.setOnTouchListener(new View.OnTouchListener() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//按下按鈕開(kāi)始錄制
ivSpeak.setText("正在說(shuō)話");
//顯示錄音提示
relativeLayout.setVisibility(View.VISIBLE);
try {
if (audioRecordThread == null) {
audioRecordThread = new AudioRecordThread(handler);
}
audioRecordThread.setInetAddressName(tvReceiveIp.getText().toString());
audioRecordThread.setFlag(true);
new Thread(audioRecordThread).start();
} catch (SocketException e) {
e.printStackTrace();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
//松開(kāi)按鈕結(jié)束錄制
ivSpeak.setText("按住說(shuō)話");
relativeLayout.setVisibility(View.GONE);
audioRecordThread.setFlag(false);
mStopTime = audioRecordThread.getmStopTime();
mStartTime = audioRecordThread.getmStartTime();
creatMessageBean((mStopTime - mStartTime) / 1000, true);
break;
}
return true;
}
});