Enable squelch and add loopback setting

aprs
sh123 2022-08-11 12:01:02 +03:00
rodzic 5d315c3dea
commit b0c331a8bb
11 zmienionych plików z 98 dodań i 32 usunięć

Wyświetl plik

@ -62,7 +62,7 @@ public class AppWorker extends Thread {
// output data., mic -> bt
private AudioRecord _systemAudioRecorder;
private final short[] _recordAudioBuffer;
private short[] _recordAudioBuffer;
// callbacks
private final Handler _onPlayerStateChanged;
@ -98,7 +98,6 @@ public class AppWorker extends Thread {
_protocol = ProtocolFactory.create(_codec2Mode, context);
_processPeriodicTimer = new Timer();
_recordAudioBuffer = new short[_protocol.getPcmAudioBufferSize()];
constructSystemAudioDevices(transportType);
}
@ -541,6 +540,7 @@ public class AppWorker extends Thread {
try {
_protocol.initialize(_transport, _context, _protocolCallback);
_recordAudioBuffer = new short[_protocol.getPcmAudioBufferSize()];
startWorkerMessageHandler();
Looper.loop();
} catch (IOException e) {

Wyświetl plik

@ -1,9 +1,15 @@
package com.radio.codec2talkie.protocol;
import android.content.Context;
import android.content.SharedPreferences;
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;
import com.radio.codec2talkie.transport.Transport;
import com.ustadmobile.codec2.Codec2;
@ -11,8 +17,7 @@ import java.io.IOException;
import java.util.Arrays;
public class Freedv implements Protocol {
private final int _freedvMode;
private final Protocol _childProtocol;
private static final String TAG = Freedv.class.getSimpleName();
private ProtocolCallback _parentProtocolCallback;
private Transport _transport;
@ -22,18 +27,20 @@ public class Freedv implements Protocol {
private short[] _modemTxBuffer;
private short[] _speechRxBuffer;
public Freedv(Protocol childProtocol, int freedvMode) {
_childProtocol = childProtocol;
_freedvMode = freedvMode;
public Freedv() {
}
@Override
public void initialize(Transport transport, Context context, ProtocolCallback parentProtocolCallback) throws IOException {
_transport = transport;
_parentProtocolCallback = parentProtocolCallback;
_childProtocol.initialize(transport, context, _parentProtocolCallback);
_freedv = Codec2.freedvCreate(_freedvMode);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String modemType = sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_TYPE, "1200");
int mode = Integer.parseInt(modemType.substring(1));
Log.i(TAG, "Using freedv mode " + mode);
_freedv = Codec2.freedvCreate(mode);
_modemTxBuffer = new short[Codec2.freedvGetNomModemSamples(_freedv)];
_speechRxBuffer = new short[Codec2.freedvGetMaxSpeechSamples(_freedv)];
}
@ -46,7 +53,9 @@ public class Freedv implements Protocol {
@Override
public void sendPcmAudio(String src, String dst, int codec, short[] pcmFrame) throws IOException {
Codec2.freedvTx(_freedv, _modemTxBuffer, pcmFrame);
Log.i(TAG, "send pcm " + _modemTxBuffer.length);
_transport.write(_modemTxBuffer);
_parentProtocolCallback.onTransmitPcmAudio(src, dst, codec, pcmFrame);
}
@Override
@ -69,6 +78,7 @@ public class Freedv implements Protocol {
if (bytesRead == nin) {
long cntRead = Codec2.freedvRx(_freedv, _speechRxBuffer, buf);
if (cntRead > 0) {
Log.i(TAG, "receive " + cntRead);
_parentProtocolCallback.onReceivePcmAudio(null, null, -1, Arrays.copyOf(_speechRxBuffer, (int) cntRead));
return true;
}

Wyświetl plik

@ -14,7 +14,8 @@ public class ProtocolFactory {
HDLC("HDLC"),
KISS("KISS"),
KISS_BUFFERED("KISS BUF"),
KISS_PARROT("KISS RPT");
KISS_PARROT("KISS RPT"),
FREEDV("FREEDV");
private final String _name;
@ -35,7 +36,11 @@ public class ProtocolFactory {
// Use HDLC instead of KISS for the sound modem as we are the modem
if (sharedPreferences.getString(PreferenceKeys.PORTS_TYPE, "loopback").equals("sound_modem")) {
protocolType = ProtocolFactory.ProtocolType.HDLC;
if (sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_TYPE, "1200").startsWith("F")) {
protocolType = ProtocolType.FREEDV;
} else {
protocolType = ProtocolFactory.ProtocolType.HDLC;
}
} else if (sharedPreferences.getBoolean(PreferenceKeys.KISS_ENABLED, true)) {
if (sharedPreferences.getBoolean(PreferenceKeys.KISS_PARROT, false)) {
protocolType = ProtocolFactory.ProtocolType.KISS_PARROT;
@ -77,6 +82,9 @@ public class ProtocolFactory {
case HDLC:
proto = new Hdlc(sharedPreferences);
break;
case FREEDV:
// standalone
return new Freedv();
case RAW:
default:
proto = new Raw();
@ -96,7 +104,7 @@ public class ProtocolFactory {
proto = new AudioFrameAggregator(proto, codec2ModeId);
proto = new AudioCodec2(proto, codec2ModeId);
if (aprsEnabled) { // && protocolType != ProtocolType.RAW) {
if (aprsEnabled) {
proto = new Aprs(proto);
}
return proto;

Wyświetl plik

@ -23,6 +23,7 @@ public final class PreferenceKeys {
public static String PORTS_SOUND_MODEM_RIG = "ports_sound_modem_rig";
public static String PORTS_SOUND_MODEM_GAIN ="ports_sound_modem_gain";
public static String PORTS_SOUND_MODEM_PTT_OFF_DELAY_MS = "ports_sound_modem_ptt_off_delay_ms";
public static String PORTS_SOUND_MODEM_LOOPBACK="ports_sound_modem_loopback";
public static String CODEC2_MODE = "codec2_mode";
public static String CODEC2_RECORDING_ENABLED = "codec2_recording_enabled";

Wyświetl plik

@ -17,6 +17,7 @@ import com.radio.codec2talkie.rigctl.RigCtlFactory;
import com.radio.codec2talkie.settings.PreferenceKeys;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import java.util.Timer;
@ -43,12 +44,17 @@ public class SoundModem implements Transport, Runnable {
private final ShortBuffer _recordAudioBuffer;
private boolean _isLoopback = false;
public SoundModem(Context context) {
_name = "SndModem";
_isPttOn = false;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
boolean disableRx = sharedPreferences.getBoolean(PreferenceKeys.PORTS_SOUND_MODEM_DISABLE_RX, false);
_pttOffDelayMs = Integer.parseInt(sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_PTT_OFF_DELAY_MS, "1000"));
_name = "SndModem";
_isLoopback = sharedPreferences.getBoolean(PreferenceKeys.PORTS_SOUND_MODEM_LOOPBACK, false);
constructSystemAudioDevices(disableRx);
@ -59,11 +65,9 @@ public class SoundModem implements Transport, Runnable {
e.printStackTrace();
}
_recordAudioBuffer = ShortBuffer.allocate(4096);
_recordAudioBuffer = ShortBuffer.allocate(_isLoopback ? 1024*100 : 1024*10);
_isPttOn = false;
if (!disableRx)
if (!disableRx && !_isLoopback)
new Thread(this).start();
}
@ -124,6 +128,7 @@ public class SoundModem implements Transport, Runnable {
public int read(short[] audioSamples) throws IOException {
synchronized (_recordAudioBuffer) {
if (_recordAudioBuffer.position() >= audioSamples.length) {
//Log.i(TAG, "read " + _recordAudioBuffer.position());
_recordAudioBuffer.flip();
_recordAudioBuffer.get(audioSamples);
_recordAudioBuffer.compact();
@ -138,7 +143,20 @@ public class SoundModem implements Transport, Runnable {
pttOn();
if (_systemAudioPlayer.getPlayState() != AudioTrack.PLAYSTATE_PLAYING)
_systemAudioPlayer.play();
_systemAudioPlayer.write(audioSamples, 0, audioSamples.length);
if (_isLoopback) {
synchronized (_recordAudioBuffer) {
for (short sample : audioSamples) {
try {
_recordAudioBuffer.put(sample);
} catch (BufferOverflowException e) {
e.printStackTrace();
_recordAudioBuffer.clear();
}
}
}
} else {
_systemAudioPlayer.write(audioSamples, 0, audioSamples.length);
}
_systemAudioPlayer.stop();
pttOff();
return audioSamples.length;
@ -156,6 +174,7 @@ public class SoundModem implements Transport, Runnable {
@Override
public void run() {
Log.i(TAG, "Starting receive thread");
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
int readSize = 16;
short [] sampleBuf = new short[readSize];
@ -172,7 +191,12 @@ public class SoundModem implements Transport, Runnable {
}
synchronized (_recordAudioBuffer) {
for (short sample : sampleBuf) {
_recordAudioBuffer.put(sample);
try {
_recordAudioBuffer.put(sample);
} catch (BufferOverflowException e) {
e.printStackTrace();
_recordAudioBuffer.clear();
}
}
}
}

Wyświetl plik

@ -53,7 +53,7 @@ public class SoundModemFsk implements Transport, Runnable {
private boolean _isRunning = true;
private final ByteBuffer _sampleBuffer;
private final boolean _isLoopback = false;
private boolean _isLoopback = false;
private final long _fskModem;
@ -70,6 +70,8 @@ public class SoundModemFsk implements Transport, Runnable {
int bitRate = Integer.parseInt(_sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_TYPE, "1200"));
int gain = Integer.parseInt(_sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_GAIN, "10000"));
_pttOffDelayMs = Integer.parseInt(_sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_PTT_OFF_DELAY_MS, "1000"));
_isLoopback = _sharedPreferences.getBoolean(PreferenceKeys.PORTS_SOUND_MODEM_LOOPBACK, false);
_name = "SndModemFsk" + bitRate;
if (bitRate == 300) {
// <230 spacing for 300 bps does not work with codec2 fsk for receive

Wyświetl plik

@ -1,11 +1,15 @@
package com.radio.codec2talkie.transport;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.preference.PreferenceManager;
import com.radio.codec2talkie.connect.BleHandler;
import com.radio.codec2talkie.connect.BluetoothSocketHandler;
import com.radio.codec2talkie.connect.TcpIpSocketHandler;
import com.radio.codec2talkie.connect.UsbPortHandler;
import com.radio.codec2talkie.settings.PreferenceKeys;
import java.io.IOException;
@ -32,6 +36,7 @@ public class TransportFactory {
}
public static Transport create(TransportType transportType, Context context) throws IOException {
switch (transportType) {
case USB:
return new UsbSerial(UsbPortHandler.getPort(), UsbPortHandler.getName());
@ -42,10 +47,16 @@ public class TransportFactory {
case BLE:
return new Ble(BleHandler.getGatt(), BleHandler.getName());
case SOUND_MODEM:
return new SoundModemFsk(context);
return isFreeDv(context) ? new SoundModem(context) : new SoundModemFsk(context);
case LOOPBACK:
default:
return new Loopback();
}
}
private static boolean isFreeDv(Context context) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String modemType = sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_TYPE, "1200");
return modemType.startsWith("F");
}
}

Wyświetl plik

@ -332,9 +332,9 @@
<item>FreeDV 800XA</item>
<item>FreeDV 700C</item>
<item>FreeDV 700D</item>
<item>FreeDV 2020</item>
<!--item>FreeDV 2020</item>
<item>FreeDV 2020B</item>
<item>FreeDV 700E</item>
<item>FreeDV 700E</item-->
</string-array>
<string-array name="ports_sound_modem_type_values">
@ -346,9 +346,9 @@
<item>F5</item>
<item>F6</item>
<item>F7</item>
<item>F8</item>
<!--item>F8</item>
<item>F16</item>
<item>F13</item>
<item>F13</item-->
</string-array>
<string-array name="ports_type_labels">

Wyświetl plik

@ -307,4 +307,6 @@
<string name="ports_sound_modem_rig_label">&#127899;</string>
<string name="ports_sound_modem_ptt_off_delay_ms_title">CAT PTT transmit off delay</string>
<string name="ports_sound_modem_ptt_off_delay_ms_summary">How long to wait before switching off the transmission after last data is sent out (milliseconds)</string>
<string name="ports_sound_modem_loopback_title">Enable modulator loopback mode</string>
<string name="ports_sound_modem_loopback_summary">Audio modulated samples will be fed back to de-modulator</string>
</resources>

Wyświetl plik

@ -22,13 +22,6 @@
app:defaultValue="200">
</EditTextPreference>
<SwitchPreference
app:key="ports_sound_modem_disable_rx"
app:title="@string/ports_sound_modem_disable_rx_title"
app:summary="@string/ports_sound_modem_disable_rx_summary"
app:defaultValue="false">
</SwitchPreference>
<ListPreference
app:key="ports_sound_modem_rig"
app:title="@string/ports_sound_modem_rig_title"
@ -54,5 +47,19 @@
app:defaultValue="1000">
</EditTextPreference>
<SwitchPreference
app:key="ports_sound_modem_disable_rx"
app:title="@string/ports_sound_modem_disable_rx_title"
app:summary="@string/ports_sound_modem_disable_rx_summary"
app:defaultValue="false">
</SwitchPreference>
<SwitchPreference
app:key="ports_sound_modem_loopback"
app:title="@string/ports_sound_modem_loopback_title"
app:summary="@string/ports_sound_modem_loopback_summary"
app:defaultValue="false">
</SwitchPreference>
</PreferenceCategory>
</PreferenceScreen>

Wyświetl plik

@ -105,6 +105,7 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
freedv_get_n_max_speech_samples(conFreedv->freeDv) * sizeof(short)));
conFreedv->modemSamples = static_cast<short *>(malloc(
freedv_get_n_max_modem_samples(conFreedv->freeDv) * sizeof(short)));
freedv_set_squelch_en(conFreedv->freeDv, 1);
return reinterpret_cast<jlong>(conFreedv);
}