From 275710a7d60e4aab68d212ea0ab17c729da0d1dc Mon Sep 17 00:00:00 2001 From: Doug McLain Date: Sat, 19 Feb 2022 18:43:11 -0500 Subject: [PATCH] Add better mic gain control defaults and better slider scaling. Level meter better represents level during TX now --- MainTab.qml | 22 +++++++++++++++++----- README.md | 12 +++++------- audioengine.h | 1 + codec.cpp | 5 +++-- codec.h | 3 ++- dcscodec.cpp | 2 +- dmrcodec.cpp | 4 ++-- droidstar.cpp | 12 ++++++------ m17codec.cpp | 2 +- main.qml | 20 +++++++++++++++----- nxdncodec.cpp | 2 +- p25codec.cpp | 2 +- refcodec.cpp | 4 ++-- xrfcodec.cpp | 2 +- ysfcodec.cpp | 2 +- 15 files changed, 59 insertions(+), 36 deletions(-) diff --git a/MainTab.qml b/MainTab.qml index 88edadc..63050e4 100644 --- a/MainTab.qml +++ b/MainTab.qml @@ -67,6 +67,7 @@ Item { property alias uitimer: _uitimer property alias comboMode: _comboMode property alias comboHost: _comboHost + property alias dtmflabel: _dtmflabel property alias editIAXDTMF: _editIAXDTMF property alias dtmfsendbutton: _dtmfsendbutton property alias comboModule: _comboModule @@ -319,6 +320,17 @@ Item { //console.log("screen size ", parent.width, " x ", parent.height); } } + Text { + id: _dtmflabel + x: 5 + y: (parent.height / rows + 1) * 1; + width: parent.width / 5 + height: parent.height / rows; + text: qsTr("DTMF") + color: "white" + font.pixelSize: parent.height / 30; + verticalAlignment: Text.AlignVCenter + } TextField { id: _editIAXDTMF x: (parent.width / 4) @@ -326,7 +338,7 @@ Item { width: (parent.width * 3 / 8) - 4; height: parent.height / rows; font.pixelSize: parent.height / 35 - inputMethodHints: "ImhPreferNumbers" + //inputMethodHints: "ImhPreferNumbers" } Button { id: _dtmfsendbutton @@ -431,9 +443,9 @@ Item { y: (parent.height / rows + 1) * 3; width: parent.width / 4; height: parent.height / rows; - text: qsTr("TX") + text: qsTr("Mic") color: "white" - font.pixelSize: parent.height / 30; + font.pixelSize: parent.height / 40; verticalAlignment: Text.AlignVCenter } Slider { @@ -444,11 +456,11 @@ Item { y: (parent.height / rows + 1) * 3; width: (parent.width * 3 / 4) - 20 height: parent.height / rows; - value: 0.5 + value: 0.1 onValueChanged: { v = value * 100; droidstar.set_input_volume(value); - micgain_label.text = "TX " + v.toFixed(1); + micgain_label.text = "Mic " + v.toFixed(1); } } Text { diff --git a/README.md b/README.md index 8e30600..cf32d1a 100644 --- a/README.md +++ b/README.md @@ -16,18 +16,16 @@ DroidStar supports MMDVM and MMDVM_HS (hotspot) modems, with basic (possibly bug There is a vocoder plugin API available for loading of vocoder software. Any vocoder plugin used with DroidStar should be properly licensed by the user if any copyright patents apply. Do not use any patented vocoder plugin that you are not licensed to use. I have no information regarding aquiring a software vocoder. # Loading a vocoder plugin -A vocoder plugin is placed in the standard Download location for the given platform: -- Linux: ~/Downloads -- MacOS: ~/Downloads -- Windows: C:/Users/User/Documents -- Android: /storage/emulated/0/Download (typically referred to as Internal storage -> Download +A vocoder plugin can be downloaded from a URL, which will place the vocoder into the correct location for the platform. Add a full http url, including the filename, to the Vocoder URL option on the settings tab, and click the Download vocoder button. -A vocoder can also be downloaded from a URL. Add a full http url, including the filename, to the Vocoder URL option on the settings tab, and click the Download vocoder button. +For Android and iOS devices, the vocoder URL download method is the only way to load a vocoder plugin. For Linux/MacOS/Windows, a vocoder can also be manually placed. Copy the plugin to the system settings file location. On Linux, this is ~/.config/dudetronics. It is the same place where the host and id files are located (DMRHosts.txt, DMRIDs.data, etc). The vocoder plugin filename must be named vocoder_plugin.platform.arch where platform and arch can be any of the following: platform: linux, darwin, winnt, android, ios arch: x86_64, arm, arm64 +The platform and arch for your device are identified on the About tab. + There are no software vocoder plugins available in this repository, and I have no information on obtaining one. DONT ASK! # Optional FLite Text-to-speech build @@ -62,7 +60,7 @@ Host: hostname or IP address of node. Port: UDP port of node, usually 4569. -Add DTMF commands like \*3node, \*1node, \*70, etc in the IAX DTMF box and hit send to send the DTMF string. The asterisk (*) character is already added on the Droidstar app, so only input the numeric portion of the command (70 instead of *70, etc). Details on various commands can be found at the AllStar wiki and others. +Add DTMF commands like \*3node, \*1node, \*70, etc in the IAX DTMF box and hit send to send the DTMF string. Details on various commands can be found at the AllStar wiki and others. # General building instructions This software is written primarily in C++ on Linux and requires Qt5 >= Qt5.15, and natually the devel packages to build. The imbe_vocoder library is also required. Java, QML (Javascript based), and C# code is also used where necessary. The preferred way to obtain Qt 5.15 is to use the Qt open source online installer from the Qt website. Run this installer as a user (not root) to keep the Qt installation separate from your system libs. Select the option as shown in this pic https://imgur.com/i0WuFCY which will install everything under ~/Qt. diff --git a/audioengine.h b/audioengine.h index 1d304ae..fd9b1e6 100644 --- a/audioengine.h +++ b/audioengine.h @@ -24,6 +24,7 @@ #include #include #include +#include #define AUDIO_OUT 1 #define AUDIO_IN 0 diff --git a/codec.cpp b/codec.cpp index 9f822a8..2393e60 100644 --- a/codec.cpp +++ b/codec.cpp @@ -30,7 +30,7 @@ extern cst_voice * register_cmu_us_awb(const char *); } #endif -Codec::Codec(QString callsign, char module, QString hostname, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout) : +Codec::Codec(QString callsign, char module, QString hostname, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout, uint8_t attenuation) : m_module(module), m_hostname(hostname), m_tx(false), @@ -38,6 +38,7 @@ Codec::Codec(QString callsign, char module, QString hostname, QString host, int m_audioin(audioin), m_audioout(audioout), m_rxwatchdog(0), + m_attenuation(attenuation), #ifdef Q_OS_WIN m_rxtimerint(19), #else @@ -105,7 +106,7 @@ void Codec::mmdvm_connect_status(bool s) void Codec::in_audio_vol_changed(qreal v) { - m_audio->set_input_volume(v); + m_audio->set_input_volume(v / m_attenuation); } void Codec::out_audio_vol_changed(qreal v) diff --git a/codec.h b/codec.h index 552e631..72c4a48 100644 --- a/codec.h +++ b/codec.h @@ -37,7 +37,7 @@ class Codec : public QObject { Q_OBJECT public: - Codec(QString callsign, char module, QString hostname, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout); + Codec(QString callsign, char module, QString hostname, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout, uint8_t attenuation); ~Codec(); void set_modem_flags(bool rxInvert, bool txInvert, bool pttInvert, bool useCOSAsLockout, bool duplex) { m_rxInvert = rxInvert; m_txInvert = txInvert; m_pttInvert = pttInvert; m_useCOSAsLockout = useCOSAsLockout; m_duplex = duplex; } void set_modem_params(uint32_t baud, uint32_t rxfreq, uint32_t txfreq, uint32_t txDelay, float rxLevel, float rfLevel, uint32_t ysfTXHang, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagTXLevel, float m17TXLevel) @@ -170,6 +170,7 @@ protected: QString m_audioin; QString m_audioout; uint32_t m_rxwatchdog; + uint8_t m_attenuation; uint8_t m_rxtimerint; uint8_t m_txtimerint; QQueue m_rxcodecq; diff --git a/dcscodec.cpp b/dcscodec.cpp index 3a584a8..b83cbf4 100755 --- a/dcscodec.cpp +++ b/dcscodec.cpp @@ -23,7 +23,7 @@ //#define DEBUG DCSCodec::DCSCodec(QString callsign, QString hostname, char module, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout) : - Codec(callsign, module, hostname, host, port, ipv6, vocoder, modem, audioin, audioout) + Codec(callsign, module, hostname, host, port, ipv6, vocoder, modem, audioin, audioout, 5) { } diff --git a/dmrcodec.cpp b/dmrcodec.cpp index dda3d3a..6c64581 100755 --- a/dmrcodec.cpp +++ b/dmrcodec.cpp @@ -40,7 +40,7 @@ const uint32_t ENCODING_TABLE_1676[] = 0xF104U, 0xF377U, 0xF5E1U, 0xF792U, 0xF8CDU, 0xFABEU, 0xFC28U, 0xFE5BU}; DMRCodec::DMRCodec(QString callsign, uint32_t dmrid, uint8_t essid, QString password, QString lat, QString lon, QString location, QString desc, QString freq, QString url, QString swid, QString pkid, QString options, uint32_t dstid, QString host, uint32_t port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout) : - Codec(callsign, 0, NULL, host, port, ipv6, vocoder, modem, audioin, audioout), + Codec(callsign, 0, NULL, host, port, ipv6, vocoder, modem, audioin, audioout, 5), m_dmrid(dmrid), m_password(password), m_lat(lat), @@ -568,7 +568,7 @@ unsigned char * DMRCodec::get_eot() void DMRCodec::build_frame() { - qDebug() << "DMR: slot:cc == " << m_txslot << ":" << m_txcc; + //qDebug() << "DMR: slot:cc == " << m_txslot << ":" << m_txcc; m_dmrFrame[0U] = 'D'; m_dmrFrame[1U] = 'M'; m_dmrFrame[2U] = 'R'; diff --git a/droidstar.cpp b/droidstar.cpp index addf021..d7ff6ad 100644 --- a/droidstar.cpp +++ b/droidstar.cpp @@ -196,7 +196,7 @@ void DroidStar::file_downloaded(QString filename) void DroidStar::dtmf_send_clicked(QString dtmf) { QByteArray tx(dtmf.simplified().toUtf8(), dtmf.simplified().size()); - tx.prepend('*'); + //tx.prepend('*'); emit send_dtmf(tx); } @@ -244,7 +244,7 @@ void DroidStar::process_connect() #ifdef Q_OS_IOS MicPermission::check_permission(); #endif - +#include "build.h" if( (m_callsign.size() < 4) || (m_dmrid < 250000) || (m_callsign != m_dmrids[m_dmrid])) @@ -1627,7 +1627,7 @@ void DroidStar::update_nxdn_data(Codec::MODEINFO info) if( (connect_status == Codec::CONNECTING) && ( info.status == Codec::CONNECTED_RW)){ connect_status = Codec::CONNECTED_RW; emit connect_status_changed(2); - emit in_audio_vol_changed(0.1); + emit in_audio_vol_changed(0.5); emit swtx_state(!m_nxdn->get_hwtx()); emit swrx_state(!m_nxdn->get_hwrx()); emit update_log("Connected to " + m_protocol + " " + m_host + " " + m_hostname + ":" + QString::number(m_port)); @@ -1708,7 +1708,7 @@ void DroidStar::update_dmr_data(Codec::MODEINFO info) if( (connect_status == Codec::CONNECTING) && ( info.status == Codec::CONNECTED_RW)){ connect_status = Codec::CONNECTED_RW; emit connect_status_changed(2); - emit in_audio_vol_changed(0.1); + emit in_audio_vol_changed(0.5); emit swtx_state(!m_dmr->get_hwtx()); emit swrx_state(!m_dmr->get_hwrx()); emit update_log("Connected to " + m_protocol + " " + m_host + " " + m_hostname + ":" + QString::number(m_port)); @@ -1793,7 +1793,7 @@ void DroidStar::update_ysf_data(Codec::MODEINFO info) if( (connect_status == Codec::CONNECTING) && (info.status == Codec::CONNECTED_RW)){ connect_status = Codec::CONNECTED_RW; emit connect_status_changed(2); - emit in_audio_vol_changed(0.1); + emit in_audio_vol_changed(0.5); emit swtx_state(!m_ysf->get_hwtx()); emit swrx_state(!m_ysf->get_hwrx()); emit update_log("Connected to " + m_protocol + " " + m_host + " " + m_hostname + ":" + QString::number(m_port)); @@ -1881,7 +1881,7 @@ void DroidStar::update_p25_data(Codec::MODEINFO info) if( (connect_status == Codec::CONNECTING) && (info.status == Codec::CONNECTED_RW)){ connect_status = Codec::CONNECTED_RW; emit connect_status_changed(2); - emit in_audio_vol_changed(0.2); + emit in_audio_vol_changed(0.5); emit swtx_state(!m_p25->get_hwtx()); emit swrx_state(!m_p25->get_hwrx()); emit update_log("Connected to " + m_protocol + " " + m_host + " " + m_hostname + ":" + QString::number(m_port)); diff --git a/m17codec.cpp b/m17codec.cpp index d8d64a6..f54bbf9 100755 --- a/m17codec.cpp +++ b/m17codec.cpp @@ -84,7 +84,7 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 #define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) 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, 1), m_c2(NULL), m_txrate(1) { diff --git a/main.qml b/main.qml index 8511371..fa9dccb 100644 --- a/main.qml +++ b/main.qml @@ -194,6 +194,7 @@ ApplicationWindow { if(droidstar.get_mode() === "REF"){ //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; + mainTab.dtmflabel.visible = false; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_ref_host()); @@ -209,6 +210,7 @@ ApplicationWindow { if(droidstar.get_mode() === "DCS"){ //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; + mainTab.dtmflabel.visible = false; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_dcs_host()); @@ -224,6 +226,7 @@ ApplicationWindow { if(droidstar.get_mode() === "XRF"){ //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; + mainTab.dtmflabel.visible = false; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_xrf_host()); @@ -239,6 +242,7 @@ ApplicationWindow { if(droidstar.get_mode() === "YSF"){ //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; + mainTab.dtmflabel.visible = false; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_ysf_host()); @@ -249,11 +253,12 @@ ApplicationWindow { mainTab.dmrtgidEdit.visible = false; mainTab.comboM17CAN.visible = false; mainTab.privateBox.visible = false; - mainTab.sliderMicGain.value = 0.1; + mainTab.sliderMicGain.value = 0.5; } if(droidstar.get_mode() === "FCS"){ //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; + mainTab.dtmflabel.visible = false; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_fcs_host()); @@ -264,11 +269,12 @@ ApplicationWindow { mainTab.dmrtgidEdit.visible = false; mainTab.comboM17CAN.visible = false; mainTab.privateBox.visible = false; - mainTab.sliderMicGain.value = 0.1; + mainTab.sliderMicGain.value = 0.5; } if(droidstar.get_mode() === "DMR"){ //mainTab.comboMode.width = (mainTab.width / 5) - 5; mainTab.comboHost.visible = true; + mainTab.dtmflabel.visible = false; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_dmr_host()); @@ -280,11 +286,12 @@ ApplicationWindow { mainTab.dmrtgidEdit.visible = true; mainTab.comboM17CAN.visible = false; mainTab.privateBox.visible = true; - mainTab.sliderMicGain.value = 0.1; + mainTab.sliderMicGain.value = 0.5; } if(droidstar.get_mode() === "P25"){ //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; + mainTab.dtmflabel.visible = false; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_p25_host()); @@ -296,11 +303,12 @@ ApplicationWindow { mainTab.dmrtgidEdit.visible = true; mainTab.comboM17CAN.visible = false; mainTab.privateBox.visible = false; - mainTab.sliderMicGain.value = 0.2; + mainTab.sliderMicGain.value = 0.5; } if(droidstar.get_mode() === "NXDN"){ //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; + mainTab.dtmflabel.visible = false; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_nxdn_host()); @@ -311,11 +319,12 @@ ApplicationWindow { mainTab.dmrtgidEdit.visible = false; mainTab.comboM17CAN.visible = false; mainTab.privateBox.visible = false; - mainTab.sliderMicGain.value = 0.1; + mainTab.sliderMicGain.value = 0.5; } if(droidstar.get_mode() === "M17"){ //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; + mainTab.dtmflabel.visible = false; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_m17_host()); @@ -333,6 +342,7 @@ ApplicationWindow { if(droidstar.get_mode() === "IAX"){ //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = false; + mainTab.dtmflabel.visible = true; mainTab.editIAXDTMF.visible = true; mainTab.dtmfsendbutton.visible = true; mainTab.comboModule.visible = false; diff --git a/nxdncodec.cpp b/nxdncodec.cpp index 9975e5e..cbaa94e 100755 --- a/nxdncodec.cpp +++ b/nxdncodec.cpp @@ -40,7 +40,7 @@ const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04 #define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) NXDNCodec::NXDNCodec(QString callsign, uint16_t nxdnid, uint32_t gwid, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout) : - Codec(callsign, 0, NULL, host, port, ipv6, vocoder, modem, audioin, audioout), + Codec(callsign, 0, NULL, host, port, ipv6, vocoder, modem, audioin, audioout, 5), m_nxdnid(nxdnid) { m_txcnt = 0; diff --git a/p25codec.cpp b/p25codec.cpp index d40a206..7ddab73 100755 --- a/p25codec.cpp +++ b/p25codec.cpp @@ -46,7 +46,7 @@ const unsigned char REC80[] = {0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, #define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) P25Codec::P25Codec(QString callsign, int dmrid, int hostname, QString host, int port, bool ipv6, QString modem, QString audioin, QString audioout) : - Codec(callsign, 0, NULL, host, port, ipv6, NULL, modem, audioin, audioout), + Codec(callsign, 0, NULL, host, port, ipv6, NULL, modem, audioin, audioout, 2), m_hostname(hostname), m_dmrid(dmrid) { diff --git a/refcodec.cpp b/refcodec.cpp index 31d4a4a..d8971ff 100755 --- a/refcodec.cpp +++ b/refcodec.cpp @@ -20,7 +20,7 @@ #include "refcodec.h" #include "CRCenc.h" -//#define DEBUG +#define DEBUG const unsigned char MMDVM_DSTAR_HEADER = 0x10U; const unsigned char MMDVM_DSTAR_DATA = 0x11U; @@ -28,7 +28,7 @@ const unsigned char MMDVM_DSTAR_LOST = 0x12U; const unsigned char MMDVM_DSTAR_EOT = 0x13U; REFCodec::REFCodec(QString callsign, QString hostname, char module, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout) : - Codec(callsign, module, hostname, host, port, ipv6, vocoder, modem, audioin, audioout) + Codec(callsign, module, hostname, host, port, ipv6, vocoder, modem, audioin, audioout, 5) { } diff --git a/xrfcodec.cpp b/xrfcodec.cpp index f2a9f0e..fd81e72 100755 --- a/xrfcodec.cpp +++ b/xrfcodec.cpp @@ -24,7 +24,7 @@ //#define DEBUG XRFCodec::XRFCodec(QString callsign, QString hostname, char module, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout) : - Codec(callsign, module, hostname, host, port, ipv6, vocoder, modem, audioin, audioout) + Codec(callsign, module, hostname, host, port, ipv6, vocoder, modem, audioin, audioout, 5) { } diff --git a/ysfcodec.cpp b/ysfcodec.cpp index 6129dc9..42a344b 100755 --- a/ysfcodec.cpp +++ b/ysfcodec.cpp @@ -100,7 +100,7 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 #define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) YSFCodec::YSFCodec(QString callsign, QString hostname, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout) : - Codec(callsign, 0, hostname, host, port, ipv6, vocoder, modem, audioin, audioout), + Codec(callsign, 0, hostname, host, port, ipv6, vocoder, modem, audioin, audioout, 5), m_fcs(false), m_txfullrate(false)