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
|
/* -*- c++ -*- */
/*
* Copyright 2004,2006,2012,2018 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "squelch_base_ff_impl.h"
#include <gnuradio/io_signature.h>
#include <gnuradio/math.h>
#include <pmt/pmt.h>
namespace gr {
namespace analog {
squelch_base_ff_impl::squelch_base_ff_impl(const char* name, int ramp, bool gate)
: block(name,
io_signature::make(1, 1, sizeof(float)),
io_signature::make(1, 1, sizeof(float))),
d_sob_key(pmt::intern("squelch_sob")),
d_eob_key(pmt::intern("squelch_eob")),
d_tag_next_unmuted(true)
{
set_ramp(ramp);
set_gate(gate);
d_state = ST_MUTED;
d_envelope = d_ramp ? 0.0 : 1.0;
d_ramped = 0;
}
squelch_base_ff_impl::~squelch_base_ff_impl() {}
int squelch_base_ff_impl::ramp() const { return d_ramp; }
void squelch_base_ff_impl::set_ramp(int ramp) { d_ramp = ramp; }
bool squelch_base_ff_impl::gate() const { return d_gate; }
void squelch_base_ff_impl::set_gate(bool gate) { d_gate = gate; }
bool squelch_base_ff_impl::unmuted() const
{
return (d_state == ST_UNMUTED || d_state == ST_ATTACK);
}
int squelch_base_ff_impl::general_work(int noutput_items,
gr_vector_int& ninput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items)
{
const float* in = (const float*)input_items[0];
float* out = (float*)output_items[0];
int j = 0;
for (int i = 0; i < noutput_items; i++) {
update_state(in[i]);
// Adjust envelope based on current state
switch (d_state) {
case ST_MUTED:
if (!mute()) {
// If not ramping, go straight to unmuted
d_state = d_ramp ? ST_ATTACK : ST_UNMUTED;
if (d_state == ST_UNMUTED)
d_tag_next_unmuted = true;
}
break;
case ST_UNMUTED:
if (d_tag_next_unmuted) {
d_tag_next_unmuted = false;
add_item_tag(0, nitems_written(0) + j, d_sob_key, pmt::PMT_NIL);
}
if (mute()) {
// If not ramping, go straight to muted
d_state = d_ramp ? ST_DECAY : ST_MUTED;
if (d_state == ST_MUTED)
add_item_tag(0, nitems_written(0) + j, d_eob_key, pmt::PMT_NIL);
}
break;
case ST_ATTACK:
// FIXME: precalculate window for speed
d_envelope = 0.5 - std::cos(GR_M_PI * (++d_ramped) / d_ramp) / 2.0;
// use >= in case d_ramp is set to lower value elsewhere
if (d_ramped >= d_ramp) {
d_state = ST_UNMUTED;
d_tag_next_unmuted = true;
d_envelope = 1.0;
}
break;
case ST_DECAY:
// FIXME: precalculate window for speed
d_envelope = 0.5 - std::cos(GR_M_PI * (--d_ramped) / d_ramp) / 2.0;
if (d_ramped == 0.0) {
d_state = ST_MUTED;
add_item_tag(0, nitems_written(0) + j, d_eob_key, pmt::PMT_NIL);
}
break;
};
// If unmuted, copy input times envelope to output
// Otherwise, if not gating, copy zero to output
if (d_state != ST_MUTED)
out[j++] = in[i] * d_envelope;
else if (!d_gate)
out[j++] = 0.0;
}
consume_each(noutput_items); // Use all the inputs
return j; // But only report outputs copied
}
} /* namespace analog */
} /* namespace gr */
|