mirror of https://github.com/f4exb/sdrangel.git
SSB demod: implemented interpolator for audio
This commit is contained in:
parent
1e3980c5e0
commit
e7215b54da
|
@ -157,124 +157,133 @@ void SSBDemod::configure(MessageQueue* messageQueue,
|
||||||
void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly)
|
void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly)
|
||||||
{
|
{
|
||||||
(void) positiveOnly;
|
(void) positiveOnly;
|
||||||
Complex ci;
|
Complex ci;
|
||||||
fftfilt::cmplx *sideband;
|
|
||||||
int n_out;
|
|
||||||
|
|
||||||
m_settingsMutex.lock();
|
m_settingsMutex.lock();
|
||||||
|
|
||||||
int decim = 1<<(m_spanLog2 - 1);
|
|
||||||
unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
|
|
||||||
|
|
||||||
for(SampleVector::const_iterator it = begin; it < end; ++it)
|
for(SampleVector::const_iterator it = begin; it < end; ++it)
|
||||||
{
|
{
|
||||||
Complex c(it->real(), it->imag());
|
Complex c(it->real(), it->imag());
|
||||||
c *= m_nco.nextIQ();
|
c *= m_nco.nextIQ();
|
||||||
|
|
||||||
if(m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
|
if (m_interpolatorDistance < 1.0f) // interpolate
|
||||||
{
|
{
|
||||||
if (m_dsb)
|
while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci))
|
||||||
{
|
{
|
||||||
n_out = DSBFilter->runDSB(ci, &sideband);
|
processOneSample(ci);
|
||||||
}
|
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
n_out = SSBFilter->runSSB(ci, &sideband, m_usb);
|
else
|
||||||
}
|
{
|
||||||
|
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
|
||||||
|
{
|
||||||
|
processOneSample(ci);
|
||||||
|
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
m_settingsMutex.unlock();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
n_out = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < n_out; i++)
|
void SSBDemod::processOneSample(Complex &ci)
|
||||||
{
|
{
|
||||||
// Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
|
fftfilt::cmplx *sideband;
|
||||||
// smart decimation with bit gain using float arithmetic (23 bits significand)
|
int n_out = 0;
|
||||||
|
int decim = 1<<(m_spanLog2 - 1);
|
||||||
|
unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
|
||||||
|
|
||||||
m_sum += sideband[i];
|
if (m_dsb) {
|
||||||
|
n_out = DSBFilter->runDSB(ci, &sideband);
|
||||||
|
} else {
|
||||||
|
n_out = SSBFilter->runSSB(ci, &sideband, m_usb);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(m_undersampleCount++ & decim_mask))
|
for (int i = 0; i < n_out; i++)
|
||||||
{
|
{
|
||||||
Real avgr = m_sum.real() / decim;
|
// Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
|
||||||
Real avgi = m_sum.imag() / decim;
|
// smart decimation with bit gain using float arithmetic (23 bits significand)
|
||||||
m_magsq = (avgr * avgr + avgi * avgi) / (SDR_RX_SCALED*SDR_RX_SCALED);
|
|
||||||
|
|
||||||
m_magsqSum += m_magsq;
|
m_sum += sideband[i];
|
||||||
|
|
||||||
if (m_magsq > m_magsqPeak)
|
if (!(m_undersampleCount++ & decim_mask))
|
||||||
|
{
|
||||||
|
Real avgr = m_sum.real() / decim;
|
||||||
|
Real avgi = m_sum.imag() / decim;
|
||||||
|
m_magsq = (avgr * avgr + avgi * avgi) / (SDR_RX_SCALED*SDR_RX_SCALED);
|
||||||
|
|
||||||
|
m_magsqSum += m_magsq;
|
||||||
|
|
||||||
|
if (m_magsq > m_magsqPeak)
|
||||||
|
{
|
||||||
|
m_magsqPeak = m_magsq;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_magsqCount++;
|
||||||
|
|
||||||
|
if (!m_dsb & !m_usb)
|
||||||
|
{ // invert spectrum for LSB
|
||||||
|
m_sampleBuffer.push_back(Sample(avgi, avgr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_sampleBuffer.push_back(Sample(avgr, avgi));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sum.real(0.0);
|
||||||
|
m_sum.imag(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 10.0; // 10.0 for 3276.8, 1.0 for 327.68
|
||||||
|
fftfilt::cmplx& delayedSample = m_squelchDelayLine.readBack(m_agc.getStepDownDelay());
|
||||||
|
m_audioActive = delayedSample.real() != 0.0;
|
||||||
|
m_squelchDelayLine.write(sideband[i]*agcVal);
|
||||||
|
|
||||||
|
if (m_audioMute)
|
||||||
|
{
|
||||||
|
m_audioBuffer[m_audioBufferFill].r = 0;
|
||||||
|
m_audioBuffer[m_audioBufferFill].l = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fftfilt::cmplx z = delayedSample * m_agc.getStepValue();
|
||||||
|
|
||||||
|
if (m_audioBinaual)
|
||||||
|
{
|
||||||
|
if (m_audioFlipChannels)
|
||||||
{
|
{
|
||||||
m_magsqPeak = m_magsq;
|
m_audioBuffer[m_audioBufferFill].r = (qint16)(z.imag() * m_volume);
|
||||||
|
m_audioBuffer[m_audioBufferFill].l = (qint16)(z.real() * m_volume);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_audioBuffer[m_audioBufferFill].r = (qint16)(z.real() * m_volume);
|
||||||
|
m_audioBuffer[m_audioBufferFill].l = (qint16)(z.imag() * m_volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Real demod = (z.real() + z.imag()) * 0.7;
|
||||||
|
qint16 sample = (qint16)(demod * m_volume);
|
||||||
|
m_audioBuffer[m_audioBufferFill].l = sample;
|
||||||
|
m_audioBuffer[m_audioBufferFill].r = sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_magsqCount++;
|
++m_audioBufferFill;
|
||||||
|
|
||||||
if (!m_dsb & !m_usb)
|
if (m_audioBufferFill >= m_audioBuffer.size())
|
||||||
{ // invert spectrum for LSB
|
{
|
||||||
m_sampleBuffer.push_back(Sample(avgi, avgr));
|
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_sampleBuffer.push_back(Sample(avgr, avgi));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sum.real(0.0);
|
if (res != m_audioBufferFill)
|
||||||
m_sum.imag(0.0);
|
{
|
||||||
}
|
qDebug("SSBDemod::feed: %u/%u samples written", res, m_audioBufferFill);
|
||||||
|
}
|
||||||
|
|
||||||
float agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 10.0; // 10.0 for 3276.8, 1.0 for 327.68
|
m_audioBufferFill = 0;
|
||||||
fftfilt::cmplx& delayedSample = m_squelchDelayLine.readBack(m_agc.getStepDownDelay());
|
}
|
||||||
m_audioActive = delayedSample.real() != 0.0;
|
}
|
||||||
m_squelchDelayLine.write(sideband[i]*agcVal);
|
|
||||||
|
|
||||||
if (m_audioMute)
|
|
||||||
{
|
|
||||||
m_audioBuffer[m_audioBufferFill].r = 0;
|
|
||||||
m_audioBuffer[m_audioBufferFill].l = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fftfilt::cmplx z = delayedSample * m_agc.getStepValue();
|
|
||||||
|
|
||||||
if (m_audioBinaual)
|
|
||||||
{
|
|
||||||
if (m_audioFlipChannels)
|
|
||||||
{
|
|
||||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(z.imag() * m_volume);
|
|
||||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(z.real() * m_volume);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(z.real() * m_volume);
|
|
||||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(z.imag() * m_volume);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Real demod = (z.real() + z.imag()) * 0.7;
|
|
||||||
qint16 sample = (qint16)(demod * m_volume);
|
|
||||||
m_audioBuffer[m_audioBufferFill].l = sample;
|
|
||||||
m_audioBuffer[m_audioBufferFill].r = sample;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++m_audioBufferFill;
|
|
||||||
|
|
||||||
if (m_audioBufferFill >= m_audioBuffer.size())
|
|
||||||
{
|
|
||||||
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill);
|
|
||||||
|
|
||||||
if (res != m_audioBufferFill)
|
|
||||||
{
|
|
||||||
qDebug("SSBDemod::feed: %u/%u samples written", res, m_audioBufferFill);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_audioBufferFill = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill);
|
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill);
|
||||||
|
|
||||||
|
@ -292,7 +301,6 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||||
|
|
||||||
m_sampleBuffer.clear();
|
m_sampleBuffer.clear();
|
||||||
|
|
||||||
m_settingsMutex.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemod::start()
|
void SSBDemod::start()
|
||||||
|
|
|
@ -338,6 +338,8 @@ private:
|
||||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
|
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
|
||||||
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const SSBDemodSettings& settings, bool force);
|
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const SSBDemodSettings& settings, bool force);
|
||||||
|
|
||||||
|
void processOneSample(Complex &ci);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void networkManagerFinished(QNetworkReply *reply);
|
void networkManagerFinished(QNetworkReply *reply);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue