kopia lustrzana https://github.com/sh123/codec2_talkie
Refactoring
rodzic
8ac5e9e998
commit
11c0e6c32f
|
@ -492,16 +492,11 @@ public class AppWorker extends Thread {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Log.i(TAG, "Starting message loop");
|
Log.i(TAG, "Starting message loop");
|
||||||
try {
|
|
||||||
sleep(2000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
|
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
|
||||||
Looper.prepare();
|
Looper.prepare();
|
||||||
|
|
||||||
sendStatusUpdate(AppMessage.EV_CONNECTED, null);
|
sendStatusUpdate(AppMessage.EV_CONNECTED, null);
|
||||||
//_systemAudioPlayer.play();
|
_systemAudioPlayer.play();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_protocol.initialize(_transport, _context, _protocolCallback);
|
_protocol.initialize(_transport, _context, _protocolCallback);
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
package com.radio.codec2talkie.protocol;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.radio.codec2talkie.protocol.message.TextMessage;
|
||||||
|
import com.radio.codec2talkie.protocol.position.Position;
|
||||||
|
import com.radio.codec2talkie.tools.BitTools;
|
||||||
|
import com.radio.codec2talkie.tools.ChecksumTools;
|
||||||
|
import com.radio.codec2talkie.transport.Transport;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class Hdlc implements Protocol {
|
||||||
|
|
||||||
|
protected Transport _transport;
|
||||||
|
private ProtocolCallback _parentProtocolCallback;
|
||||||
|
|
||||||
|
public Hdlc() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(Transport transport, Context context, ProtocolCallback protocolCallback) throws IOException {
|
||||||
|
_transport = transport;
|
||||||
|
_parentProtocolCallback = protocolCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPcmAudioBufferSize() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendPcmAudio(String src, String dst, int codec, short[] pcmFrame) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendCompressedAudio(String src, String dst, int codec, byte[] frame) throws IOException {
|
||||||
|
_transport.write(hdlcEncode(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendTextMessage(TextMessage textMessage) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendData(String src, String dst, byte[] dataPacket) throws IOException {
|
||||||
|
_transport.write(hdlcEncode(dataPacket));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean receive() throws IOException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendPosition(Position position) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] genPreamble(int count) {
|
||||||
|
byte[] preamble = new byte[count];
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
preamble[i] = (byte)0x7e;
|
||||||
|
return BitTools.convertToHDLCBitArray(preamble, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] hdlcEncode(byte[] dataSrc) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(dataSrc.length + 2);
|
||||||
|
|
||||||
|
// TODO, read from settings
|
||||||
|
int prefixLen = 30;
|
||||||
|
int suffixLen = 5;
|
||||||
|
|
||||||
|
// include checksum
|
||||||
|
buffer.put(dataSrc);
|
||||||
|
int fcs = ChecksumTools.calculateFcs(dataSrc);
|
||||||
|
// least significant byte first
|
||||||
|
buffer.put((byte)(fcs & 0xff));
|
||||||
|
buffer.put((byte)((fcs >> 8) & 0xff));
|
||||||
|
|
||||||
|
// convert to bits
|
||||||
|
buffer.flip();
|
||||||
|
byte[] data = new byte[buffer.remaining()];
|
||||||
|
buffer.get(data);
|
||||||
|
byte[] dataBytesAsBits = BitTools.convertToHDLCBitArray(data, true);
|
||||||
|
|
||||||
|
// add preamble
|
||||||
|
ByteBuffer hdlcBitBuffer = ByteBuffer.allocate(dataBytesAsBits.length + 8*prefixLen + 8*suffixLen);
|
||||||
|
hdlcBitBuffer.put(genPreamble(prefixLen));
|
||||||
|
hdlcBitBuffer.put(dataBytesAsBits);
|
||||||
|
hdlcBitBuffer.put(genPreamble(suffixLen));
|
||||||
|
|
||||||
|
// return
|
||||||
|
hdlcBitBuffer.flip();
|
||||||
|
byte[] r = new byte[hdlcBitBuffer.remaining()];
|
||||||
|
hdlcBitBuffer.get(r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ public class ProtocolFactory {
|
||||||
|
|
||||||
public enum ProtocolType {
|
public enum ProtocolType {
|
||||||
RAW("RAW"),
|
RAW("RAW"),
|
||||||
|
HDLC("HDLC"),
|
||||||
KISS("KISS"),
|
KISS("KISS"),
|
||||||
KISS_BUFFERED("KISS BUF"),
|
KISS_BUFFERED("KISS BUF"),
|
||||||
KISS_PARROT("KISS RPT");
|
KISS_PARROT("KISS RPT");
|
||||||
|
@ -32,7 +33,9 @@ public class ProtocolFactory {
|
||||||
|
|
||||||
ProtocolFactory.ProtocolType protocolType;
|
ProtocolFactory.ProtocolType protocolType;
|
||||||
|
|
||||||
if (sharedPreferences.getBoolean(PreferenceKeys.KISS_ENABLED, true)) {
|
if (sharedPreferences.getBoolean(PreferenceKeys.PORTS_SOUND_MODEM_ENABLED, true)) {
|
||||||
|
protocolType = ProtocolFactory.ProtocolType.HDLC;
|
||||||
|
} else if (sharedPreferences.getBoolean(PreferenceKeys.KISS_ENABLED, true)) {
|
||||||
if (sharedPreferences.getBoolean(PreferenceKeys.KISS_PARROT, false)) {
|
if (sharedPreferences.getBoolean(PreferenceKeys.KISS_PARROT, false)) {
|
||||||
protocolType = ProtocolFactory.ProtocolType.KISS_PARROT;
|
protocolType = ProtocolFactory.ProtocolType.KISS_PARROT;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +73,9 @@ public class ProtocolFactory {
|
||||||
case KISS_PARROT:
|
case KISS_PARROT:
|
||||||
proto = new KissParrot();
|
proto = new KissParrot();
|
||||||
break;
|
break;
|
||||||
|
case HDLC:
|
||||||
|
proto = new Hdlc();
|
||||||
|
break;
|
||||||
case RAW:
|
case RAW:
|
||||||
default:
|
default:
|
||||||
proto = new Raw();
|
proto = new Raw();
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.radio.codec2talkie.tools;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class BitTools {
|
||||||
|
|
||||||
|
public static byte[] convertToNRZI(byte[] bitsAsBytes) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(bitsAsBytes.length);
|
||||||
|
byte last = 0;
|
||||||
|
for (byte bitAsByte : bitsAsBytes) {
|
||||||
|
if (bitAsByte == 0) {
|
||||||
|
last = last == 0 ? (byte) 1 : (byte) 0;
|
||||||
|
}
|
||||||
|
buffer.put(last);
|
||||||
|
}
|
||||||
|
buffer.flip();
|
||||||
|
byte[] r = new byte[buffer.remaining()];
|
||||||
|
buffer.get(r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] convertToHDLCBitArray(byte[] data, boolean shouldBitStuff) {
|
||||||
|
ByteBuffer bitBuffer = ByteBuffer.allocate(2 * data.length * 8);
|
||||||
|
|
||||||
|
int bitStuffCnt = 5;
|
||||||
|
int cntOnes = 0;
|
||||||
|
for (int i = 0; i < 8 * data.length; i++) {
|
||||||
|
int b = ((int) data[i / 8]) & 0xff;
|
||||||
|
// HDLC transmits least significant bit first
|
||||||
|
if ((b & (1 << (i % 8))) > 0) {
|
||||||
|
bitBuffer.put((byte) 1);
|
||||||
|
if (shouldBitStuff)
|
||||||
|
cntOnes += 1;
|
||||||
|
} else {
|
||||||
|
bitBuffer.put((byte) 0);
|
||||||
|
cntOnes = 0;
|
||||||
|
}
|
||||||
|
if (cntOnes == bitStuffCnt) {
|
||||||
|
bitBuffer.put((byte) 0);
|
||||||
|
cntOnes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bitBuffer.flip();
|
||||||
|
byte[] r = new byte[bitBuffer.remaining()];
|
||||||
|
bitBuffer.get(r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import android.util.Log;
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import com.radio.codec2talkie.tools.BitTools;
|
||||||
import com.radio.codec2talkie.tools.ChecksumTools;
|
import com.radio.codec2talkie.tools.ChecksumTools;
|
||||||
import com.ustadmobile.codec2.Codec2;
|
import com.ustadmobile.codec2.Codec2;
|
||||||
|
|
||||||
|
@ -45,6 +46,7 @@ public class SoundModem implements Transport {
|
||||||
_context = context;
|
_context = context;
|
||||||
_sharedPreferences = PreferenceManager.getDefaultSharedPreferences(_context);
|
_sharedPreferences = PreferenceManager.getDefaultSharedPreferences(_context);
|
||||||
|
|
||||||
|
// TODO, read from settings
|
||||||
//_fskModem = Codec2.fskCreate(AUDIO_SAMPLE_SIZE, 300, 1600, 200);
|
//_fskModem = Codec2.fskCreate(AUDIO_SAMPLE_SIZE, 300, 1600, 200);
|
||||||
_fskModem = Codec2.fskCreate(AUDIO_SAMPLE_SIZE, 1200, 1200, 1000);
|
_fskModem = Codec2.fskCreate(AUDIO_SAMPLE_SIZE, 1200, 1200, 1000);
|
||||||
|
|
||||||
|
@ -102,102 +104,9 @@ public class SoundModem implements Transport {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] toHdlcByteBitArray(byte[] data, boolean shouldBitStuff) {
|
|
||||||
StringBuilder s = new StringBuilder();
|
|
||||||
StringBuilder s2 = new StringBuilder();
|
|
||||||
ByteBuffer bitBuffer = ByteBuffer.allocate(512*8);
|
|
||||||
|
|
||||||
int cntOnes = 0;
|
|
||||||
for (int i = 0; i < 8 * data.length; i++) {
|
|
||||||
int b = ((int)data[i / 8]) & 0xff;
|
|
||||||
// HDLC transmits least significant bit first
|
|
||||||
if ((b & (1 << (i % 8))) > 0) {
|
|
||||||
bitBuffer.put((byte)1);
|
|
||||||
s.append('1');
|
|
||||||
if (shouldBitStuff)
|
|
||||||
cntOnes += 1;
|
|
||||||
} else {
|
|
||||||
bitBuffer.put((byte)0);
|
|
||||||
s.append(0);
|
|
||||||
cntOnes = 0;
|
|
||||||
}
|
|
||||||
if (shouldBitStuff && cntOnes == 5) {
|
|
||||||
bitBuffer.put((byte)0);
|
|
||||||
s.append('0');
|
|
||||||
s2.append(' ');
|
|
||||||
cntOnes = 0;
|
|
||||||
}
|
|
||||||
if (i % 8 == 3) s.append(':');
|
|
||||||
if (i % 8 == 7) {
|
|
||||||
s.append(' ');
|
|
||||||
s2.append(String.format("%02x ", b));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.i(TAG, s2.toString());
|
|
||||||
Log.i(TAG, s.toString());
|
|
||||||
|
|
||||||
bitBuffer.flip();
|
|
||||||
byte[] r = new byte[bitBuffer.remaining()];
|
|
||||||
bitBuffer.get(r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] genPreamble(int count) {
|
|
||||||
byte[] preamble = new byte[count];
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
preamble[i] = (byte)0x7e;
|
|
||||||
return toHdlcByteBitArray(preamble, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] hdlcEncode(byte[] dataSrc) {
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(512);
|
|
||||||
|
|
||||||
buffer.put(dataSrc);
|
|
||||||
int fcs = ChecksumTools.calculateFcs(dataSrc);
|
|
||||||
//least significant byte first
|
|
||||||
buffer.put((byte)(fcs & 0xff));
|
|
||||||
buffer.put((byte)((fcs >> 8) & 0xff));
|
|
||||||
|
|
||||||
buffer.flip();
|
|
||||||
byte[] data = new byte[buffer.remaining()];
|
|
||||||
buffer.get(data);
|
|
||||||
|
|
||||||
//Log.i(TAG, String.format("checksum: %x", fcs));
|
|
||||||
Log.i(TAG, "" + Arrays.toString(data));
|
|
||||||
|
|
||||||
byte[] dataBytesAsBits = toHdlcByteBitArray(data, true);
|
|
||||||
Log.i(TAG, "write() " + data.length + " " + 8 * data.length + " " + dataBytesAsBits.length + " " + _playbackBitBuffer.length);
|
|
||||||
|
|
||||||
ByteBuffer hdlcBitBuffer = ByteBuffer.allocate(512*8);
|
|
||||||
hdlcBitBuffer.put(genPreamble(30));
|
|
||||||
hdlcBitBuffer.put(dataBytesAsBits);
|
|
||||||
hdlcBitBuffer.put(genPreamble(5));
|
|
||||||
|
|
||||||
hdlcBitBuffer.flip();
|
|
||||||
byte[] r = new byte[hdlcBitBuffer.remaining()];
|
|
||||||
hdlcBitBuffer.get(r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] toNrzi(byte[] data) {
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(data.length);
|
|
||||||
byte last = 0;
|
|
||||||
for (int i = 0; i < data.length; i++) {
|
|
||||||
if (data[i] == 0) {
|
|
||||||
last = last == 0 ? (byte)1 : (byte)0;
|
|
||||||
}
|
|
||||||
buffer.put(last);
|
|
||||||
}
|
|
||||||
buffer.flip();
|
|
||||||
byte[] r = new byte[buffer.remaining()];
|
|
||||||
buffer.get(r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int write(byte[] dataSrc) throws IOException {
|
public int write(byte[] srcDataBytesAsBits) throws IOException {
|
||||||
byte[] dataBytesAsBits = toNrzi(hdlcEncode(dataSrc));
|
byte[] dataBytesAsBits = BitTools.convertToNRZI(srcDataBytesAsBits);
|
||||||
|
|
||||||
int j = 0;
|
int j = 0;
|
||||||
StringBuilder ss = new StringBuilder();
|
StringBuilder ss = new StringBuilder();
|
||||||
|
@ -206,8 +115,8 @@ public class SoundModem implements Transport {
|
||||||
Log.i(TAG, "-- " + i + " " + j);
|
Log.i(TAG, "-- " + i + " " + j);
|
||||||
Codec2.fskModulate(_fskModem, _playbackAudioBuffer, _playbackBitBuffer);
|
Codec2.fskModulate(_fskModem, _playbackAudioBuffer, _playbackBitBuffer);
|
||||||
StringBuilder s = new StringBuilder();
|
StringBuilder s = new StringBuilder();
|
||||||
for (int x = 0; x < _playbackAudioBuffer.length; x++) {
|
for (short value : _playbackAudioBuffer) {
|
||||||
s.append(_playbackAudioBuffer[x]);
|
s.append(value);
|
||||||
s.append(' ');
|
s.append(' ');
|
||||||
}
|
}
|
||||||
Log.i(TAG, s.toString());
|
Log.i(TAG, s.toString());
|
||||||
|
|
|
@ -137,7 +137,6 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
|
||||||
con->buf[i] = v;
|
con->buf[i] = v;
|
||||||
}
|
}
|
||||||
env->ReleaseShortArrayElements(inputBuffer, jbuf, 0);
|
env->ReleaseShortArrayElements(inputBuffer, jbuf, 0);
|
||||||
//env->DeleteLocalRef(inputBuffer);
|
|
||||||
|
|
||||||
codec2_encode(con->c2, con->bits, con->buf);
|
codec2_encode(con->c2, con->bits, con->buf);
|
||||||
|
|
||||||
|
@ -146,7 +145,6 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
|
||||||
jbits[i] = con->bits[i];
|
jbits[i] = con->bits[i];
|
||||||
}
|
}
|
||||||
env->ReleaseCharArrayElements(outputBits, jbits, 0);
|
env->ReleaseCharArrayElements(outputBits, jbits, 0);
|
||||||
//env->DeleteLocalRef(outputBits);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +158,6 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
|
||||||
conFsk->modBits[i] = v;
|
conFsk->modBits[i] = v;
|
||||||
}
|
}
|
||||||
env->ReleaseByteArrayElements(inputBits, jbuf, 0);
|
env->ReleaseByteArrayElements(inputBits, jbuf, 0);
|
||||||
//env->DeleteLocalRef(inputBits);
|
|
||||||
|
|
||||||
fsk_mod(conFsk->fsk, conFsk->modBuf, conFsk->modBits, inputBitsSize);
|
fsk_mod(conFsk->fsk, conFsk->modBuf, conFsk->modBits, inputBitsSize);
|
||||||
|
|
||||||
|
@ -169,7 +166,6 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
|
||||||
jOutBuf[i] = (int16_t)(conFsk->modBuf[i] * FDMDV_SCALE);
|
jOutBuf[i] = (int16_t)(conFsk->modBuf[i] * FDMDV_SCALE);
|
||||||
}
|
}
|
||||||
env->ReleaseShortArrayElements(outputSamples, jOutBuf, 0);
|
env->ReleaseShortArrayElements(outputSamples, jOutBuf, 0);
|
||||||
//env->DeleteLocalRef(outputSamples);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue