fix clicking when processors become active/inactive; reduce crazy 2.5sec delay for...
[ardour.git] / libs / ardour / meter.cc
1 /*
2     Copyright (C) 2006 Paul Davis 
3     
4     This program is free software; you can redistribute it and/or modify it
5     under the terms of the GNU General Public License as published by the Free
6     Software Foundation; either version 2 of the License, or (at your option)
7     any later version.
8     
9     This program is distributed in the hope that it will be useful, but WITHOUT
10     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12     for more details.
13     
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include "ardour/meter.h"
20 #include <algorithm>
21 #include <cmath>
22 #include "ardour/buffer_set.h"
23 #include "ardour/peak.h"
24 #include "ardour/dB.h"
25 #include "ardour/session.h"
26 #include "ardour/midi_buffer.h"
27 #include "ardour/audio_buffer.h"
28 #include "ardour/runtime_functions.h"
29
30 using namespace std;
31
32 using namespace ARDOUR;
33
34 sigc::signal<void> Metering::Meter;
35 Glib::StaticMutex  Metering::m_meter_signal_lock;
36
37 sigc::connection
38 Metering::connect (sigc::slot<void> the_slot)
39 {
40         // SignalProcessor::Meter is emitted from another thread so the
41         // Meter signal must be protected.
42         Glib::Mutex::Lock guard (m_meter_signal_lock);
43         return Meter.connect (the_slot);
44 }
45
46 void
47 Metering::disconnect (sigc::connection& c)
48 {
49         Glib::Mutex::Lock guard (m_meter_signal_lock);
50         c.disconnect ();
51 }
52
53 /**
54     Update the meters.
55
56     The meter signal lock is taken to prevent modification of the 
57     Meter signal while updating the meters, taking the meter signal
58     lock prior to taking the io_lock ensures that all IO will remain 
59     valid while metering.
60 */   
61 void
62 Metering::update_meters()
63 {
64         Glib::Mutex::Lock guard (m_meter_signal_lock);
65         Meter(); /* EMIT SIGNAL */
66 }
67
68 /** Get peaks from @a bufs
69  * Input acceptance is lenient - the first n buffers from @a bufs will
70  * be metered, where n was set by the last call to setup(), excess meters will
71  * be set to 0.
72  */
73 void
74 PeakMeter::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
75 {
76         if (!_active && !_pending_active) {
77                 return;
78         }
79
80         const uint32_t n_audio = min(_configured_input.n_audio(), bufs.count().n_audio());
81         const uint32_t n_midi  = min(_configured_input.n_midi(), bufs.count().n_midi());
82         
83         uint32_t n = 0;
84         
85         // Meter MIDI in to the first n_midi peaks
86         for (uint32_t i = 0; i < n_midi; ++i, ++n) {
87                 float val = 0.0f;
88                 for (MidiBuffer::iterator e = bufs.get_midi(i).begin(); e != bufs.get_midi(i).end(); ++e) {
89                         const Evoral::MIDIEvent<nframes_t> ev(*e, false);
90                         if (ev.is_note_on()) {
91                                 const float this_vel = log(ev.buffer()[2] / 127.0 * (M_E*M_E-M_E) + M_E) - 1.0;
92                                 if (this_vel > val) {
93                                         val = this_vel;
94                                 }
95                         } else {
96                                 val += 1.0 / bufs.get_midi(n).capacity();
97                                 if (val > 1.0) {
98                                         val = 1.0;
99                                 }
100                         }
101                 }
102                 _peak_power[n] = val;
103         }
104
105         // Meter audio in to the rest of the peaks
106         for (uint32_t i = 0; i < n_audio; ++i, ++n) {
107                 _peak_power[n] = compute_peak (bufs.get_audio(i).data(), nframes, _peak_power[n]); 
108         }
109
110         // Zero any excess peaks
111         for (uint32_t i = n; i < _peak_power.size(); ++i) {
112                 _peak_power[i] = 0.0f;
113         }
114
115         _active = _pending_active;
116 }
117
118 PeakMeter::PeakMeter (Session& s, const XMLNode& node)
119         : Processor (s, node)
120 {
121 }
122
123 void
124 PeakMeter::reset ()
125 {
126         for (size_t i = 0; i < _peak_power.size(); ++i) {
127                 _peak_power[i] = 0.0f;
128         }
129 }
130
131 void
132 PeakMeter::reset_max ()
133 {
134         for (size_t i = 0; i < _max_peak_power.size(); ++i) {
135                 _max_peak_power[i] = -INFINITY;
136         }
137 }
138
139 bool
140 PeakMeter::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
141 {
142         out = in;
143         return true;
144 }
145
146 bool
147 PeakMeter::configure_io (ChanCount in, ChanCount out)
148 {
149         if (out != in) { // always 1:1
150                 return false;
151         }
152         
153         uint32_t limit = in.n_total();
154         
155         while (_peak_power.size() > limit) {
156                 _peak_power.pop_back();
157                 _visible_peak_power.pop_back();
158                 _max_peak_power.pop_back();
159         }
160
161         while (_peak_power.size() < limit) {
162                 _peak_power.push_back(0);
163                 _visible_peak_power.push_back(minus_infinity());
164                 _max_peak_power.push_back(minus_infinity());
165         }
166
167         assert(_peak_power.size() == limit);
168         assert(_visible_peak_power.size() == limit);
169         assert(_max_peak_power.size() == limit);
170
171         return Processor::configure_io (in, out);
172 }
173
174 /** To be driven by the Meter signal from IO.
175  * Caller MUST hold its own processor_lock to prevent reconfiguration
176  * of meter size during this call.
177  */
178
179 void
180 PeakMeter::meter ()
181 {
182         if (!_active) {
183                 return;
184         }
185
186         assert(_visible_peak_power.size() == _peak_power.size());
187
188         const size_t limit = _peak_power.size();
189
190         for (size_t n = 0; n < limit; ++n) {
191
192                 /* grab peak since last read */
193
194                 float new_peak = _peak_power[n]; /* XXX we should use atomic exchange from here ... */
195                 _peak_power[n] = 0;              /* ... to here */
196
197                 /* compute new visible value using falloff */
198
199                 if (new_peak > 0.0) {
200                         new_peak = coefficient_to_dB (new_peak);
201                 } else {
202                         new_peak = minus_infinity();
203                 }
204                 
205                 /* update max peak */
206                 
207                 _max_peak_power[n] = std::max (new_peak, _max_peak_power[n]);
208                 
209                 if (Config->get_meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
210                         _visible_peak_power[n] = new_peak;
211                 } else {
212                         // do falloff
213                         new_peak = _visible_peak_power[n] - (Config->get_meter_falloff() * 0.01f);
214                         _visible_peak_power[n] = std::max (new_peak, -INFINITY);
215                 }
216         }
217 }
218
219 XMLNode&
220 PeakMeter::state (bool full_state)
221 {
222         XMLNode& node (Processor::state (full_state));
223         node.add_property("type", "meter");
224         return node;
225 }
226
227
228 bool
229 PeakMeter::visible() const
230 {
231         return true;
232 }