96 lines
2.2 KiB
C++
96 lines
2.2 KiB
C++
/* #define DEBUGTRACE_ENABLED */
|
|
#include "lasp_siggen.h"
|
|
#include "debugtrace.hpp"
|
|
#include "lasp_mathtypes.h"
|
|
#include <cassert>
|
|
#include <type_traits>
|
|
using std::cerr;
|
|
using std::endl;
|
|
using rte = std::runtime_error;
|
|
|
|
inline d level_amp(d level_dB) { return pow(10, level_dB / 20); }
|
|
|
|
using slock = std::scoped_lock<std::recursive_mutex>;
|
|
|
|
vd Siggen::genSignal(const us nframes) {
|
|
|
|
DEBUGTRACE_ENTER;
|
|
slock lck(_mtx);
|
|
|
|
DEBUGTRACE_PRINT(nframes);
|
|
vd signal(nframes, arma::fill::value(_dc_offset));
|
|
|
|
if (!_muted) {
|
|
vd signal_dynamic = _level_linear * genSignalUnscaled(nframes);
|
|
|
|
// Filter signal
|
|
for (auto f : _filters) {
|
|
assert(f.second);
|
|
f.second->filter(signal_dynamic);
|
|
}
|
|
|
|
// Check whether we are running / not for signal interruption.
|
|
bool activated = false;
|
|
if (_interrupt_period_s < 0) {
|
|
activated = true;
|
|
} else {
|
|
if (_interruption_frame_count < _interrupt_period_s*_fs) {
|
|
activated = true;
|
|
}
|
|
_interruption_frame_count += nframes;
|
|
|
|
if (_interruption_frame_count >= 2 * _interrupt_period_s*_fs) {
|
|
_interruption_frame_count = 0;
|
|
}
|
|
}
|
|
|
|
if (activated) {
|
|
signal += signal_dynamic;
|
|
}
|
|
} // end if(!_muted)
|
|
|
|
return signal;
|
|
}
|
|
void Siggen::setInterruptPeriod(const d newPeriod) {
|
|
slock lck(_mtx);
|
|
if (newPeriod == 0) {
|
|
throw rte("Interruption period cannot be 0");
|
|
}
|
|
if (newPeriod < 0) {
|
|
_interrupt_period_s = -1;
|
|
} else {
|
|
_interrupt_period_s = newPeriod;
|
|
}
|
|
}
|
|
void Siggen::setFilter(const std::string &name,
|
|
std::shared_ptr<Filter> filter) {
|
|
DEBUGTRACE_ENTER;
|
|
slock lck(_mtx);
|
|
if (filter) {
|
|
_filters[name] = filter;
|
|
} else if (_filters.find(name) != _filters.end()) {
|
|
_filters.extract(name);
|
|
}
|
|
}
|
|
void Siggen::setDCOffset(const d offset) {
|
|
DEBUGTRACE_ENTER;
|
|
slock lck(_mtx);
|
|
_dc_offset = offset;
|
|
}
|
|
void Siggen::setLevel(const d level, bool dB) {
|
|
DEBUGTRACE_ENTER;
|
|
slock lck(_mtx);
|
|
_level_linear = dB ? level_amp(level) : level;
|
|
}
|
|
void Siggen::reset(const d newFs) {
|
|
DEBUGTRACE_ENTER;
|
|
slock lck(_mtx);
|
|
_fs = newFs;
|
|
for (auto &f : _filters) {
|
|
assert(f.second);
|
|
f.second->reset();
|
|
}
|
|
_interruption_frame_count = 0;
|
|
resetImpl();
|
|
}
|