1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
|
/*
* Copyright (C) 2021 Linux Studio Plugins Project <https://lsp-plug.in/>
* (C) 2021 Vladimir Sadovnikov <sadko4u@gmail.com>
*
* This file is part of lsp-plugins-profiler
* Created on: 3 авг. 2021 г.
*
* lsp-plugins-profiler is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* lsp-plugins-profiler 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with lsp-plugins-profiler. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef PRIVATE_PLUGINS_PROFILER_H_
#define PRIVATE_PLUGINS_PROFILER_H_
#include <lsp-plug.in/plug-fw/plug.h>
#include <lsp-plug.in/dsp-units/ctl/Bypass.h>
#include <lsp-plug.in/dsp-units/sampling/Sample.h>
#include <lsp-plug.in/dsp-units/util/LatencyDetector.h>
#include <lsp-plug.in/dsp-units/util/Oscillator.h>
#include <lsp-plug.in/dsp-units/util/ResponseTaker.h>
#include <lsp-plug.in/dsp-units/util/SyncChirpProcessor.h>
#include <private/meta/profiler.h>
namespace lsp
{
namespace plugins
{
class profiler: public plug::Module
{
protected:
// Class to handle profiling time series generation task
class PreProcessor: public ipc::ITask
{
private:
profiler *pCore;
public:
explicit PreProcessor(profiler *base);
virtual ~PreProcessor();
public:
virtual status_t run();
};
// Task to handle generation of the convolution result
class Convolver: public ipc::ITask
{
private:
profiler *pCore;
public:
explicit Convolver(profiler *base);
virtual ~Convolver();
public:
virtual status_t run();
};
// Class to handle post processing of the convolution result
class PostProcessor: public ipc::ITask
{
private:
profiler *pCore;
ssize_t nIROffset;
dspu::scp_rtcalc_t enAlgo;
public:
explicit PostProcessor(profiler *base);
virtual ~PostProcessor();
public:
void set_ir_offset(ssize_t ir_offset);
inline ssize_t get_ir_offset() const { return nIROffset; }
void set_rt_algo(dspu::scp_rtcalc_t algo);
virtual status_t run();
};
// Class to handle saving of the convolution result
class Saver: public ipc::ITask
{
private:
profiler *pCore;
ssize_t nIROffset;
char sFile[PATH_MAX]; // The name of file for saving
public:
explicit Saver(profiler *base);
virtual ~Saver();
public:
void set_file_name(const char *fname);
void set_ir_offset(ssize_t ir_offset);
inline ssize_t get_ir_offset() const { return nIROffset; }
bool is_file_set() const;
virtual status_t run();
};
// Object state descriptor
enum state_t
{
IDLE, // Realtime: doing nothing, awaiting for command
CALIBRATION, // Realtime: callibrating device
LATENCYDETECTION, // Realtime: detecting loopback latency
PREPROCESSING, // Offline: PreProcessor task
WAIT, // Realtime: waiting for signal fall-off
RECORDING, // Realtime: recording response
CONVOLVING, // Offline: Convolver task
POSTPROCESSING, // Offline: PostProcessor task
SAVING // Offline: Saver task
};
enum triggers_t
{
T_CHANGE = 1 << 0, // Change of any following trigger below:
T_CALIBRATION = 1 << 1, // Calibration switch is pressed on
T_SKIP_LATENCY_DETECT = 1 << 2, // Latency detection switch is pressed on
T_POSTPROCESS = 1 << 3, // Post-process switch is pressed on
T_POSTPROCESS_STATE = 1 << 4, // Current post-process switch state
T_LAT_TRIGGER = 1 << 5, // Latency measurement trigger was pressed
T_LAT_TRIGGER_STATE = 1 << 6, // Latency measurement trigger state
T_LIN_TRIGGER = 1 << 7, // Linear measurement trigger is pressed
T_LIN_TRIGGER_STATE = 1 << 8, // Linear measurement trigger state
T_FEEDBACK = 1 << 9 // feedback break switch is pressed on
};
typedef struct postproc_t
{
float fReverbTime; // Reverberation time [seconds]
size_t nReverbTime; // Reverberation time [samples]
float fCorrCoeff; // Energy decay correlation coefficient
float fIntgLimit; // IR intgration limit [seconds]
bool bRTAccuray; // If true, dynamic range and bacjground noise are optimal for RT accuracy.
} posproc_t;
typedef struct channel_t
{
dspu::Bypass sBypass;
dspu::LatencyDetector sLatencyDetector; // For latency assessment
dspu::ResponseTaker sResponseTaker; // To take response of system after Synch Chirp stimulation
size_t nLatency; // Store latency value
bool bLatencyMeasured; // If true, a latency measurement was performed
bool bLCycleComplete; // If true, a latency measurement cycle was finished
bool bRCycleComplete; // If true, a chirp response recording cycle was finished.
postproc_t sPostProc; // Holds IR postproc info.
float *vBuffer; // Auxiliary processing buffer
float *vIn; // Input buffer binding
float *vOut; // Output buffer binding
plug::IPort *pIn;
plug::IPort *pOut;
plug::IPort *pLevelMeter; // dB Input Level Meter
plug::IPort *pLatencyScreen; // Little screen displaying latency value
plug::IPort *pRTScreen; // Little screen displaying RT value
plug::IPort *pRTAccuracyLed; // Led to show whether the RT measurement can be considered accurate
plug::IPort *pILScreen; // Little screen displaying IL (integration limit) value
plug::IPort *pRScreen; // Little screen displaying R (RT regression line correlation coefficient) value
plug::IPort *pResultMesh; // Mesh for result plot
} channel_t;
typedef struct response_t
{
dspu::Sample **vResponses;
size_t *vOffsets;
uint8_t *pData;
} response_t;
typedef struct save_t
{
status_codes enSaveStatus;
float fSavePercent;
} save_t;
protected:
size_t nChannels;
channel_t *vChannels;
response_t sResponseData;
save_t sSaveData;
state_t nState; // Object State
dspu::Oscillator sCalOscillator; // For calibration
dspu::SyncChirpProcessor sSyncChirpProcessor; // To handle Synch Chirp profiling signal and related operations
ipc::IExecutor *pExecutor; // Executor Service
PreProcessor *pPreProcessor; // Pre Processor Task
Convolver *pConvolver; // Convolver Task
PostProcessor *pPostProcessor; // Post Processor Task
Saver *pSaver; // Saver Task
size_t nSampleRate; // Sample Rate
float fLtAmplitude; // Amplitude factor for Latency Detection chirp
ssize_t nWaitCounter; // Count the samples for wait state
bool bDoLatencyOnly; // If true, only latency is measured
float fScpDurationPrevious; // Store Sync Chirp Duration Setting between calls to update_settings()
bool bIRMeasured; // If true, an IR measurement was performed and post processed
size_t nSaveMode; // Hold save mode enumeration index
size_t nTriggers; // Set of triggers controlled by triggers_t
float *vTempBuffer; // Additional auxiliary buffer for processing
float *vDisplayAbscissa; // Buffer for display. Abscissa data
float *vDisplayOrdinate; // Buffer for display. Ordinate data
uint8_t *pData;
plug::IPort *pBypass;
plug::IPort *pStateLEDs; // State LEDs
plug::IPort *pCalFrequency; // Calibration wave frequency
plug::IPort *pCalAmplitude; // Calibration wave amplitude
plug::IPort *pCalSwitch; // Calibration wave switch
plug::IPort *pFeedback; // Switch to open feedback loop
plug::IPort *pLdMaxLatency; // Latency Detector Max expected latency
plug::IPort *pLdPeakThs; // Latency Detector Peak Threshold
plug::IPort *pLdAbsThs; // Latency Detector Absolute Threshold
plug::IPort *pLdEnableSwitch; // Switch to enable LATENCYDETECTION phase in measurement (if possible)
plug::IPort *pLatTrigger; // Trigger for a latency measurement
plug::IPort *pDuration; // Profiling Sync Chirp Duration
plug::IPort *pActualDuration; // Actual Sync Chirp Duration after optimisation
plug::IPort *pLinTrigger; // Trigger for linear system measurement
plug::IPort *pIROffset; // Offset of the measured convolution result, for plot and export
plug::IPort *pRTAlgoSelector; // Selector for RT calculation algorithm
plug::IPort *pPostTrigger; // Trigger for post processing
plug::IPort *pSaveModeSelector; // Selector for Save Mode
plug::IPort *pIRFileName; // File name for IR file
plug::IPort *pIRSaveCmd; // Command to save IR file
plug::IPort *pIRSaveStatus; // IR file saving status
plug::IPort *pIRSavePercent; // IR file saving percent
protected:
static dspu::scp_rtcalc_t get_rt_algorithm(size_t algorithm);
void update_pre_processing_info();
void commit_state_change();
void reset_tasks();
bool update_post_processing_info();
void update_saving_info();
void process_buffer(size_t to_do);
public:
explicit profiler(const meta::plugin_t *metadata, size_t channels);
virtual ~profiler();
virtual void init(plug::IWrapper *wrapper, plug::IPort **ports);
virtual void destroy();
public:
virtual void update_settings();
virtual void update_sample_rate(long sr);
virtual void process(size_t samples);
virtual void dump(dspu::IStateDumper *v) const;
};
} // namespace plugins
} // namespace lsp
#endif /* PRIVATE_PLUGINS_PROFILER_H_ */
|