kopia lustrzana https://github.com/f4exb/sdrangel
NFMDemodSink: Proper audio scaling to 16-bit
rodzic
1e5ae8ea0f
commit
00ba5115f3
|
@ -27,6 +27,7 @@
|
|||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "dsp/devicesamplemimo.h"
|
||||
#include "dsp/misc.h"
|
||||
#include "device/deviceapi.h"
|
||||
|
||||
#include "nfmdemodreport.h"
|
||||
|
@ -58,6 +59,7 @@ NFMDemodSink::NFMDemodSink() :
|
|||
{
|
||||
m_agcLevel = 1.0;
|
||||
m_audioBuffer.resize(1<<16);
|
||||
m_phaseDiscri.setFMScaling(1.0f);
|
||||
|
||||
applySettings(m_settings, true);
|
||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||
|
@ -174,9 +176,11 @@ void NFMDemodSink::processOneSample(Complex &ci)
|
|||
if (!m_settings.m_audioMute && (m_settings.m_ctcssOn && m_ctcssIndexSelected == ctcssIndex || m_ctcssIndexSelected == 0))
|
||||
{
|
||||
Real audioSample = m_squelchDelayLine.readBack(m_squelchGate);
|
||||
Q_ASSERT(audioSample >= -1.0f && audioSample <= 1.0f);
|
||||
audioSample = m_settings.m_highPass ? m_bandpass.filter(audioSample) : m_lowpass.filter(audioSample);
|
||||
audioSample *= m_settings.m_volume * m_filterTaps;
|
||||
sample = std::lrint(audioSample);
|
||||
|
||||
audioSample *= m_settings.m_volume * std::numeric_limits<int16_t>::max();
|
||||
sample = clamp<float>(std::rint(audioSample), std::numeric_limits<int16_t>::lowest(), std::numeric_limits<int16_t>::max());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,11 +262,6 @@ void NFMDemodSink::applySettings(const NFMDemodSettings& settings, bool force)
|
|||
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) m_audioSampleRate;
|
||||
}
|
||||
|
||||
if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force)
|
||||
{
|
||||
m_phaseDiscri.setFMScaling((8.0f*m_audioSampleRate) / static_cast<float>(settings.m_fmDeviation)); // integrate 4x factor
|
||||
}
|
||||
|
||||
if ((settings.m_afBandwidth != m_settings.m_afBandwidth) || force)
|
||||
{
|
||||
m_bandpass.create(m_filterTaps, m_audioSampleRate, 300.0, settings.m_afBandwidth);
|
||||
|
@ -324,7 +323,6 @@ void NFMDemodSink::applyAudioSampleRate(unsigned int sampleRate)
|
|||
m_afSquelch.setCoefficients(sampleRate/2000, 600, sampleRate, 200, 0, afSqTones); // 0.5ms test period, 300ms average span, audio SR, 100ms attack, no decay
|
||||
}
|
||||
|
||||
m_phaseDiscri.setFMScaling((8.0f*sampleRate) / static_cast<float>(m_settings.m_fmDeviation)); // integrate 4x factor
|
||||
m_audioFifo.setSize(sampleRate);
|
||||
m_squelchDelayLine.resize(sampleRate/2);
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
|
|
|
@ -139,39 +139,6 @@ private:
|
|||
|
||||
void processOneSample(Complex &ci);
|
||||
MessageQueue *getMessageQueueToGUI() { return m_messageQueueToGUI; }
|
||||
|
||||
inline float arctan2(Real y, Real x)
|
||||
{
|
||||
Real coeff_1 = M_PI / 4;
|
||||
Real coeff_2 = 3 * coeff_1;
|
||||
Real abs_y = fabs(y) + 1e-10; // kludge to prevent 0/0 condition
|
||||
Real angle;
|
||||
if( x>= 0) {
|
||||
Real r = (x - abs_y) / (x + abs_y);
|
||||
angle = coeff_1 - coeff_1 * r;
|
||||
} else {
|
||||
Real r = (x + abs_y) / (abs_y - x);
|
||||
angle = coeff_2 - coeff_1 * r;
|
||||
}
|
||||
if(y < 0) {
|
||||
return(-angle);
|
||||
} else {
|
||||
return(angle);
|
||||
}
|
||||
}
|
||||
|
||||
inline Real angleDist(Real a, Real b)
|
||||
{
|
||||
Real dist = b - a;
|
||||
|
||||
while(dist <= M_PI)
|
||||
dist += 2 * M_PI;
|
||||
while(dist >= M_PI)
|
||||
dist -= 2 * M_PI;
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // INCLUDE_NFMDEMODSINK_H
|
||||
|
|
|
@ -52,6 +52,19 @@ void generateLowPassFilter(int nTaps, double sampleRate, double cutoff, std::vec
|
|||
int n = i - (nTaps - 1) / 2;
|
||||
taps[i] *= 0.42 + 0.5 * cos((2.0 * M_PI * n) / nTaps) + 0.08 * cos((4.0 * M_PI * n) / nTaps);
|
||||
}
|
||||
|
||||
Real sum = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < taps.size() - 1; ++i) {
|
||||
sum += taps[i] * 2.0;
|
||||
}
|
||||
|
||||
sum += taps[i];
|
||||
|
||||
for (i = 0; i < taps.size(); ++i) {
|
||||
taps[i] /= sum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <cmath>
|
||||
#include "dsp/dsptypes.h"
|
||||
#include "dsp/misc.h"
|
||||
#include "export.h"
|
||||
|
||||
namespace FirFilterGenerators
|
||||
|
@ -74,22 +75,6 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
void normalize(Real sum_fix = 0.0)
|
||||
{
|
||||
Real sum = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < m_taps.size() - 1; ++i) {
|
||||
sum += m_taps[i] * 2.0;
|
||||
}
|
||||
|
||||
sum += m_taps[i] + sum_fix;
|
||||
|
||||
for (i = 0; i < m_taps.size(); ++i) {
|
||||
m_taps[i] /= sum;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<Real> m_taps;
|
||||
std::vector<Type> m_samples;
|
||||
|
@ -104,7 +89,6 @@ public:
|
|||
{
|
||||
this->init(nTaps);
|
||||
FirFilterGenerators::generateLowPassFilter(nTaps, sampleRate, cutoff, this->m_taps);
|
||||
this->normalize();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -129,7 +113,6 @@ struct Bandpass : public FirFilter<T>
|
|||
}
|
||||
|
||||
this->m_taps[this->m_taps.size() - 1] += 1;
|
||||
this->normalize(-1.0);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -146,6 +129,5 @@ struct Highpass : public FirFilter<T>
|
|||
}
|
||||
|
||||
this->m_taps[this->m_taps.size() - 1] += 1;
|
||||
this->normalize(-1.0);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -36,7 +36,8 @@ inline float cosc(float x)
|
|||
return (fabs(x) < 1e-10) ? 0.0 : ((1.0 - cos(M_PI * x)) / (M_PI * x));
|
||||
}
|
||||
|
||||
inline float clamp(float x, float min, float max)
|
||||
template<typename T>
|
||||
inline T clamp(T x, T min, T max)
|
||||
{
|
||||
return (x < min) ? min : ((x > max) ? max : x);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue