diff --git a/plugins/channeltx/modnfm/nfmmodgui.cpp b/plugins/channeltx/modnfm/nfmmodgui.cpp index cf1937b4b..4f8486524 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.cpp +++ b/plugins/channeltx/modnfm/nfmmodgui.cpp @@ -202,6 +202,12 @@ void NFMModGUI::on_afBW_valueChanged(int value) applySettings(); } +void NFMModGUI::on_preEmphasis_toggled(bool checked) +{ + m_settings.m_preEmphasisOn = checked; + applySettings(); +} + void NFMModGUI::on_fmDev_valueChanged(int value) { ui->fmDevText->setText(QString("%1%2k").arg(QChar(0xB1, 0x00)).arg(value / 10.0, 0, 'f', 1)); @@ -352,6 +358,12 @@ void NFMModGUI::on_dcsPositive_toggled(bool checked) applySettings(); } +void NFMModGUI::on_bpf_toggled(bool checked) +{ + m_settings.m_bpfOn = checked; + applySettings(); +} + void NFMModGUI::configureFileName() { qDebug() << "FileSourceGui::configureFileName: " << m_fileName.toStdString().c_str(); @@ -546,6 +558,7 @@ void NFMModGUI::displaySettings() ui->afBWText->setText(QString("%1k").arg(m_settings.m_afBandwidth / 1000.0, 0, 'f', 1)); ui->afBW->setValue(m_settings.m_afBandwidth / 100.0); + ui->preEmphasis->setChecked(m_settings.m_preEmphasisOn); ui->fmDevText->setText(QString("%1%2k").arg(QChar(0xB1, 0x00)).arg(m_settings.m_fmDeviation / 2000.0, 0, 'f', 1)); ui->fmDev->setValue(m_settings.m_fmDeviation / 200.0); @@ -567,6 +580,7 @@ void NFMModGUI::displaySettings() ui->dcsOn->setEnabled(!m_settings.m_ctcssOn); 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->channelMute->setChecked(m_settings.m_channelMute); ui->playLoop->setChecked(m_settings.m_playLoop); @@ -707,6 +721,7 @@ void NFMModGUI::makeUIConnections() QObject::connect(ui->channelSpacingApply, &QPushButton::clicked, this, &NFMModGUI::on_channelSpacingApply_clicked); QObject::connect(ui->rfBW, &QSlider::valueChanged, this, &NFMModGUI::on_rfBW_valueChanged); QObject::connect(ui->afBW, &QSlider::valueChanged, this, &NFMModGUI::on_afBW_valueChanged); + QObject::connect(ui->preEmphasis, &QCheckBox::toggled, this, &NFMModGUI::on_preEmphasis_toggled); QObject::connect(ui->fmDev, &QSlider::valueChanged, this, &NFMModGUI::on_fmDev_valueChanged); QObject::connect(ui->toneFrequency, &QDial::valueChanged, this, &NFMModGUI::on_toneFrequency_valueChanged); QObject::connect(ui->volume, &QDial::valueChanged, this, &NFMModGUI::on_volume_valueChanged); @@ -723,6 +738,7 @@ void NFMModGUI::makeUIConnections() QObject::connect(ui->dcsOn, &QCheckBox::toggled, this, &NFMModGUI::on_dcsOn_toggled); QObject::connect(ui->dcsCode, &QLineEdit::editingFinished, this, &NFMModGUI::on_dcsCode_editingFinished); QObject::connect(ui->dcsPositive, &QCheckBox::toggled, this, &NFMModGUI::on_dcsPositive_toggled); + QObject::connect(ui->bpf, &QCheckBox::toggled, this, &NFMModGUI::on_bpf_toggled); QObject::connect(ui->feedbackEnable, &QToolButton::toggled, this, &NFMModGUI::on_feedbackEnable_toggled); QObject::connect(ui->feedbackVolume, &QDial::valueChanged, this, &NFMModGUI::on_feedbackVolume_valueChanged); } diff --git a/plugins/channeltx/modnfm/nfmmodgui.h b/plugins/channeltx/modnfm/nfmmodgui.h index 3d20b38e4..d94ef701c 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.h +++ b/plugins/channeltx/modnfm/nfmmodgui.h @@ -114,6 +114,7 @@ private slots: void on_channelSpacingApply_clicked(); void on_rfBW_valueChanged(int value); void on_afBW_valueChanged(int value); + void on_preEmphasis_toggled(bool checked); void on_fmDev_valueChanged(int value); void on_toneFrequency_valueChanged(int value); void on_volume_valueChanged(int value); @@ -132,6 +133,7 @@ private slots: void on_dcsOn_toggled(bool checked); void on_dcsCode_editingFinished(); void on_dcsPositive_toggled(bool checked); + void on_bpf_toggled(bool checked); void on_feedbackEnable_toggled(bool checked); void on_feedbackVolume_valueChanged(int value); diff --git a/plugins/channeltx/modnfm/nfmmodgui.ui b/plugins/channeltx/modnfm/nfmmodgui.ui index 086c4d5da..12c468693 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.ui +++ b/plugins/channeltx/modnfm/nfmmodgui.ui @@ -279,6 +279,42 @@ + + + + + 24 + 0 + + + + Pre-emphasis (120us) on/off + + + P + + + + + + + + 24 + 16777215 + + + + Audio high pass filter for CTCSS on/off + + + + + + + :/filter_highpass.png:/filter_highpass.png + + + diff --git a/plugins/channeltx/modnfm/nfmmodsettings.cpp b/plugins/channeltx/modnfm/nfmmodsettings.cpp index 956466aaa..e857d5e5d 100644 --- a/plugins/channeltx/modnfm/nfmmodsettings.cpp +++ b/plugins/channeltx/modnfm/nfmmodsettings.cpp @@ -66,6 +66,8 @@ void NFMModSettings::resetToDefaults() m_dcsOn = false; m_dcsCode = 0023; m_dcsPositive = false; + m_preEmphasisOn = true; + m_bpfOn = true; m_rgbColor = QColor(255, 0, 0).rgb(); m_title = "NFM Modulator"; m_modAFInput = NFMModInputAF::NFMModInputNone; @@ -98,15 +100,16 @@ QByteArray NFMModSettings::serialize() const if (m_cwKeyerGUI) { s.writeBlob(8, m_cwKeyerGUI->serialize()); } else { // standalone operation with presets - s.writeBlob(6, m_cwKeyerSettings.serialize()); + s.writeBlob(8, m_cwKeyerSettings.serialize()); } + s.writeBool(9, m_ctcssOn); + s.writeS32(10, m_ctcssIndex); + if (m_channelMarker) { s.writeBlob(11, m_channelMarker->serialize()); } - s.writeBool(9, m_ctcssOn); - s.writeS32(10, m_ctcssIndex); s.writeString(12, m_title); s.writeS32(13, (int) m_modAFInput); s.writeString(14, m_audioDeviceName); @@ -130,6 +133,8 @@ QByteArray NFMModSettings::serialize() const s.writeS32(28, m_workspaceIndex); s.writeBlob(29, m_geometryBytes); s.writeBool(30, m_hidden); + s.writeBool(31, m_preEmphasisOn); + s.writeBool(32, m_bpfOn); return s.final(); } @@ -217,6 +222,8 @@ bool NFMModSettings::deserialize(const QByteArray& data) d.readS32(28, &m_workspaceIndex, 0); d.readBlob(29, &m_geometryBytes); d.readBool(30, &m_hidden, false); + d.readBool(31, &m_preEmphasisOn, true); + d.readBool(32, &m_bpfOn, true); return true; } diff --git a/plugins/channeltx/modnfm/nfmmodsettings.h b/plugins/channeltx/modnfm/nfmmodsettings.h index 9ce5fbf68..d64ab0d40 100644 --- a/plugins/channeltx/modnfm/nfmmodsettings.h +++ b/plugins/channeltx/modnfm/nfmmodsettings.h @@ -54,6 +54,8 @@ struct NFMModSettings bool m_dcsOn; int m_dcsCode; bool m_dcsPositive; + bool m_preEmphasisOn; + bool m_bpfOn; quint32 m_rgbColor; QString m_title; NFMModInputAF m_modAFInput; diff --git a/plugins/channeltx/modnfm/nfmmodsource.cpp b/plugins/channeltx/modnfm/nfmmodsource.cpp index 032dc1b27..97a2c64a7 100644 --- a/plugins/channeltx/modnfm/nfmmodsource.cpp +++ b/plugins/channeltx/modnfm/nfmmodsource.cpp @@ -144,7 +144,12 @@ void NFMModSource::modulateSample() Real t0, t1, t; pullAF(t0); - m_preemphasisFilter.process(t0, t); + + if (m_settings.m_preEmphasisOn) { + m_preemphasisFilter.process(t0, t); + } else { + t = t0; + } if (m_settings.m_feedbackAudioEnable) { pushFeedback(t * m_settings.m_feedbackVolumeFactor * 16384.0f); @@ -156,8 +161,10 @@ void NFMModSource::modulateSample() t1 = (0.85f * m_bandpass.filter(t) + 0.15f * 0.625f * m_ctcssNco.next()) * 1.2f; } else if (m_settings.m_dcsOn) { t1 = (0.9f * m_bandpass.filter(t) + 0.1f * 0.625f * m_dcsMod.next()) * 1.2f; - } else { + } else if (m_settings.m_bpfOn) { t1 = m_bandpass.filter(t) * 1.2f; + } else { + t1 = m_lowpass.filter(t) * 1.2f; } m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * t1; @@ -350,7 +357,7 @@ void NFMModSource::applyAudioSampleRate(int sampleRate) m_interpolatorConsumed = false; m_interpolatorDistance = (Real) sampleRate / (Real) m_channelSampleRate; m_interpolator.create(48, sampleRate, m_settings.m_rfBandwidth / 2.2, 3.0); - m_lowpass.create(301, sampleRate, 250.0); + m_lowpass.create(301, sampleRate, m_settings.m_afBandwidth); m_bandpass.create(301, sampleRate, 300.0, m_settings.m_afBandwidth); m_toneNco.setFreq(m_settings.m_toneFrequency, sampleRate); m_ctcssNco.setFreq(NFMModSettings::getCTCSSFreq(m_settings.m_ctcssIndex), sampleRate);