FT8CN/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/icom/XieGuAudioUdp.java

192 wiersze
6.8 KiB
Java
Czysty Wina Historia

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.bg7yoz.ft8cn.icom;
/**
* 处理协谷的音频流继承至AudioUdp。
*
* @author BGY70Z
* @date 2023-08-26
*/
import android.util.Log;
import com.bg7yoz.ft8cn.GeneralVariables;
import java.net.DatagramPacket;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class XieGuAudioUdp extends AudioUdp {
private static final String TAG = "XieGuAudioUdp";
private final ExecutorService doTXThreadPool = Executors.newCachedThreadPool();
// private final DoTXAudioRunnable doTXAudioRunnable = new DoTXAudioRunnable(this);
private final AudioRunnable audioRunnable = new AudioRunnable(this);
private boolean audioIsRunning = false;
//private DatagramPacket packet;
//private byte[] data;
@Override
public void sendTxAudioData(float[] audioData) {
if (audioData == null) return;
short[] temp = new short[audioData.length];//12000
//传递过来的音频是LPCM,32 float12000Hz
//要做一下浮点到16位int的转换
for (int i = 0; i < audioData.length; i++) {
float x = audioData[i];
if (x > 0.999999f)
temp[i] = 32767;
else if (x < -0.999999f)
temp[i] = -32766;
else
temp[i] = (short) (x * 32767.0);
}
audioRunnable.setAudioData(temp);
//doTXAudioRunnable.audioData = temp;
//doTXThreadPool.execute(doTXAudioRunnable);
}
@Override
public void startTxAudio() {
if (!audioIsRunning) {
audioIsRunning = true;
doTXThreadPool.execute(audioRunnable);
}
}
@Override
public void stopTXAudio() {
audioIsRunning = false;
audioRunnable.stop();
}
private static class AudioRunnable implements Runnable {
private final int partialLen = (int) (IComPacketTypes.AUDIO_SAMPLE_RATE * 0.02);//20ms的数据包的长度
private final byte[] audioPacket = new byte[partialLen * 2];
private final byte[] ft8Audio = new byte[15 * IComPacketTypes.AUDIO_SAMPLE_RATE * 2];//15秒采样率*216位所以2倍
private int index = 0;
XieGuAudioUdp audioUdp;
private boolean isRunning = true;
public AudioRunnable(XieGuAudioUdp audioUdp) {
this.audioUdp = audioUdp;
Log.e(TAG, "AudioRunnable: create runnable");
}
public void setAudioData(short[] audioData) {
for (int i = 0; i < audioData.length; i++) {
System.arraycopy(IComPacketTypes.shortToBigEndian((short)
(audioData[i]
* GeneralVariables.volumePercent))//乘以信号量的比率
, 0, ft8Audio, i * 2, 2);
}
index = 0;
}
@Override
public void run() {
while (isRunning) {
long now = System.currentTimeMillis() - 1;//获取当前时间
if (audioUdp.isPttOn) {
System.arraycopy(ft8Audio, index, audioPacket, 0, audioPacket.length);
index = index + partialLen * 2;
if (index >= ft8Audio.length) index = 0;
}
audioUdp.sendTrackedPacket(IComPacketTypes.AudioPacket.getTxAudioPacket(audioPacket
, (short) 0, audioUdp.localId, audioUdp.remoteId, audioUdp.innerSeq));
audioUdp.innerSeq++;
while (isRunning) {
if (System.currentTimeMillis() - now >= 21) {//20毫秒一个周期
break;
}
}
}
}
public void stop() {
isRunning = false;
}
}
//
// private static class DoTXAudioRunnable implements Runnable {
// XieGuAudioUdp audioUdp;
// short[] audioData;//传递过来的音频是LPCM 16bit Int,12000hz
//
// public DoTXAudioRunnable(XieGuAudioUdp audioUdp) {
// this.audioUdp = audioUdp;
// }
//
// @Override
// public void run() {
// if (audioData == null) return;
//
// final int partialLen = (int) (IComPacketTypes.AUDIO_SAMPLE_RATE * 0.02);//20ms的数据包的长度
//
// //要转换一下到BYTE,小端模式
// //先播放是给出空的声音for i 循环做了一个判断是给前面的空声音for j循环做得判断是让后面发送空声音
// byte[] audioPacket = new byte[partialLen * 2];
// for (int i = 0; i < (audioData.length / partialLen) + 8; i++) {//多出6个周期前面3个后面3个多
// if (!audioUdp.isPttOn) break;
// long now = System.currentTimeMillis() - 1;//获取当前时间
//
// audioUdp.sendTrackedPacket(IComPacketTypes.AudioPacket.getTxAudioPacket(audioPacket
// , (short) 0, audioUdp.localId, audioUdp.remoteId, audioUdp.innerSeq));
// audioUdp.innerSeq++;
//
// Arrays.fill(audioPacket, (byte) 0x00);
// if (i >= 3) {//让前两个空数据发送出去
// for (int j = 0; j < partialLen; j++) {
// if ((i - 3) * partialLen + j < audioData.length) {
// System.arraycopy(IComPacketTypes.shortToBigEndian((short)
// (audioData[(i - 3) * partialLen + j]
// * GeneralVariables.volumePercent))//乘以信号量的比率
// , 0, audioPacket, j * 2, 2);
// }
// }
// }
// while (audioUdp.isPttOn) {
// if (System.currentTimeMillis() - now >= 21) {//20毫秒一个周期
// break;
// }
// }
// }
// Log.d(TAG, "run: 音频发送完毕!!");
// Thread.currentThread().interrupt();
// }
//
// }
/**
* 接收到电台发过来的音频数据
*
* @param packet 数据包
* @param data 数据
*/
@Override
public void onDataReceived(DatagramPacket packet, byte[] data) {
super.onDataReceived(packet, data);
if (IComPacketTypes.CONTROL_SIZE == data.length) {
if (IComPacketTypes.ControlPacket.getType(data) == IComPacketTypes.CMD_I_AM_READY) {
startTxAudio();
}
}
if (!IComPacketTypes.AudioPacket.isAudioPacket(data)) return;
byte[] audioData = IComPacketTypes.AudioPacket.getAudioData(data);
if (onStreamEvents != null) {
onStreamEvents.OnReceivedAudioData(audioData);
}
}
}