fix crash when copy'ing latent plugins
[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 const *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, z1, z2;
53
54     // Get filter state.
55     z1 = _z1 > 50 ? 50 : (_z1 < 0 ? 0 : _z1);
56     z2 = _z2 > 50 ? 50 : (_z2 < 0 ? 0 : _z2);
57
58     // Perform filtering. The second filter is evaluated
59     // only every 4th sample - this is just an optimisation.
60     n /= 4;  // Loop is unrolled by 4.
61     while (n--)
62     {
63         s = *p++;
64         s *= s;
65         z1 += _omega * (s - z1);      // Update first filter.
66         s = *p++;
67         s *= s;
68         z1 += _omega * (s - z1);      // Update first filter.
69         s = *p++;
70         s *= s;
71         z1 += _omega * (s - z1);      // Update first filter.
72         s = *p++;
73         s *= s;
74         z1 += _omega * (s - z1);      // Update first filter.
75         z2 += 4 * _omega * (z1 - z2); // Update second filter.
76     }
77
78     if (isnan(z1)) z1 = 0;
79     if (isnan(z2)) z2 = 0;
80     // Save filter state. The added constants avoid denormals.
81     _z1 = z1 + 1e-20f;
82     _z2 = z2 + 1e-20f;
83
84     s = sqrtf (2.0f * z2);
85
86     if (_flag) // Display thread has read the rms value.
87     {
88         _rms  = s;
89         _flag = false;
90     }
91     else
92     {
93         // Adjust RMS value and update maximum since last read().
94         if (s > _rms) _rms = s;
95     }
96 }
97
98 /* Returns highest _rms value since last call */
99 float Kmeterdsp::read ()
100 {
101     float rv= _rms;
102     _flag = true; // Resets _rms in next process().
103     return rv;
104 }
105
106 void Kmeterdsp::reset ()
107 {
108     _z1 = _z2 = _rms = .0f;
109     _flag = false;
110 }
111
112 /* vi:set ts=8 sts=8 sw=4: */