-
Notifications
You must be signed in to change notification settings - Fork 240
/
SquelchingAMDemodulator.java
151 lines (134 loc) · 4.81 KB
/
SquelchingAMDemodulator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
* *****************************************************************************
* Copyright (C) 2014-2023 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.dsp.am;
import io.github.dsheirer.dsp.fm.ISquelchingDemodulator;
import io.github.dsheirer.dsp.magnitude.IMagnitudeCalculator;
import io.github.dsheirer.dsp.magnitude.MagnitudeFactory;
import io.github.dsheirer.dsp.squelch.SimpleSquelch;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.source.SourceEvent;
/**
* AM demodulator with integrated squelch control.
*/
public class SquelchingAMDemodulator implements ISquelchingDemodulator, Listener<SourceEvent>
{
private static final float ZERO = 0.0f;
private IMagnitudeCalculator mMagnitudeCalculator = MagnitudeFactory.getMagnitudeCalculator();
private IAmDemodulator mAmDemodulator;
private SimpleSquelch mSimpleSquelch;
private boolean mSquelchChanged = false;
/**
* Constructs an instance
* @param gain to apply to the demodulated AM samples (e.g. 500.0f)
* @param alpha decay value of the single pole IIR filter in range: 0.0 - 1.0. The smaller the alpha value,
* the slower the squelch response.
* @param squelchThreshold in decibels. Signal power must exceed this threshold value for unsquelch.
*/
public SquelchingAMDemodulator(float gain, float alpha, float squelchThreshold)
{
mAmDemodulator = AmDemodulatorFactory.getAmDemodulator(gain);
mSimpleSquelch = new SimpleSquelch(alpha, squelchThreshold);
}
/**
* Set or update the sample rate for the squelch to adjust the power level notification rate.
* @param sampleRate in hertz
*/
public void setSampleRate(int sampleRate)
{
mSimpleSquelch.setSampleRate(sampleRate);
}
/**
* Registers the listener to receive notifications of squelch change events from the power squelch.
*/
public void setSourceEventListener(Listener<SourceEvent> listener)
{
mSimpleSquelch.setSourceEventListener(listener);
}
/**
* Demodulates the complex sample arrays.
* @param i inphase sample array
* @param q quadrature sample array
* @return demodulated AM samples with gain applied.
*/
public float[] demodulate(float[] i, float[] q)
{
setSquelchChanged(false);
float[] magnitude = mMagnitudeCalculator.getMagnitude(i, q);
float[] demodulated = mAmDemodulator.demodulateMagnitude(magnitude);
for(int x = 0; x < i.length; x++)
{
mSimpleSquelch.process(magnitude[x]);
if(!(mSimpleSquelch.isUnmuted()))
{
demodulated[x] = ZERO;
}
if(mSimpleSquelch.isSquelchChanged())
{
setSquelchChanged(true);
}
}
return demodulated;
}
/**
* Sets the threshold for squelch control
* @param threshold (dB)
*/
public void setSquelchThreshold(double threshold)
{
mSimpleSquelch.setSquelchThreshold(threshold);
}
/**
* Indicates if the squelch state has changed during the processing of buffer(s)
*/
public boolean isSquelchChanged()
{
return mSquelchChanged;
}
/**
* Sets or resets the squelch changed flag.
*/
private void setSquelchChanged(boolean changed)
{
mSquelchChanged = changed;
}
/**
* Indicates if the squelch state is currently muted
*/
public boolean isMuted()
{
return mSimpleSquelch.isMuted();
}
/**
* Process source events initiated by the timer and end-user.
* @param sourceEvent to process.
*/
@Override
public void receive(SourceEvent sourceEvent)
{
//Only forward squelch threshold change request and set squelch threshold request events
if(sourceEvent.getEvent() == SourceEvent.Event.REQUEST_CHANGE_SQUELCH_THRESHOLD)
{
mSimpleSquelch.receive(sourceEvent);
}
else if(sourceEvent.getEvent() == SourceEvent.Event.REQUEST_CURRENT_SQUELCH_THRESHOLD)
{
mSimpleSquelch.receive(sourceEvent);
}
}
}