From 175e4ca98a01236767d9dc49bf40b934a6769c3b Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 24 Jun 2018 02:29:54 +0200 Subject: [PATCH] DV serial: use HP filter before interpolation and LP filter. Set HP -3dB corner at 300 Hz (for 8 kHz sampling rate) --- sdrbase/dsp/dvserialworker.cpp | 72 +++++++++++++++------------------- sdrbase/dsp/dvserialworker.h | 7 +++- sdrbase/dsp/filtermbe.cpp | 14 ++++++- sdrbase/dsp/filtermbe.h | 3 ++ 4 files changed, 52 insertions(+), 44 deletions(-) diff --git a/sdrbase/dsp/dvserialworker.cpp b/sdrbase/dsp/dvserialworker.cpp index 0423f48b6..7600c3cce 100644 --- a/sdrbase/dsp/dvserialworker.cpp +++ b/sdrbase/dsp/dvserialworker.cpp @@ -27,13 +27,16 @@ DVSerialWorker::DVSerialWorker() : m_running(false), m_currentGainIn(0), m_currentGainOut(0), - m_upsamplerLastValue(0), - m_phase(0) + m_upsamplerLastValue(0.0f), + m_phase(0), + m_upsampling(1), + m_volume(1.0f) { m_audioBuffer.resize(48000); m_audioBufferFill = 0; m_audioFifo = 0; memset(m_dvAudioSamples, 0, SerialDV::MBE_AUDIO_BLOCK_SIZE*sizeof(short)); + setVolumeFactors(); } DVSerialWorker::~DVSerialWorker() @@ -81,14 +84,21 @@ void DVSerialWorker::handleInputMessages() { MsgMbeDecode *decodeMsg = (MsgMbeDecode *) message; int dBVolume = (decodeMsg->getVolumeIndex() - 30) / 2; + float volume = pow(10.0, dBVolume / 10.0f); + int upsampling = decodeMsg->getUpsampling(); + upsampling = upsampling > 6 ? 6 : upsampling < 1 ? 1 : upsampling; + + if ((volume != m_volume) || (upsampling != m_upsampling)) + { + m_volume = volume; + m_upsampling = upsampling; + setVolumeFactors(); + } m_upsampleFilter.useHP(decodeMsg->getUseHP()); - if (m_dvController.decode(m_dvAudioSamples, decodeMsg->getMbeFrame(), decodeMsg->getMbeRate(), dBVolume)) + if (m_dvController.decode(m_dvAudioSamples, decodeMsg->getMbeFrame(), decodeMsg->getMbeRate())) { - int upsampling = decodeMsg->getUpsampling(); - upsampling = upsampling > 6 ? 6 : upsampling < 1 ? 1 : upsampling; - if (upsampling > 1) { upsample(upsampling, m_dvAudioSamples, SerialDV::MBE_AUDIO_BLOCK_SIZE, decodeMsg->getChannels()); } else { @@ -145,45 +155,17 @@ bool DVSerialWorker::hasFifo(AudioFifo *audioFifo) return m_audioFifo == audioFifo; } -void DVSerialWorker::upsample6(short *in, int nbSamplesIn, unsigned char channels) -{ - for (int i = 0; i < nbSamplesIn; i++) - { - int cur = (int) in[i]; - int prev = (int) m_upsamplerLastValue; - qint16 upsample; - - for (int j = 1; j < 7; j++) - { - upsample = m_upsampleFilter.run((qint16) ((cur*j + prev*(6-j)) / 6)); - m_audioBuffer[m_audioBufferFill].l = channels & 1 ? upsample : 0; - m_audioBuffer[m_audioBufferFill].r = (channels>>1) & 1 ? upsample : 0; - - if (m_audioBufferFill < m_audioBuffer.size() - 1) - { - ++m_audioBufferFill; - } - else - { - qDebug("DVSerialWorker::upsample6: audio buffer is full check its size"); - } - } - - m_upsamplerLastValue = in[i]; - } -} - void DVSerialWorker::upsample(int upsampling, short *in, int nbSamplesIn, unsigned char channels) { for (int i = 0; i < nbSamplesIn; i++) { - int cur = (int) in[i]; - int prev = (int) m_upsamplerLastValue; + float cur = m_upsampleFilter.usesHP() ? m_upsampleFilter.runHP((float) in[i]) : (float) in[i]; + float prev = m_upsamplerLastValue; qint16 upsample; for (int j = 1; j <= upsampling; j++) { - upsample = m_upsampleFilter.run((qint16) ((cur*j + prev*(upsampling-j)) / upsampling)); + upsample = (qint16) m_upsampleFilter.runLP(cur*m_upsamplingFactors[j] + prev*m_upsamplingFactors[upsampling-j]); m_audioBuffer[m_audioBufferFill].l = channels & 1 ? upsample : 0; m_audioBuffer[m_audioBufferFill].r = (channels>>1) & 1 ? upsample : 0; @@ -197,7 +179,7 @@ void DVSerialWorker::upsample(int upsampling, short *in, int nbSamplesIn, unsign } } - m_upsamplerLastValue = in[i]; + m_upsamplerLastValue = cur; } } @@ -205,8 +187,9 @@ void DVSerialWorker::noUpsample(short *in, int nbSamplesIn, unsigned char channe { for (int i = 0; i < nbSamplesIn; i++) { - m_audioBuffer[m_audioBufferFill].l = channels & 1 ? in[i] : 0; - m_audioBuffer[m_audioBufferFill].r = (channels>>1) & 1 ? in[i] : 0; + float cur = m_upsampleFilter.usesHP() ? m_upsampleFilter.runHP((float) in[i]) : (float) in[i]; + m_audioBuffer[m_audioBufferFill].l = channels & 1 ? cur*m_upsamplingFactors[0] : 0; + m_audioBuffer[m_audioBufferFill].r = (channels>>1) & 1 ? cur*m_upsamplingFactors[0] : 0; if (m_audioBufferFill < m_audioBuffer.size() - 1) { @@ -219,6 +202,15 @@ void DVSerialWorker::noUpsample(short *in, int nbSamplesIn, unsigned char channe } } +void DVSerialWorker::setVolumeFactors() +{ + m_upsamplingFactors[0] = m_volume; + + for (int i = 1; i <= m_upsampling; i++) { + m_upsamplingFactors[i] = (i*m_volume) / (float) m_upsampling; + } +} + //void DVSerialWorker::upsample6(short *in, short *out, int nbSamplesIn) //{ // for (int i = 0; i < nbSamplesIn; i++) diff --git a/sdrbase/dsp/dvserialworker.h b/sdrbase/dsp/dvserialworker.h index 87f2d44ef..e1ea1a347 100644 --- a/sdrbase/dsp/dvserialworker.h +++ b/sdrbase/dsp/dvserialworker.h @@ -135,9 +135,9 @@ public slots: private: //void upsample6(short *in, short *out, int nbSamplesIn); - void upsample6(short *in, int nbSamplesIn, unsigned char channels); void upsample(int upsampling, short *in, int nbSamplesIn, unsigned char channels); void noUpsample(short *in, int nbSamplesIn, unsigned char channels); + void setVolumeFactors(); SerialDV::DVController m_dvController; volatile bool m_running; @@ -147,9 +147,12 @@ private: //short m_audioSamples[SerialDV::MBE_AUDIO_BLOCK_SIZE * 6 * 2]; // upsample to 48k and duplicate channel AudioVector m_audioBuffer; uint m_audioBufferFill; - short m_upsamplerLastValue; + float m_upsamplerLastValue; float m_phase; MBEAudioInterpolatorFilter m_upsampleFilter; + int m_upsampling; + float m_volume; + float m_upsamplingFactors[7]; }; #endif /* SDRBASE_DSP_DVSERIALWORKER_H_ */ diff --git a/sdrbase/dsp/filtermbe.cpp b/sdrbase/dsp/filtermbe.cpp index 63b5dc9da..bad18b3f2 100644 --- a/sdrbase/dsp/filtermbe.cpp +++ b/sdrbase/dsp/filtermbe.cpp @@ -20,8 +20,8 @@ const float MBEAudioInterpolatorFilter::m_lpa[3] = {1.0, 1.392667E+00, -5.474446E-01}; const float MBEAudioInterpolatorFilter::m_lpb[3] = {3.869430E-02, 7.738860E-02, 3.869430E-02}; -const float MBEAudioInterpolatorFilter::m_hpa[3] = {1.000000e+00, 1.955578e+00, -9.565437e-01}; -const float MBEAudioInterpolatorFilter::m_hpb[3] = {9.780305e-01, -1.956061e+00, 9.780305e-01}; +const float MBEAudioInterpolatorFilter::m_hpa[3] = {1.000000e+00, 1.667871e+00, -7.156964e-01}; +const float MBEAudioInterpolatorFilter::m_hpb[3] = {8.459039e-01, -1.691760e+00, 8.459039e-01}; MBEAudioInterpolatorFilter::MBEAudioInterpolatorFilter() : m_filterLP(m_lpa, m_lpb), @@ -37,3 +37,13 @@ float MBEAudioInterpolatorFilter::run(const float& sample) { return m_useHP ? m_filterLP.run(m_filterHP.run(sample)) : m_filterLP.run(sample); } + +float MBEAudioInterpolatorFilter::runHP(const float& sample) +{ + return m_filterHP.run(sample); +} + +float MBEAudioInterpolatorFilter::runLP(const float& sample) +{ + return m_filterLP.run(sample); +} diff --git a/sdrbase/dsp/filtermbe.h b/sdrbase/dsp/filtermbe.h index a9ce75db3..2b4cc3dc1 100644 --- a/sdrbase/dsp/filtermbe.h +++ b/sdrbase/dsp/filtermbe.h @@ -67,7 +67,10 @@ public: ~MBEAudioInterpolatorFilter(); void useHP(bool useHP) { m_useHP = useHP; } + bool usesHP() const { return m_useHP; } float run(const float& sample); + float runHP(const float& sample); + float runLP(const float& sample); private: IIRFilter m_filterLP;