WFM modulator: fixed RF bandwidth issue

This commit is contained in:
f4exb 2017-01-05 06:29:08 +01:00
parent b626cf67e6
commit f91b0382e5
5 changed files with 60 additions and 22 deletions

View File

@ -59,9 +59,13 @@ WFMMod::WFMMod() :
m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_rfFilter = new fftfilt(-62500.0 / 384000.0, 62500.0 / 384000.0, m_rfFilterFFTLength); 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(); apply();
m_audioBuffer.resize(1<<14); m_audioBuffer.resize(1<<14);
m_audioBufferFill = 0; m_audioBufferFill = 0;
@ -70,6 +74,7 @@ WFMMod::WFMMod() :
m_magsq = 0.0; m_magsq = 0.0;
m_toneNco.setFreq(1000.0, m_config.m_audioSampleRate); m_toneNco.setFreq(1000.0, m_config.m_audioSampleRate);
m_toneNcoRF.setFreq(1000.0, m_config.m_outputSampleRate);
DSPEngine::instance()->addAudioSource(&m_audioFifo); DSPEngine::instance()->addAudioSource(&m_audioFifo);
// CW keyer // CW keyer
@ -82,6 +87,7 @@ WFMMod::WFMMod() :
WFMMod::~WFMMod() WFMMod::~WFMMod()
{ {
delete m_rfFilter; delete m_rfFilter;
delete[] m_rfFilterBuffer;
DSPEngine::instance()->removeAudioSource(&m_audioFifo); DSPEngine::instance()->removeAudioSource(&m_audioFifo);
} }
@ -109,25 +115,43 @@ void WFMMod::pull(Sample& sample)
Complex ci, ri; Complex ci, ri;
Real t; Real t;
fftfilt::cmplx *rf;
int rf_out;
m_settingsMutex.lock(); m_settingsMutex.lock();
if (m_interpolator.interpolate(&m_interpolatorDistanceRemain, m_modSample, &ri)) if ((m_afInput == WFMModInputFile) || (m_afInput == WFMModInputAudio) || (m_afInput == WFMModInputCWTone))
{ {
pullAF(m_modSample); if (m_interpolator.interpolate(&m_interpolatorDistanceRemain, m_modSample, &ri))
calculateLevel(m_modSample.real()); {
m_audioBufferFill++; 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; 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.real(cos(m_modPhasor) * 29204.0f); // -1 dB
ci.imag(sin(m_modPhasor) * 29204.0f); 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(); m_settingsMutex.unlock();
@ -158,7 +182,7 @@ void WFMMod::pullAF(Complex& sample)
switch (m_afInput) switch (m_afInput)
{ {
case WFMModInputTone: case WFMModInputTone:
sample.real(m_toneNco.next() * m_running.m_volumeFactor); sample.real(m_toneNcoRF.next() * m_running.m_volumeFactor);
sample.imag(0.0f); sample.imag(0.0f);
break; break;
case WFMModInputFile: case WFMModInputFile:
@ -390,6 +414,14 @@ void WFMMod::apply()
m_settingsMutex.unlock(); 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) if (m_config.m_audioSampleRate != m_running.m_audioSampleRate)
{ {
m_cwKeyer.setSampleRate(m_config.m_audioSampleRate); m_cwKeyer.setSampleRate(m_config.m_audioSampleRate);

View File

@ -310,14 +310,18 @@ private:
NCO m_carrierNco; NCO m_carrierNco;
NCOF m_toneNco; NCOF m_toneNco;
NCOF m_toneNcoRF;
float m_modPhasor; //!< baseband modulator phasor float m_modPhasor; //!< baseband modulator phasor
Complex m_modSample; Complex m_modSample;
Interpolator m_interpolator; Interpolator m_interpolator;
Real m_interpolatorDistance; Real m_interpolatorDistance;
Real m_interpolatorDistanceRemain; Real m_interpolatorDistanceRemain;
bool m_interpolatorConsumed; bool m_interpolatorConsumed;
fftfilt* m_rfFilter; fftfilt* m_rfFilter;
static const int m_rfFilterFFTLength; static const int m_rfFilterFFTLength;
fftfilt::cmplx *m_rfFilterBuffer;
int m_rfFilterBufferIndex;
Real m_magsq; Real m_magsq;
MovingAverage<Real> m_movingAverage; MovingAverage<Real> m_movingAverage;

View File

@ -40,6 +40,16 @@ const int WFMModGUI::m_rfBW[] = {
}; };
const int WFMModGUI::m_nbRfBW = 14; 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* WFMModGUI::create(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI)
{ {
WFMModGUI* gui = new WFMModGUI(pluginAPI, deviceAPI); WFMModGUI* gui = new WFMModGUI(pluginAPI, deviceAPI);
@ -430,7 +440,7 @@ void WFMModGUI::applySettings()
setTitleColor(m_channelMarker.getColor()); setTitleColor(m_channelMarker.getColor());
m_channelizer->configure(m_channelizer->getInputMessageQueue(), m_channelizer->configure(m_channelizer->getInputMessageQueue(),
48000, requiredBW(m_rfBW[ui->rfBW->currentIndex()]),
m_channelMarker.getCenterFrequency()); m_channelMarker.getCenterFrequency());
ui->deltaFrequency->setValue(abs(m_channelMarker.getCenterFrequency())); ui->deltaFrequency->setValue(abs(m_channelMarker.getCenterFrequency()));

View File

@ -109,6 +109,7 @@ private:
explicit WFMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* parent = NULL); explicit WFMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* parent = NULL);
virtual ~WFMModGUI(); virtual ~WFMModGUI();
int requiredBW(int rfBW);
void blockApplySettings(bool block); void blockApplySettings(bool block);
void applySettings(); void applySettings();
void updateWithStreamData(); void updateWithStreamData();

View File

@ -56,16 +56,7 @@
<property name="spacing"> <property name="spacing">
<number>3</number> <number>3</number>
</property> </property>
<property name="leftMargin"> <property name="margin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number> <number>2</number>
</property> </property>
<item> <item>
@ -455,7 +446,7 @@
<number>10</number> <number>10</number>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>250</number> <number>1000</number>
</property> </property>
<property name="pageStep"> <property name="pageStep">
<number>1</number> <number>1</number>