kopia lustrzana https://github.com/sh123/codec2_talkie
Refactoring
rodzic
8ac5e9e998
commit
11c0e6c32f
|
@ -492,16 +492,11 @@ public class AppWorker extends Thread {
|
|||
@Override
|
||||
public void run() {
|
||||
Log.i(TAG, "Starting message loop");
|
||||
try {
|
||||
sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
|
||||
Looper.prepare();
|
||||
|
||||
sendStatusUpdate(AppMessage.EV_CONNECTED, null);
|
||||
//_systemAudioPlayer.play();
|
||||
_systemAudioPlayer.play();
|
||||
|
||||
try {
|
||||
_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 {
|
||||
RAW("RAW"),
|
||||
HDLC("HDLC"),
|
||||
KISS("KISS"),
|
||||
KISS_BUFFERED("KISS BUF"),
|
||||
KISS_PARROT("KISS RPT");
|
||||
|
@ -32,7 +33,9 @@ public class ProtocolFactory {
|
|||
|
||||
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)) {
|
||||
protocolType = ProtocolFactory.ProtocolType.KISS_PARROT;
|
||||
}
|
||||
|
@ -70,6 +73,9 @@ public class ProtocolFactory {
|
|||
case KISS_PARROT:
|
||||
proto = new KissParrot();
|
||||
break;
|
||||
case HDLC:
|
||||
proto = new Hdlc();
|
||||
break;
|
||||
case RAW:
|
||||
default:
|
||||
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 com.radio.codec2talkie.tools.BitTools;
|
||||
import com.radio.codec2talkie.tools.ChecksumTools;
|
||||
import com.ustadmobile.codec2.Codec2;
|
||||
|
||||
|
@ -45,6 +46,7 @@ public class SoundModem implements Transport {
|
|||
_context = context;
|
||||
_sharedPreferences = PreferenceManager.getDefaultSharedPreferences(_context);
|
||||
|
||||
// TODO, read from settings
|
||||
//_fskModem = Codec2.fskCreate(AUDIO_SAMPLE_SIZE, 300, 1600, 200);
|
||||
_fskModem = Codec2.fskCreate(AUDIO_SAMPLE_SIZE, 1200, 1200, 1000);
|
||||
|
||||
|
@ -102,102 +104,9 @@ public class SoundModem implements Transport {
|
|||
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
|
||||
public int write(byte[] dataSrc) throws IOException {
|
||||
byte[] dataBytesAsBits = toNrzi(hdlcEncode(dataSrc));
|
||||
public int write(byte[] srcDataBytesAsBits) throws IOException {
|
||||
byte[] dataBytesAsBits = BitTools.convertToNRZI(srcDataBytesAsBits);
|
||||
|
||||
int j = 0;
|
||||
StringBuilder ss = new StringBuilder();
|
||||
|
@ -206,8 +115,8 @@ public class SoundModem implements Transport {
|
|||
Log.i(TAG, "-- " + i + " " + j);
|
||||
Codec2.fskModulate(_fskModem, _playbackAudioBuffer, _playbackBitBuffer);
|
||||
StringBuilder s = new StringBuilder();
|
||||
for (int x = 0; x < _playbackAudioBuffer.length; x++) {
|
||||
s.append(_playbackAudioBuffer[x]);
|
||||
for (short value : _playbackAudioBuffer) {
|
||||
s.append(value);
|
||||
s.append(' ');
|
||||
}
|
||||
Log.i(TAG, s.toString());
|
||||
|
|
|
@ -137,7 +137,6 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
|
|||
con->buf[i] = v;
|
||||
}
|
||||
env->ReleaseShortArrayElements(inputBuffer, jbuf, 0);
|
||||
//env->DeleteLocalRef(inputBuffer);
|
||||
|
||||
codec2_encode(con->c2, con->bits, con->buf);
|
||||
|
||||
|
@ -146,7 +145,6 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
|
|||
jbits[i] = con->bits[i];
|
||||
}
|
||||
env->ReleaseCharArrayElements(outputBits, jbits, 0);
|
||||
//env->DeleteLocalRef(outputBits);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -160,7 +158,6 @@ namespace Java_com_ustadmobile_codec2_Codec2 {
|
|||
conFsk->modBits[i] = v;
|
||||
}
|
||||
env->ReleaseByteArrayElements(inputBits, jbuf, 0);
|
||||
//env->DeleteLocalRef(inputBits);
|
||||
|
||||
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);
|
||||
}
|
||||
env->ReleaseShortArrayElements(outputSamples, jOutBuf, 0);
|
||||
//env->DeleteLocalRef(outputSamples);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue