kopia lustrzana https://github.com/sh123/codec2_talkie
Enable squelch and add loopback setting
rodzic
5d315c3dea
commit
b0c331a8bb
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -307,4 +307,6 @@
|
|||
<string name="ports_sound_modem_rig_label">🎛</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>
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue