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_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);

View File

@ -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<Real> m_movingAverage;

View File

@ -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()));

View File

@ -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();

View File

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