mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 13:11:20 -05:00 
			
		
		
		
	SSB demod: better algorithm for AGC limitation. For #1918
This commit is contained in:
		
							parent
							
								
									f98800702c
								
							
						
					
					
						commit
						68601d6947
					
				@ -143,7 +143,7 @@ This AGC is based on the calculated magnitude (square root of power of the filte
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<h4>13.3: AGC clamping</h4>
 | 
					<h4>13.3: AGC clamping</h4>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When on this clamps signal at the maximum amplitude. Normally this is not needed for most signals as the AGC amplitude order is quite conservative at 10% of the maximum. You may switch it on if you notice a loud click when a transmission starts.
 | 
					This limits AGC gain when signal rises up sharply avoiding peak audio overload. You may switch it on if you notice a loud click on strong signals after silences.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<h4>13.4: Noise Reduction</h4>
 | 
					<h4>13.4: Noise Reduction</h4>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -73,8 +73,6 @@ SSBDemodSink::SSBDemodSink() :
 | 
				
			|||||||
	m_magsqSum = 0.0;
 | 
						m_magsqSum = 0.0;
 | 
				
			||||||
	m_magsqPeak = 0.0;
 | 
						m_magsqPeak = 0.0;
 | 
				
			||||||
	m_magsqCount = 0;
 | 
						m_magsqCount = 0;
 | 
				
			||||||
    m_magsqCur = 0.0;
 | 
					 | 
				
			||||||
    m_magsqPrev = 0.0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, m_ssbFftLen);
 | 
						SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, m_ssbFftLen);
 | 
				
			||||||
	DSBFilter = new fftfilt((2.0f * m_Bandwidth) / m_audioSampleRate, 2 * m_ssbFftLen);
 | 
						DSBFilter = new fftfilt((2.0f * m_Bandwidth) / m_audioSampleRate, 2 * m_ssbFftLen);
 | 
				
			||||||
@ -175,24 +173,20 @@ void SSBDemodSink::processOneSample(Complex &ci)
 | 
				
			|||||||
        float agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 1.0;
 | 
					        float agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 1.0;
 | 
				
			||||||
        fftfilt::cmplx& delayedSample = m_squelchDelayLine.readBack(m_agc.getStepDownDelay());
 | 
					        fftfilt::cmplx& delayedSample = m_squelchDelayLine.readBack(m_agc.getStepDownDelay());
 | 
				
			||||||
        m_audioActive = delayedSample.real() != 0.0;
 | 
					        m_audioActive = delayedSample.real() != 0.0;
 | 
				
			||||||
        m_magsqCur = std::norm(sideband[i]*agcVal);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Prevent overload based on squared magnitude variation
 | 
					        // Prevent overload based on squared magnitude variation
 | 
				
			||||||
        // Only if AGC is active
 | 
					        // Only if AGC is active
 | 
				
			||||||
        if (m_agcActive && m_agcClamping && (std::abs(m_magsqCur - m_magsqPrev) > m_agcTarget*m_agcTarget*5.0) & (agcVal > 100.0))
 | 
					        if (m_agcActive && m_agcClamping && agcVal > 100.0)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            float target = m_agcTarget*sqrt(agcVal); // Quench AGC depending on previous value
 | 
					            qDebug("SSBDemodSink::processOneSample: %f", agcVal);
 | 
				
			||||||
            m_agc.reset(target);
 | 
					            m_agc.reset(m_agcTarget*m_agcTarget);
 | 
				
			||||||
            m_squelchDelayLine.write(fftfilt::cmplx{target, 0.0});
 | 
					            m_squelchDelayLine.write(fftfilt::cmplx{0.0, 0.0});
 | 
				
			||||||
            m_magsqCur = target*target;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            m_squelchDelayLine.write(sideband[i]*agcVal);
 | 
					            m_squelchDelayLine.write(sideband[i]*agcVal);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        m_magsqPrev = m_magsqCur;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (m_audioMute)
 | 
					        if (m_audioMute)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            m_audioBuffer[m_audioBufferFill].r = 0;
 | 
					            m_audioBuffer[m_audioBufferFill].r = 0;
 | 
				
			||||||
@ -200,7 +194,6 @@ void SSBDemodSink::processOneSample(Complex &ci)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // fftfilt::cmplx z = m_agcActive ? delayedSample * m_agc.getStepValue() : delayedSample;
 | 
					 | 
				
			||||||
            fftfilt::cmplx z = (m_agcActive && m_agcClamping) ?
 | 
					            fftfilt::cmplx z = (m_agcActive && m_agcClamping) ?
 | 
				
			||||||
                fftfilt::cmplx{m_lowpassI.filter(delayedSample.real()), m_lowpassQ.filter(delayedSample.imag())}
 | 
					                fftfilt::cmplx{m_lowpassI.filter(delayedSample.real()), m_lowpassQ.filter(delayedSample.imag())}
 | 
				
			||||||
                : delayedSample;
 | 
					                : delayedSample;
 | 
				
			||||||
 | 
				
			|||||||
@ -102,8 +102,6 @@ private:
 | 
				
			|||||||
	double m_magsqSum;
 | 
						double m_magsqSum;
 | 
				
			||||||
	double m_magsqPeak;
 | 
						double m_magsqPeak;
 | 
				
			||||||
    int  m_magsqCount;
 | 
					    int  m_magsqCount;
 | 
				
			||||||
    double m_magsqCur;
 | 
					 | 
				
			||||||
    double m_magsqPrev;
 | 
					 | 
				
			||||||
    MagSqLevelsStore m_magSqLevelStore;
 | 
					    MagSqLevelsStore m_magSqLevelStore;
 | 
				
			||||||
    MagAGC m_agc;
 | 
					    MagAGC m_agc;
 | 
				
			||||||
    bool m_agcActive;
 | 
					    bool m_agcActive;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user