diff --git a/codec2talkie/build.gradle b/codec2talkie/build.gradle
index 3c08299..fe1bab7 100644
--- a/codec2talkie/build.gradle
+++ b/codec2talkie/build.gradle
@@ -10,8 +10,8 @@ android {
applicationId "com.radio.codec2talkie"
minSdkVersion 21
targetSdkVersion 30
- versionCode 132
- versionName "1.32"
+ versionCode 133
+ versionName "1.33"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/MainActivity.java b/codec2talkie/src/main/java/com/radio/codec2talkie/MainActivity.java
index 19bc5ff..46ce723 100644
--- a/codec2talkie/src/main/java/com/radio/codec2talkie/MainActivity.java
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/MainActivity.java
@@ -110,6 +110,7 @@ public class MainActivity extends AppCompatActivity implements ServiceConnection
private boolean _isConnecting = false;
private boolean _isAppExit = false;
private boolean _isAppRestart = false;
+ private boolean _isRigCtlUsbConnected = false;
private long _backPressedTimestamp;
@@ -262,7 +263,11 @@ public class MainActivity extends AppCompatActivity implements ServiceConnection
break;
case "sound_modem":
_textConnInfo.setText(R.string.main_status_sound_modem);
- startAppService(TransportFactory.TransportType.SOUND_MODEM);
+ String rig = _sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_RIG, "Disabled");
+ if (rig.equals("Disabled"))
+ startAppService(TransportFactory.TransportType.SOUND_MODEM);
+ else
+ startUsbConnectActivity();
break;
case "tcp_ip":
startTcpIpConnectActivity();
@@ -284,7 +289,11 @@ public class MainActivity extends AppCompatActivity implements ServiceConnection
Intent data = result.getData();
assert data != null;
int resultCode = result.getResultCode();
- if (resultCode == RESULT_CANCELED) {
+ String transportType = _sharedPreferences.getString(PreferenceKeys.PORTS_TYPE, "loopback");
+ if (transportType.equals("sound_modem")) {
+ _isRigCtlUsbConnected = resultCode == RESULT_OK;
+ startAppService(TransportFactory.TransportType.SOUND_MODEM);
+ } else if (resultCode == RESULT_CANCELED) {
_textConnInfo.setText(R.string.main_status_loopback_test);
startAppService(TransportFactory.TransportType.LOOPBACK);
} else if (resultCode == RESULT_OK) {
@@ -296,6 +305,7 @@ public class MainActivity extends AppCompatActivity implements ServiceConnection
protected void startUsbConnectActivity() {
_isConnecting = true;
+ _isRigCtlUsbConnected = false;
_usbActivityLauncher.launch(new Intent(this, UsbConnectActivity.class));
}
@@ -456,6 +466,12 @@ public class MainActivity extends AppCompatActivity implements ServiceConnection
status += getString(R.string.kiss_scrambler_label);
}
+ // rig CAT control
+ String rigName = _sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_RIG, "Disabled");
+ if (!rigName.equals("Disabled") && _isRigCtlUsbConnected) {
+ status += getString(R.string.ports_sound_modem_rig_label);
+ }
+
// aprs
boolean aprsEnabled = _sharedPreferences.getBoolean(PreferenceKeys.APRS_ENABLED, false);
if (aprsEnabled) {
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/connect/UsbConnectActivity.java b/codec2talkie/src/main/java/com/radio/codec2talkie/connect/UsbConnectActivity.java
index 5d86560..ccc06a4 100644
--- a/codec2talkie/src/main/java/com/radio/codec2talkie/connect/UsbConnectActivity.java
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/connect/UsbConnectActivity.java
@@ -92,7 +92,7 @@ public class UsbConnectActivity extends AppCompatActivity {
customTable.addProduct(0x1b4f, 0x9204, CdcAcmSerialDriver.class);
// Arduino Due
customTable.addProduct(0x2341, 0x003d, CdcAcmSerialDriver.class);
- // STM
+ // STM, MCHF
customTable.addProduct(0x0483, 0x5732, CdcAcmSerialDriver.class);
return new UsbSerialProber(customTable);
}
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/protocol/Hdlc.java b/codec2talkie/src/main/java/com/radio/codec2talkie/protocol/Hdlc.java
index a7742bf..91f66e3 100644
--- a/codec2talkie/src/main/java/com/radio/codec2talkie/protocol/Hdlc.java
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/protocol/Hdlc.java
@@ -15,6 +15,7 @@ import com.radio.codec2talkie.transport.SoundModem;
import com.radio.codec2talkie.transport.Transport;
import java.io.IOException;
+import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -121,7 +122,12 @@ public class Hdlc implements Protocol {
_readByte = 0;
_prevHdlc = 0;
} else {
- _currentFrameBuffer.put(bit);
+ try {
+ _currentFrameBuffer.put(bit);
+ } catch (BufferOverflowException e) {
+ e.printStackTrace();
+ _currentFrameBuffer.clear();
+ }
_prevHdlc++;
}
}
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/Disabled.java b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/Disabled.java
new file mode 100644
index 0000000..e700b27
--- /dev/null
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/Disabled.java
@@ -0,0 +1,21 @@
+package com.radio.codec2talkie.rigctl;
+
+import android.content.Context;
+
+import com.radio.codec2talkie.transport.Transport;
+
+import java.io.IOException;
+
+public class Disabled implements RigCtl{
+ @Override
+ public void initialize(Transport transport, Context context, RigCtlCallback protocolCallback) throws IOException {
+ }
+
+ @Override
+ public void pttOn() {
+ }
+
+ @Override
+ public void pttOff() {
+ }
+}
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/Ft817.java b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/Ft817.java
new file mode 100644
index 0000000..4e9ad0b
--- /dev/null
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/Ft817.java
@@ -0,0 +1,51 @@
+package com.radio.codec2talkie.rigctl;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.radio.codec2talkie.transport.Transport;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+// http://www.ka7oei.com/ft817_meow.html
+public class Ft817 implements RigCtl {
+ private static final String TAG = Ft817.class.getSimpleName();
+
+ private Transport _transport;
+
+ @Override
+ public void initialize(Transport transport, Context context, RigCtlCallback protocolCallback) throws IOException {
+ _transport = transport;
+ }
+
+ @Override
+ public void pttOn() throws IOException {
+ // 0x00, 0x00, 0x00, 0x00, 0x08
+ // returns 0x00 (was un-keyed), 0xf0 (already keyed)
+ Log.i(TAG, "PTT ON");
+ ByteBuffer cmd = ByteBuffer.allocate(5);
+ cmd.put((byte)0x00).put((byte)0x00).put((byte)0x00).put((byte)0x00).put((byte)0x08);
+ _transport.write(cmd.array());
+ Log.i(TAG, "PTT ON done");
+
+ byte[] response = new byte[1];
+ int bytesRead = _transport.read(response);
+ Log.i(TAG, "PTT ON response: " + bytesRead + " " + response[0]);
+ }
+
+ @Override
+ public void pttOff() throws IOException {
+ // 0x00, 0x00, 0x00, 0x00, 0x88
+ // returns 0x00 (was keyed), 0xf0 (already un-keyed)
+ Log.i(TAG, "PTT OFF");
+ ByteBuffer cmd = ByteBuffer.allocate(5);
+ cmd.put((byte)0x00).put((byte)0x00).put((byte)0x00).put((byte)0x00).put((byte)0x88);
+ _transport.write(cmd.array());
+ Log.i(TAG, "PTT OFF done");
+
+ byte[] response = new byte[1];
+ int bytesRead = _transport.read(response);
+ Log.i(TAG, "PTT OFF response: " + bytesRead + " " + response[0]);
+ }
+}
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/RigCtl.java b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/RigCtl.java
new file mode 100644
index 0000000..31788f3
--- /dev/null
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/RigCtl.java
@@ -0,0 +1,15 @@
+package com.radio.codec2talkie.rigctl;
+
+import android.content.Context;
+
+import com.radio.codec2talkie.protocol.ProtocolCallback;
+import com.radio.codec2talkie.transport.Transport;
+
+import java.io.IOException;
+
+public interface RigCtl {
+ void initialize(Transport transport, Context context, RigCtlCallback protocolCallback) throws IOException;
+
+ void pttOn() throws IOException;
+ void pttOff() throws IOException;
+}
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/RigCtlCallback.java b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/RigCtlCallback.java
new file mode 100644
index 0000000..ecc7b06
--- /dev/null
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/RigCtlCallback.java
@@ -0,0 +1,4 @@
+package com.radio.codec2talkie.rigctl;
+
+public interface RigCtlCallback {
+}
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/RigCtlFactory.java b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/RigCtlFactory.java
new file mode 100644
index 0000000..38af74e
--- /dev/null
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/rigctl/RigCtlFactory.java
@@ -0,0 +1,29 @@
+package com.radio.codec2talkie.rigctl;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Log;
+
+import androidx.preference.PreferenceManager;
+
+import com.radio.codec2talkie.connect.UsbPortHandler;
+import com.radio.codec2talkie.settings.PreferenceKeys;
+
+public class RigCtlFactory {
+ private static final String TAG = RigCtlFactory.class.getSimpleName();
+
+ public static RigCtl create(Context context) {
+ if (UsbPortHandler.getPort() == null)
+ return new Disabled();
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+ String rigName = sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_RIG, "Disabled");
+ try {
+ Class> loadClass = Class.forName(String.format("com.radio.codec2talkie.rigctl.%s", rigName));
+ Log.i(TAG, "Using rig " + rigName);
+ return (RigCtl)loadClass.newInstance();
+ } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
+ e.printStackTrace();
+ return new Disabled();
+ }
+ }
+}
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/settings/PreferenceKeys.java b/codec2talkie/src/main/java/com/radio/codec2talkie/settings/PreferenceKeys.java
index 596a0e5..90cf9b5 100644
--- a/codec2talkie/src/main/java/com/radio/codec2talkie/settings/PreferenceKeys.java
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/settings/PreferenceKeys.java
@@ -20,6 +20,8 @@ public final class PreferenceKeys {
public static String PORTS_SOUND_MODEM_TYPE = "ports_sound_modem_type";
public static String PORTS_SOUND_MODEM_PREAMBLE = "ports_sound_modem_preamble";
public static String PORTS_SOUND_MODEM_DISABLE_RX = "ports_sound_modem_disable_rx";
+ 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 CODEC2_MODE = "codec2_mode";
public static String CODEC2_RECORDING_ENABLED = "codec2_recording_enabled";
diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/transport/SoundModem.java b/codec2talkie/src/main/java/com/radio/codec2talkie/transport/SoundModem.java
index 12032c8..705efe4 100644
--- a/codec2talkie/src/main/java/com/radio/codec2talkie/transport/SoundModem.java
+++ b/codec2talkie/src/main/java/com/radio/codec2talkie/transport/SoundModem.java
@@ -12,6 +12,8 @@ import android.util.Log;
import androidx.preference.PreferenceManager;
+import com.radio.codec2talkie.rigctl.RigCtl;
+import com.radio.codec2talkie.rigctl.RigCtlFactory;
import com.radio.codec2talkie.settings.PreferenceKeys;
import com.radio.codec2talkie.tools.AudioTools;
import com.radio.codec2talkie.tools.BitTools;
@@ -22,13 +24,18 @@ import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.Timer;
+import java.util.TimerTask;
public class SoundModem implements Transport, Runnable {
private static final String TAG = SoundModem.class.getSimpleName();
+ private static final int PTT_OFF_DELAY_MS = 1000;
+
// NOTE, codec2 library requires that sample_rate % bit_rate == 0
public static final int SAMPLE_RATE = 19200;
+ //public static final int SAMPLE_RATE = 48000;
private final String _name;
@@ -52,20 +59,25 @@ public class SoundModem implements Transport, Runnable {
private final long _fskModem;
+ private final RigCtl _rigCtl;
+ private Timer _pttOffTimer;
+ private boolean _isPttOn = false;
+
public SoundModem(Context context) {
_context = context;
_sharedPreferences = PreferenceManager.getDefaultSharedPreferences(_context);
boolean disableRx = _sharedPreferences.getBoolean(PreferenceKeys.PORTS_SOUND_MODEM_DISABLE_RX, false);
int bitRate = Integer.parseInt(_sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_TYPE, "1200"));
+ int gain = Integer.parseInt(_sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_GAIN, "10000"));
_name = "SoundModem" + bitRate;
if (bitRate == 300) {
// <230 spacing for 300 bps does not work with codec2 fsk for receive
- _fskModem = Codec2.fskCreate(SAMPLE_RATE, 300, 1600, 200);
+ _fskModem = Codec2.fskCreate(SAMPLE_RATE, 300, 1600, 200, gain);
} else if (bitRate == 1200) {
- _fskModem = Codec2.fskCreate(SAMPLE_RATE, 1200, 1200, 1000);
+ _fskModem = Codec2.fskCreate(SAMPLE_RATE, 1200, 1200, 1000, gain);
} else {
- _fskModem = Codec2.fskCreate(SAMPLE_RATE, 2400, 2165, 1805);
+ _fskModem = Codec2.fskCreate(SAMPLE_RATE, 2400, 2165, 1805, gain);
}
_recordAudioBuffer = new short[Codec2.fskDemodSamplesBufSize(_fskModem)];
@@ -82,6 +94,15 @@ public class SoundModem implements Transport, Runnable {
else
_sampleBuffer = ByteBuffer.allocate(0);
+ _rigCtl = RigCtlFactory.create(context);
+ try {
+ _rigCtl.initialize(TransportFactory.create(TransportFactory.TransportType.USB, context), context, null);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ _isPttOn = false;
+
if (!disableRx)
new Thread(this).start();
}
@@ -147,6 +168,8 @@ public class SoundModem implements Transport, Runnable {
@Override
public int write(byte[] srcDataBytesAsBits) throws IOException {
+ pttOn();
+
//Log.v(TAG, "write " + DebugTools.byteBitsToFlatString(srcDataBytesAsBits));
byte[] dataBytesAsBits = BitTools.convertToNRZI(srcDataBytesAsBits);
//Log.v(TAG, "write NRZ " + DebugTools.byteBitsToFlatString(dataBytesAsBits));
@@ -184,6 +207,7 @@ public class SoundModem implements Transport, Runnable {
} else {
_systemAudioPlayer.write(_playbackAudioBuffer, 0, bitBufferTail.length * _samplesPerSymbol);
}
+ pttOff();
return 0;
}
@@ -226,8 +250,10 @@ public class SoundModem implements Transport, Runnable {
}
} else {
int readCnt = _systemAudioRecorder.read(_recordAudioBuffer, 0, nin);
+ // TODO, read tail
if (readCnt != nin) {
- Log.e(TAG, "" + readCnt + " != " + nin);
+ Log.w(TAG, "" + readCnt + " != " + nin);
+ continue;
}
//Log.v(TAG, "read samples: " + DebugTools.shortsToHex(_recordAudioBuffer));
}
@@ -248,4 +274,36 @@ public class SoundModem implements Transport, Runnable {
}
}
}
+
+ private void pttOn() {
+ if (_isPttOn) return;
+
+ try {
+ _rigCtl.pttOn();
+ _isPttOn = true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void pttOff() {
+ if (!_isPttOn) return;
+ if (_pttOffTimer != null) {
+ _pttOffTimer.cancel();
+ _pttOffTimer.purge();
+ _pttOffTimer = null;
+ }
+ _pttOffTimer = new Timer();
+ _pttOffTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ try {
+ _rigCtl.pttOff();
+ _isPttOn = false;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }, PTT_OFF_DELAY_MS);
+ }
}
diff --git a/codec2talkie/src/main/res/values/arrays.xml b/codec2talkie/src/main/res/values/arrays.xml
index 7f31538..569fda1 100644
--- a/codec2talkie/src/main/res/values/arrays.xml
+++ b/codec2talkie/src/main/res/values/arrays.xml
@@ -352,4 +352,46 @@
- usb
- sound_modem
+
+
+ - Do not use rig control
+ - FT-817/818/MCHF
+
+
+
+ - Disabled
+ - Ft817
+
+
+
+ - +0 db
+ - +1 db
+ - +2 db
+ - +3 db
+ - +4 db
+ - +5 db
+ - +6 db
+ - +7 db
+ - +8 db
+ - +9 db
+ - +10 db
+ - +11 db
+ - +12 db
+
+
+
+ - 1000
+ - 1258
+ - 1584
+ - 1995
+ - 2511
+ - 3162
+ - 3981
+ - 5011
+ - 6309
+ - 7943
+ - 10000
+ - 12589
+ - 15848
+
\ No newline at end of file
diff --git a/codec2talkie/src/main/res/values/strings.xml b/codec2talkie/src/main/res/values/strings.xml
index d6a2332..bd09f34 100644
--- a/codec2talkie/src/main/res/values/strings.xml
+++ b/codec2talkie/src/main/res/values/strings.xml
@@ -302,4 +302,7 @@
TNC transport type
Disable receive
Run modem in transmit only mode, receive is disabled to save CPU cycles
+ Select RIG model for CAT PTT control
+ Set modem audio gain
+ 🎛
\ No newline at end of file
diff --git a/codec2talkie/src/main/res/xml/preferences_sound_modem.xml b/codec2talkie/src/main/res/xml/preferences_sound_modem.xml
index ffe11a0..1716424 100644
--- a/codec2talkie/src/main/res/xml/preferences_sound_modem.xml
+++ b/codec2talkie/src/main/res/xml/preferences_sound_modem.xml
@@ -29,5 +29,23 @@
app:defaultValue="false">
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libcodec2-android/src/main/cpp/Codec2JNI.cpp b/libcodec2-android/src/main/cpp/Codec2JNI.cpp
index 698a3f3..fe1df4b 100644
--- a/libcodec2-android/src/main/cpp/Codec2JNI.cpp
+++ b/libcodec2-android/src/main/cpp/Codec2JNI.cpp
@@ -25,6 +25,7 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
int Nbits;
int N;
int Ts;
+ int gain;
};
static Context *getContext(jlong jp) {
@@ -56,7 +57,7 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
return pv;
}
- static jlong fskCreate(JNIEnv *env, jclass clazz, int sampleFrequency, int symbolRate, int toneFreq, int toneSpacing) {
+ static jlong fskCreate(JNIEnv *env, jclass clazz, int sampleFrequency, int symbolRate, int toneFreq, int toneSpacing, int gain) {
struct ContextFsk *conFsk;
conFsk = (struct ContextFsk *) malloc(sizeof(struct ContextFsk));
struct FSK *fsk;
@@ -74,6 +75,8 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
conFsk->demodBits = (uint8_t*)malloc(sizeof(uint8_t) * fsk->Nbits);
conFsk->demodBuf = (int16_t*)malloc(sizeof(short) * (fsk->N + 2 * fsk->Ts));
+ conFsk->gain = gain;
+
fsk_set_freq_est_limits(fsk, 500, sampleFrequency / 4);
fsk_set_freq_est_alg(fsk, 0);
@@ -168,7 +171,7 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
fsk_mod(conFsk->fsk, conFsk->modBuf, conFsk->modBits, inputBitsSize);
jshort *jOutBuf = env->GetShortArrayElements(outputSamples, nullptr);
for (int i = 0; i < conFsk->N; i++) {
- jOutBuf[i] = (int16_t)(conFsk->modBuf[i] * FDMDV_SCALE);
+ jOutBuf[i] = (int16_t)(conFsk->modBuf[i] * conFsk->gain);
}
env->ReleaseShortArrayElements(outputSamples, jOutBuf, 0);
return 0;
@@ -186,7 +189,7 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
ContextFsk *conFsk = getContextFsk(n);
env->GetShortArrayRegion(inputSamples, 0, conFsk->N, reinterpret_cast(conFsk->demodBuf));
for(int i = 0; i < fsk_nin(conFsk->fsk); i++){
- conFsk->demodCBuf[i].real = ((float)conFsk->demodBuf[i]) / FDMDV_SCALE;
+ conFsk->demodCBuf[i].real = ((float)conFsk->demodBuf[i]) / conFsk->gain;
conFsk->demodCBuf[i].imag = 0.0;
}
fsk_demod(conFsk->fsk, conFsk->demodBits, conFsk->demodCBuf);
@@ -201,7 +204,7 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
{"destroy", "(J)I", (void *) destroy},
{"encode", "(J[S[C)J", (void *) encode},
{"decode", "(J[S[B)J", (void *) decode},
- {"fskCreate", "(IIII)J", (void *) fskCreate},
+ {"fskCreate", "(IIIII)J", (void *) fskCreate},
{"fskDestroy", "(J)I", (void *) fskDestroy},
{"fskModulate", "(J[S[B)J", (void *) fskModulate},
{"fskDemodulate", "(J[S[B)J", (void *) fskDemodulate},
diff --git a/libcodec2-android/src/main/java/com/ustadmobile/codec2/Codec2.java b/libcodec2-android/src/main/java/com/ustadmobile/codec2/Codec2.java
index 4c8a58d..5de0986 100644
--- a/libcodec2-android/src/main/java/com/ustadmobile/codec2/Codec2.java
+++ b/libcodec2-android/src/main/java/com/ustadmobile/codec2/Codec2.java
@@ -35,7 +35,7 @@ public class Codec2 {
public native static long encode(long con, short[] inputSamples, char[] outputBits);
public native static long decode(long con, short[] outputSamples, byte[] inputsBits);
- public native static long fskCreate(int sampleFrequency, int symbolRate, int toneFreq, int toneSpacing);
+ public native static long fskCreate(int sampleFrequency, int symbolRate, int toneFreq, int toneSpacing, int gain);
public native static int fskDestroy(long conFsk);
public native static int fskDemodBitsBufSize(long conFsk);