Moved state variables of PWM compensator and DC removal filter outside the function bodies to allow keeping their consistency among function calls

pull/68/head
Silvano Seva 2022-04-02 14:57:15 +02:00
rodzic 9139b19aac
commit e5b5daba85
5 zmienionych plików z 88 dodań i 30 usunięć

Wyświetl plik

@ -39,23 +39,45 @@ typedef int16_t audio_sample_t;
extern "C" { extern "C" {
#endif #endif
/**
* Data structure holding the internal state of a filter.
*/
typedef struct
{
float u[3]; // input values u(k), u(k-1), u(k-2)
float y[3]; // output values y(k), y(k-1), y(k-2)
bool initialised; // state variables initialised
}
filter_state_t;
/**
* Reset the filter state variables.
*
* @param state: pointer to the data structure containing the filter state.
*/
void dsp_resetFilterState(filter_state_t *state);
/** /**
* Compensate for the filtering applied by the PWM output over the modulated * Compensate for the filtering applied by the PWM output over the modulated
* signal. The buffer is be processed in place to save memory. * signal. The buffer is be processed in place to save memory.
* *
* @param state: pointer to the data structure containing the filter state.
* @param buffer: the buffer to be used as both source and destination. * @param buffer: the buffer to be used as both source and destination.
* @param length: the length of the input buffer. * @param length: the length of the input buffer.
*/ */
void dsp_pwmCompensate(audio_sample_t *buffer, size_t length); void dsp_pwmCompensate(filter_state_t *state, audio_sample_t *buffer,
size_t length);
/** /**
* Remove the DC offset from a collection of audio samples, processing data * Remove the DC offset from a collection of audio samples, processing data
* in-place. * in-place.
* *
* @param state: pointer to the data structure containing the filter state.
* @param buffer: buffer containing the audio samples. * @param buffer: buffer containing the audio samples.
* @param length: number of samples contained in the buffer. * @param length: number of samples contained in the buffer.
*/ */
void dsp_dcRemoval(audio_sample_t *buffer, size_t length); void dsp_dcRemoval(filter_state_t *state, audio_sample_t *buffer, size_t length);
/* /*
* Inverts the phase of the audio buffer passed as paramenter. * Inverts the phase of the audio buffer passed as paramenter.

Wyświetl plik

@ -28,6 +28,7 @@
#include <interfaces/audio_stream.h> #include <interfaces/audio_stream.h>
#include <cstdint> #include <cstdint>
#include <array> #include <array>
#include <dsp.h>
namespace M17 namespace M17
{ {
@ -125,6 +126,10 @@ private:
streamId outStream; ///< Baseband output stream ID. streamId outStream; ///< Baseband output stream ID.
bool txRunning; ///< Transmission running. bool txRunning; ///< Transmission running.
bool stopTx; ///< Stop transmission request. bool stopTx; ///< Stop transmission request.
#if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0)
filter_state_t pwmFilterState;
#endif
}; };
} /* M17 */ } /* M17 */

Wyświetl plik

@ -174,6 +174,9 @@ static void *encodeFunc(void *arg)
{ {
(void) arg; (void) arg;
filter_state_t dcrState;
dsp_resetFilterState(&dcrState);
codec2 = codec2_create(CODEC2_MODE_3200); codec2 = codec2_create(CODEC2_MODE_3200);
while(running) while(running)
@ -187,7 +190,7 @@ static void *encodeFunc(void *arg)
for(size_t i = 0; i < audio.len; i++) audio.data[i] *= micGainPre; for(size_t i = 0; i < audio.len; i++) audio.data[i] *= micGainPre;
// DC removal // DC removal
dsp_dcRemoval(audio.data, audio.len); dsp_dcRemoval(&dcrState, audio.data, audio.len);
// Post-amplification stage // Post-amplification stage
for(size_t i = 0; i < audio.len; i++) audio.data[i] *= micGainPost; for(size_t i = 0; i < audio.len; i++) audio.data[i] *= micGainPost;

Wyświetl plik

@ -20,15 +20,22 @@
#include <dsp.h> #include <dsp.h>
void dsp_pwmCompensate(audio_sample_t *buffer, size_t length) void dsp_resetFilterState(filter_state_t *state)
{ {
float u = 0.0f; // Current input value state->u[0] = 0.0f;
float y = 0.0f; // Current output value state->u[1] = 0.0f;
float uo = 0.0f; // u(k-1) state->u[2] = 0.0f;
float uoo = 0.0f; // u(k-2)
float yo = 0.0f; // y(k-1)
float yoo = 0.0f; // y(k-2)
state->y[0] = 0.0f;
state->y[1] = 0.0f;
state->y[2] = 0.0f;
state->initialised = false;
}
void dsp_pwmCompensate(filter_state_t *state, audio_sample_t *buffer,
size_t length)
{
static constexpr float a = 4982680082321166792352.0f; static constexpr float a = 4982680082321166792352.0f;
static constexpr float b = -6330013275146484168000.0f; static constexpr float b = -6330013275146484168000.0f;
static constexpr float c = 1871109008789062500000.0f; static constexpr float c = 1871109008789062500000.0f;
@ -38,22 +45,32 @@ void dsp_pwmCompensate(audio_sample_t *buffer, size_t length)
// Initialise filter with first two values, for smooth transient. // Initialise filter with first two values, for smooth transient.
if(length <= 2) return; if(length <= 2) return;
uoo = static_cast< float >(buffer[0]);
uo = static_cast< float >(buffer[1]); if(state->initialised == false)
{
state->u[2] = static_cast< float >(buffer[0]);
state->u[1] = static_cast< float >(buffer[1]);
state->initialised = true;
}
for(size_t i = 2; i < length; i++) for(size_t i = 2; i < length; i++)
{ {
u = static_cast< float >(buffer[i]); state->u[0] = static_cast< float >(buffer[i]);
y = (a/d)*u + (b/d)*uo + (c/d)*uoo - (e/d)*yo - (f/d)*yoo; state->y[0] = (a/d)*(state->u[0])
uoo = uo; + (b/d)*(state->u[1])
uo = u; + (c/d)*(state->u[2])
yoo = yo; - (e/d)*(state->y[1])
yo = y; - (f/d)*(state->y[2]);
buffer[i] = static_cast< audio_sample_t >(y * 0.5f);
state->u[2] = state->u[1];
state->u[1] = state->u[0];
state->y[2] = state->y[1];
state->y[1] = state->y[0];
buffer[i] = static_cast< audio_sample_t >((state->y[0] * 0.5f) + 0.5f);
} }
} }
void dsp_dcRemoval(audio_sample_t *buffer, size_t length) void dsp_dcRemoval(filter_state_t *state, audio_sample_t *buffer, size_t length)
{ {
/* /*
* Removal of DC component performed using an high-pass filter with * Removal of DC component performed using an high-pass filter with
@ -64,19 +81,25 @@ void dsp_dcRemoval(audio_sample_t *buffer, size_t length)
if(length < 2) return; if(length < 2) return;
audio_sample_t uo = buffer[0]; if(state->initialised == false)
audio_sample_t yo = 0; {
state->u[1] = static_cast< float >(buffer[0]);
state->initialised = true;
}
static constexpr float alpha = 0.99f; static constexpr float alpha = 0.99f;
for(size_t i = 1; i < length; i++) for(size_t i = 1; i < length; i++)
{ {
float yold = static_cast< float >(yo) * alpha; state->u[0] = static_cast< float >(buffer[i]);
audio_sample_t u = buffer[i]; state->y[0] = (state->u[0])
buffer[i] = u - uo + static_cast< audio_sample_t >(yold); - (state->u[1])
uo = u; + alpha * (state->y[1]);
yo = buffer[i];
state->u[1] = state->u[0];
state->y[1] = state->y[0];
buffer[i] = static_cast< audio_sample_t >(state->y[0] + 0.5f);
} }
buffer[0] = buffer[1];
} }
void dsp_invertPhase(audio_sample_t *buffer, uint16_t length) void dsp_invertPhase(audio_sample_t *buffer, uint16_t length)

Wyświetl plik

@ -19,7 +19,6 @@
***************************************************************************/ ***************************************************************************/
#include <new> #include <new>
#include <dsp.h>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <experimental/array> #include <experimental/array>
@ -54,6 +53,9 @@ void M17Modulator::init()
baseband_buffer = new int16_t[2 * M17_FRAME_SAMPLES_48K]; baseband_buffer = new int16_t[2 * M17_FRAME_SAMPLES_48K];
idleBuffer = baseband_buffer; idleBuffer = baseband_buffer;
txRunning = false; txRunning = false;
#if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0)
dsp_resetFilterState(&pwmFilterState);
#endif
} }
void M17Modulator::terminate() void M17Modulator::terminate()
@ -106,7 +108,7 @@ void M17Modulator::generateBaseband()
void M17Modulator::emitBaseband() void M17Modulator::emitBaseband()
{ {
#if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0) #if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0)
dsp_pwmCompensate(idleBuffer, M17_FRAME_SAMPLES_48K); dsp_pwmCompensate(&pwmFilterState, idleBuffer, M17_FRAME_SAMPLES_48K);
dsp_invertPhase(idleBuffer, M17_FRAME_SAMPLES_48K); dsp_invertPhase(idleBuffer, M17_FRAME_SAMPLES_48K);
#endif #endif
@ -135,6 +137,9 @@ void M17Modulator::emitBaseband()
stopTx = false; stopTx = false;
txRunning = false; txRunning = false;
idleBuffer = baseband_buffer; idleBuffer = baseband_buffer;
#if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0)
dsp_resetFilterState(&pwmFilterState);
#endif
} }
else else
{ {