APRS transmit over FreeDV data

aprs
sh123 2022-08-14 15:57:05 +03:00
rodzic 2e48935c67
commit 8aedde6f9c
5 zmienionych plików z 52 dodań i 23 usunięć

Wyświetl plik

@ -6,7 +6,6 @@ import android.util.Log;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import com.radio.codec2talkie.app.AppWorker;
import com.radio.codec2talkie.protocol.message.TextMessage; import com.radio.codec2talkie.protocol.message.TextMessage;
import com.radio.codec2talkie.protocol.position.Position; import com.radio.codec2talkie.protocol.position.Position;
import com.radio.codec2talkie.settings.PreferenceKeys; import com.radio.codec2talkie.settings.PreferenceKeys;
@ -25,10 +24,14 @@ public class Freedv implements Protocol {
private Transport _transport; private Transport _transport;
private long _freedv; private long _freedv;
private long _freedvData;
private short[] _modemTxBuffer; private short[] _modemTxBuffer;
private short[] _speechRxBuffer; private short[] _speechRxBuffer;
private short[] _dataSamplesBuffer;
private byte[] _dataTxBuffer;
public Freedv() { public Freedv() {
} }
@ -48,6 +51,10 @@ public class Freedv implements Protocol {
_freedv = Codec2.freedvCreate(mode, isSquelchEnabled, squelchSnr); _freedv = Codec2.freedvCreate(mode, isSquelchEnabled, squelchSnr);
_modemTxBuffer = new short[Codec2.freedvGetNomModemSamples(_freedv)]; _modemTxBuffer = new short[Codec2.freedvGetNomModemSamples(_freedv)];
_speechRxBuffer = new short[Codec2.freedvGetMaxSpeechSamples(_freedv)]; _speechRxBuffer = new short[Codec2.freedvGetMaxSpeechSamples(_freedv)];
_freedvData = Codec2.freedvCreate(dataMode, isSquelchEnabled, squelchSnr);
_dataTxBuffer = new byte[Codec2.freedvGetBitsPerModemFrame(_freedvData) / 8];
_dataSamplesBuffer = new short[Codec2.freedvGetNTxSamples(_freedvData)];
} }
@Override @Override
@ -75,7 +82,24 @@ public class Freedv implements Protocol {
@Override @Override
public void sendData(String src, String dst, byte[] dataPacket) throws IOException { public void sendData(String src, String dst, byte[] dataPacket) throws IOException {
// TODO, send as data Log.v(TAG, "sendData() " + dataPacket.length);
if (dataPacket.length > _dataTxBuffer.length - 2) {
Log.e(TAG, "Too large packet " + dataPacket.length + " > " + _dataTxBuffer.length);
return;
}
long cnt = Codec2.freedvRawDataPreambleTx(_freedvData, _dataSamplesBuffer);
Log.v(TAG, "sendData() write preamble " + cnt);
_transport.write(Arrays.copyOf(_dataSamplesBuffer, (int) cnt));
Arrays.fill(_dataTxBuffer, (byte) 0);
System.arraycopy(dataPacket, 0, _dataTxBuffer, 0, dataPacket.length);
Codec2.freedvRawDataTx(_freedvData, _dataSamplesBuffer, _dataTxBuffer);
Log.v(TAG, "sendData() write data " + _dataSamplesBuffer.length);
_transport.write(_dataSamplesBuffer);
cnt = Codec2.freedvRawDataPostambleTx(_freedvData, _dataSamplesBuffer);
Log.v(TAG, "sendData() write postamble " + cnt);
_transport.write(Arrays.copyOf(_dataSamplesBuffer, (int) cnt));
} }
@Override @Override
@ -109,6 +133,7 @@ public class Freedv implements Protocol {
@Override @Override
public void close() { public void close() {
Codec2.freedvDestroy(_freedvData);
Codec2.freedvDestroy(_freedv); Codec2.freedvDestroy(_freedv);
} }
} }

Wyświetl plik

