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; + } +}