Fix audio receive bug when receiving M17 1600 V/D with AGC on and add compile time option to use external codec2 library

pull/3/head
Doug McLain 3 years ago
parent f2073c919a
commit 015b2a2637

@ -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 += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
DEFINES += VOCODER_PLUGIN DEFINES += VOCODER_PLUGIN
#DEFINES += USE_FLITE #DEFINES += USE_FLITE
#DEFINES += USE_EXTERNAL_CODEC2
HEADERS += \ HEADERS += \
CRCenc.h \ CRCenc.h \
@ -45,14 +46,6 @@ HEADERS += \
cgolay2087.h \ cgolay2087.h \
chamming.h \ chamming.h \
codec.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 \ crs129.h \
dcscodec.h \ dcscodec.h \
dmrcodec.h \ dmrcodec.h \
@ -85,14 +78,6 @@ SOURCES += \
cgolay2087.cpp \ cgolay2087.cpp \
chamming.cpp \ chamming.cpp \
codec.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 \ crs129.cpp \
dcscodec.cpp \ dcscodec.cpp \
dmrcodec.cpp \ dmrcodec.cpp \
@ -108,6 +93,29 @@ SOURCES += \
serialmodem.cpp \ serialmodem.cpp \
xrfcodec.cpp \ xrfcodec.cpp \
ysfcodec.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 macx:OBJECTIVE_SOURCES += micpermission.mm
ios:OBJECTIVE_SOURCES += micpermission.mm ios:OBJECTIVE_SOURCES += micpermission.mm

@ -352,12 +352,12 @@ void AudioEngine::process_audio(int16_t *pcm, size_t s)
} }
} }
gaindelta /= static_cast<float>(160); gaindelta /= static_cast<float>(s); //160
// adjust output gain // adjust output gain
m_audio_out_temp_buf_p = m_audio_out_temp_buf; 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<float>(i) * gaindelta)) * (*m_audio_out_temp_buf_p); *m_audio_out_temp_buf_p = (m_aout_gain + (static_cast<float>(i) * gaindelta)) * (*m_audio_out_temp_buf_p);
m_audio_out_temp_buf_p++; m_audio_out_temp_buf_p++;
} }

@ -65,7 +65,7 @@ private:
bool m_agc; bool m_agc;
float m_srm; // sample rate multiplier for macOS HACK 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_temp_buf_p;
//float m_audio_out_float_buf[1120]; //!< output of upsampler - 1 frame of 160 samples upampled up to 7 times //float m_audio_out_float_buf[1120]; //!< output of upsampler - 1 frame of 160 samples upampled up to 7 times

@ -36,7 +36,7 @@
#include "nlp.h" #include "nlp.h"
#include "lpc.h" #include "lpc.h"
#include "quantise.h" #include "quantise.h"
#include "codec2.h" #include "codec2_api.h"
#include "codec2_internal.h" #include "codec2_internal.h"
#define HPF_BETA 0.125 #define HPF_BETA 0.125

