kopia lustrzana https://github.com/f4exb/sdrangel
				
				
				
			FreeDV demod: fixed filters
							rodzic
							
								
									6c3536e0a0
								
							
						
					
					
						commit
						7759f9cebc
					
				| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue