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 593790b..7978deb 100644 --- a/codec2talkie/src/main/java/com/radio/codec2talkie/protocol/Hdlc.java +++ b/codec2talkie/src/main/java/com/radio/codec2talkie/protocol/Hdlc.java @@ -86,7 +86,7 @@ public class Hdlc implements Protocol { _readByte |= bit; _readByte &= 0xff; if (_readByte == 0x7e) { - Log.i(TAG, "HDLC " + _prevHdlc/8); + //Log.i(TAG, "HDLC " + _prevHdlc/8); int pos = _currentFrameBuffer.position(); // shift/flush back previous 8 - 1 bits @@ -103,15 +103,18 @@ public class Hdlc implements Protocol { // get bytes from bits byte[] packetBytes = BitTools.convertFromHDLCBitArray(packetBits); if (packetBytes != null) { - Log.i(TAG, DebugTools.byteBitsToString(packetBits)); - Log.i(TAG, DebugTools.bytesToHex(packetBytes)); + //Log.i(TAG, DebugTools.byteBitsToString(packetBits)); + //Log.i(TAG, DebugTools.bytesToHex(packetBytes)); if (packetBytes.length > 2) { byte[] contentBytes = Arrays.copyOf(packetBytes, packetBytes.length - 2); int calculatedCrc = ChecksumTools.calculateFcs(contentBytes); int packetCrc = ((int)packetBytes[packetBytes.length - 2] & 0xff) | (((int)packetBytes[packetBytes.length - 1] & 0xff) << 8); - Log.i(TAG, "checksum: " + calculatedCrc + " " + packetCrc); + //Log.i(TAG, "checksum: " + calculatedCrc + " " + packetCrc); if (calculatedCrc == packetCrc) { + Log.i(TAG, DebugTools.byteBitsToString(packetBits)); + Log.i(TAG, DebugTools.bytesToHex(packetBytes)); Log.i(TAG, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + _parentProtocolCallback.onReceiveCompressedAudio(null, null, -1, contentBytes); } } } @@ -166,10 +169,10 @@ public class Hdlc implements Protocol { byte[] dataBytesAsBits = BitTools.convertToHDLCBitArray(data, true); // add preamble - ByteBuffer hdlcBitBuffer = ByteBuffer.allocate(dataBytesAsBits.length + 8*_prefixSymCount + 8); + ByteBuffer hdlcBitBuffer = ByteBuffer.allocate(dataBytesAsBits.length + 8*_prefixSymCount + 8*10); hdlcBitBuffer.put(genPreamble(_prefixSymCount)); hdlcBitBuffer.put(dataBytesAsBits); - hdlcBitBuffer.put(genPreamble(1)); + hdlcBitBuffer.put(genPreamble(10)); // return hdlcBitBuffer.flip(); diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/tools/BitTools.java b/codec2talkie/src/main/java/com/radio/codec2talkie/tools/BitTools.java index b41cfd1..d8e9f24 100644 --- a/codec2talkie/src/main/java/com/radio/codec2talkie/tools/BitTools.java +++ b/codec2talkie/src/main/java/com/radio/codec2talkie/tools/BitTools.java @@ -21,9 +21,9 @@ public class BitTools { return r; } - public static byte[] convertFromNRZI(byte[] bitsAsBytes, byte prevLastBit) { + public static byte[] convertFromNRZI(byte[] bitsAsBytes, byte prevBit) { ByteBuffer buffer = ByteBuffer.allocate(bitsAsBytes.length); - byte last = prevLastBit; + byte last = prevBit; for (byte bitAsByte : bitsAsBytes) { // no transition -> 1 if (last == bitAsByte) { @@ -109,7 +109,7 @@ public class BitTools { cntBits++; } //if (cntBits % 8 != 0) return null; - Log.i("----", s.toString()); + //Log.i("----", s.toString()); // return byteBuffer.flip(); byte[] r = new byte[byteBuffer.remaining()]; diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/tools/DebugTools.java b/codec2talkie/src/main/java/com/radio/codec2talkie/tools/DebugTools.java index c25589b..eb836c0 100644 --- a/codec2talkie/src/main/java/com/radio/codec2talkie/tools/DebugTools.java +++ b/codec2talkie/src/main/java/com/radio/codec2talkie/tools/DebugTools.java @@ -33,6 +33,14 @@ public class DebugTools { return s.toString(); } + public static String byteBitsToFlatString(byte[] bytesAsBits) { + StringBuilder s = new StringBuilder(); + for (int i = 0; i < bytesAsBits.length; i++) { + s.append(bytesAsBits[i]); + } + return s.toString(); + } + public static boolean isPrintableAscii(byte value) { return (value >= 32 ) && (value < 127); diff --git a/codec2talkie/src/main/java/com/radio/codec2talkie/tracker/Manual.java b/codec2talkie/src/main/java/com/radio/codec2talkie/tracker/Manual.java index c61a0c9..8902062 100644 --- a/codec2talkie/src/main/java/com/radio/codec2talkie/tracker/Manual.java +++ b/codec2talkie/src/main/java/com/radio/codec2talkie/tracker/Manual.java @@ -52,6 +52,7 @@ public class Manual implements Tracker { position.bearingDegrees = 0; position.speedMetersPerSecond = 0; position.altitudeMeters = 0; + position.maidenHead = UnitTools.decimalToMaidenhead(position.latitude, position.longitude); _trackerCallback.onSendLocation(position); } 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 8a49dc0..0da157b 100644 --- a/codec2talkie/src/main/java/com/radio/codec2talkie/transport/SoundModem.java +++ b/codec2talkie/src/main/java/com/radio/codec2talkie/transport/SoundModem.java @@ -46,7 +46,9 @@ public class SoundModem implements Transport, Runnable { private final SharedPreferences _sharedPreferences; private boolean _isRunning = true; - private final boolean _loopbackTest = false; + + private final ByteBuffer _sampleBuffer; + private final boolean _isLoopback = false; private final long _fskModem; @@ -67,12 +69,16 @@ public class SoundModem implements Transport, Runnable { _playbackAudioBuffer = new short[Codec2.fskModSamplesBufSize(_fskModem)]; _playbackBitBuffer = new byte[Codec2.fskModBitsBufSize(_fskModem)]; _samplesPerSymbol = Codec2.fskSamplesPerSymbol(_fskModem); - _bitBuffer = ByteBuffer.allocate(10 * _recordBitBuffer.length); + _bitBuffer = ByteBuffer.allocate(100 * _recordBitBuffer.length); constructSystemAudioDevices(); - if (!_loopbackTest) - new Thread(this).start(); + if (_isLoopback) + _sampleBuffer = ByteBuffer.allocate(1000000 ); + else + _sampleBuffer = ByteBuffer.allocate(0); + + new Thread(this).start(); } private void constructSystemAudioDevices() { @@ -87,7 +93,7 @@ public class SoundModem implements Transport, Runnable { AUDIO_SAMPLE_SIZE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, - audioRecorderMinBufferSize); + 10*audioRecorderMinBufferSize); int audioPlayerMinBufferSize = AudioTrack.getMinBufferSize( AUDIO_SAMPLE_SIZE, @@ -135,18 +141,24 @@ public class SoundModem implements Transport, Runnable { @Override public int write(byte[] srcDataBytesAsBits) throws IOException { + //Log.i(TAG, "write " + DebugTools.byteBitsToFlatString(srcDataBytesAsBits)); byte[] dataBytesAsBits = BitTools.convertToNRZI(srcDataBytesAsBits); - - if (_loopbackTest) { - Log.i(TAG, "write " + DebugTools.byteBitsToString(srcDataBytesAsBits)); - _bitBuffer.put(BitTools.convertFromNRZI(dataBytesAsBits, (byte) 0)); - } + //Log.i(TAG, "write " + DebugTools.byteBitsToString(dataBytesAsBits)); + //Log.i(TAG, "write " + DebugTools.byteBitsToFlatString(dataBytesAsBits)); int j = 0; for (int i = 0; i < dataBytesAsBits.length; i++, j++) { if (j >= _playbackBitBuffer.length) { Codec2.fskModulate(_fskModem, _playbackAudioBuffer, _playbackBitBuffer); - _systemAudioPlayer.write(_playbackAudioBuffer, 0, _playbackAudioBuffer.length); + if (_isLoopback) { + synchronized (_sampleBuffer) { + for (short sample : _playbackAudioBuffer) { + _sampleBuffer.putShort(sample); + } + } + } else { + _systemAudioPlayer.write(_playbackAudioBuffer, 0, _playbackAudioBuffer.length); + } j = 0; } _playbackBitBuffer[j] = dataBytesAsBits[i]; @@ -156,6 +168,15 @@ public class SoundModem implements Transport, Runnable { byte [] bitBufferTail = Arrays.copyOf(_playbackBitBuffer, j); Codec2.fskModulate(_fskModem, _playbackAudioBuffer, bitBufferTail); _systemAudioPlayer.write(_playbackAudioBuffer, 0, bitBufferTail.length * _samplesPerSymbol); + if (_isLoopback) { + synchronized (_sampleBuffer) { + for (short sample : _playbackAudioBuffer) { + _sampleBuffer.putShort(sample); + } + } + } else { + _systemAudioPlayer.write(_playbackAudioBuffer, 0, bitBufferTail.length * _samplesPerSymbol); + } return 0; } @@ -172,21 +193,37 @@ public class SoundModem implements Transport, Runnable { @Override public void run() { - byte prevLastBit = 0; + byte prevBit = 0; while (_isRunning) { + int nin = Codec2.fskNin(_fskModem); // TODO, take readCnt into account, do not read if playback is active - int readCnt = _systemAudioRecorder.read(_recordAudioBuffer, 0, Codec2.fskNin(_fskModem)); + if (_isLoopback) { + synchronized (_sampleBuffer) { + if (_sampleBuffer.position() / 2 >= nin) { + _sampleBuffer.flip(); + for (int i = 0; i < nin; i++) { + _recordAudioBuffer[i] = _sampleBuffer.getShort(); + } + _sampleBuffer.compact(); + } else { + continue; + } + } + } else { + int readCnt = _systemAudioRecorder.read(_recordAudioBuffer, 0, nin); + } //Log.i(TAG, "! " + AudioTools.getSampleLevelDb(Arrays.copyOf(_recordAudioBuffer, Codec2.fskNin(_fskModem)))); //Log.i(TAG, DebugTools.shortsToHex(_recordAudioBuffer)); //Log.i(TAG, readCnt + " " + _recordAudioBuffer.length + " " + Codec2.fskNin(_fskModem)); Codec2.fskDemodulate(_fskModem, _recordAudioBuffer, _recordBitBuffer); - //Log.i(TAG, "-- " + DebugTools.byteBitsToString(_recordBitBuffer)); + //Log.i(TAG, "----- " + DebugTools.byteBitsToFlatString(_recordBitBuffer)); + //Log.i(TAG, "----- " + DebugTools.byteBitsToFlatString(BitTools.convertFromNRZI(_recordBitBuffer, prevBit))); //Log.i(TAG, "== " + DebugTools.byteBitsToString(BitTools.convertFromNRZI(_recordBitBuffer, prevLastBit))); synchronized (_bitBuffer) { try { - _bitBuffer.put(BitTools.convertFromNRZI(_recordBitBuffer, prevLastBit)); - prevLastBit = _recordBitBuffer[_recordBitBuffer.length - 1]; + _bitBuffer.put(BitTools.convertFromNRZI(_recordBitBuffer, prevBit)); + prevBit = _recordBitBuffer[_recordBitBuffer.length - 1]; } catch (BufferOverflowException e) { e.printStackTrace(); _bitBuffer.clear(); diff --git a/libcodec2-android/src/main/cpp/Codec2JNI.cpp b/libcodec2-android/src/main/cpp/Codec2JNI.cpp index 720cc4c..694b98c 100644 --- a/libcodec2-android/src/main/cpp/Codec2JNI.cpp +++ b/libcodec2-android/src/main/cpp/Codec2JNI.cpp @@ -74,8 +74,9 @@ 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)); - fsk_set_freq_est_limits(fsk, 500, 2700); - fsk_set_freq_est_alg(fsk, 1); + //fsk_set_freq_est_limits(fsk, 500, 2700); + fsk_set_freq_est_limits(fsk, 0, sampleFrequency / 2); + fsk_set_freq_est_alg(fsk, 0); auto pv = (unsigned long) conFsk; return pv;