From e3a128f035d623eb88d673caf6af6809f31cd776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Izzo?= Date: Fri, 16 Apr 2021 09:41:08 +0200 Subject: [PATCH] Add DSP code with DC removal and FIR PWM filter compensation Add generic FIR implementation, specialized to compensate the PWM filter applied by STM32 targets when modulating M17 signal. Add DC bias compensation to normalize audio signal received from STM32 ADC. TG-85 #ready-for-test TG-199 #ready-for-test --- meson.build | 1 + openrtx/include/dsp.h | 75 +++++++++++++++++++++++++++++++++++++++++++ openrtx/src/dsp.cpp | 70 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 openrtx/include/dsp.h create mode 100644 openrtx/src/dsp.cpp diff --git a/meson.build b/meson.build index 1437e59a..b29506bc 100644 --- a/meson.build +++ b/meson.build @@ -25,6 +25,7 @@ openrtx_src = ['openrtx/src/state.c', 'openrtx/src/queue.c', 'openrtx/src/rtx.c', 'openrtx/src/gps.c', + 'openrtx/src/dsp.cpp', 'openrtx/src/memory_profiling.cpp'] openrtx_inc = ['openrtx/include', diff --git a/openrtx/include/dsp.h b/openrtx/include/dsp.h new file mode 100644 index 00000000..f822239b --- /dev/null +++ b/openrtx/include/dsp.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN, * + * Silvano Seva IU2KWO, * + * Frederik Saraci IU2NRO * + * * + * 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 * + ***************************************************************************/ + +#ifndef DSP_H +#define DSP_H + +#include +#include + +typedef int16_t audio_sample_t; + +/* + * This header contains various DSP utilities which can be used to condition + * input or output signals when implementing digital modes on OpenRTX. + */ + +#ifdef __cplusplus +#include +extern "C" { +#endif + +/* + * Compensate for the filtering applied by the PWM output over the modulated + * signal. The buffer will be processed in place to save memory. + * + * @param buffer: the buffer to be used as both source and destination. + * @param length: the length of the input buffer. + */ +void dsp_pwmCompensate(audio_sample_t *buffer, uint16_t length); + +/* + * Remove any DC bias from the audio buffer passed as parameter. + * The buffer will be processed in place to save memory. + * + * @param buffer: the buffer to be used as both source and destination. + * @param length: the length of the input buffer. + */ +void dsp_dcRemoval(audio_sample_t *buffer, uint16_t length); + +#ifdef __cplusplus +} + +/* + * Applies a generic FIR filter on the audio buffer passed as parameter. + * The buffer will be processed in place to save memory. + * + * @param buffer: the buffer to be used as both source and destination. + * @param length: the length of the input buffer. + * @param taps: an array of coefficients which defines the transfer function. + */ +template +void dsp_applyFIR(audio_sample_t *buffer, + uint16_t length, + std::array taps); + +#endif // __cplusplus + +#endif /* DSP_H */ diff --git a/openrtx/src/dsp.cpp b/openrtx/src/dsp.cpp new file mode 100644 index 00000000..4dc04d69 --- /dev/null +++ b/openrtx/src/dsp.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN, * + * Silvano Seva IU2KWO, * + * Frederik Saraci IU2NRO * + * * + * 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 * + ***************************************************************************/ + +#include + +/* + * Applies a generic FIR filter on the audio buffer passed as parameter. + * The buffer will be processed in place to save memory. + */ +template +void dsp_applyFIR(audio_sample_t *buffer, + uint16_t length, + std::array taps) +{ + for(int i = length - 1; i >= 0; i--) { + float acc = 0.0f; + for(uint16_t j = 0; j < order; j++) { + if (i >= j) + acc += buffer[i - j] * taps[j]; + } + buffer[i] = (audio_sample_t) acc; + } +} + +/* + * Compensate for the filtering applied by the PWM output over the modulated + * signal. The buffer will be processed in place to save memory. + */ +void dsp_pwmCompensate(audio_sample_t *buffer, uint16_t length) +{ + // FIR filter designed by Wojciech SP5WWP + std::array taps = { 0.01f, -0.05f, 0.88, -0.05f, 0.01f }; + dsp_applyFIR(buffer, length, taps); +} + +/* + * Remove any DC bias from the audio buffer passed as parameter. + * The buffer will be processed in place to save memory. + */ +void dsp_dcRemoval(audio_sample_t *buffer, uint16_t length) +{ + // Compute the average of all the samples + float acc = 0.0f; + for (int i = 0; i < length; i++) { + acc += buffer[i]; + } + float mean = acc / (float) length; + + // Subtract it to all the samples + for (int i = 0; i < length; i++) { + buffer[i] -= mean; + } +}