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