1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-26 17:58:43 -05:00

Allow interpolation in AM demodulator i.e. input sample rate lower than audio rate

This commit is contained in:
f4exb 2016-10-28 05:08:53 +02:00
parent babd4f8014
commit cd347bca4f
2 changed files with 85 additions and 67 deletions

View File

@ -77,77 +77,25 @@ void AMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector
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
{ {
Real magsq = ci.real() * ci.real() + ci.imag() * ci.imag(); processOneSample(ci);
magsq /= (1<<30);
m_movingAverage.feed(magsq);
m_magsq = m_movingAverage.average();
if (m_magsq >= m_squelchLevel) while (m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci))
{ {
if (m_squelchCount <= m_running.m_audioSampleRate / 10) processOneSample(ci);
{
m_squelchCount++;
}
}
else
{
if (m_squelchCount > 1)
{
m_squelchCount -= 2;
}
}
qint16 sample;
if ((m_squelchCount >= m_running.m_audioSampleRate / 20) && !m_running.m_audioMute)
{
Real demod = sqrt(magsq);
demod = m_lowpass.filter(demod);
if (demod < -1)
{
demod = -1;
}
else if (demod > 1)
{
demod = 1;
}
m_volumeAGC.feed(demod);
Real attack = (m_squelchCount - (m_running.m_audioSampleRate / 20)) / (Real) (m_running.m_audioSampleRate / 20);
demod *= ((0.003 * attack) / m_volumeAGC.getValue());
demod *= m_running.m_volume;
sample = demod * 32700 * 16;
m_squelchOpen = true;
}
else
{
sample = 0;
m_squelchOpen = false;
}
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, 10);
if (res != m_audioBufferFill)
{
qDebug("AMDemod::feed: %u/%u audio samples written", res, m_audioBufferFill);
}
m_audioBufferFill = 0;
} }
m_interpolatorDistanceRemain += m_interpolatorDistance; m_interpolatorDistanceRemain += m_interpolatorDistance;
} }
else // decimate
{
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
{
processOneSample(ci);
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
} }
if (m_audioBufferFill > 0) if (m_audioBufferFill > 0)

View File

@ -134,6 +134,76 @@ private:
QMutex m_settingsMutex; QMutex m_settingsMutex;
void apply(); void apply();
void processOneSample(Complex &ci)
{
Real magsq = ci.real() * ci.real() + ci.imag() * ci.imag();
magsq /= (1<<30);
m_movingAverage.feed(magsq);
m_magsq = m_movingAverage.average();
if (m_magsq >= m_squelchLevel)
{
if (m_squelchCount <= m_running.m_audioSampleRate / 10)
{
m_squelchCount++;
}
}
else
{
if (m_squelchCount > 1)
{
m_squelchCount -= 2;
}
}
qint16 sample;
if ((m_squelchCount >= m_running.m_audioSampleRate / 20) && !m_running.m_audioMute)
{
Real demod = sqrt(magsq);
demod = m_lowpass.filter(demod);
if (demod < -1)
{
demod = -1;
}
else if (demod > 1)
{
demod = 1;
}
m_volumeAGC.feed(demod);
Real attack = (m_squelchCount - (m_running.m_audioSampleRate / 20)) / (Real) (m_running.m_audioSampleRate / 20);
demod *= ((0.003 * attack) / m_volumeAGC.getValue());
demod *= m_running.m_volume;
sample = demod * 32700 * 16;
m_squelchOpen = true;
}
else
{
sample = 0;
m_squelchOpen = false;
}
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, 10);
if (res != m_audioBufferFill)
{
qDebug("AMDemod::feed: %u/%u audio samples written", res, m_audioBufferFill);
}
m_audioBufferFill = 0;
}
}
}; };
#endif // INCLUDE_AMDEMOD_H #endif // INCLUDE_AMDEMOD_H