Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 99 additions & 77 deletions docs/CONFIGURE.md

Large diffs are not rendered by default.

504 changes: 224 additions & 280 deletions trunk-recorder/call_concluder/call_concluder.cc

Large diffs are not rendered by default.

43 changes: 29 additions & 14 deletions trunk-recorder/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -395,36 +395,51 @@ bool load_config(string config_file, Config &config, gr::top_block_sptr &tb, std
BOOST_LOG_TRIVIAL(info) << "Audio Archive: " << system->get_audio_archive();
system->set_transmission_archive(element.value("transmissionArchive", false));
BOOST_LOG_TRIVIAL(info) << "Transmission Archive: " << system->get_transmission_archive();
bool audio_postprocess_enabled = false;
int audio_highpass_hz = 0;
int audio_lowpass_hz = 0;
bool audio_postprocess_enabled = true;
int audio_highpass_hz = 300;
int audio_lowpass_hz = 3000;
int audio_bandreject_hz = 0;
int audio_bandreject_width_hz = 0;
bool audio_loudnorm = true;
bool audio_loudnorm_two_pass = true;
double audio_loudnorm_i = -16.0;
double audio_loudnorm_tp = -0.1;
double audio_loudnorm_lra = 11.0;
double audio_loudnorm_tp = -1.5;
double audio_loudnorm_lra = 7.0;
bool audio_final_limiter = true;
std::string audio_ffmpeg_filter = "";
bool audio_output_raw_audio = false;

if (element.contains("audio_postprocess") && element["audio_postprocess"].is_object()) {
const json &audio_post = element["audio_postprocess"];

audio_postprocess_enabled = audio_post.value("enabled", false);
audio_highpass_hz = audio_post.value("highpass_hz", 0);
audio_lowpass_hz = audio_post.value("lowpass_hz", 0);
audio_postprocess_enabled = audio_post.value("enabled", true);
audio_highpass_hz = audio_post.value("highpass_hz", 300);
audio_lowpass_hz = audio_post.value("lowpass_hz", 3000);
audio_bandreject_hz = audio_post.value("bandreject_hz", 0);
audio_bandreject_width_hz = audio_post.value("bandreject_width_hz", 0);

audio_loudnorm = audio_post.value("loudnorm", true);
audio_loudnorm_two_pass = audio_post.value("loudnorm_two_pass", true);
audio_loudnorm_i = audio_post.value("loudnorm_i", -16.0);
audio_loudnorm_tp = audio_post.value("loudnorm_tp", -0.1);
audio_loudnorm_lra = audio_post.value("loudnorm_lra", 11.0);
audio_loudnorm_tp = audio_post.value("loudnorm_tp", -1.5);
audio_loudnorm_lra = audio_post.value("loudnorm_lra", 7.0);
audio_final_limiter = audio_post.value("final_limiter", true);

audio_ffmpeg_filter = audio_post.value("ffmpeg_filter", "");
audio_output_raw_audio = audio_post.value("outputRawAudio", false);

// Migration warning: `enabled` used to gate only the cleanup chain;
// loudnorm and the (new) final limiter had independent flags. It is
// now the master switch — false skips the entire post-processing
// pipeline. Warn loudly if the user explicitly set it false so they
// don't get silently wider-band, un-normalized audio they didn't
// expect.
if (audio_post.contains("enabled") && audio_post["enabled"].is_boolean()
&& audio_post["enabled"].get<bool>() == false) {
BOOST_LOG_TRIVIAL(warning)
<< "\033[0;33maudio_postprocess.enabled=false is now a master switch — "
<< "cleanup, loudnorm, and final_limiter are ALL skipped. The recorded "
<< "audio will be the raw concatenation of transmissions. Previously this "
<< "flag only disabled cleanup. See CONFIGURE.md for the new semantics.\033[0m";
}
}

if (audio_highpass_hz < 0) {
Expand Down Expand Up @@ -453,10 +468,10 @@ bool load_config(string config_file, Config &config, gr::top_block_sptr &tb, std
system->set_audio_bandreject_hz(audio_bandreject_hz);
system->set_audio_bandreject_width_hz(audio_bandreject_width_hz);
system->set_audio_loudnorm(audio_loudnorm);
system->set_audio_loudnorm_two_pass(audio_loudnorm_two_pass);
system->set_audio_loudnorm_i(audio_loudnorm_i);
system->set_audio_loudnorm_tp(audio_loudnorm_tp);
system->set_audio_loudnorm_lra(audio_loudnorm_lra);
system->set_audio_final_limiter(audio_final_limiter);
system->set_audio_ffmpeg_filter(audio_ffmpeg_filter);
system->set_audio_output_raw_audio(audio_output_raw_audio);

Expand All @@ -466,10 +481,10 @@ bool load_config(string config_file, Config &config, gr::top_block_sptr &tb, std
BOOST_LOG_TRIVIAL(info) << "Audio Bandreject (Hz): " << system->get_audio_bandreject_hz();
BOOST_LOG_TRIVIAL(info) << "Audio Bandreject Width (Hz): " << system->get_audio_bandreject_width_hz();
BOOST_LOG_TRIVIAL(info) << "Audio Loudnorm: " << system->get_audio_loudnorm();
BOOST_LOG_TRIVIAL(info) << "Audio Loudnorm Two Pass: " << system->get_audio_loudnorm_two_pass();
BOOST_LOG_TRIVIAL(info) << "Audio Loudnorm I: " << system->get_audio_loudnorm_i();
BOOST_LOG_TRIVIAL(info) << "Audio Loudnorm TP: " << system->get_audio_loudnorm_tp();
BOOST_LOG_TRIVIAL(info) << "Audio Loudnorm LRA: " << system->get_audio_loudnorm_lra();
BOOST_LOG_TRIVIAL(info) << "Audio Final Limiter: " << system->get_audio_final_limiter();

if (!system->get_audio_ffmpeg_filter().empty()) {
BOOST_LOG_TRIVIAL(info) << "Audio FFmpeg Filter Override: " << system->get_audio_ffmpeg_filter();
Expand Down
23 changes: 17 additions & 6 deletions trunk-recorder/global_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,30 @@ struct Config {
};

struct Audio_Postprocess_Config {
bool enabled = false;
// Master switch. When false, the entire post-processing pipeline is
// skipped — cleanup, loudnorm, and final_limiter are all bypassed —
// and the call's main file is the raw concat of transmission WAVs.
// Defaults to true, which preserves the analog audio character that
// used to come from the in-recorder bandpass (highpass_hz / lowpass_hz
// below default to 300/3000, matching the old hardcoded GR-chain FIR).
bool enabled = true;

int highpass_hz = 0;
int lowpass_hz = 0;
int highpass_hz = 300;
int lowpass_hz = 3000;

int bandreject_hz = 0;
int bandreject_width_hz = 0;

bool loudnorm = true;
bool loudnorm_two_pass = true;
double loudnorm_i = -16.0;
double loudnorm_tp = -0.1;
double loudnorm_lra = 11.0;
double loudnorm_tp = -1.5;
double loudnorm_lra = 7.0;

// Brick-wall true-peak limiter applied after per-transmission loudnorm and
// the concat filter. Hardcoded ceiling is derived from loudnorm_tp + 0.5 dB
// of headroom so loudnorm has room to work and the limiter just catches
// accidental overshoots.
bool final_limiter = true;

std::string ffmpeg_filter = "";

Expand Down
29 changes: 9 additions & 20 deletions trunk-recorder/recorders/analog_recorder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -180,37 +180,26 @@ analog_recorder::analog_recorder(Source *src, System *system, Recorder_Type type
decoder_sink = gr::blocks::decoder_wrapper_impl::make(wav_sample_rate, std::bind(&analog_recorder::decoder_callback_handler, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
BOOST_LOG_TRIVIAL(info) << "\t Decoder sink created!" << std::endl;

// Analog audio band pass from 300 to 3000 Hz
// can't use gnuradio.filter.firdes.band_pass since we have different transition widths
// 300 Hz high pass (275-325 Hz): removes CTCSS/DCS and Type II 150 bps Low Speed Data (LSD), or "FSK wobble"
#if GNURADIO_VERSION < 0x030900
high_f_taps = gr::filter::firdes::high_pass(1, wav_sample_rate, 300, 50, gr::filter::firdes::WIN_HANN); // Configurable
low_f_taps = gr::filter::firdes::low_pass(1, wav_sample_rate, 3250, 500, gr::filter::firdes::WIN_HANN);
#else
high_f_taps = gr::filter::firdes::high_pass(1, wav_sample_rate, 300, 50, gr::fft::window::WIN_HANN); // Configurable
low_f_taps = gr::filter::firdes::low_pass(1, wav_sample_rate, 3250, 500, gr::fft::window::WIN_HANN);
#endif

high_f = gr::filter::fir_filter_fff::make(1, high_f_taps);
// 3000 Hz low pass (3000-3500 Hz)

low_f = gr::filter::fir_filter_fff::make(1, low_f_taps);
// Voice-band cleanup (300/3000 Hz bandpass) used to live here as FIR
// blocks. It now runs in ffmpeg during call conclusion (see
// audio_postprocess in CONFIGURE.md), so wav_sink receives the
// post-demod / post-deemph signal directly — actual discriminator
// audio. This keeps the recording pipeline cheaper and lets users
// tune or disable the bandpass per system.

// using squelch
connect(self(), 0, prefilter, 0);
connect(prefilter, 0, demod, 0);
connect(demod, 0, deemph, 0);
if (use_tone_squelch) {
connect(deemph, 0, tone_squelch, 0);
connect(tone_squelch, 0, decim_audio, 0);
connect(deemph, 0, tone_squelch, 0);
connect(tone_squelch, 0, decim_audio, 0);
} else {
connect(deemph, 0, decim_audio, 0);
}

connect(decim_audio, 0, decoder_sink, 0);
connect(decim_audio, 0, high_f, 0);
connect(high_f, 0, low_f, 0);
connect(low_f, 0, squelch_two, 0);
connect(decim_audio, 0, squelch_two, 0);
connect(squelch_two, 0, levels, 0);
connect(levels, 0, converter, 0);
connect(converter, 0, wav_sink, 0);
Expand Down
4 changes: 0 additions & 4 deletions trunk-recorder/recorders/analog_recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ class analog_recorder : public gr::hier_block2, public Recorder {
std::vector<float> lpf_taps;
std::vector<float> audio_resampler_taps;
std::vector<float> sym_taps;
std::vector<float> high_f_taps;
std::vector<float> low_f_taps;
/* De-emph IIR filter taps */
std::vector<double> d_fftaps; /*! Feed forward taps. */
std::vector<double> d_fbtaps; /*! Feed back taps. */
Expand All @@ -150,8 +148,6 @@ class analog_recorder : public gr::hier_block2, public Recorder {
gr::blocks::multiply_const_ff::sptr levels;
gr::filter::pfb_arb_resampler_ccf::sptr arb_resampler;
gr::filter::fir_filter_fff::sptr decim_audio;
gr::filter::fir_filter_fff::sptr high_f;
gr::filter::fir_filter_fff::sptr low_f;
gr::analog::pwr_squelch_ff::sptr squelch_two;
gr::analog::ctcss_squelch_ff::sptr tone_squelch;

Expand Down
6 changes: 3 additions & 3 deletions trunk-recorder/systems/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,6 @@ class System {
virtual bool get_audio_loudnorm() = 0;
virtual void set_audio_loudnorm(bool enabled) = 0;

virtual bool get_audio_loudnorm_two_pass() = 0;
virtual void set_audio_loudnorm_two_pass(bool enabled) = 0;

virtual double get_audio_loudnorm_i() = 0;
virtual void set_audio_loudnorm_i(double value) = 0;

Expand All @@ -86,6 +83,9 @@ class System {
virtual double get_audio_loudnorm_lra() = 0;
virtual void set_audio_loudnorm_lra(double value) = 0;

virtual bool get_audio_final_limiter() = 0;
virtual void set_audio_final_limiter(bool enabled) = 0;

virtual std::string get_audio_ffmpeg_filter() = 0;
virtual void set_audio_ffmpeg_filter(std::string filter) = 0;

Expand Down
28 changes: 14 additions & 14 deletions trunk-recorder/systems/system_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,6 @@ void System_impl::set_audio_loudnorm(bool enabled) {
this->audio_loudnorm = enabled;
}

bool System_impl::get_audio_loudnorm_two_pass() {
return this->audio_loudnorm_two_pass;
}

void System_impl::set_audio_loudnorm_two_pass(bool enabled) {
this->audio_loudnorm_two_pass = enabled;
}

double System_impl::get_audio_loudnorm_i() {
return this->audio_loudnorm_i;
}
Expand All @@ -141,6 +133,14 @@ void System_impl::set_audio_loudnorm_lra(double value) {
this->audio_loudnorm_lra = value;
}

bool System_impl::get_audio_final_limiter() {
return this->audio_final_limiter;
}

void System_impl::set_audio_final_limiter(bool enabled) {
this->audio_final_limiter = enabled;
}

std::string System_impl::get_audio_ffmpeg_filter() {
return this->audio_ffmpeg_filter;
}
Expand Down Expand Up @@ -207,16 +207,16 @@ System_impl::System_impl(int sys_num) {
message_count = 0;
decode_rate = 0;
msg_queue = gr::msg_queue::make(100);
audio_postprocess_enabled = false;
audio_highpass_hz = 0;
audio_lowpass_hz = 0;
audio_postprocess_enabled = true;
audio_highpass_hz = 300;
audio_lowpass_hz = 3000;
audio_bandreject_hz = 0;
audio_bandreject_width_hz = 0;
audio_loudnorm = false;
audio_loudnorm_two_pass = true;
audio_loudnorm_i = -16.0;
audio_loudnorm_tp = -0.1;
audio_loudnorm_lra = 11.0;
audio_loudnorm_tp = -1.5;
audio_loudnorm_lra = 7.0;
audio_final_limiter = true;
audio_ffmpeg_filter = "";
audio_output_raw_audio = false;
}
Expand Down
8 changes: 4 additions & 4 deletions trunk-recorder/systems/system_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ class System_impl : public System {
int audio_bandreject_hz;
int audio_bandreject_width_hz;
bool audio_loudnorm;
bool audio_loudnorm_two_pass;
double audio_loudnorm_i;
double audio_loudnorm_tp;
double audio_loudnorm_lra;
bool audio_final_limiter;
std::string audio_ffmpeg_filter;
bool audio_output_raw_audio;

Expand Down Expand Up @@ -153,9 +153,6 @@ class System_impl : public System {
bool get_audio_loudnorm() override;
void set_audio_loudnorm(bool enabled) override;

bool get_audio_loudnorm_two_pass() override;
void set_audio_loudnorm_two_pass(bool enabled) override;

double get_audio_loudnorm_i() override;
void set_audio_loudnorm_i(double value) override;

Expand All @@ -165,6 +162,9 @@ class System_impl : public System {
double get_audio_loudnorm_lra() override;
void set_audio_loudnorm_lra(double value) override;

bool get_audio_final_limiter() override;
void set_audio_final_limiter(bool enabled) override;

std::string get_audio_ffmpeg_filter() override;
void set_audio_ffmpeg_filter(std::string filter) override;

Expand Down
Loading