diff --git a/doc/img/NFMMod_plugin.png b/doc/img/NFMMod_plugin.png index 8a3158490..5823b9913 100644 Binary files a/doc/img/NFMMod_plugin.png and b/doc/img/NFMMod_plugin.png differ diff --git a/doc/img/NFMMod_plugin.xcf b/doc/img/NFMMod_plugin.xcf index 3d69da6c4..f2a9130be 100644 Binary files a/doc/img/NFMMod_plugin.xcf and b/doc/img/NFMMod_plugin.xcf differ diff --git a/doc/img/NFMMod_plugin_input.png b/doc/img/NFMMod_plugin_input.png new file mode 100644 index 000000000..1fce8861c Binary files /dev/null and b/doc/img/NFMMod_plugin_input.png differ diff --git a/doc/img/NFMMod_plugin_input.xcf b/doc/img/NFMMod_plugin_input.xcf new file mode 100644 index 000000000..89c799098 Binary files /dev/null and b/doc/img/NFMMod_plugin_input.xcf differ diff --git a/plugins/channeltx/modnfm/nfmmodgui.cpp b/plugins/channeltx/modnfm/nfmmodgui.cpp index 4f8486524..b6caf8d3c 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.cpp +++ b/plugins/channeltx/modnfm/nfmmodgui.cpp @@ -279,6 +279,12 @@ void NFMModGUI::on_mic_toggled(bool checked) applySettings(); } +void NFMModGUI::on_compressor_toggled(bool checked) +{ + m_settings.m_compressorEnable = checked; + applySettings(); +} + void NFMModGUI::on_feedbackEnable_toggled(bool checked) { m_settings.m_feedbackAudioEnable = checked; @@ -581,6 +587,7 @@ void NFMModGUI::displaySettings() ui->dcsCode->setText(tr("%1").arg(m_settings.m_dcsCode, 3, 8, QLatin1Char('0'))); ui->dcsPositive->setChecked(m_settings.m_dcsPositive); ui->bpf->setChecked(m_settings.m_bpfOn); + ui->compressor->setChecked(m_settings.m_compressorEnable); ui->channelMute->setChecked(m_settings.m_channelMute); ui->playLoop->setChecked(m_settings.m_playLoop); @@ -729,6 +736,7 @@ void NFMModGUI::makeUIConnections() QObject::connect(ui->tone, &ButtonSwitch::toggled, this, &NFMModGUI::on_tone_toggled); QObject::connect(ui->morseKeyer, &ButtonSwitch::toggled, this, &NFMModGUI::on_morseKeyer_toggled); QObject::connect(ui->mic, &ButtonSwitch::toggled, this, &NFMModGUI::on_mic_toggled); + QObject::connect(ui->compressor, &ButtonSwitch::toggled, this, &NFMModGUI::on_compressor_toggled); QObject::connect(ui->play, &ButtonSwitch::toggled, this, &NFMModGUI::on_play_toggled); QObject::connect(ui->playLoop, &ButtonSwitch::toggled, this, &NFMModGUI::on_playLoop_toggled); QObject::connect(ui->navTimeSlider, &QSlider::valueChanged, this, &NFMModGUI::on_navTimeSlider_valueChanged); diff --git a/plugins/channeltx/modnfm/nfmmodgui.h b/plugins/channeltx/modnfm/nfmmodgui.h index d94ef701c..3b93d070c 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.h +++ b/plugins/channeltx/modnfm/nfmmodgui.h @@ -122,6 +122,7 @@ private slots: void on_tone_toggled(bool checked); void on_morseKeyer_toggled(bool checked); void on_mic_toggled(bool checked); + void on_compressor_toggled(bool checked); void on_play_toggled(bool checked); void on_playLoop_toggled(bool checked); diff --git a/plugins/channeltx/modnfm/nfmmodgui.ui b/plugins/channeltx/modnfm/nfmmodgui.ui index 12c468693..3832e3d6d 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.ui +++ b/plugins/channeltx/modnfm/nfmmodgui.ui @@ -589,6 +589,16 @@ + + + + Audio input compressor on/off + + + CMP + + + diff --git a/plugins/channeltx/modnfm/nfmmodsettings.cpp b/plugins/channeltx/modnfm/nfmmodsettings.cpp index e857d5e5d..17432933d 100644 --- a/plugins/channeltx/modnfm/nfmmodsettings.cpp +++ b/plugins/channeltx/modnfm/nfmmodsettings.cpp @@ -75,6 +75,7 @@ void NFMModSettings::resetToDefaults() m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName; m_feedbackVolumeFactor = 0.5f; m_feedbackAudioEnable = false; + m_compressorEnable = false; m_streamIndex = 0; m_useReverseAPI = false; m_reverseAPIAddress = "127.0.0.1"; @@ -135,6 +136,7 @@ QByteArray NFMModSettings::serialize() const s.writeBool(30, m_hidden); s.writeBool(31, m_preEmphasisOn); s.writeBool(32, m_bpfOn); + s.writeBool(33, m_compressorEnable); return s.final(); } @@ -224,6 +226,7 @@ bool NFMModSettings::deserialize(const QByteArray& data) d.readBool(30, &m_hidden, false); d.readBool(31, &m_preEmphasisOn, true); d.readBool(32, &m_bpfOn, true); + d.readBool(33, &m_compressorEnable, false); return true; } diff --git a/plugins/channeltx/modnfm/nfmmodsettings.h b/plugins/channeltx/modnfm/nfmmodsettings.h index d64ab0d40..3bce7258f 100644 --- a/plugins/channeltx/modnfm/nfmmodsettings.h +++ b/plugins/channeltx/modnfm/nfmmodsettings.h @@ -63,6 +63,7 @@ struct NFMModSettings QString m_feedbackAudioDeviceName; //!< This is the audio device you send the audio samples to for audio feedback float m_feedbackVolumeFactor; bool m_feedbackAudioEnable; + bool m_compressorEnable; int m_streamIndex; bool m_useReverseAPI; QString m_reverseAPIAddress; diff --git a/plugins/channeltx/modnfm/nfmmodsource.cpp b/plugins/channeltx/modnfm/nfmmodsource.cpp index 97a2c64a7..0cd49d9a0 100644 --- a/plugins/channeltx/modnfm/nfmmodsource.cpp +++ b/plugins/channeltx/modnfm/nfmmodsource.cpp @@ -55,6 +55,16 @@ NFMModSource::NFMModSource() : m_magsq = 0.0; + m_audioCompressor.initSimple( + m_audioSampleRate, + -8, // pregain (dB) + -20, // threshold (dB) + 20, // knee (dB) + 15, // ratio (dB) + 0.003, // attack (s) + 0.25 // release (s) + ); + applySettings(m_settings, true); applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true); } @@ -242,7 +252,16 @@ void NFMModSource::pullAF(Real& sample) case NFMModSettings::NFMModInputAudio: if (m_audioBufferFill < m_audioBuffer.size()) { - sample = ((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_settings.m_volumeFactor; + if (m_settings.m_compressorEnable) + { + sample = ((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 3276.8f); + sample = clamp(m_audioCompressor.compress(sample), -1.0f, 1.0f) * m_settings.m_volumeFactor * 3.0f; + } + else + { + sample = ((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 3276.8f) * m_settings.m_volumeFactor; + } + m_audioBufferFill++; } else @@ -365,6 +384,8 @@ void NFMModSource::applyAudioSampleRate(int sampleRate) m_cwKeyer.setSampleRate(sampleRate); m_cwKeyer.reset(); m_preemphasisFilter.configure(m_preemphasis*sampleRate); + m_audioCompressor.m_rate = sampleRate; + m_audioCompressor.initState(); m_audioSampleRate = sampleRate; applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate); diff --git a/plugins/channeltx/modnfm/nfmmodsource.h b/plugins/channeltx/modnfm/nfmmodsource.h index 8f6a6a6c4..29a46e377 100644 --- a/plugins/channeltx/modnfm/nfmmodsource.h +++ b/plugins/channeltx/modnfm/nfmmodsource.h @@ -34,6 +34,7 @@ #include "util/movingaverage.h" #include "dsp/cwkeyer.h" #include "audio/audiofifo.h" +#include "audio/audiocompressorsnd.h" #include "nfmmodsettings.h" #include "nfmmoddcs.h" @@ -124,6 +125,8 @@ private: std::ifstream *m_ifstream; CWKeyer m_cwKeyer; + AudioCompressorSnd m_audioCompressor; + QMutex m_mutex; static const int m_levelNbSamples; diff --git a/plugins/channeltx/modnfm/readme.md b/plugins/channeltx/modnfm/readme.md index 42bddf112..1d3f7b942 100644 --- a/plugins/channeltx/modnfm/readme.md +++ b/plugins/channeltx/modnfm/readme.md @@ -122,7 +122,7 @@ You should aim at keeping the peak value below 100% using the volume control

10: Input source control

-![Modulator input source control GUI](../../../doc/img/ModControls.png) +![Modulator input source control GUI](../../../doc/img/NFMMod_plugin_input.png)

10.1: Tone input select

@@ -142,6 +142,10 @@ Left click to switch to the audio input. You must switch it off to make other in Right click to select audio input device. See [audio management documentation](../../../sdrgui/audio.md) for details. +

10.5: Audio input compression

+ +Toggles the compressor for the audio input. +

11: Audio feedback

Activate or de-activate the input source audio feedback