NBFM Channel level CTCSS/DCS and audio features (#2425)

NBFM decoder enhancements.  CTCSS and DCS squelch control.  Adds deemphasis, high pass filter control, and auto-level control
This commit is contained in:
Randy
2026-09-26 00:54:31 -06:00
committed by GitHub
parent 80360029ef
commit 97cae50bdd
34 changed files with 2377 additions and 217 deletions

View File

@@ -24,7 +24,7 @@ import org.apache.commons.math3.util.FastMath;
/**
* Implements the Goertzel Filter as described in
* http://en.wikipedia.org/wiki/Goertzel_algorithm
* <p>
*
* Calculates the magnitude of a specific frequency component within a window of
* samples, using a Goertzel Filter (ie an optimized DFT).
*/
@@ -101,9 +101,10 @@ public class GoertzelFilter
//power = s_prev2 * s_prev2 + s_prev * s_prev - coeff * s_prev * s_prev2 ;
double magnitude = (s_prev2 * s_prev2) + (s_prev * s_prev) - (mCoefficient * s_prev * s_prev2);
int binZero = getBinZeroPower(samples);
int power = (int)(20 * FastMath.log10(magnitude / binZero));
// Removed because bin(0) is likely to be (int) zero on audio samples
//int binZero = getBinZeroPower(samples);
//int power = (int)(20 * FastMath.log10(magnitude / binZero));
int power = (int)(20 * FastMath.log10(magnitude));
return power;
}
@@ -119,7 +120,6 @@ public class GoertzelFilter
{
retVal += sample;
}
return retVal;
}

View File

@@ -15,15 +15,22 @@
******************************************************************************/
package io.github.dsheirer.dsp.filter.iir;
import io.github.dsheirer.audio.AbstractAudioFilter;
import org.apache.commons.math3.util.FastMath;
public class DeemphasisFilter
public class DeemphasisFilter extends AbstractAudioFilter
{
private static final float MAX_SAMPLE_VALUE = 0.95f;
private float mAlpha;
private float mGain;
private float mPrevious = 0.0f;
/**
* Create an instance
* @param sampleRate - usually 8000 Hz
* @param cutoff - cutoff frequency
* @param gain - gain (linear)
*/
public DeemphasisFilter( float sampleRate, float cutoff, float gain )
{
mAlpha = (float)FastMath.exp( -2.0 * FastMath.PI * cutoff * ( 1.0 / sampleRate ) );
@@ -45,7 +52,7 @@ public class DeemphasisFilter
}
else return FastMath.max(value, -MAX_SAMPLE_VALUE);
}
@Override
public float[] filter( float[] samples )
{
for( int x = 0; x < samples.length; x++ )

View File

@@ -1,6 +1,6 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 Dennis Sheirer
* Copyright (C) 2014-2026 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,6 +47,7 @@ public class AudioGainAndDcFilter
private float mObjectiveGain;
private float mObjectiveAmplitude;
private float mMaxObservedAmplitude;
private float mPercentDecayRate = 10f;
/**
* Constructs an instance
@@ -82,8 +83,9 @@ public class AudioGainAndDcFilter
float currentAmplitude;
float dcAccumulator = 0.0f;
//Decay the max observed value by 10% each buffer so that an initial spike doesn't carry across all buffers
mMaxObservedAmplitude *= 0.9f;
//Decay the max observed value by a specified percentage each buffer so that an initial
// spike doesn't carry across all buffers
mMaxObservedAmplitude *= ((100 - mPercentDecayRate )/ 100);
for(float sample: samples)
{
@@ -133,7 +135,17 @@ public class AudioGainAndDcFilter
}
mCurrentGain = gain;
//mLog.debug("Gain: {}", gain);
mObjectiveGain = objective;
return processed;
}
/**
* Overrides the default decay rate of 10 %.
* @param newRate specified as a percentage (i.e. 2 equals 2%)
*/
public void setDecayRate(float newRate)
{
mPercentDecayRate = newRate;
}
}