Avoid using channel guard bands, due to possible aliasing from half-band filters

pull/1852/head
srcejon 2023-10-22 10:03:04 +01:00
rodzic ce6b08b15e
commit 3e147ec804
3 zmienionych plików z 30 dodań i 30 usunięć

Wyświetl plik

@ -292,16 +292,21 @@ void FreqScanner::stopScan()
}
}
void FreqScanner::setDeviceCenterFrequency(qint64 frequency)
{
// For RTL SDR, ChannelWebAPIUtils::setCenterFrequency takes ~50ms, which means tuneTime can be 0
if (!ChannelWebAPIUtils::setCenterFrequency(getDeviceSetIndex(), frequency)) {
qWarning() << "Freq Scanner failed to set frequency" << frequency;
}
m_minFFTStartTime = QDateTime::currentDateTime().addMSecs(m_settings.m_tuneTime);
}
void FreqScanner::initScan()
{
ChannelWebAPIUtils::setAudioMute(m_scanDeviceSetIndex, m_scanChannelIndex, true);
if (m_centerFrequency != m_stepStartFrequency)
{
if (!ChannelWebAPIUtils::setCenterFrequency(getDeviceSetIndex(), m_stepStartFrequency)) {
qWarning() << "Freq Scanner failed to set frequency" << m_stepStartFrequency;
}
m_minFFTStartTime = QDateTime::currentDateTime().addMSecs(m_settings.m_tuneTime);
if (m_centerFrequency != m_stepStartFrequency) {
setDeviceCenterFrequency(m_stepStartFrequency);
}
m_scanResults.clear();
@ -340,13 +345,14 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList<
int binsPerChannel;
calcScannerSampleRate(m_settings.m_channelBandwidth, m_basebandSampleRate, m_scannerSampleRate, fftSize, binsPerChannel);
// Align first frequency so we cover as many channels as possible, while avoiding DC bin
m_stepStartFrequency = frequencies.front() + m_scannerSampleRate / 2 - m_settings.m_channelBandwidth + m_settings.m_channelBandwidth / 2;
// Align first frequency so we cover as many channels as possible, while channel guard band
// Can we adjust this to avoid DC bin?
m_stepStartFrequency = frequencies.front() + m_scannerSampleRate / 2 - m_scannerSampleRate * 0.125f;
m_stepStopFrequency = frequencies.back();
// If all frequencies fit within bandwidth, we can have the first frequency more central
// If all frequencies fit within usable bandwidth, we can have the first frequency more central
int totalBW = frequencies.back() - frequencies.front() + 2 * m_settings.m_channelBandwidth;
if (totalBW < m_scannerSampleRate)
if (totalBW < m_scannerSampleRate * 0.75f)
{
int spareBWEachSide = (m_scannerSampleRate - totalBW) / 2;
int spareChannelsEachSide = spareBWEachSide / m_settings.m_channelBandwidth;
@ -370,16 +376,17 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList<
bool complete = false; // Have all frequencies been scanned?
bool freqInRange = false;
qint64 nextCenterFrequency = m_centerFrequency;
float usableBW = m_scannerSampleRate * 0.75f;
do
{
if (nextCenterFrequency + m_scannerSampleRate / 2 > m_stepStopFrequency)
if (nextCenterFrequency + usableBW / 2 > m_stepStopFrequency)
{
nextCenterFrequency = m_stepStartFrequency;
complete = true;
}
else
{
nextCenterFrequency += m_scannerSampleRate;
nextCenterFrequency += usableBW;
complete = false;
}
@ -387,8 +394,8 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList<
for (int i = 0; i < m_settings.m_frequencies.size(); i++)
{
if (m_settings.m_enabled[i]
&& (m_settings.m_frequencies[i] >= nextCenterFrequency - m_scannerSampleRate / 2)
&& (m_settings.m_frequencies[i] < nextCenterFrequency + m_scannerSampleRate / 2))
&& (m_settings.m_frequencies[i] >= nextCenterFrequency - usableBW / 2)
&& (m_settings.m_frequencies[i] < nextCenterFrequency + usableBW / 2))
{
freqInRange = true;
break;
@ -457,7 +464,7 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList<
// Tune device/channel to frequency
int offset;
if ((frequency < m_centerFrequency - m_scannerSampleRate / 2) || (frequency >= m_centerFrequency + m_scannerSampleRate / 2))
if ((frequency < m_centerFrequency - usableBW / 2) || (frequency >= m_centerFrequency + usableBW / 2))
{
nextCenterFrequency = frequency;
offset = 0;
@ -519,13 +526,8 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList<
}
}
if (nextCenterFrequency != m_centerFrequency)
{
// For RTL SDR, setCenterFrequency takes ~50ms, which means tuneTime can be 0
if (!ChannelWebAPIUtils::setCenterFrequency(getDeviceSetIndex(), nextCenterFrequency)) {
qWarning() << "Freq Scanner failed to set frequency" << nextCenterFrequency;
}
m_minFFTStartTime = QDateTime::currentDateTime().addMSecs(m_settings.m_tuneTime);
if (nextCenterFrequency != m_centerFrequency) {
setDeviceCenterFrequency(nextCenterFrequency);
}
if (complete) {

Wyświetl plik

@ -405,6 +405,7 @@ private:
void stopScan();
void initScan();
void processScanResults(const QDateTime& fftStartTime, const QList<MsgScanResult::ScanResult>& results);
void setDeviceCenterFrequency(qint64 frequency);
private slots:
void networkManagerFinished(QNetworkReply *reply);

Wyświetl plik

@ -58,11 +58,7 @@ void FreqScannerSink::feed(const SampleVector::const_iterator& begin, const Samp
Complex c(it->real(), it->imag());
c *= m_nco.nextIQ();
if (m_interpolatorDistance == 1.0f) // Don't call decimate, as we don't want filter applied if possible
{
processOneSample(c);
}
else if (m_interpolatorDistance < 1.0f) // interpolate
if (m_interpolatorDistance < 1.0f) // interpolate
{
while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci))
{
@ -70,7 +66,7 @@ void FreqScannerSink::feed(const SampleVector::const_iterator& begin, const Samp
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
else // decimate
else // decimate (and filter)
{
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
{
@ -121,7 +117,8 @@ void FreqScannerSink::processOneSample(Complex &ci)
qint64 diff = frequency - startFrequency;
float binBW = m_scannerSampleRate / (float)m_fftSize;
if ((diff < m_scannerSampleRate) && (diff >= 0))
// Ignore results in uppper and lower 12.5%, as there may be aliasing here from half-band filters
if ((diff < m_scannerSampleRate * 0.875f) && (diff >= m_scannerSampleRate * 0.125f))
{
int bin = std::round(diff / binBW);
@ -210,7 +207,7 @@ void FreqScannerSink::applyChannelSettings(int channelSampleRate, int channelFre
if ((m_channelSampleRate != channelSampleRate) || (m_scannerSampleRate != scannerSampleRate) || force)
{
m_interpolator.create(16, channelSampleRate, scannerSampleRate / 2.0); // Highest cutoff, so we don't attentuate first/last channel
m_interpolator.create(16, channelSampleRate, scannerSampleRate / 2.2); // Filter potential aliasing resulting from half-band filters
m_interpolatorDistance = (Real) channelSampleRate / (Real)scannerSampleRate;
m_interpolatorDistanceRemain = m_interpolatorDistance;
}