mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-12 19:36:10 -05:00
ATV Modulator: use assymetrical filter for vestigial sideband modulation
This commit is contained in:
parent
94d72d5ba5
commit
b079fae843
@ -98,6 +98,7 @@ ATVMod::~ATVMod()
|
|||||||
|
|
||||||
void ATVMod::configure(MessageQueue* messageQueue,
|
void ATVMod::configure(MessageQueue* messageQueue,
|
||||||
Real rfBandwidth,
|
Real rfBandwidth,
|
||||||
|
Real rfOppBandwidth,
|
||||||
ATVStd atvStd,
|
ATVStd atvStd,
|
||||||
ATVModInput atvModInput,
|
ATVModInput atvModInput,
|
||||||
Real uniformLevel,
|
Real uniformLevel,
|
||||||
@ -105,11 +106,11 @@ void ATVMod::configure(MessageQueue* messageQueue,
|
|||||||
bool videoPlayLoop,
|
bool videoPlayLoop,
|
||||||
bool videoPlay,
|
bool videoPlay,
|
||||||
bool cameraPlay,
|
bool cameraPlay,
|
||||||
bool channelMute,
|
bool channelMute)
|
||||||
Real vestigialRatio)
|
|
||||||
{
|
{
|
||||||
Message* cmd = MsgConfigureATVMod::create(
|
Message* cmd = MsgConfigureATVMod::create(
|
||||||
rfBandwidth,
|
rfBandwidth,
|
||||||
|
rfOppBandwidth,
|
||||||
atvStd,
|
atvStd,
|
||||||
atvModInput,
|
atvModInput,
|
||||||
uniformLevel,
|
uniformLevel,
|
||||||
@ -117,8 +118,7 @@ void ATVMod::configure(MessageQueue* messageQueue,
|
|||||||
videoPlayLoop,
|
videoPlayLoop,
|
||||||
videoPlay,
|
videoPlay,
|
||||||
cameraPlay,
|
cameraPlay,
|
||||||
channelMute,
|
channelMute);
|
||||||
vestigialRatio);
|
|
||||||
messageQueue->push(cmd);
|
messageQueue->push(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ Complex& ATVMod::modulateVestigialSSB(Real& sample)
|
|||||||
Complex ci(sample, 0.0f);
|
Complex ci(sample, 0.0f);
|
||||||
fftfilt::cmplx *filtered;
|
fftfilt::cmplx *filtered;
|
||||||
|
|
||||||
n_out = m_DSBFilter->runVestigial(ci, &filtered, m_running.m_atvModulation == ATVModulationVestigialUSB, m_running.m_vestigialRatio);
|
n_out = m_DSBFilter->runAsym(ci, &filtered, m_running.m_atvModulation == ATVModulationVestigialUSB);
|
||||||
|
|
||||||
if (n_out > 0)
|
if (n_out > 0)
|
||||||
{
|
{
|
||||||
@ -512,6 +512,7 @@ bool ATVMod::handleMessage(const Message& cmd)
|
|||||||
MsgConfigureATVMod& cfg = (MsgConfigureATVMod&) cmd;
|
MsgConfigureATVMod& cfg = (MsgConfigureATVMod&) cmd;
|
||||||
|
|
||||||
m_config.m_rfBandwidth = cfg.getRFBandwidth();
|
m_config.m_rfBandwidth = cfg.getRFBandwidth();
|
||||||
|
m_config.m_rfOppBandwidth = cfg.getRFOppBandwidth();
|
||||||
m_config.m_atvModInput = cfg.getATVModInput();
|
m_config.m_atvModInput = cfg.getATVModInput();
|
||||||
m_config.m_atvStd = cfg.getATVStd();
|
m_config.m_atvStd = cfg.getATVStd();
|
||||||
m_config.m_uniformLevel = cfg.getUniformLevel();
|
m_config.m_uniformLevel = cfg.getUniformLevel();
|
||||||
@ -520,12 +521,12 @@ bool ATVMod::handleMessage(const Message& cmd)
|
|||||||
m_config.m_videoPlay = cfg.getVideoPlay();
|
m_config.m_videoPlay = cfg.getVideoPlay();
|
||||||
m_config.m_cameraPlay = cfg.getCameraPlay();
|
m_config.m_cameraPlay = cfg.getCameraPlay();
|
||||||
m_config.m_channelMute = cfg.getChannelMute();
|
m_config.m_channelMute = cfg.getChannelMute();
|
||||||
m_config.m_vestigialRatio = cfg.getVestigialRatio();
|
|
||||||
|
|
||||||
apply();
|
apply();
|
||||||
|
|
||||||
qDebug() << "ATVMod::handleMessage: MsgConfigureATVMod:"
|
qDebug() << "ATVMod::handleMessage: MsgConfigureATVMod:"
|
||||||
<< " m_rfBandwidth: " << m_config.m_rfBandwidth
|
<< " m_rfBandwidth: " << m_config.m_rfBandwidth
|
||||||
|
<< " m_rfOppBandwidth: " << m_config.m_rfOppBandwidth
|
||||||
<< " m_atvStd: " << (int) m_config.m_atvStd
|
<< " m_atvStd: " << (int) m_config.m_atvStd
|
||||||
<< " m_atvModInput: " << (int) m_config.m_atvModInput
|
<< " m_atvModInput: " << (int) m_config.m_atvModInput
|
||||||
<< " m_uniformLevel: " << m_config.m_uniformLevel
|
<< " m_uniformLevel: " << m_config.m_uniformLevel
|
||||||
@ -533,8 +534,7 @@ bool ATVMod::handleMessage(const Message& cmd)
|
|||||||
<< " m_videoPlayLoop: " << m_config.m_videoPlayLoop
|
<< " m_videoPlayLoop: " << m_config.m_videoPlayLoop
|
||||||
<< " m_videoPlay: " << m_config.m_videoPlay
|
<< " m_videoPlay: " << m_config.m_videoPlay
|
||||||
<< " m_cameraPlay: " << m_config.m_cameraPlay
|
<< " m_cameraPlay: " << m_config.m_cameraPlay
|
||||||
<< " m_channelMute: " << m_config.m_channelMute
|
<< " m_channelMute: " << m_config.m_channelMute;
|
||||||
<< " m_vestigialRatio: " << m_config.m_vestigialRatio;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -654,11 +654,20 @@ void ATVMod::apply(bool force)
|
|||||||
memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1));
|
memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1));
|
||||||
m_SSBFilterBufferIndex = 0;
|
m_SSBFilterBufferIndex = 0;
|
||||||
|
|
||||||
m_DSBFilter->create_dsb_filter(m_config.m_rfBandwidth / m_config.m_outputSampleRate);
|
applyStandard(); // set all timings
|
||||||
|
m_settingsMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_config.m_outputSampleRate != m_running.m_outputSampleRate) ||
|
||||||
|
(m_config.m_rfOppBandwidth != m_running.m_rfOppBandwidth) ||
|
||||||
|
(m_config.m_rfBandwidth != m_running.m_rfBandwidth) || force)
|
||||||
|
{
|
||||||
|
m_settingsMutex.lock();
|
||||||
|
|
||||||
|
m_DSBFilter->create_asym_filter(m_config.m_rfOppBandwidth / m_config.m_outputSampleRate, m_config.m_rfBandwidth / m_config.m_outputSampleRate);
|
||||||
memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen));
|
memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen));
|
||||||
m_DSBFilterBufferIndex = 0;
|
m_DSBFilterBufferIndex = 0;
|
||||||
|
|
||||||
applyStandard(); // set all timings
|
|
||||||
m_settingsMutex.unlock();
|
m_settingsMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -673,6 +682,7 @@ void ATVMod::apply(bool force)
|
|||||||
m_running.m_outputSampleRate = m_config.m_outputSampleRate;
|
m_running.m_outputSampleRate = m_config.m_outputSampleRate;
|
||||||
m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset;
|
m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset;
|
||||||
m_running.m_rfBandwidth = m_config.m_rfBandwidth;
|
m_running.m_rfBandwidth = m_config.m_rfBandwidth;
|
||||||
|
m_running.m_rfOppBandwidth = m_config.m_rfOppBandwidth;
|
||||||
m_running.m_atvModInput = m_config.m_atvModInput;
|
m_running.m_atvModInput = m_config.m_atvModInput;
|
||||||
m_running.m_atvStd = m_config.m_atvStd;
|
m_running.m_atvStd = m_config.m_atvStd;
|
||||||
m_running.m_uniformLevel = m_config.m_uniformLevel;
|
m_running.m_uniformLevel = m_config.m_uniformLevel;
|
||||||
@ -681,7 +691,6 @@ void ATVMod::apply(bool force)
|
|||||||
m_running.m_videoPlay = m_config.m_videoPlay;
|
m_running.m_videoPlay = m_config.m_videoPlay;
|
||||||
m_running.m_cameraPlay = m_config.m_cameraPlay;
|
m_running.m_cameraPlay = m_config.m_cameraPlay;
|
||||||
m_running.m_channelMute = m_config.m_channelMute;
|
m_running.m_channelMute = m_config.m_channelMute;
|
||||||
m_running.m_vestigialRatio = m_config.m_vestigialRatio;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ATVMod::getSampleRateUnits(ATVStd std)
|
int ATVMod::getSampleRateUnits(ATVStd std)
|
||||||
|
@ -308,6 +308,7 @@ public:
|
|||||||
|
|
||||||
void configure(MessageQueue* messageQueue,
|
void configure(MessageQueue* messageQueue,
|
||||||
Real rfBandwidth,
|
Real rfBandwidth,
|
||||||
|
Real rfOppBandwidth,
|
||||||
ATVStd atvStd,
|
ATVStd atvStd,
|
||||||
ATVModInput atvModInput,
|
ATVModInput atvModInput,
|
||||||
Real uniformLevel,
|
Real uniformLevel,
|
||||||
@ -315,8 +316,7 @@ public:
|
|||||||
bool videoPlayLoop,
|
bool videoPlayLoop,
|
||||||
bool videoPlay,
|
bool videoPlay,
|
||||||
bool cameraPLay,
|
bool cameraPLay,
|
||||||
bool channelMute,
|
bool channelMute);
|
||||||
Real vestigialRatio);
|
|
||||||
|
|
||||||
virtual void pull(Sample& sample);
|
virtual void pull(Sample& sample);
|
||||||
virtual void pullAudio(int nbSamples); // this is used for video signal actually
|
virtual void pullAudio(int nbSamples); // this is used for video signal actually
|
||||||
@ -346,6 +346,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Real getRFBandwidth() const { return m_rfBandwidth; }
|
Real getRFBandwidth() const { return m_rfBandwidth; }
|
||||||
|
Real getRFOppBandwidth() const { return m_rfOppBandwidth; }
|
||||||
ATVStd getATVStd() const { return m_atvStd; }
|
ATVStd getATVStd() const { return m_atvStd; }
|
||||||
ATVModInput getATVModInput() const { return m_atvModInput; }
|
ATVModInput getATVModInput() const { return m_atvModInput; }
|
||||||
Real getUniformLevel() const { return m_uniformLevel; }
|
Real getUniformLevel() const { return m_uniformLevel; }
|
||||||
@ -354,10 +355,10 @@ private:
|
|||||||
bool getVideoPlay() const { return m_videoPlay; }
|
bool getVideoPlay() const { return m_videoPlay; }
|
||||||
bool getCameraPlay() const { return m_cameraPlay; }
|
bool getCameraPlay() const { return m_cameraPlay; }
|
||||||
bool getChannelMute() const { return m_channelMute; }
|
bool getChannelMute() const { return m_channelMute; }
|
||||||
Real getVestigialRatio() const { return m_vestigialRatio; }
|
|
||||||
|
|
||||||
static MsgConfigureATVMod* create(
|
static MsgConfigureATVMod* create(
|
||||||
Real rfBandwidth,
|
Real rfBandwidth,
|
||||||
|
Real rfOppBandwidth,
|
||||||
ATVStd atvStd,
|
ATVStd atvStd,
|
||||||
ATVModInput atvModInput,
|
ATVModInput atvModInput,
|
||||||
Real uniformLevel,
|
Real uniformLevel,
|
||||||
@ -365,11 +366,11 @@ private:
|
|||||||
bool videoPlayLoop,
|
bool videoPlayLoop,
|
||||||
bool videoPlay,
|
bool videoPlay,
|
||||||
bool cameraPlay,
|
bool cameraPlay,
|
||||||
bool channelMute,
|
bool channelMute)
|
||||||
Real vestigialRatio)
|
|
||||||
{
|
{
|
||||||
return new MsgConfigureATVMod(
|
return new MsgConfigureATVMod(
|
||||||
rfBandwidth,
|
rfBandwidth,
|
||||||
|
rfOppBandwidth,
|
||||||
atvStd,
|
atvStd,
|
||||||
atvModInput,
|
atvModInput,
|
||||||
uniformLevel,
|
uniformLevel,
|
||||||
@ -377,12 +378,12 @@ private:
|
|||||||
videoPlayLoop,
|
videoPlayLoop,
|
||||||
videoPlay,
|
videoPlay,
|
||||||
cameraPlay,
|
cameraPlay,
|
||||||
channelMute,
|
channelMute);
|
||||||
vestigialRatio);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Real m_rfBandwidth;
|
Real m_rfBandwidth;
|
||||||
|
Real m_rfOppBandwidth;
|
||||||
ATVStd m_atvStd;
|
ATVStd m_atvStd;
|
||||||
ATVModInput m_atvModInput;
|
ATVModInput m_atvModInput;
|
||||||
Real m_uniformLevel;
|
Real m_uniformLevel;
|
||||||
@ -391,10 +392,10 @@ private:
|
|||||||
bool m_videoPlay;
|
bool m_videoPlay;
|
||||||
bool m_cameraPlay;
|
bool m_cameraPlay;
|
||||||
bool m_channelMute;
|
bool m_channelMute;
|
||||||
Real m_vestigialRatio;
|
|
||||||
|
|
||||||
MsgConfigureATVMod(
|
MsgConfigureATVMod(
|
||||||
Real rfBandwidth,
|
Real rfBandwidth,
|
||||||
|
Real rfOppBandwidth,
|
||||||
ATVStd atvStd,
|
ATVStd atvStd,
|
||||||
ATVModInput atvModInput,
|
ATVModInput atvModInput,
|
||||||
Real uniformLevel,
|
Real uniformLevel,
|
||||||
@ -402,10 +403,10 @@ private:
|
|||||||
bool videoPlayLoop,
|
bool videoPlayLoop,
|
||||||
bool videoPlay,
|
bool videoPlay,
|
||||||
bool cameraPlay,
|
bool cameraPlay,
|
||||||
bool channelMute,
|
bool channelMute) :
|
||||||
Real vestigialRatio) :
|
|
||||||
Message(),
|
Message(),
|
||||||
m_rfBandwidth(rfBandwidth),
|
m_rfBandwidth(rfBandwidth),
|
||||||
|
m_rfOppBandwidth(rfOppBandwidth),
|
||||||
m_atvStd(atvStd),
|
m_atvStd(atvStd),
|
||||||
m_atvModInput(atvModInput),
|
m_atvModInput(atvModInput),
|
||||||
m_uniformLevel(uniformLevel),
|
m_uniformLevel(uniformLevel),
|
||||||
@ -413,8 +414,7 @@ private:
|
|||||||
m_videoPlayLoop(videoPlayLoop),
|
m_videoPlayLoop(videoPlayLoop),
|
||||||
m_videoPlay(videoPlay),
|
m_videoPlay(videoPlay),
|
||||||
m_cameraPlay(cameraPlay),
|
m_cameraPlay(cameraPlay),
|
||||||
m_channelMute(channelMute),
|
m_channelMute(channelMute)
|
||||||
m_vestigialRatio(vestigialRatio)
|
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -450,7 +450,8 @@ private:
|
|||||||
{
|
{
|
||||||
int m_outputSampleRate; //!< sample rate from channelizer
|
int m_outputSampleRate; //!< sample rate from channelizer
|
||||||
qint64 m_inputFrequencyOffset; //!< offset from baseband center frequency
|
qint64 m_inputFrequencyOffset; //!< offset from baseband center frequency
|
||||||
Real m_rfBandwidth; //!< Bandwidth of modulated signal
|
Real m_rfBandwidth; //!< Bandwidth of modulated signal or direct sideband for SSB / vestigial SSB
|
||||||
|
Real m_rfOppBandwidth; //!< Bandwidth of opposite sideband for vestigial SSB
|
||||||
ATVStd m_atvStd; //!< Standard
|
ATVStd m_atvStd; //!< Standard
|
||||||
ATVModInput m_atvModInput; //!< Input source type
|
ATVModInput m_atvModInput; //!< Input source type
|
||||||
Real m_uniformLevel; //!< Percentage between black and white for uniform screen display
|
Real m_uniformLevel; //!< Percentage between black and white for uniform screen display
|
||||||
@ -465,6 +466,7 @@ private:
|
|||||||
m_outputSampleRate(-1),
|
m_outputSampleRate(-1),
|
||||||
m_inputFrequencyOffset(0),
|
m_inputFrequencyOffset(0),
|
||||||
m_rfBandwidth(0),
|
m_rfBandwidth(0),
|
||||||
|
m_rfOppBandwidth(0),
|
||||||
m_atvStd(ATVStdPAL625),
|
m_atvStd(ATVStdPAL625),
|
||||||
m_atvModInput(ATVModInputHBars),
|
m_atvModInput(ATVModInputHBars),
|
||||||
m_uniformLevel(0.5f),
|
m_uniformLevel(0.5f),
|
||||||
@ -542,12 +544,16 @@ private:
|
|||||||
std::string m_overlayText;
|
std::string m_overlayText;
|
||||||
bool m_showOverlayText;
|
bool m_showOverlayText;
|
||||||
|
|
||||||
|
// Used for standard SSB
|
||||||
fftfilt* m_SSBFilter;
|
fftfilt* m_SSBFilter;
|
||||||
fftfilt* m_DSBFilter;
|
|
||||||
Complex* m_SSBFilterBuffer;
|
Complex* m_SSBFilterBuffer;
|
||||||
Complex* m_DSBFilterBuffer;
|
|
||||||
int m_SSBFilterBufferIndex;
|
int m_SSBFilterBufferIndex;
|
||||||
|
|
||||||
|
// Used for vestigial SSB with asymmetrical filtering (needs double sideband scheme)
|
||||||
|
fftfilt* m_DSBFilter;
|
||||||
|
Complex* m_DSBFilterBuffer;
|
||||||
int m_DSBFilterBufferIndex;
|
int m_DSBFilterBufferIndex;
|
||||||
|
|
||||||
static const int m_ssbFftLen;
|
static const int m_ssbFftLen;
|
||||||
|
|
||||||
static const float m_blackLevel;
|
static const float m_blackLevel;
|
||||||
|
@ -512,6 +512,7 @@ void ATVModGUI::applySettings()
|
|||||||
|
|
||||||
m_atvMod->configure(m_atvMod->getInputMessageQueue(),
|
m_atvMod->configure(m_atvMod->getInputMessageQueue(),
|
||||||
ui->rfBW->value() * 100000.0f,
|
ui->rfBW->value() * 100000.0f,
|
||||||
|
(ui->vestigial->value() / 100.0f) * ui->rfBW->value() * 100000.0f,
|
||||||
(ATVMod::ATVStd) ui->standard->currentIndex(),
|
(ATVMod::ATVStd) ui->standard->currentIndex(),
|
||||||
(ATVMod::ATVModInput) ui->inputSelect->currentIndex(),
|
(ATVMod::ATVModInput) ui->inputSelect->currentIndex(),
|
||||||
ui->uniformLevel->value() / 100.0f,
|
ui->uniformLevel->value() / 100.0f,
|
||||||
@ -519,8 +520,7 @@ void ATVModGUI::applySettings()
|
|||||||
ui->playLoop->isChecked(),
|
ui->playLoop->isChecked(),
|
||||||
ui->playVideo->isChecked(),
|
ui->playVideo->isChecked(),
|
||||||
ui->playCamera->isChecked(),
|
ui->playCamera->isChecked(),
|
||||||
ui->channelMute->isChecked(),
|
ui->channelMute->isChecked());
|
||||||
ui->vestigial->value() / 100.0f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,11 +54,13 @@ void fftfilt::init_filter()
|
|||||||
fft = new g_fft<float>(flen);
|
fft = new g_fft<float>(flen);
|
||||||
|
|
||||||
filter = new cmplx[flen];
|
filter = new cmplx[flen];
|
||||||
|
filterOpp = new cmplx[flen];
|
||||||
data = new cmplx[flen];
|
data = new cmplx[flen];
|
||||||
output = new cmplx[flen2];
|
output = new cmplx[flen2];
|
||||||
ovlbuf = new cmplx[flen2];
|
ovlbuf = new cmplx[flen2];
|
||||||
|
|
||||||
memset(filter, 0, flen * sizeof(cmplx));
|
memset(filter, 0, flen * sizeof(cmplx));
|
||||||
|
memset(filterOpp, 0, flen * sizeof(cmplx));
|
||||||
memset(data, 0, flen * sizeof(cmplx));
|
memset(data, 0, flen * sizeof(cmplx));
|
||||||
memset(output, 0, flen2 * sizeof(cmplx));
|
memset(output, 0, flen2 * sizeof(cmplx));
|
||||||
memset(ovlbuf, 0, flen2 * sizeof(cmplx));
|
memset(ovlbuf, 0, flen2 * sizeof(cmplx));
|
||||||
@ -92,6 +94,7 @@ fftfilt::~fftfilt()
|
|||||||
if (fft) delete fft;
|
if (fft) delete fft;
|
||||||
|
|
||||||
if (filter) delete [] filter;
|
if (filter) delete [] filter;
|
||||||
|
if (filterOpp) delete [] filterOpp;
|
||||||
if (data) delete [] data;
|
if (data) delete [] data;
|
||||||
if (output) delete [] output;
|
if (output) delete [] output;
|
||||||
if (ovlbuf) delete [] ovlbuf;
|
if (ovlbuf) delete [] ovlbuf;
|
||||||
@ -162,6 +165,55 @@ void fftfilt::create_dsb_filter(float f2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Double the size of FFT used for equivalent SSB filter or assume FFT is half the size of the one used for SSB
|
||||||
|
// used with runAsym for in band / opposite band asymmetrical filtering. Can be used for vestigial sideband modulation.
|
||||||
|
void fftfilt::create_asym_filter(float fopp, float fin)
|
||||||
|
{
|
||||||
|
// in band
|
||||||
|
// initialize the filter to zero
|
||||||
|
memset(filter, 0, flen * sizeof(cmplx));
|
||||||
|
|
||||||
|
for (int i = 0; i < flen2; i++) {
|
||||||
|
filter[i] = fsinc(fin, i, flen2);
|
||||||
|
filter[i] *= _blackman(i, flen2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fft->ComplexFFT(filter);
|
||||||
|
|
||||||
|
// normalize the output filter for unity gain
|
||||||
|
float scale = 0, mag;
|
||||||
|
for (int i = 0; i < flen2; i++) {
|
||||||
|
mag = abs(filter[i]);
|
||||||
|
if (mag > scale) scale = mag;
|
||||||
|
}
|
||||||
|
if (scale != 0) {
|
||||||
|
for (int i = 0; i < flen; i++)
|
||||||
|
filter[i] /= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// opposite band
|
||||||
|
// initialize the filter to zero
|
||||||
|
memset(filterOpp, 0, flen * sizeof(cmplx));
|
||||||
|
|
||||||
|
for (int i = 0; i < flen2; i++) {
|
||||||
|
filterOpp[i] = fsinc(fopp, i, flen2);
|
||||||
|
filterOpp[i] *= _blackman(i, flen2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fft->ComplexFFT(filterOpp);
|
||||||
|
|
||||||
|
// normalize the output filter for unity gain
|
||||||
|
scale = 0;
|
||||||
|
for (int i = 0; i < flen2; i++) {
|
||||||
|
mag = abs(filterOpp[i]);
|
||||||
|
if (mag > scale) scale = mag;
|
||||||
|
}
|
||||||
|
if (scale != 0) {
|
||||||
|
for (int i = 0; i < flen; i++)
|
||||||
|
filterOpp[i] /= scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test bypass
|
// test bypass
|
||||||
int fftfilt::noFilt(const cmplx & in, cmplx **out)
|
int fftfilt::noFilt(const cmplx & in, cmplx **out)
|
||||||
{
|
{
|
||||||
@ -271,13 +323,9 @@ int fftfilt::runDSB(const cmplx & in, cmplx **out)
|
|||||||
return flen2;
|
return flen2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version for vestigial sideband. You have to double the FFT size used for SSB.
|
// Version for asymmetrical sidebands. You have to double the FFT size used for SSB.
|
||||||
int fftfilt::runVestigial(const cmplx & in, cmplx **out, bool usb, float vf)
|
int fftfilt::runAsym(const cmplx & in, cmplx **out, bool usb)
|
||||||
{
|
{
|
||||||
if (vf < 0.0f) vf = 0.0f;
|
|
||||||
if (vf > 1.0f) vf = 1.0f;
|
|
||||||
if (usb) vf = 1.0f - vf;
|
|
||||||
|
|
||||||
data[inptr++] = in;
|
data[inptr++] = in;
|
||||||
if (inptr < flen2)
|
if (inptr < flen2)
|
||||||
return 0;
|
return 0;
|
||||||
@ -292,24 +340,14 @@ int fftfilt::runVestigial(const cmplx & in, cmplx **out, bool usb, float vf)
|
|||||||
for (int i = 1; i < flen2; i++)
|
for (int i = 1; i < flen2; i++)
|
||||||
{
|
{
|
||||||
data[i] *= filter[i]; // usb
|
data[i] *= filter[i]; // usb
|
||||||
|
data[flen2 + i] *= filterOpp[flen2 + i]; // lsb is the opposite
|
||||||
if (i > (int) (vf * flen2)) { // vestigial lsb
|
|
||||||
data[flen2 + i] *= filter[flen2 + i];
|
|
||||||
} else {
|
|
||||||
data[flen2 + i] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 1; i < flen2; i++)
|
for (int i = 1; i < flen2; i++)
|
||||||
{
|
{
|
||||||
if (i < (int) (vf * flen2)) { // vestigial usb
|
data[i] *= filterOpp[i]; // usb is the opposite
|
||||||
data[i] *= filter[i];
|
|
||||||
} else {
|
|
||||||
data[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
data[flen2 + i] *= filter[flen2 + i]; // lsb
|
data[flen2 + i] *= filter[flen2 + i]; // lsb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,13 @@ public:
|
|||||||
// f1 > f2 ==> band reject
|
// f1 > f2 ==> band reject
|
||||||
void create_filter(float f1, float f2);
|
void create_filter(float f1, float f2);
|
||||||
void create_dsb_filter(float f2);
|
void create_dsb_filter(float f2);
|
||||||
|
void create_asym_filter(float fopp, float fin); //!< two different filters for in band and opposite band
|
||||||
|
|
||||||
int noFilt(const cmplx& in, cmplx **out);
|
int noFilt(const cmplx& in, cmplx **out);
|
||||||
int runFilt(const cmplx& in, cmplx **out);
|
int runFilt(const cmplx& in, cmplx **out);
|
||||||
int runSSB(const cmplx& in, cmplx **out, bool usb, bool getDC = true);
|
int runSSB(const cmplx& in, cmplx **out, bool usb, bool getDC = true);
|
||||||
int runDSB(const cmplx& in, cmplx **out);
|
int runDSB(const cmplx& in, cmplx **out);
|
||||||
int runVestigial(const cmplx & in, cmplx **out, bool usb, float vf);
|
int runAsym(const cmplx & in, cmplx **out, bool usb); //!< Asymmetrical fitering can be used for vestigial sideband
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int flen;
|
int flen;
|
||||||
@ -36,6 +37,7 @@ protected:
|
|||||||
g_fft<float> *fft;
|
g_fft<float> *fft;
|
||||||
g_fft<float> *ift;
|
g_fft<float> *ift;
|
||||||
cmplx *filter;
|
cmplx *filter;
|
||||||
|
cmplx *filterOpp;
|
||||||
cmplx *data;
|
cmplx *data;
|
||||||
cmplx *ovlbuf;
|
cmplx *ovlbuf;
|
||||||
cmplx *output;
|
cmplx *output;
|
||||||
|
Loading…
Reference in New Issue
Block a user