Skip to content

Commit 4f8b8e9

Browse files
DSheirerDennis Sheirer
andauthored
#35 Updates AM & NBFM decoders to use Adaptive Squelch, a power squelch that includes an adaptive noise floor monitor. Implements vectorized magnitude operations for AM & FM decoders. Adds talkgroup assignment and squelch controls to AM channel configuration editor. Implements new AM gain control that attempts to normalize audio gain quickly at beginning of call/transmission and maintains that gain across lifecycle of the call and resets the gain for the next call. (#1540)
Notes on usage: - When using either AM or FM squelch control use either the Heterodyne channelizer or if using the Polyphase channelizer, avoid using trunk tracking decoders like DMR or P25 or set the squelch threshold high enough to avoid changes in noise floor from polyphase channelizer where it can vary between using the one channel or the two-channel combined channel sources. Co-authored-by: Dennis Sheirer <[email protected]>
1 parent 5654254 commit 4f8b8e9

File tree

74 files changed

+4626
-2008
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+4626
-2008
lines changed

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormat.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
*/
3535
public enum TalkgroupFormat
3636
{
37+
AM("*****", 1, 0xFFFF, "1 to 65,535",
38+
"AM valid value range is 1-65,535"),
3739
APCO25("********", 0, 0xFFFF, "0 to 65,535",
3840
"<html>APCO25 talkgroup valid range is 0 to 65,535"),
3941
DMR("********", 0, 0xFFFFFF, "0 to 16,777,215",
@@ -122,6 +124,8 @@ public static TalkgroupFormat get(Protocol protocol)
122124

123125
switch(protocol)
124126
{
127+
case AM:
128+
return AM;
125129
case APCO25:
126130
return APCO25;
127131
case FLEETSYNC:

src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormatter.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/*
2-
* ******************************************************************************
3-
* sdrtrunk
4-
* Copyright (C) 2014-2019 Dennis Sheirer
2+
* *****************************************************************************
3+
* Copyright (C) 2014-2023 Dennis Sheirer
54
*
65
* This program is free software: you can redistribute it and/or modify
76
* it under the terms of the GNU General Public License as published by
@@ -15,29 +14,28 @@
1514
*
1615
* You should have received a copy of the GNU General Public License
1716
* along with this program. If not, see <http://www.gnu.org/licenses/>
18-
* *****************************************************************************
17+
* ****************************************************************************
1918
*/
2019

2120
package io.github.dsheirer.alias.id.talkgroup;
2221

2322
import io.github.dsheirer.preference.identifier.IntegerFormat;
2423
import io.github.dsheirer.preference.identifier.talkgroup.APCO25TalkgroupFormatter;
2524
import io.github.dsheirer.preference.identifier.talkgroup.AbstractIntegerFormatter;
25+
import io.github.dsheirer.preference.identifier.talkgroup.AnalogTalkgroupFormatter;
2626
import io.github.dsheirer.preference.identifier.talkgroup.DMRTalkgroupFormatter;
2727
import io.github.dsheirer.preference.identifier.talkgroup.FleetsyncTalkgroupFormatter;
2828
import io.github.dsheirer.preference.identifier.talkgroup.LTRTalkgroupFormatter;
2929
import io.github.dsheirer.preference.identifier.talkgroup.MDC1200TalkgroupFormatter;
3030
import io.github.dsheirer.preference.identifier.talkgroup.MPT1327TalkgroupFormatter;
31-
import io.github.dsheirer.preference.identifier.talkgroup.NBFMTalkgroupFormatter;
3231
import io.github.dsheirer.preference.identifier.talkgroup.PassportTalkgroupFormatter;
3332
import io.github.dsheirer.preference.identifier.talkgroup.UnknownTalkgroupFormatter;
3433
import io.github.dsheirer.protocol.Protocol;
35-
import org.slf4j.Logger;
36-
import org.slf4j.LoggerFactory;
37-
3834
import java.text.ParseException;
3935
import java.util.EnumMap;
4036
import java.util.Map;
37+
import org.slf4j.Logger;
38+
import org.slf4j.LoggerFactory;
4139

4240
/**
4341
* Protocol-specific formatting of talkgroup values and parsing of formatted talkgroup values.
@@ -49,6 +47,10 @@ public class TalkgroupFormatter
4947

5048
static
5149
{
50+
AnalogTalkgroupFormatter analogTalkgroupFormatter = new AnalogTalkgroupFormatter();
51+
mFormatterMap.put(Protocol.AM, analogTalkgroupFormatter);
52+
mFormatterMap.put(Protocol.NBFM, analogTalkgroupFormatter);
53+
5254
mFormatterMap.put(Protocol.APCO25, new APCO25TalkgroupFormatter());
5355
mFormatterMap.put(Protocol.DMR, new DMRTalkgroupFormatter());
5456
mFormatterMap.put(Protocol.FLEETSYNC, new FleetsyncTalkgroupFormatter());
@@ -57,7 +59,6 @@ public class TalkgroupFormatter
5759
mFormatterMap.put(Protocol.LTR_NET, ltr);
5860
mFormatterMap.put(Protocol.MDC1200, new MDC1200TalkgroupFormatter());
5961
mFormatterMap.put(Protocol.MPT1327, new MPT1327TalkgroupFormatter());
60-
mFormatterMap.put(Protocol.NBFM, new NBFMTalkgroupFormatter());
6162
mFormatterMap.put(Protocol.PASSPORT, new PassportTalkgroupFormatter());
6263
mFormatterMap.put(Protocol.UNKNOWN, new UnknownTalkgroupFormatter());
6364
}

src/main/java/io/github/dsheirer/audio/AudioModule.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,16 @@ public class SquelchStateListener implements Listener<SquelchStateEvent>
141141
@Override
142142
public void receive(SquelchStateEvent event)
143143
{
144-
mSquelchState = event.getSquelchState();
144+
SquelchState squelchState = event.getSquelchState();
145145

146-
if(mSquelchState == SquelchState.SQUELCH)
146+
if(mSquelchState != squelchState)
147147
{
148-
closeAudioSegment();
148+
mSquelchState = squelchState;
149+
150+
if(mSquelchState == SquelchState.SQUELCH)
151+
{
152+
closeAudioSegment();
153+
}
149154
}
150155
}
151156
}

src/main/java/io/github/dsheirer/buffer/FloatCircularBuffer.java

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* *****************************************************************************
3-
* Copyright (C) 2014-2022 Dennis Sheirer
3+
* Copyright (C) 2014-2023 Dennis Sheirer
44
*
55
* This program is free software: you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -21,21 +21,16 @@
2121
import java.util.Arrays;
2222

2323
/**
24-
* Circular sample buffer - allocates a buffer and stores samples in a circular
25-
* fashion, overwriting older samples with newly arrived samples. Initially
26-
* fills buffer with 0-valued samples
27-
*
28-
* Can be used as a delay-type buffer, to delay samples by the 'size' amount
24+
* Circular sample buffer - allocates a buffer and stores samples in a circular fashion, overwriting older samples with
25+
* newly arrived samples. Initially fills buffer with 0-valued (default) samples or with a specified value.
2926
*/
3027
public class FloatCircularBuffer
3128
{
3229
private float[] mBuffer;
3330
private int mBufferPointer = 0;
34-
private float mOldestSample;
3531

3632
/**
3733
* Creates a circular double buffer of the specified size and all entries filled with the specified initial value.
38-
*
3934
* @param size of the buffer
4035
* @param initialFillValue to fill the buffer entries
4136
*/
@@ -47,41 +42,41 @@ public FloatCircularBuffer(int size, float initialFillValue)
4742

4843
/**
4944
* Creates a circular double buffer of the specified size and all entries filled with an initial value of zero.
50-
*
5145
* @param size of the buffer
5246
*/
5347
public FloatCircularBuffer(int size)
5448
{
5549
this(size, 0.0f);
5650
}
5751

58-
public float[] getBuffer()
52+
/**
53+
* Resets the delay buffer to an all zeros state
54+
*/
55+
public void reset(float fillValue)
5956
{
60-
return mBuffer;
57+
Arrays.fill(mBuffer, fillValue);
6158
}
6259

6360
/**
64-
* Gets the current buffer value and overwrites that value position in the buffer with the new value.
61+
* Puts the new value into the buffer and returns the oldest buffer value that it replaced
6562
*
6663
* @param newValue to add to the buffer
6764
* @return oldest value that was overwritten by the new value
6865
*/
69-
public float getAndPut(float newValue)
66+
public float get(float newValue)
7067
{
71-
mOldestSample = mBuffer[mBufferPointer];
72-
put(newValue);
73-
return mOldestSample;
74-
}
68+
float oldestSample = mBuffer[mBufferPointer];
7569

76-
/**
77-
* Puts the value into the buffer, updates the pointer and returns the buffer value at the pointer position.
78-
* @param sample to add
79-
* @return next pointed sample.
80-
*/
81-
public float putAndGet(float sample)
82-
{
83-
put(sample);
84-
return mBuffer[mBufferPointer];
70+
mBuffer[mBufferPointer] = newValue;
71+
72+
mBufferPointer++;
73+
74+
if(mBufferPointer >= mBuffer.length)
75+
{
76+
mBufferPointer = 0;
77+
}
78+
79+
return oldestSample;
8580
}
8681

8782
public float[] getAll()
@@ -105,13 +100,70 @@ public float[] getAll()
105100

106101
/**
107102
* Places the new value into the buffer, overwriting the oldest value
108-
*
109103
* @param newValue to add to the buffer
110104
*/
111105
public void put(float newValue)
112106
{
113107
mBuffer[mBufferPointer] = newValue;
108+
114109
mBufferPointer++;
115-
mBufferPointer %= mBuffer.length;
110+
111+
if(mBufferPointer >= mBuffer.length)
112+
{
113+
mBufferPointer = 0;
114+
}
115+
}
116+
117+
/**
118+
* Returns the maximum from the values currently in the buffer
119+
*/
120+
public float max(float referenceValue)
121+
{
122+
float max = referenceValue;
123+
124+
for(int x = 0; x < mBuffer.length; x++)
125+
{
126+
if(mBuffer[x] > max)
127+
{
128+
max = mBuffer[x];
129+
}
130+
}
131+
132+
// System.out.println("Max [" + max + "] from " + Arrays.toString(mBuffer));
133+
134+
return max;
135+
}
136+
137+
/**
138+
* Returns the minimum from the values currently in the buffer
139+
*/
140+
public float min()
141+
{
142+
float min = 0.0f;
143+
144+
for(int x = 0; x < mBuffer.length; x++)
145+
{
146+
if(mBuffer[x] < min)
147+
{
148+
min = mBuffer[x];
149+
}
150+
}
151+
152+
return min;
153+
}
154+
155+
/**
156+
* Calculates the average/mean of the values contained in this buffer
157+
*/
158+
public float mean()
159+
{
160+
double accumulator = 0.0;
161+
162+
for(float value: mBuffer)
163+
{
164+
accumulator += value;
165+
}
166+
167+
return (float)(accumulator / mBuffer.length);
116168
}
117169
}

0 commit comments

Comments
 (0)