From f91b0382e546c2b8ee73e6d6b961cc53e473bcbd Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 5 Jan 2017 06:29:08 +0100 Subject: [PATCH] WFM modulator: fixed RF bandwidth issue --- plugins/channeltx/modwfm/wfmmod.cpp | 52 +++++++++++++++++++++----- plugins/channeltx/modwfm/wfmmod.h | 4 ++ plugins/channeltx/modwfm/wfmmodgui.cpp | 12 +++++- plugins/channeltx/modwfm/wfmmodgui.h | 1 + plugins/channeltx/modwfm/wfmmodgui.ui | 13 +------ 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/plugins/channeltx/modwfm/wfmmod.cpp b/plugins/channeltx/modwfm/wfmmod.cpp index 1a6bcb572..27903dfef 100644 --- a/plugins/channeltx/modwfm/wfmmod.cpp +++ b/plugins/channeltx/modwfm/wfmmod.cpp @@ -59,9 +59,13 @@ WFMMod::WFMMod() : m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); m_rfFilter = new fftfilt(-62500.0 / 384000.0, 62500.0 / 384000.0, m_rfFilterFFTLength); + m_rfFilterBuffer = new Complex[m_rfFilterFFTLength]; + memset(m_rfFilterBuffer, 0, sizeof(Complex)*(m_rfFilterFFTLength)); + m_rfFilterBufferIndex = 0; apply(); + m_audioBuffer.resize(1<<14); m_audioBufferFill = 0; @@ -70,6 +74,7 @@ WFMMod::WFMMod() : m_magsq = 0.0; m_toneNco.setFreq(1000.0, m_config.m_audioSampleRate); + m_toneNcoRF.setFreq(1000.0, m_config.m_outputSampleRate); DSPEngine::instance()->addAudioSource(&m_audioFifo); // CW keyer @@ -82,6 +87,7 @@ WFMMod::WFMMod() : WFMMod::~WFMMod() { delete m_rfFilter; + delete[] m_rfFilterBuffer; DSPEngine::instance()->removeAudioSource(&m_audioFifo); } @@ -109,25 +115,43 @@ void WFMMod::pull(Sample& sample) Complex ci, ri; Real t; + fftfilt::cmplx *rf; + int rf_out; m_settingsMutex.lock(); - if (m_interpolator.interpolate(&m_interpolatorDistanceRemain, m_modSample, &ri)) - { - pullAF(m_modSample); - calculateLevel(m_modSample.real()); - m_audioBufferFill++; - } + if ((m_afInput == WFMModInputFile) || (m_afInput == WFMModInputAudio) || (m_afInput == WFMModInputCWTone)) + { + if (m_interpolator.interpolate(&m_interpolatorDistanceRemain, m_modSample, &ri)) + { + pullAF(m_modSample); + calculateLevel(m_modSample.real()); + m_audioBufferFill++; + } - m_interpolatorDistanceRemain += m_interpolatorDistance; + m_interpolatorDistanceRemain += m_interpolatorDistance; + } + else + { + pullAF(ri); + } m_modPhasor += (m_running.m_fmDeviation / (float) m_running.m_outputSampleRate) * ri.real() * M_PI; ci.real(cos(m_modPhasor) * 29204.0f); // -1 dB ci.imag(sin(m_modPhasor) * 29204.0f); - // RF filtering is unnecessary + // RF filtering + rf_out = m_rfFilter->runFilt(ci, &rf); - ci *= m_carrierNco.nextIQ(); // shift to carrier frequency + if (rf_out > 0) + { + memcpy((void *) m_rfFilterBuffer, (const void *) rf, rf_out*sizeof(Complex)); + m_rfFilterBufferIndex = 0; + + } + + ci = m_rfFilterBuffer[m_rfFilterBufferIndex] * m_carrierNco.nextIQ(); // shift to carrier frequency + m_rfFilterBufferIndex++; m_settingsMutex.unlock(); @@ -158,7 +182,7 @@ void WFMMod::pullAF(Complex& sample) switch (m_afInput) { case WFMModInputTone: - sample.real(m_toneNco.next() * m_running.m_volumeFactor); + sample.real(m_toneNcoRF.next() * m_running.m_volumeFactor); sample.imag(0.0f); break; case WFMModInputFile: @@ -390,6 +414,14 @@ void WFMMod::apply() m_settingsMutex.unlock(); } + if ((m_config.m_toneFrequency != m_running.m_toneFrequency) || + (m_config.m_outputSampleRate != m_running.m_outputSampleRate)) + { + m_settingsMutex.lock(); + m_toneNcoRF.setFreq(m_config.m_toneFrequency, m_config.m_outputSampleRate); + m_settingsMutex.unlock(); + } + if (m_config.m_audioSampleRate != m_running.m_audioSampleRate) { m_cwKeyer.setSampleRate(m_config.m_audioSampleRate); diff --git a/plugins/channeltx/modwfm/wfmmod.h b/plugins/channeltx/modwfm/wfmmod.h index 940c2f02a..f172eb14e 100644 --- a/plugins/channeltx/modwfm/wfmmod.h +++ b/plugins/channeltx/modwfm/wfmmod.h @@ -310,14 +310,18 @@ private: NCO m_carrierNco; NCOF m_toneNco; + NCOF m_toneNcoRF; float m_modPhasor; //!< baseband modulator phasor Complex m_modSample; Interpolator m_interpolator; Real m_interpolatorDistance; Real m_interpolatorDistanceRemain; bool m_interpolatorConsumed; + fftfilt* m_rfFilter; static const int m_rfFilterFFTLength; + fftfilt::cmplx *m_rfFilterBuffer; + int m_rfFilterBufferIndex; Real m_magsq; MovingAverage m_movingAverage; diff --git a/plugins/channeltx/modwfm/wfmmodgui.cpp b/plugins/channeltx/modwfm/wfmmodgui.cpp index dacf851e4..111f5ce43 100644 --- a/plugins/channeltx/modwfm/wfmmodgui.cpp +++ b/plugins/channeltx/modwfm/wfmmodgui.cpp @@ -40,6 +40,16 @@ const int WFMModGUI::m_rfBW[] = { }; const int WFMModGUI::m_nbRfBW = 14; +int WFMModGUI::requiredBW(int rfBW) +{ + if (rfBW <= 48000) + return 48000; + else if (rfBW < 100000) + return 96000; + else + return 384000; +} + WFMModGUI* WFMModGUI::create(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI) { WFMModGUI* gui = new WFMModGUI(pluginAPI, deviceAPI); @@ -430,7 +440,7 @@ void WFMModGUI::applySettings() setTitleColor(m_channelMarker.getColor()); m_channelizer->configure(m_channelizer->getInputMessageQueue(), - 48000, + requiredBW(m_rfBW[ui->rfBW->currentIndex()]), m_channelMarker.getCenterFrequency()); ui->deltaFrequency->setValue(abs(m_channelMarker.getCenterFrequency())); diff --git a/plugins/channeltx/modwfm/wfmmodgui.h b/plugins/channeltx/modwfm/wfmmodgui.h index 037c1407c..e9f0512e0 100644 --- a/plugins/channeltx/modwfm/wfmmodgui.h +++ b/plugins/channeltx/modwfm/wfmmodgui.h @@ -109,6 +109,7 @@ private: explicit WFMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* parent = NULL); virtual ~WFMModGUI(); + int requiredBW(int rfBW); void blockApplySettings(bool block); void applySettings(); void updateWithStreamData(); diff --git a/plugins/channeltx/modwfm/wfmmodgui.ui b/plugins/channeltx/modwfm/wfmmodgui.ui index c118478d1..aafa4fb5f 100644 --- a/plugins/channeltx/modwfm/wfmmodgui.ui +++ b/plugins/channeltx/modwfm/wfmmodgui.ui @@ -56,16 +56,7 @@ 3 - - 2 - - - 2 - - - 2 - - + 2 @@ -455,7 +446,7 @@ 10 - 250 + 1000 1