4ad0f585805092d7750051e58743744d67bdeb03
[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 boost::signals2::signal<void()> Metering::Meter;
35 Glib::StaticMutex  Metering::m_meter_signal_lock;
36
37 boost::signals2::connection
38 Metering::connect (boost::function<void()> f)
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 (f);
44 }
45
46 void
47 Metering::disconnect (boost::signals2::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 PeakMeter::PeakMeter (Session& s, const XMLNode& node)
69         : Processor (s, node)
70 {
71         current_meters = 0;
72 }
73
74 /** Get peaks from @a bufs
75  * Input acceptance is lenient - the first n buffers from @a bufs will
76  * be metered, where n was set by the last call to setup(), excess meters will
77  * be set to 0.
78  */
79 void
80 PeakMeter::run (BufferSet& bufs, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t nframes, bool)
81 {
82         if (!_active && !_pending_active) {
83                 return;
84         }
85
86         const uint32_t n_audio = min(_configured_input.n_audio(), bufs.count().n_audio());
87         const uint32_t n_midi  = min(_configured_input.n_midi(), bufs.count().n_midi());
88
89         uint32_t n = 0;
90
91         // Meter MIDI in to the first n_midi peaks
92         for (uint32_t i = 0; i < n_midi; ++i, ++n) {
93                 float val = 0.0f;
94                 for (MidiBuffer::iterator e = bufs.get_midi(i).begin(); e != bufs.get_midi(i).end(); ++e) {
95                         const Evoral::MIDIEvent<nframes_t> ev(*e, false);
96                         if (ev.is_note_on()) {
97                                 const float this_vel = log(ev.buffer()[2] / 127.0 * (M_E*M_E-M_E) + M_E) - 1.0;
98                                 if (this_vel > val) {
99                                         val = this_vel;
100                                 }
101                         } else {
102                                 val += 1.0 / bufs.get_midi(n).capacity();
103                                 if (val > 1.0) {
104                                         val = 1.0;
105                                 }
106                         }
107                 }
108                 _peak_power[n] = val;
109         }
110
111         // Meter audio in to the rest of the peaks
112         for (uint32_t i = 0; i < n_audio; ++i, ++n) {
113                 _peak_power[n] = compute_peak (bufs.get_audio(i).data(), nframes, _peak_power[n]);
114         }
115
116         // Zero any excess peaks
117         for (uint32_t i = n; i < _peak_power.size(); ++i) {
118                 _peak_power[i] = 0.0f;
119         }
120
121         _active = _pending_active;
122 }
123
124 void
125 PeakMeter::reset ()
126 {
127         for (size_t i = 0; i < _peak_power.size(); ++i) {
128                 _peak_power[i] = 0.0f;
129         }
130 }
131
132 void
133 PeakMeter::reset_max ()
134 {
135         for (size_t i = 0; i < _max_peak_power.size(); ++i) {
136                 _max_peak_power[i] = -INFINITY;
137         }
138 }
139
140 bool
141 PeakMeter::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
142 {
143         out = in;
144         return true;
145 }
146
147 bool
148 PeakMeter::configure_io (ChanCount in, ChanCount out)
149 {
150         if (out != in) { // always 1:1
151                 return false;
152         }
153
154         current_meters = in.n_total ();
155
156         return Processor::configure_io (in, out);
157 }
158
159 void
160 PeakMeter::reflect_inputs (const ChanCount& in)
161 {
162         current_meters = in.n_total ();
163 }
164
165 void
166 PeakMeter::reset_max_channels (const ChanCount& chn)
167 {
168         uint32_t limit = chn.n_total();
169
170         while (_peak_power.size() > limit) {
171                 _peak_power.pop_back();
172                 _visible_peak_power.pop_back();
173                 _max_peak_power.pop_back();
174         }
175
176         while (_peak_power.size() < limit) {
177                 _peak_power.push_back(0);
178                 _visible_peak_power.push_back(minus_infinity());
179                 _max_peak_power.push_back(minus_infinity());
180         }
181
182         assert(_peak_power.size() == limit);
183         assert(_visible_peak_power.size() == limit);
184         assert(_max_peak_power.size() == limit);
185 }
186
187 /** To be driven by the Meter signal from IO.
188  * Caller MUST hold its own processor_lock to prevent reconfiguration
189  * of meter size during this call.
190  */
191
192 void
193 PeakMeter::meter ()
194 {
195         if (!_active) {
196                 return;
197         }
198
199         assert(_visible_peak_power.size() == _peak_power.size());
200
201         const size_t limit = min (_peak_power.size(), (size_t) current_meters);
202
203         for (size_t n = 0; n < limit; ++n) {
204
205                 /* grab peak since last read */
206
207                 float new_peak = _peak_power[n]; /* XXX we should use atomic exchange from here ... */
208                 _peak_power[n] = 0;              /* ... to here */
209
210                 /* compute new visible value using falloff */
211
212                 if (new_peak > 0.0) {
213                         new_peak = fast_coefficient_to_dB (new_peak);
214                 } else {
215                         new_peak = minus_infinity();
216                 }
217
218                 /* update max peak */
219
220                 _max_peak_power[n] = std::max (new_peak, _max_peak_power[n]);
221
222                 if (Config->get_meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
223                         _visible_peak_power[n] = new_peak;
224                 } else {
225                         // do falloff
226                         new_peak = _visible_peak_power[n] - (Config->get_meter_falloff() * 0.01f);
227                         _visible_peak_power[n] = std::max (new_peak, -INFINITY);
228                 }
229         }
230 }
231
232 XMLNode&
233 PeakMeter::state (bool full_state)
234 {
235         XMLNode& node (Processor::state (full_state));
236         node.add_property("type", "meter");
237         return node;
238 }
239
240