Revert "Revert new meter types (postponed until after 3.3 release)"
[ardour.git] / libs / ardour / kmeterdsp.cc
1 /*
2     Copyright (C) 2008-2011 Fons Adriaensen <fons@linuxaudio.org>
3     Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <math.h>
21 #include "ardour/kmeterdsp.h"
22
23
24 float  Kmeterdsp::_omega;
25
26
27 Kmeterdsp::Kmeterdsp (void) :
28     _z1 (0),
29     _z2 (0),
30     _rms (0),
31     _flag (false)
32 {
33 }
34
35
36 Kmeterdsp::~Kmeterdsp (void)
37 {
38 }
39
40 void Kmeterdsp::init (int fsamp)
41 {
42     _omega = 9.72f / fsamp; // ballistic filter coefficient
43 }
44
45 void Kmeterdsp::process (float *p, int n)
46 {
47     // Called by JACK's process callback.
48     //
49     // p : pointer to sample buffer
50     // n : number of samples to process
51
52     float  s, t, z1, z2;
53
54     // Get filter state.
55     z1 = _z1;
56     z2 = _z2;
57
58     // Process n samples. Find digital peak value for this
59     // period and perform filtering. The second filter is
60     // evaluated only every 4th sample - this is just an
61     // optimisation.
62     t = 0;
63     n /= 4;  // Loop is unrolled by 4.
64     while (n--)
65     {
66         s = *p++;
67         s *= s;
68         if (t < s) t = s;             // Update digital peak.
69         z1 += _omega * (s - z1);      // Update first filter.
70         s = *p++;
71         s *= s;
72         if (t < s) t = s;             // Update digital peak.
73         z1 += _omega * (s - z1);      // Update first filter.
74         s = *p++;
75         s *= s;
76         if (t < s) t = s;             // Update digital peak.
77         z1 += _omega * (s - z1);      // Update first filter.
78         s = *p++;
79         s *= s;
80         if (t < s) t = s;             // Update digital peak.
81         z1 += _omega * (s - z1);      // Update first filter.
82         z2 += 4 * _omega * (z1 - z2); // Update second filter.
83     }
84     t = sqrtf (t);
85
86     // Save filter state. The added constants avoid denormals.
87     _z1 = z1 + 1e-20f;
88     _z2 = z2 + 1e-20f;
89
90     s = sqrtf (2 * z2);
91
92     if (_flag) // Display thread has read the rms value.
93     {
94         _rms  = s;
95         _flag = false;
96     }
97     else
98     {
99         // Adjust RMS value and update maximum since last read().
100         if (s > _rms) _rms = s;
101     }
102 }
103
104 /* Returns highest _rms value since last call */
105 float Kmeterdsp::read ()
106 {
107     float rv= _rms;
108     _flag = true; // Resets _rms in next process().
109     return rv;
110 }
111
112 void Kmeterdsp::reset ()
113 {
114     _z1 = _z2 = _rms = .0f;
115     _flag = false;
116 }
117
118 /* vi:set ts=8 sts=8 sw=4: */