2 * Peak metering facilities.
4 * Copyright (C) 2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #ifndef __CALF_VUMETER_H
22 #define __CALF_VUMETER_H
31 /// Measured signal level
33 /// Falloff of signal level (b1 coefficient of a 1-pole filter)
35 /// Clip indicator (set to 1 when |value| >= 1, fading otherwise)
37 /// Falloff of clip indicator (b1 coefficient of a 1-pole filter); set to 1 if no falloff is required (manual reset of clip indicator)
39 /// Amount of samples > 1.f; Clipping occurs if 3 samples are over 0dB
47 clip_falloff
= 0.999f
;
54 level
= reverse
? 1 : 0;
58 /// Set falloff so that the meter falls 20dB in time_20dB seconds, assuming sample rate of sample_rate
59 /// @arg time_20dB time for the meter to move by 20dB (default 300ms if <= 0)
60 void set_falloff(double time_20dB
, double sample_rate
)
64 // 20dB = 10x +/- --> 0.1 = pow(falloff, sample_rate * time_20dB) = exp(sample_rate * ln(falloff))
65 // ln(0.1) = sample_rate * ln(falloff)
66 falloff
= pow(0.1, 1 / (sample_rate
* time_20dB
));
67 clip_falloff
= falloff
;
70 void set_reverse(bool rev
) {
74 /// Copy falloff from another object
75 void copy_falloff(const vumeter
&src
)
77 falloff
= src
.falloff
;
78 clip_falloff
= src
.clip_falloff
;
81 /// Update peak meter based on input signal
82 inline void update(const float *src
, unsigned int len
)
84 update_stereo(src
, NULL
, len
);
86 /// Update peak meter based on louder of two input signals
87 inline void update_stereo(const float *src1
, const float *src2
, unsigned int len
)
90 // Process input samples - to get peak value, take a max of all values in the input signal and "aged" old peak
91 // Clip is set to 1 if any sample is out-of-range, if no clip occurs, the "aged" value is assumed
93 run_sample_loop(src1
, len
);
95 run_sample_loop(src2
, len
);
97 inline void run_sample_loop(const float *src
, unsigned int len
)
99 for (unsigned int i
= 0; i
< len
; i
++)
102 inline void process(const float value
)
104 level
= reverse
? std::min(level
, (float)fabs(value
)) : std::max(level
, (float)fabs(value
));
112 void fall(unsigned int len
) {
113 // "Age" the old level by falloff^length
115 level
/= pow(falloff
, len
);
117 level
*= pow(falloff
, len
);
118 // Same for clip level (using different fade constant)
119 clip
*= pow(clip_falloff
, len
);
120 dsp::sanitize(level
);
123 /// Update clip meter as if update was called with all-zero input signal
124 inline void update_zeros(unsigned int len
)
126 level
*= pow((double)falloff
, (double)len
);
127 clip
*= pow((double)clip_falloff
, (double)len
);
128 dsp::sanitize(level
);