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