@ -68,7 +68,9 @@ public class ProtocolFactory {
boolean scramblingEnabled = SettingsWrapper.isKissScramblerEnabled(sharedPreferences); boolean scramblingEnabled = SettingsWrapper.isKissScramblerEnabled(sharedPreferences);
String scramblingKey = SettingsWrapper.getKissScramblerKey(sharedPreferences); String scramblingKey = SettingsWrapper.getKissScramblerKey(sharedPreferences);
boolean aprsEnabled = SettingsWrapper.isAprsEnabled(sharedPreferences); boolean aprsEnabled = SettingsWrapper.isAprsEnabled(sharedPreferences);
boolean freedvEnabled = SettingsWrapper.isFreeDvSoundModemModulation(sharedPreferences);
// "root" protocol
Protocol proto; Protocol proto;
switch (protocolType) { switch (protocolType) {
case KISS: case KISS:
@ -84,8 +86,8 @@ public class ProtocolFactory {
proto = new Hdlc(sharedPreferences); proto = new Hdlc(sharedPreferences);
break; break;
case FREEDV: case FREEDV:
// standalone proto = new Freedv();
return new Freedv(); break;
case RAW: case RAW:
default: default:
proto = new Raw(); proto = new Raw();
@ -98,12 +100,14 @@ public class ProtocolFactory {
if (aprsEnabled) { if (aprsEnabled) {
proto = new Ax25(proto); proto = new Ax25(proto);
} }
if (recordingEnabled) { if (!freedvEnabled) {
proto = new Recorder(proto, codec2ModeId); if (recordingEnabled) {
} proto = new Recorder(proto, codec2ModeId);
}
proto = new AudioFrameAggregator(proto, codec2ModeId); proto = new AudioFrameAggregator(proto, codec2ModeId);
proto = new AudioCodec2(proto, codec2ModeId); proto = new AudioCodec2(proto, codec2ModeId);
}
if (aprsEnabled) { if (aprsEnabled) {
proto = new Aprs(proto); proto = new Aprs(proto);

Wyświetl plik

@ -85,7 +85,6 @@ public class SettingsWrapper {
} }
public static boolean isAprsEnabled(SharedPreferences sharedPreferences) { public static boolean isAprsEnabled(SharedPreferences sharedPreferences) {
return sharedPreferences.getBoolean(PreferenceKeys.APRS_ENABLED, false) && return sharedPreferences.getBoolean(PreferenceKeys.APRS_ENABLED, false);
!isFreeDvSoundModemModulation(sharedPreferences); // no aprs when in freedv
} }
} }

Wyświetl plik

@ -73,7 +73,7 @@ public class SoundModemBase implements Runnable {
} }
private void constructSystemAudioDevices(boolean disableRx, int sampleRate) { private void constructSystemAudioDevices(boolean disableRx, int sampleRate) {
int audioRecorderMinBufferSize = AudioRecord.getMinBufferSize( int audioRecorderMinBufferSize = 10 * AudioRecord.getMinBufferSize(
sampleRate, sampleRate,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT); AudioFormat.ENCODING_PCM_16BIT);
@ -84,12 +84,13 @@ public class SoundModemBase implements Runnable {
sampleRate, sampleRate,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, AudioFormat.ENCODING_PCM_16BIT,
10*audioRecorderMinBufferSize); audioRecorderMinBufferSize);
int audioPlayerMinBufferSize = AudioTrack.getMinBufferSize( int audioPlayerMinBufferSize = 10 * AudioTrack.getMinBufferSize(
sampleRate, sampleRate,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT); AudioFormat.ENCODING_PCM_16BIT);
if (!disableRx) if (!disableRx)
_systemAudioRecorder.startRecording(); _systemAudioRecorder.startRecording();
@ -105,9 +106,11 @@ public class SoundModemBase implements Runnable {
.setChannelMask(AudioFormat.CHANNEL_OUT_MONO) .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
.build()) .build())
.setTransferMode(AudioTrack.MODE_STREAM) .setTransferMode(AudioTrack.MODE_STREAM)
.setBufferSizeInBytes(10*audioPlayerMinBufferSize) .setBufferSizeInBytes(audioPlayerMinBufferSize)
.build(); .build();
_systemAudioPlayer.setVolume(AudioTrack.getMaxVolume()); _systemAudioPlayer.setVolume(AudioTrack.getMaxVolume());
Log.i(TAG, "Play buffer size " + audioPlayerMinBufferSize + ", recorder " + audioRecorderMinBufferSize);
} }
protected int read(short[] sampleBuffer, int samplesToRead) { protected int read(short[] sampleBuffer, int samplesToRead) {

Wyświetl plik

@ -112,7 +112,7 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
conFreedv->rawData = static_cast<unsigned char *>(malloc( conFreedv->rawData = static_cast<unsigned char *>(malloc(
freedv_get_bits_per_modem_frame(conFreedv->freeDv) / 8)); freedv_get_bits_per_modem_frame(conFreedv->freeDv) / 8));
conFreedv->rawDataSamples = static_cast<short *>(malloc( conFreedv->rawDataSamples = static_cast<short *>(malloc(
freedv_get_n_tx_modem_samples(conFreedv->freeDv))); freedv_get_n_tx_modem_samples(conFreedv->freeDv) * sizeof(short)));
// squelch // squelch
freedv_set_squelch_en(conFreedv->freeDv, isSquelchEnabled); freedv_set_squelch_en(conFreedv->freeDv, isSquelchEnabled);
freedv_set_snr_squelch_thresh(conFreedv->freeDv, squelchSnr); freedv_set_snr_squelch_thresh(conFreedv->freeDv, squelchSnr);
@ -278,23 +278,21 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
conFreedv->rawData[cntBytes-1] = crc16 & 0xff; conFreedv->rawData[cntBytes-1] = crc16 & 0xff;
freedv_rawdatatx(conFreedv->freeDv, conFreedv->rawDataSamples, conFreedv->rawData); freedv_rawdatatx(conFreedv->freeDv, conFreedv->rawDataSamples, conFreedv->rawData);
int cntSamples = freedv_get_n_tx_modem_samples(conFreedv->freeDv); int cntSamples = freedv_get_n_tx_modem_samples(conFreedv->freeDv);
env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->modemSamples); env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->rawDataSamples);
return cntSamples; return cntSamples;
} }
static jlong freedvRawDataPreambleTx(JNIEnv *env, jclass clazz, jlong n, jshortArray outputModemSamples) { static jlong freedvRawDataPreambleTx(JNIEnv *env, jclass clazz, jlong n, jshortArray outputModemSamples) {
ContextFreedv *conFreedv = getContextFreedv(n); ContextFreedv *conFreedv = getContextFreedv(n);
freedv_rawdatapreambletx(conFreedv->freeDv, conFreedv->rawDataSamples); int cntSamples = freedv_rawdatapreambletx(conFreedv->freeDv, conFreedv->rawDataSamples);
int cntSamples = freedv_get_n_tx_modem_samples(conFreedv->freeDv); env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->rawDataSamples);
env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->modemSamples);
return cntSamples; return cntSamples;
} }
static jlong freedvRawDataPostambleTx(JNIEnv *env, jclass clazz, jlong n, jshortArray outputModemSamples) { static jlong freedvRawDataPostambleTx(JNIEnv *env, jclass clazz, jlong n, jshortArray outputModemSamples) {
ContextFreedv *conFreedv = getContextFreedv(n); ContextFreedv *conFreedv = getContextFreedv(n);
freedv_rawdatapostambletx(conFreedv->freeDv, conFreedv->rawDataSamples); int cntSamples = freedv_rawdatapostambletx(conFreedv->freeDv, conFreedv->rawDataSamples);
int cntSamples = freedv_get_n_tx_modem_samples(conFreedv->freeDv); env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->rawDataSamples);
env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->modemSamples);
return cntSamples; return cntSamples;
} }