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 com.radio.codec2talkie.app.AppWorker;
import com.radio.codec2talkie.protocol.message.TextMessage;
import com.radio.codec2talkie.protocol.position.Position;
import com.radio.codec2talkie.settings.PreferenceKeys;
@ -25,10 +24,14 @@ public class Freedv implements Protocol {
private Transport _transport;
private long _freedv;
private long _freedvData;
private short[] _modemTxBuffer;
private short[] _speechRxBuffer;
private short[] _dataSamplesBuffer;
private byte[] _dataTxBuffer;
public Freedv() {
}
@ -48,6 +51,10 @@ public class Freedv implements Protocol {
_freedv = Codec2.freedvCreate(mode, isSquelchEnabled, squelchSnr);
_modemTxBuffer = new short[Codec2.freedvGetNomModemSamples(_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
@ -75,7 +82,24 @@ public class Freedv implements Protocol {
@Override
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
@ -109,6 +133,7 @@ public class Freedv implements Protocol {
@Override
public void close() {
Codec2.freedvDestroy(_freedvData);
Codec2.freedvDestroy(_freedv);
}
}

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -73,7 +73,7 @@ public class SoundModemBase implements Runnable {
}
private void constructSystemAudioDevices(boolean disableRx, int sampleRate) {
int audioRecorderMinBufferSize = AudioRecord.getMinBufferSize(
int audioRecorderMinBufferSize = 10 * AudioRecord.getMinBufferSize(
sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
@ -84,12 +84,13 @@ public class SoundModemBase implements Runnable {
sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
10*audioRecorderMinBufferSize);
audioRecorderMinBufferSize);
int audioPlayerMinBufferSize = AudioTrack.getMinBufferSize(
int audioPlayerMinBufferSize = 10 * AudioTrack.getMinBufferSize(
sampleRate,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (!disableRx)
_systemAudioRecorder.startRecording();
@ -105,9 +106,11 @@ public class SoundModemBase implements Runnable {
.setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
.build())
.setTransferMode(AudioTrack.MODE_STREAM)
.setBufferSizeInBytes(10*audioPlayerMinBufferSize)
.setBufferSizeInBytes(audioPlayerMinBufferSize)
.build();
_systemAudioPlayer.setVolume(AudioTrack.getMaxVolume());
Log.i(TAG, "Play buffer size " + audioPlayerMinBufferSize + ", recorder " + audioRecorderMinBufferSize);
}
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(
freedv_get_bits_per_modem_frame(conFreedv->freeDv) / 8));
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
freedv_set_squelch_en(conFreedv->freeDv, isSquelchEnabled);
freedv_set_snr_squelch_thresh(conFreedv->freeDv, squelchSnr);
@ -278,23 +278,21 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
conFreedv->rawData[cntBytes-1] = crc16 & 0xff;
freedv_rawdatatx(conFreedv->freeDv, conFreedv->rawDataSamples, conFreedv->rawData);
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;
}
static jlong freedvRawDataPreambleTx(JNIEnv *env, jclass clazz, jlong n, jshortArray outputModemSamples) {
ContextFreedv *conFreedv = getContextFreedv(n);
freedv_rawdatapreambletx(conFreedv->freeDv, conFreedv->rawDataSamples);
int cntSamples = freedv_get_n_tx_modem_samples(conFreedv->freeDv);
env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->modemSamples);
int cntSamples = freedv_rawdatapreambletx(conFreedv->freeDv, conFreedv->rawDataSamples);
env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->rawDataSamples);
return cntSamples;
}
static jlong freedvRawDataPostambleTx(JNIEnv *env, jclass clazz, jlong n, jshortArray outputModemSamples) {
ContextFreedv *conFreedv = getContextFreedv(n);
freedv_rawdatapostambletx(conFreedv->freeDv, conFreedv->rawDataSamples);
int cntSamples = freedv_get_n_tx_modem_samples(conFreedv->freeDv);
env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->modemSamples);
int cntSamples = freedv_rawdatapostambletx(conFreedv->freeDv, conFreedv->rawDataSamples);
env->SetShortArrayRegion(outputModemSamples, 0, cntSamples, conFreedv->rawDataSamples);
return cntSamples;
}