From 015b2a26374b9d05014e175050665bf7bec30e51 Mon Sep 17 00:00:00 2001 From: Doug McLain Date: Thu, 30 Dec 2021 10:53:52 -0500 Subject: [PATCH] Fix audio receive bug when receiving M17 1600 V/D with AGC on and add compile time option to use external codec2 library --- DroidStar.pro | 40 +++++++++------- audioengine.cpp | 4 +- audioengine.h | 2 +- codec2/codec2.cpp | 2 +- codec2/{codec2.h => codec2_api.h} | 0 m17codec.cpp | 77 +++++++++++++++++++++++++------ m17codec.h | 14 ++++-- 7 files changed, 102 insertions(+), 37 deletions(-) rename codec2/{codec2.h => codec2_api.h} (100%) diff --git a/DroidStar.pro b/DroidStar.pro index 97729fd..09cf11f 100644 --- a/DroidStar.pro +++ b/DroidStar.pro @@ -27,6 +27,7 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 DEFINES += VOCODER_PLUGIN #DEFINES += USE_FLITE +#DEFINES += USE_EXTERNAL_CODEC2 HEADERS += \ CRCenc.h \ @@ -45,14 +46,6 @@ HEADERS += \ cgolay2087.h \ chamming.h \ codec.h \ - codec2/codec2.h \ - codec2/codec2_internal.h \ - codec2/defines.h \ - codec2/kiss_fft.h \ - codec2/lpc.h \ - codec2/nlp.h \ - codec2/qbase.h \ - codec2/quantise.h \ crs129.h \ dcscodec.h \ dmrcodec.h \ @@ -85,14 +78,6 @@ SOURCES += \ cgolay2087.cpp \ chamming.cpp \ codec.cpp \ - codec2/codebooks.cpp \ - codec2/codec2.cpp \ - codec2/kiss_fft.cpp \ - codec2/lpc.cpp \ - codec2/nlp.cpp \ - codec2/pack.cpp \ - codec2/qbase.cpp \ - codec2/quantise.cpp \ crs129.cpp \ dcscodec.cpp \ dmrcodec.cpp \ @@ -108,6 +93,29 @@ SOURCES += \ serialmodem.cpp \ xrfcodec.cpp \ ysfcodec.cpp +!contains(DEFINES, USE_EXTERNAL_CODEC2){ +HEADERS += \ + codec2/codec2_api.h \ + codec2/codec2_internal.h \ + codec2/defines.h \ + codec2/kiss_fft.h \ + codec2/lpc.h \ + codec2/nlp.h \ + codec2/qbase.h \ + codec2/quantise.h +SOURCES += \ + codec2/codebooks.cpp \ + codec2/codec2.cpp \ + codec2/kiss_fft.cpp \ + codec2/lpc.cpp \ + codec2/nlp.cpp \ + codec2/pack.cpp \ + codec2/qbase.cpp \ + codec2/quantise.cpp +} +contains(DEFINES, USE_EXTERNAL_CODEC2){ +LIBS += -lcodec2 +} macx:OBJECTIVE_SOURCES += micpermission.mm ios:OBJECTIVE_SOURCES += micpermission.mm diff --git a/audioengine.cpp b/audioengine.cpp index 8e19d63..31cae20 100644 --- a/audioengine.cpp +++ b/audioengine.cpp @@ -352,12 +352,12 @@ void AudioEngine::process_audio(int16_t *pcm, size_t s) } } - gaindelta /= static_cast(160); + gaindelta /= static_cast(s); //160 // adjust output gain m_audio_out_temp_buf_p = m_audio_out_temp_buf; - for (size_t i = 0; i < 160; i++){ + for (size_t i = 0; i < s; i++){ *m_audio_out_temp_buf_p = (m_aout_gain + (static_cast(i) * gaindelta)) * (*m_audio_out_temp_buf_p); m_audio_out_temp_buf_p++; } diff --git a/audioengine.h b/audioengine.h index 967abfb..1d304ae 100644 --- a/audioengine.h +++ b/audioengine.h @@ -65,7 +65,7 @@ private: bool m_agc; float m_srm; // sample rate multiplier for macOS HACK - float m_audio_out_temp_buf[160]; //!< output of decoder + float m_audio_out_temp_buf[320]; //!< output of decoder float *m_audio_out_temp_buf_p; //float m_audio_out_float_buf[1120]; //!< output of upsampler - 1 frame of 160 samples upampled up to 7 times diff --git a/codec2/codec2.cpp b/codec2/codec2.cpp index afa037b..6d6268e 100644 --- a/codec2/codec2.cpp +++ b/codec2/codec2.cpp @@ -36,7 +36,7 @@ #include "nlp.h" #include "lpc.h" #include "quantise.h" -#include "codec2.h" +#include "codec2_api.h" #include "codec2_internal.h" #define HPF_BETA 0.125 diff --git a/codec2/codec2.h b/codec2/codec2_api.h similarity index 100% rename from codec2/codec2.h rename to codec2/codec2_api.h diff --git a/m17codec.cpp b/m17codec.cpp index aa395b5..41ab273 100755 --- a/m17codec.cpp +++ b/m17codec.cpp @@ -85,6 +85,7 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 M17Codec::M17Codec(QString callsign, char module, QString hostname, QString host, int port, bool ipv6, QString modem, QString audioin, QString audioout) : Codec(callsign, module, hostname, host, port, ipv6, NULL, modem, audioin, audioout), + m_c2(NULL), m_txrate(1) { m_modeinfo.callsign = callsign; @@ -148,14 +149,62 @@ void M17Codec::decode_callsign(uint8_t *callsign) } } +void M17Codec::set_mode(bool m) +{ +#ifdef USE_EXTERNAL_CODEC2 + if(m_c2){ + codec2_destroy(m_c2); + m_c2 = NULL; + } + + if(m){ + m_c2 = codec2_create(CODEC2_MODE_3200); + } + else{ + m_c2 = codec2_create(CODEC2_MODE_1600); + } +#else + m_c2->codec2_set_mode(m); +#endif +} + +bool M17Codec::get_mode() +{ + bool m = true; +#ifdef USE_EXTERNAL_CODEC2 + if(m_c2){ + if(codec2_samples_per_frame(m_c2) == 160){ + m = true; + } + else{ + m = false; + } + } +#else + return m_c2->codec2_get_mode(); +#endif + return m; +} void M17Codec::decode_c2(int16_t *audio, uint8_t *c) { +#ifdef USE_EXTERNAL_CODEC2 + if(m_c2){ + codec2_decode(m_c2, audio, c); + } +#else m_c2->codec2_decode(audio, c); +#endif } void M17Codec::encode_c2(int16_t *audio, uint8_t *c) { +#ifdef USE_EXTERNAL_CODEC2 + if(m_c2){ + codec2_encode(m_c2, c, audio); + } +#else m_c2->codec2_encode(c, audio); +#endif } void M17Codec::process_udp() @@ -189,8 +238,9 @@ void M17Codec::process_udp() connect(m_modem, SIGNAL(connected(bool)), this, SLOT(mmdvm_connect_status(bool))); connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray))); } - +#ifndef USE_EXTERNAL_CODEC2 m_c2 = new CCodec2(true); +#endif m_txtimer = new QTimer(); connect(m_txtimer, SIGNAL(timeout()), this, SLOT(transmit())); m_rxtimer = new QTimer(); @@ -330,7 +380,9 @@ void M17Codec::mmdvm_direct_connect() qDebug() << "No modem, cant do MMDVM_DIRECT"; } +#ifndef USE_EXTERNAL_CODEC2 m_c2 = new CCodec2(true); +#endif m_txtimer = new QTimer(); connect(m_txtimer, SIGNAL(timeout()), this, SLOT(transmit())); m_rxtimer = new QTimer(); @@ -675,7 +727,7 @@ void M17Codec::toggle_tx(bool tx) void M17Codec::start_tx() { - m_c2->codec2_set_mode(m_txrate); + set_mode(m_txrate); Codec::start_tx(); } @@ -699,17 +751,19 @@ void M17Codec::transmit() ttscnt++; } } - m_c2->codec2_encode(c2, pcm); + + encode_c2(pcm, c2); + if(get_mode()){ - m_c2->codec2_encode(c2+8, pcm+160); + encode_c2(pcm+160, c2+8); } } #endif if(m_ttsid == 0){ if(m_audio->read(pcm, 320)){ - m_c2->codec2_encode(c2, pcm); + encode_c2(pcm, c2); if(get_mode()){ - m_c2->codec2_encode(c2+8, pcm+160); + encode_c2(pcm+160, c2+8); } } else{ @@ -724,7 +778,6 @@ void M17Codec::transmit() if(m_tx){ if(txstreamid == 0){ txstreamid = static_cast((::rand() & 0xFFFF)); - //std::cerr << "txstreamid == " << txstreamid << std::endl; if(!m_rxtimer->isActive() && (m_modeinfo.host == "MMDVM_DIRECT")){ m_rxmodemq.clear(); m_modeinfo.stream_state = STREAM_NEW; @@ -770,7 +823,6 @@ void M17Codec::transmit() txframe.append((char)(tx_cnt >> 8)); txframe.append((char)tx_cnt & 0xff); txframe.append((char *)c2, 16); - //txframe.append(2, 0x00); for(int i = 0; i < 28; ++i){ lsf[i] = txframe.data()[6+i]; @@ -779,8 +831,6 @@ void M17Codec::transmit() encodeCRC16(lsf, M17_LSF_LENGTH_BYTES); txframe.append(lsf[28]); txframe.append(lsf[29]); - //QString ss = QString("%1").arg(txstreamid, 4, 16, QChar('0')); - //QString n = QString("TX %1").arg(tx_cnt, 4, 16, QChar('0')); if(m_modeinfo.host == "MMDVM_DIRECT"){ send_modem_data(txframe); @@ -793,7 +843,7 @@ void M17Codec::transmit() ++tx_cnt; m_modeinfo.src = m_modeinfo.callsign; m_modeinfo.dst = m_hostname; - m_modeinfo.type = get_mode();// ? "3200 Voice" : "1600 V/D"; + m_modeinfo.type = get_mode(); m_modeinfo.frame_number = tx_cnt; m_modeinfo.streamid = txstreamid; emit update(m_modeinfo); @@ -841,7 +891,6 @@ void M17Codec::transmit() txframe.append((char *)quiet, 8); txframe.append(2, 0x00); - //QString n = QString("%1").arg(tx_cnt, 4, 16, QChar('0')); if(m_modeinfo.host == "MMDVM_DIRECT"){ send_modem_data(txframe); m_modeinfo.stream_state = STREAM_END; @@ -860,7 +909,7 @@ void M17Codec::transmit() } m_modeinfo.src = m_modeinfo.callsign; m_modeinfo.dst = m_hostname; - m_modeinfo.type = get_mode();// ? "3200 Voice" : "1600 V/D"; + m_modeinfo.type = get_mode(); m_modeinfo.frame_number = tx_cnt; m_modeinfo.streamid = txstreamid; emit update(m_modeinfo); @@ -906,7 +955,7 @@ void M17Codec::process_rx_data() for(int i = 0; i < 8; ++i){ codec2[i] = m_rxcodecq.dequeue(); } - m_c2->codec2_decode(pcm, codec2); + decode_c2(pcm, codec2); int s = get_mode() ? 160 : 320; m_audio->write(pcm, s); emit update_output_level(m_audio->level()); diff --git a/m17codec.h b/m17codec.h index ba73b30..e97d5ee 100755 --- a/m17codec.h +++ b/m17codec.h @@ -20,7 +20,11 @@ #include #include "codec.h" -#include "codec2/codec2.h" +#ifdef USE_EXTERNAL_CODEC2 +#include +#else +#include "codec2/codec2_api.h" +#endif class M17Codec : public Codec { @@ -32,9 +36,13 @@ public: static void decode_callsign(uint8_t *); void decode_c2(int16_t *, uint8_t *); void encode_c2(int16_t *, uint8_t *); - void set_mode(bool m){ m_c2->codec2_set_mode(m);} - bool get_mode(){ return m_c2->codec2_get_mode(); } + void set_mode(bool); + bool get_mode(); +#ifdef USE_EXTERNAL_CODEC2 + CODEC2 *m_c2; +#else CCodec2 *m_c2; +#endif private slots: void process_udp(); void process_modem_data(QByteArray);