Line data Source code
1 : #include "audio/dsp/level_analyzer.h"
2 :
3 : #include <algorithm>
4 : #include <cmath>
5 : #include <cstdint>
6 : #include <cstring>
7 :
8 : namespace Amplitron {
9 :
10 : namespace {
11 48 : inline bool is_invalid_rms(float x) {
12 16 : uint32_t bits;
13 48 : std::memcpy(&bits, &x, sizeof(float));
14 48 : volatile uint32_t vbits = bits; // Bypass -ffast-math optimizations
15 48 : if ((vbits & 0x7F800000) == 0x7F800000) {
16 4 : return true; // NaN or Infinity
17 : }
18 42 : return x < 0.0f;
19 16 : }
20 :
21 33 : inline bool is_invalid_dt(float x) {
22 11 : uint32_t bits;
23 33 : std::memcpy(&bits, &x, sizeof(float));
24 33 : volatile uint32_t vbits = bits; // Bypass -ffast-math optimizations
25 33 : if ((vbits & 0x7F800000) == 0x7F800000) {
26 2 : return true; // NaN or Infinity
27 : }
28 30 : return x <= 0.0f;
29 11 : }
30 : } // namespace
31 :
32 33 : void LevelAnalyzer::update(float input_rms, float output_rms, bool input_clipped,
33 : bool output_clipped, float dt) {
34 47 : if (is_invalid_dt(dt) || is_invalid_rms(input_rms) || is_invalid_rms(output_rms)) {
35 18 : return;
36 : }
37 :
38 : // RMS smoothing
39 15 : smoothed_input_rms_ += (input_rms - smoothed_input_rms_) * 0.22f;
40 15 : smoothed_output_rms_ += (output_rms - smoothed_output_rms_) * 0.22f;
41 :
42 : // Peak hold decay
43 15 : const float peak_decay = 0.45f;
44 15 : input_peak_hold_ = std::max(smoothed_input_rms_, input_peak_hold_ - peak_decay * dt);
45 15 : output_peak_hold_ = std::max(smoothed_output_rms_, output_peak_hold_ - peak_decay * dt);
46 :
47 : // Clip flash indicator decays
48 15 : if (input_clipped) {
49 3 : input_clip_flash_ = 1.0f;
50 1 : }
51 15 : if (output_clipped) {
52 3 : output_clip_flash_ = 1.0f;
53 1 : }
54 :
55 15 : input_clip_flash_ = std::max(0.0f, input_clip_flash_ - dt * 2.0f);
56 15 : output_clip_flash_ = std::max(0.0f, output_clip_flash_ - dt * 2.0f);
57 11 : }
58 :
59 : } // namespace Amplitron
|