1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-23 01:55:48 -05:00

FreeDV demod: fixed filters

This commit is contained in:
f4exb 2019-02-27 00:31:45 +01:00
parent 6c3536e0a0
commit 7759f9cebc
5 changed files with 29 additions and 30 deletions

View File

@ -49,8 +49,8 @@ const QString FreeDVDemod::m_channelId = "FreeDVDemod";
FreeDVDemod::FreeDVDemod(DeviceSourceAPI *deviceAPI) :
ChannelSinkAPI(m_channelIdURI),
m_deviceAPI(deviceAPI),
m_hiCutoff(5000),
m_lowCutoff(300),
m_hiCutoff(6000),
m_lowCutoff(0),
m_volume(2),
m_spanLog2(3),
m_sum(0),
@ -97,7 +97,7 @@ FreeDVDemod::FreeDVDemod(DeviceSourceAPI *deviceAPI) :
m_agc.setClampMax(SDR_RX_SCALED/100.0);
m_agc.setClamping(m_agcClamping);
SSBFilter = new fftfilt(m_lowCutoff / m_audioSampleRate, m_hiCutoff / m_audioSampleRate, ssbFftLen);
SSBFilter = new fftfilt(m_lowCutoff / m_modemSampleRate, m_hiCutoff / m_modemSampleRate, ssbFftLen);
applyChannelSettings(m_inputSampleRate, m_inputFrequencyOffset, true);
applySettings(m_settings, true);
@ -320,7 +320,7 @@ bool FreeDVDemod::handleMessage(const Message& cmd)
void FreeDVDemod::pushSampleToDV(int16_t sample)
{
qint16 speechSample, audioSample;
qint16 audioSample;
if (m_iModem == m_nin)
{
@ -328,9 +328,7 @@ void FreeDVDemod::pushSampleToDV(int16_t sample)
for (int i = 0; i < nout; i++)
{
speechSample = (qint16)(m_speechOut[i] * m_volume);
while (!m_audioResampler.upSample(speechSample, audioSample)) {
while (!m_audioResampler.upSample(m_speechOut[i], audioSample)) {
pushSampleToAudio(audioSample);
}
@ -346,8 +344,8 @@ void FreeDVDemod::pushSampleToDV(int16_t sample)
void FreeDVDemod::pushSampleToAudio(int16_t sample)
{
m_audioBuffer[m_audioBufferFill].l = sample;
m_audioBuffer[m_audioBufferFill].r = sample;
m_audioBuffer[m_audioBufferFill].l = sample * m_volume;
m_audioBuffer[m_audioBufferFill].r = sample * m_volume;
++m_audioBufferFill;
if (m_audioBufferFill >= m_audioBuffer.size())
@ -379,7 +377,7 @@ void FreeDVDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOf
m_settingsMutex.lock();
m_interpolator.create(16, inputSampleRate, m_hiCutoff * 1.5f, 2.0f);
m_interpolatorDistanceRemain = 0;
m_interpolatorDistance = (Real) inputSampleRate / (Real) m_audioSampleRate;
m_interpolatorDistance = (Real) inputSampleRate / (Real) m_modemSampleRate;
m_settingsMutex.unlock();
}
@ -394,7 +392,7 @@ void FreeDVDemod::applyAudioSampleRate(int sampleRate)
m_settingsMutex.lock();
m_audioFifo.setSize(sampleRate);
m_audioResampler.setDecimation(sampleRate / m_speechSampleRate);
m_audioResampler.setAudioFilters(sampleRate, m_speechSampleRate, 250, 3300);
m_audioResampler.setAudioFilters(sampleRate, sampleRate, 250, 3300, 4.0f);
m_settingsMutex.unlock();
m_audioSampleRate = sampleRate;
@ -415,15 +413,17 @@ void FreeDVDemod::applyFreeDVMode(FreeDVDemodSettings::FreeDVMode mode)
modemSampleRate, m_settings.m_inputFrequencyOffset);
m_inputMessageQueue.push(channelConfigMsg);
m_interpolator.create(16, m_inputSampleRate, m_hiCutoff * 1.5f, 2.0f);
m_interpolatorDistanceRemain = 0;
//m_interpolatorConsumed = false;
m_interpolatorDistance = (Real) m_inputSampleRate / (Real) modemSampleRate;
m_interpolator.create(16, m_inputSampleRate, m_hiCutoff * 1.5f, 2.0f);
SSBFilter->create_filter(m_lowCutoff / (float) modemSampleRate, m_hiCutoff / (float) modemSampleRate);
int agcNbSamples = (modemSampleRate / 1000) * (1<<m_settings.m_agcTimeLog2);
int agcThresholdGate = (modemSampleRate / 1000) * m_settings.m_agcThresholdGate; // ms
m_modemSampleRate = modemSampleRate;
if (m_agcNbSamples != agcNbSamples)
{
m_agc.resize(agcNbSamples, agcNbSamples/2, agcTarget);
@ -437,8 +437,6 @@ void FreeDVDemod::applyFreeDVMode(FreeDVDemodSettings::FreeDVMode mode)
m_agcThresholdGate = agcThresholdGate;
}
m_modemSampleRate = modemSampleRate;
if (getMessageQueueToGUI())
{
DSPConfigureAudio *cfg = new DSPConfigureAudio(m_modemSampleRate);
@ -583,10 +581,10 @@ void FreeDVDemod::applySettings(const FreeDVDemodSettings& settings, bool force)
(m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) ||
(m_settings.m_agcClamping != settings.m_agcClamping) || force)
{
int agcNbSamples = (m_audioSampleRate / 1000) * (1<<settings.m_agcTimeLog2);
int agcNbSamples = (m_modemSampleRate / 1000) * (1<<settings.m_agcTimeLog2);
m_agc.setThresholdEnable(settings.m_agcPowerThreshold != -FreeDVDemodSettings::m_minPowerThresholdDB);
double agcPowerThreshold = CalcDb::powerFromdB(settings.m_agcPowerThreshold) * (SDR_RX_SCALED*SDR_RX_SCALED);
int agcThresholdGate = (m_audioSampleRate / 1000) * settings.m_agcThresholdGate; // ms
int agcThresholdGate = (m_modemSampleRate / 1000) * settings.m_agcThresholdGate; // ms
bool agcClamping = settings.m_agcClamping;
if (m_agcNbSamples != agcNbSamples)
@ -752,7 +750,7 @@ int FreeDVDemod::webapiSettingsPutPatch(
if (frequencyOffsetChanged)
{
MsgConfigureChannelizer* channelConfigMsg = MsgConfigureChannelizer::create(
m_audioSampleRate, settings.m_inputFrequencyOffset);
m_modemSampleRate, settings.m_inputFrequencyOffset);
m_inputMessageQueue.push(channelConfigMsg);
}

View File

@ -38,23 +38,23 @@ AudioFilter::~AudioFilter()
{}
void AudioFilter::setDecimFilters(int srHigh, int srLow, float fcHigh, float fcLow)
void AudioFilter::setDecimFilters(int srHigh, int srLow, float fcHigh, float fcLow, float fgain)
{
double fcNormHigh = fcHigh / srHigh;
double fcNormLow = fcLow / srLow;
calculate2(false, fcNormHigh, m_lpva, m_lpvb);
calculate2(true, fcNormLow, m_hpva, m_hpvb);
calculate2(false, fcNormHigh, m_lpva, m_lpvb, fgain);
calculate2(true, fcNormLow, m_hpva, m_hpvb, fgain);
m_filterLP.setCoeffs(m_lpva, m_lpvb);
m_filterHP.setCoeffs(m_hpva, m_hpvb);
}
void AudioFilter::calculate2(bool highPass, double fc, float *va, float *vb)
void AudioFilter::calculate2(bool highPass, double fc, float *va, float *vb, float fgain)
{
double a[22], b[22];
cheby(highPass, fc, 0.5, 2, a, b); // low-pass, 0.5% ripple, 2 pole filter
cheby(highPass, fc, 0.5, 2, a, b, fgain); // low-pass, 0.5% ripple, 2 pole filter
// Copy to the 2-pole filter coefficients
for (int i=0; i<3; i++) {
@ -79,7 +79,7 @@ void AudioFilter::calculate2(bool highPass, double fc, float *va, float *vb)
* Adapted from BASIC program in table 20-4 of
* https://www.analog.com/media/en/technical-documentation/dsp-book/dsp_book_Ch20.pdf
*/
void AudioFilter::cheby(bool highPass, double fc, float pr, int np, double *a, double *b)
void AudioFilter::cheby(bool highPass, double fc, float pr, int np, double *a, double *b, float fgain)
{
double a0, a1, a2, b1, b2;
double ta[22], tb[22];
@ -135,6 +135,7 @@ void AudioFilter::cheby(bool highPass, double fc, float pr, int np, double *a, d
}
double gain = sa/(1.0 -sb);
gain /= fgain;
for (int i=0; i<20; i++) {
a[i] /= gain;

View File

@ -47,14 +47,14 @@ public:
void useHP(bool useHP) { m_useHP = useHP; }
bool usesHP() const { return m_useHP; }
void setDecimFilters(int srHigh, int srLow, float fcHigh, float fcLow);
void setDecimFilters(int srHigh, int srLow, float fcHigh, float fcLow, float gain = 1.0f);
float run(const float& sample);
float runHP(const float& sample);
float runLP(const float& sample);
private:
void calculate2(bool highPass, double fc, float *a, float *b); // two pole Chebyshev calculation
void cheby(bool highPass, double fc, float pr, int np, double *a, double *b);
void calculate2(bool highPass, double fc, float *a, float *b, float fgain); // two pole Chebyshev calculation
void cheby(bool highPass, double fc, float pr, int np, double *a, double *b, float fgain);
void cheby_sub(bool highPass, double fc, float pr, int np, int stage,
double& a0, double& a1, double& a2, double& b1, double& b2);

View File

@ -30,7 +30,7 @@ void AudioResampler::setDecimation(uint32_t decimation)
m_decimation = decimation == 0 ? 1 : decimation;
}
void AudioResampler::setAudioFilters(int srHigh, int srLow, int fcLow, int fcHigh)
void AudioResampler::setAudioFilters(int srHigh, int srLow, int fcLow, int fcHigh, float gain)
{
srHigh = (srHigh <= 100 ? 100 : srHigh);
srLow = (srLow <= 0 ? 1 : srLow);
@ -40,7 +40,7 @@ void AudioResampler::setAudioFilters(int srHigh, int srLow, int fcLow, int fcHig
fcHigh = fcHigh < 100 ? 100 : fcHigh;
fcLow = fcLow > fcHigh - 100 ? fcHigh - 100 : fcLow;
m_audioFilter.setDecimFilters(srHigh, srLow, fcHigh, fcLow);
m_audioFilter.setDecimFilters(srHigh, srLow, fcHigh, fcLow, gain);
}
bool AudioResampler::downSample(qint16 sampleIn, qint16& sampleOut)

View File

@ -29,7 +29,7 @@ public:
void setDecimation(uint32_t decimation);
uint32_t getDecimation() const { return m_decimation; }
void setAudioFilters(int srHigh, int srLow, int fcLow, int fcHigh);
void setAudioFilters(int srHigh, int srLow, int fcLow, int fcHigh, float gain=1.0f);
bool downSample(qint16 sampleIn, qint16& sampleOut);
bool upSample(qint16 sampleIn, qint16& sampleOut);