@ -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) : 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), Codec(callsign, module, hostname, host, port, ipv6, NULL, modem, audioin, audioout),
m_c2(NULL),
m_txrate(1) m_txrate(1)
{ {
m_modeinfo.callsign = callsign; 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) 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); m_c2->codec2_decode(audio, c);
#endif
} }
void M17Codec::encode_c2(int16_t *audio, uint8_t *c) 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); m_c2->codec2_encode(c, audio);
#endif
} }
void M17Codec::process_udp() 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(connected(bool)), this, SLOT(mmdvm_connect_status(bool)));
connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray))); connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray)));
} }
#ifndef USE_EXTERNAL_CODEC2
m_c2 = new CCodec2(true); m_c2 = new CCodec2(true);
#endif
m_txtimer = new QTimer(); m_txtimer = new QTimer();
connect(m_txtimer, SIGNAL(timeout()), this, SLOT(transmit())); connect(m_txtimer, SIGNAL(timeout()), this, SLOT(transmit()));
m_rxtimer = new QTimer(); m_rxtimer = new QTimer();
@ -330,7 +380,9 @@ void M17Codec::mmdvm_direct_connect()
qDebug() << "No modem, cant do MMDVM_DIRECT"; qDebug() << "No modem, cant do MMDVM_DIRECT";
} }
#ifndef USE_EXTERNAL_CODEC2
m_c2 = new CCodec2(true); m_c2 = new CCodec2(true);
#endif
m_txtimer = new QTimer(); m_txtimer = new QTimer();
connect(m_txtimer, SIGNAL(timeout()), this, SLOT(transmit())); connect(m_txtimer, SIGNAL(timeout()), this, SLOT(transmit()));
m_rxtimer = new QTimer(); m_rxtimer = new QTimer();
@ -675,7 +727,7 @@ void M17Codec::toggle_tx(bool tx)
void M17Codec::start_tx() void M17Codec::start_tx()
{ {
m_c2->codec2_set_mode(m_txrate); set_mode(m_txrate);
Codec::start_tx(); Codec::start_tx();
} }
@ -699,17 +751,19 @@ void M17Codec::transmit()
ttscnt++; ttscnt++;
} }
} }
m_c2->codec2_encode(c2, pcm);
encode_c2(pcm, c2);
if(get_mode()){ if(get_mode()){
m_c2->codec2_encode(c2+8, pcm+160); encode_c2(pcm+160, c2+8);
} }
} }
#endif #endif
if(m_ttsid == 0){ if(m_ttsid == 0){
if(m_audio->read(pcm, 320)){ if(m_audio->read(pcm, 320)){
m_c2->codec2_encode(c2, pcm); encode_c2(pcm, c2);
if(get_mode()){ if(get_mode()){
m_c2->codec2_encode(c2+8, pcm+160); encode_c2(pcm+160, c2+8);
} }
} }
else{ else{
@ -724,7 +778,6 @@ void M17Codec::transmit()
if(m_tx){ if(m_tx){
if(txstreamid == 0){ if(txstreamid == 0){
txstreamid = static_cast<uint16_t>((::rand() & 0xFFFF)); txstreamid = static_cast<uint16_t>((::rand() & 0xFFFF));
//std::cerr << "txstreamid == " << txstreamid << std::endl;
if(!m_rxtimer->isActive() && (m_modeinfo.host == "MMDVM_DIRECT")){ if(!m_rxtimer->isActive() && (m_modeinfo.host == "MMDVM_DIRECT")){
m_rxmodemq.clear(); m_rxmodemq.clear();
m_modeinfo.stream_state = STREAM_NEW; m_modeinfo.stream_state = STREAM_NEW;
@ -770,7 +823,6 @@ void M17Codec::transmit()
txframe.append((char)(tx_cnt >> 8)); txframe.append((char)(tx_cnt >> 8));
txframe.append((char)tx_cnt & 0xff); txframe.append((char)tx_cnt & 0xff);
txframe.append((char *)c2, 16); txframe.append((char *)c2, 16);
//txframe.append(2, 0x00);
for(int i = 0; i < 28; ++i){ for(int i = 0; i < 28; ++i){
lsf[i] = txframe.data()[6+i]; lsf[i] = txframe.data()[6+i];
@ -779,8 +831,6 @@ void M17Codec::transmit()
encodeCRC16(lsf, M17_LSF_LENGTH_BYTES); encodeCRC16(lsf, M17_LSF_LENGTH_BYTES);
txframe.append(lsf[28]); txframe.append(lsf[28]);
txframe.append(lsf[29]); 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"){ if(m_modeinfo.host == "MMDVM_DIRECT"){
send_modem_data(txframe); send_modem_data(txframe);
@ -793,7 +843,7 @@ void M17Codec::transmit()
++tx_cnt; ++tx_cnt;
m_modeinfo.src = m_modeinfo.callsign; m_modeinfo.src = m_modeinfo.callsign;
m_modeinfo.dst = m_hostname; 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.frame_number = tx_cnt;
m_modeinfo.streamid = txstreamid; m_modeinfo.streamid = txstreamid;
emit update(m_modeinfo); emit update(m_modeinfo);
@ -841,7 +891,6 @@ void M17Codec::transmit()
txframe.append((char *)quiet, 8); txframe.append((char *)quiet, 8);
txframe.append(2, 0x00); txframe.append(2, 0x00);
//QString n = QString("%1").arg(tx_cnt, 4, 16, QChar('0'));
if(m_modeinfo.host == "MMDVM_DIRECT"){ if(m_modeinfo.host == "MMDVM_DIRECT"){
send_modem_data(txframe); send_modem_data(txframe);
m_modeinfo.stream_state = STREAM_END; m_modeinfo.stream_state = STREAM_END;
@ -860,7 +909,7 @@ void M17Codec::transmit()
} }
m_modeinfo.src = m_modeinfo.callsign; m_modeinfo.src = m_modeinfo.callsign;
m_modeinfo.dst = m_hostname; 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.frame_number = tx_cnt;
m_modeinfo.streamid = txstreamid; m_modeinfo.streamid = txstreamid;
emit update(m_modeinfo); emit update(m_modeinfo);
@ -906,7 +955,7 @@ void M17Codec::process_rx_data()
for(int i = 0; i < 8; ++i){ for(int i = 0; i < 8; ++i){
codec2[i] = m_rxcodecq.dequeue(); codec2[i] = m_rxcodecq.dequeue();
} }
m_c2->codec2_decode(pcm, codec2); decode_c2(pcm, codec2);
int s = get_mode() ? 160 : 320; int s = get_mode() ? 160 : 320;
m_audio->write(pcm, s); m_audio->write(pcm, s);
emit update_output_level(m_audio->level()); emit update_output_level(m_audio->level());

@ -20,7 +20,11 @@
#include <string> #include <string>
#include "codec.h" #include "codec.h"
#include "codec2/codec2.h" #ifdef USE_EXTERNAL_CODEC2
#include <codec2/codec2.h>
#else
#include "codec2/codec2_api.h"
#endif
class M17Codec : public Codec class M17Codec : public Codec
{ {
@ -32,9 +36,13 @@ public:
static void decode_callsign(uint8_t *); static void decode_callsign(uint8_t *);
void decode_c2(int16_t *, uint8_t *); void decode_c2(int16_t *, uint8_t *);
void encode_c2(int16_t *, uint8_t *); void encode_c2(int16_t *, uint8_t *);
void set_mode(bool m){ m_c2->codec2_set_mode(m);} void set_mode(bool);
bool get_mode(){ return m_c2->codec2_get_mode(); } bool get_mode();
#ifdef USE_EXTERNAL_CODEC2
CODEC2 *m_c2;
#else
CCodec2 *m_c2; CCodec2 *m_c2;
#endif
private slots: private slots:
void process_udp(); void process_udp();
void process_modem_data(QByteArray); void process_modem_data(QByteArray);

Loading…
Cancel
Save