Add: ClipHandler
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Casper Jansen 2023-01-27 14:56:46 +01:00
parent 4fde79b64b
commit e435dc9ecd
4 changed files with 184 additions and 0 deletions

View File

@ -14,6 +14,7 @@ set(lasp_dsp_files
lasp_slm.cpp
lasp_threadedindatahandler.cpp
lasp_ppm.cpp
lasp_clip.cpp
)

View File

@ -0,0 +1,94 @@
/* #define DEBUGTRACE_ENABLED */
#include "debugtrace.hpp"
#include "lasp_clip.h"
#include <mutex>
using std::cerr;
using std::endl;
using Lck = std::scoped_lock<std::mutex>;
using rte = std::runtime_error;
ClipHandler::ClipHandler(StreamMgr &mgr)
: ThreadedInDataHandler(mgr){
DEBUGTRACE_ENTER;
}
bool ClipHandler::inCallback_threaded(const DaqData &d) {
DEBUGTRACE_ENTER;
Lck lck(_mtx);
dmat data = d.toFloat();
const us nchannels = d.nchannels;
assert(data.n_cols == nchannels);
if (nchannels != _clip_time.size()) {
DEBUGTRACE_PRINT("Resizing clip indication");
_clip_time = vd(nchannels, arma::fill::value(-1));
}
/// Obtain max abs values for each column, convert this row-vec to a column
/// vector, and scale with the max-range for each channel
vd maxabs = arma::max(arma::abs(data), 0).as_col() / _max_range;
/// Find indices for channels that have a clip
arma::uvec clips = maxabs > clip_point;
for (us i = 0; i < nchannels; i++) {
if (clips(i)) {
/// Reset clip counter
_clip_time(i) = 0;
} else if (_clip_time(i) > clip_indication_time) {
/// Reset to 'unclipped'
_clip_time(i) = -1;
} else if (_clip_time(i) >= 0) {
/// Add a bit of clip time
_clip_time(i) += _dt;
}
}
return true;
}
arma::uvec ClipHandler::getCurrentValue() const {
DEBUGTRACE_ENTER;
Lck lck(_mtx);
arma::uvec clips(_clip_time.size(), arma::fill::zeros);
clips.elem(arma::find(_clip_time >= 0)).fill(1);
return {clips};
}
void ClipHandler::reset(const Daq *daq) {
DEBUGTRACE_ENTER;
Lck lck(_mtx);
if (daq) {
const us nchannels = daq->neninchannels();
_max_range.resize(nchannels);
dvec ranges = daq->inputRangeForEnabledChannels();
assert(ranges.size() == nchannels);
for(us i=0;i<daq->neninchannels();i++) {
_max_range[i] = ranges[i];
}
_clip_time.fill(-1);
const d fs = daq->samplerate();
/* DEBUGTRACE_PRINT(fs); */
_dt = daq->framesPerBlock() / fs;
}
}
ClipHandler::~ClipHandler() {
DEBUGTRACE_ENTER;
Lck lck(_mtx);
stop();
}

77
src/lasp/dsp/lasp_clip.h Normal file
View File

@ -0,0 +1,77 @@
// lasp_clip.h
//
// Author: J.A. de Jong - ASCEE
//
// Description: Peak Programme Meter
#pragma once
#include <memory>
#include "lasp_filter.h"
#include "lasp_mathtypes.h"
#include "lasp_threadedindatahandler.h"
/**
* \addtogroup dsp
* @{
*
* \addtogroup rt
* @{
*/
/**
* @brief Clipping detector (Clip). Detects when a signal overdrives the input
* */
class ClipHandler: public ThreadedInDataHandler {
/**
* @brief Assuming full scale of a signal is +/- 1.0. If a value is found
*/
static inline const d clip_point = 0.98;
/**
* @brief How long it takes in [s] after a clip event has happened, that we
* are actually still in 'clip' mode.
*/
static inline const d clip_indication_time = 2.0;
/**
* @brief Inverse of block sampling frequency [s]: (framesPerBlock/fs)
*/
d _dt;
mutable std::mutex _mtx;
/**
* @brief How long ago the last clip has happened. Negative in case no clip
* has happened.
*/
vd _clip_time;
/**
* @brief Storage for maximum values
*/
vd _max_range;
public:
/**
* @brief Constructs Clipping indicator
*
* @param mgr Stream Mgr to operate on
*/
ClipHandler(StreamMgr& mgr);
~ClipHandler();
/**
* @brief Get the current values of the clip handler. Returns a vector of of True's.
*
* @return clipping indication
*/
arma::uvec getCurrentValue() const;
bool inCallback_threaded(const DaqData& ) override final;
void reset(const Daq*) override final;
};
/** @} */
/** @} */

View File

@ -3,6 +3,7 @@
#include "arma_npy.h"
#include "debugtrace.hpp"
#include "lasp_ppm.h"
#include "lasp_clip.h"
#include "lasp_rtaps.h"
#include "lasp_streammgr.h"
#include "lasp_threadedindatahandler.h"
@ -192,6 +193,17 @@ void init_datahandler(py::module &m) {
ColToNpy<arma::uword>(std::get<1>(tp)));
});
/// Clip Detector
py::class_<ClipHandler, ThreadedInDataHandler> clip(m, "ClipHandler");
clip.def(py::init<StreamMgr &>());
clip.def("getCurrentValue", [](const ClipHandler &clip) {
arma::uvec cval = clip.getCurrentValue();
return ColToNpy<arma::uword>(cval); // something goes wrong here
});
/// Real time Aps
///
py::class_<RtAps, ThreadedInDataHandler> rtaps(m, "RtAps");