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 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
|
/*
* Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
* (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
*
* This file is part of lsp-dsp-units
* Created on: 03 авг. 2016 г.
*
* lsp-dsp-units 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-dsp-units 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-dsp-units. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef LSP_PLUG_IN_DSP_UNITS_UTIL_CROSSOVER_H_
#define LSP_PLUG_IN_DSP_UNITS_UTIL_CROSSOVER_H_
#include <lsp-plug.in/dsp-units/version.h>
#include <lsp-plug.in/dsp-units/iface/IStateDumper.h>
#include <lsp-plug.in/dsp-units/filters/Filter.h>
#include <lsp-plug.in/dsp-units/filters/Equalizer.h>
namespace lsp
{
/*
The overall schema of signal processing by the crossover for 4 bands
(filters are following in order of the increasing frequency):
INPUT = Input signal passed to the process() method
LPF = Low-pass filter
HPF = High-pass filter
APF = All-pass filter
OUT = Output signal for the particular band passed to the crossover_func_t callback function
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
│INPUT│──┬─►│LPF 0│────►│APF 1│────►│APF 2│────►│OUT 0│
└─────┘ │ └─────┘ └─────┘ └─────┘ └─────┘
│
│
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
└─►│HPF 0│──┬─►│LPF 1│────►│APF 2│────►│OUT 1│
└─────┘ │ └─────┘ └─────┘ └─────┘
│
│
│ ┌─────┐ ┌─────┐ ┌─────┐
└─►│HPF 1│──┬─►│LPF 2│────►│OUT 2│
└─────┘ │ └─────┘ └─────┘
│
│
│ ┌─────┐ ┌─────┐
└─►│HPF 2│────►│OUT 3│
└─────┘ └─────┘
*/
namespace dspu
{
/**
* Crossover callback function for processing band signal
*
* @param object the object that handles callback
* @param subject the subject that is used to handle callback
* @param band number of the band
* @param data the output band signal produced by crossover,
* is valid only until the function returns
* @param first index of the first sample in input buffer
* @param count number of processed samples in the data buffer
*/
typedef void (* crossover_func_t)(void *object, void *subject, size_t band, const float *data, size_t first, size_t count);
/**
* Crossover filter type
*/
enum crossover_mode_t
{
CROSS_MODE_BT, //!< CROSS_MODE_BT bilinear transform
CROSS_MODE_MT //!< CROSS_MODE_MT matched transform
};
/** Crossover, splits signal into bands, calls processing handler (if present)
* and mixes processed bands back after adjusting the post-processing amplification gain
*
*/
class LSP_DSP_UNITS_PUBLIC Crossover
{
private:
Crossover & operator = (const Crossover &);
Crossover(const Crossover &);
protected:
enum xover_type_t
{
FILTER_LPF, // Low-pass filter
FILTER_HPF, // High-pass filter
FILTER_APF // All-pass filter
};
typedef struct split_t
{
Equalizer sLPF; // Lo-pass filter
Filter sHPF; // Hi-pass filter with all-pass filters
size_t nBandId; // Number of split point
size_t nSlope; // Filter slope (0 = off)
float fFreq; // Frequency
crossover_mode_t nMode; // Filter type
} split_t;
typedef struct band_t
{
float fGain; // Output gain of the band
float fStart; // Start frequency of the band
float fEnd; // End frequency of the band
bool bEnabled; // Enabled flag
split_t *pStart; // Pointer to starting split point
split_t *pEnd; // Pointer to ending split point
crossover_func_t pFunc; // Function
void *pObject; // Bound object
void *pSubject; // Bound subject
size_t nId; // Number of the band
} band_t;
enum reconfigure_t
{
R_GAIN = 1 << 0, // We can reconfigure band gain in softer mode
R_SPLIT = 1 << 1, // Need to reconfigure filter order
R_ALL = R_GAIN | R_SPLIT
} reconfigure_t;
protected:
size_t nReconfigure; // Change flag
size_t nSplits; // Number of splits
size_t nBufSize; // Buffer size
size_t nSampleRate; // Sample rate
band_t *vBands; // List of bands
split_t *vSplit; // List of split points
split_t **vPlan; // Split plan
size_t nPlanSize; // Size of plan
float *vLpfBuf; // Buffer for LPF
float *vHpfBuf; // Buffer for HPF
uint8_t *pData; // Unaligned data
protected:
inline filter_type_t select_filter(xover_type_t type, crossover_mode_t mode);
public:
explicit Crossover();
~Crossover();
/** Construct crossover
*
*/
void construct();
/** Destroy crossover
*
*/
void destroy();
/** Initialize crossover
*
* @param bands number of bands
* @param buf_size maximum signal processing buffer size
* @return status of operation
*/
bool init(size_t bands, size_t buf_size);
public:
/**
* Get number of bands
* @return number of bands
*/
inline size_t num_bands() const { return nSplits+1; }
/**
* Get number of split points
* @return number of split points
*/
inline size_t num_splits() const { return nSplits; }
/**
* Get maximum buffer size for one iteration, if the provided
* buffer is greater than max_buffer_size, the signal will be processed
* in more than one iteration.
*
* @return maximum buffer size
*/
inline size_t max_buffer_size() const { return nBufSize; }
/** Set slope of crossover
*
* @param sp split point number
* @param slope slope of crossover filters
*/
void set_slope(size_t sp, size_t slope);
/**
* Get slope of the split point
* @param sp split point number
* @return slope of the split point, 0 means split point is off,
* negative value means invalid index
*/
ssize_t get_slope(size_t sp) const;
/** Set frequency of split point
*
* @param sp split point number
* @param freq split frequency of the split point
*/
void set_frequency(size_t sp, float freq);
/**
* Get split frequency of the split point
* @param sp split point number
* @return split frequency of the split point, negative value
* means invalid index
*/
float get_frequency(size_t sp) const;
/**
* Set filter mode for the split point
* @param sp split point
* @param mode mode for the split point
*/
void set_mode(size_t sp, crossover_mode_t mode);
/**
* Get filter mode of the split point
* @param sp split point
* @param mode mode for the split point or negative value on invalid index
*/
ssize_t get_mode(size_t sp) const;
/**
* Set gain of the specific output band
* @param band band number
* @param gain gain of the band
*/
void set_gain(size_t band, float gain);
/**
* Get gain of the specific output band
* @param band band number
* @return gain of the band, negative value on invalid index
*/
float get_gain(size_t band) const;
/**
* Get start frequency of the band, may call reconfigure()
* @param band band number
* @return start frequency of the band or negative value on invalid index
*/
float get_band_start(size_t band);
/**
* Get end frequency of the band, may call reconfigure()
* @param band band number
* @return end frequency of the band or negative value on invalid index
*/
float get_band_end(size_t band);
/**
* Check that the band is active (always true for band 0), may call reconfigure()
* @param band band number
* @return true if band is active
*/
bool band_active(size_t band);
/**
* Set band signal handler
* @param band band number
* @param func handler function
* @param object object to pass to function
* @param subject subject to pass to function
* @return false if invalid band number has been specified
*/
bool set_handler(size_t band, crossover_func_t func, void *object, void *subject);
/**
* Unset band signal handler
* @param band band number
* @return false if invalid band number has been specified
*/
bool unset_handler(size_t band);
/** Set sample rate, needs reconfiguration
*
* @param sr sample rate to set
*/
void set_sample_rate(size_t sr);
/**
* Get sample rate of the crossover
* @return sample rate
*/
inline size_t get_sample_rate() { return nSampleRate; }
/** Get frequency chart of the crossover band. This method returns frequency chart
* without applied all-pass filters
*
* @param band number of the band
* @param re real part of the frequency chart
* @param im imaginary part of the frequency chart
* @param f frequencies to calculate value
* @param count number of points for the chart
* @return false if invalid band index is specified
*/
bool freq_chart(size_t band, float *re, float *im, const float *f, size_t count);
/** Get frequency chart of the crossover. This method returns frequency chart
* without applied all-pass filters
*
* @param band number of the band
* @param c transfer function (packed complex numbers)
* @param f frequencies to calculate value
* @param count number of points for the chart
* @return false if invalid band index is specified
*/
bool freq_chart(size_t band, float *c, const float *f, size_t count);
/**
* Check that we need to call reconfigure()
* @return true if we need to call reconfigure()
*/
inline bool needs_reconfiguration() const { return nReconfigure != 0; }
/** Reconfigure crossover after parameter update
*
*/
void reconfigure();
/** Process data and issue callbacks, automatically calls reconfigure()
* if the reconfiguration is required
*
* @param in input buffer to process data
* @param samples number of samples to process
*/
void process(const float *in, size_t samples);
/**
* Dump the state
* @param dumper dumper
*/
void dump(IStateDumper *v) const;
};
}
} /* namespace lsp */
#endif /* LSP_PLUG_IN_DSP_UNITS_UTIL_CROSSOVER_H_ */
|