first part of fixing up send/return metering ; make send-controlling faders work...
[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) {
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
116 PeakMeter::PeakMeter (Session& s, const XMLNode& node)
117         : Processor (s, node)
118 {
119 }
120
121 void
122 PeakMeter::reset ()
123 {
124         for (size_t i = 0; i < _peak_power.size(); ++i) {
125                 _peak_power[i] = 0.0f;
126         }
127 }
128
129 void
130 PeakMeter::reset_max ()
131 {
132         for (size_t i = 0; i < _max_peak_power.size(); ++i) {
133                 _max_peak_power[i] = -INFINITY;
134         }
135 }
136
137 bool
138 PeakMeter::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
139 {
140         out = in;
141         return true;
142 }
143
144 bool
145 PeakMeter::configure_io (ChanCount in, ChanCount out)
146 {
147         if (out != in) { // always 1:1
148                 return false;
149         }
150         
151         uint32_t limit = in.n_total();
152         
153         while (_peak_power.size() > limit) {
154                 _peak_power.pop_back();
155                 _visible_peak_power.pop_back();
156                 _max_peak_power.pop_back();
157         }
158
159         while (_peak_power.size() < limit) {
160                 _peak_power.push_back(0);
161                 _visible_peak_power.push_back(minus_infinity());
162                 _max_peak_power.push_back(minus_infinity());
163         }
164
165         assert(_peak_power.size() == limit);
166         assert(_visible_peak_power.size() == limit);
167         assert(_max_peak_power.size() == limit);
168
169         return Processor::configure_io (in, out);
170 }
171
172 /** To be driven by the Meter signal from IO.
173  * Caller MUST hold its own processor_lock to prevent reconfiguration
174  * of meter size during this call.
175  */
176
177 void
178 PeakMeter::meter ()
179 {
180         if (!_active) {
181                 return;
182         }
183
184         assert(_visible_peak_power.size() == _peak_power.size());
185
186         const size_t limit = _peak_power.size();
187
188         for (size_t n = 0; n < limit; ++n) {
189
190                 /* grab peak since last read */
191
192                 float new_peak = _peak_power[n]; /* XXX we should use atomic exchange from here ... */
193                 _peak_power[n] = 0;              /* ... to here */
194
195                 /* compute new visible value using falloff */
196
197                 if (new_peak > 0.0) {
198                         new_peak = coefficient_to_dB (new_peak);
199                 } else {
200                         new_peak = minus_infinity();
201                 }
202                 
203                 /* update max peak */
204                 
205                 _max_peak_power[n] = std::max (new_peak, _max_peak_power[n]);
206                 
207                 if (Config->get_meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
208                         _visible_peak_power[n] = new_peak;
209                 } else {
210                         // do falloff
211                         new_peak = _visible_peak_power[n] - (Config->get_meter_falloff() * 0.01f);
212                         _visible_peak_power[n] = std::max (new_peak, -INFINITY);
213                 }
214         }
215 }
216
217 XMLNode&
218 PeakMeter::state (bool full_state)
219 {
220         XMLNode& node (Processor::state (full_state));
221         node.add_property("type", "meter");
222         return node;
223 }
224
225
226 bool
227 PeakMeter::visible() const
228 {
229         return true;
230 }