ardour
meter.cc
Go to the documentation of this file.
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 <algorithm>
20 #include <cmath>
21 #include <limits>
22 
23 #include "pbd/compose.h"
24 
25 #include "ardour/audio_buffer.h"
26 #include "ardour/buffer_set.h"
27 #include "ardour/dB.h"
28 #include "ardour/meter.h"
29 #include "ardour/midi_buffer.h"
30 #include "ardour/session.h"
33 
34 using namespace std;
35 
36 using namespace ARDOUR;
37 
38 PeakMeter::PeakMeter (Session& s, const std::string& name)
39  : Processor (s, string_compose ("meter-%1", name))
40 {
45  _pending_active = true;
47  _reset_dpm = true;
48  _reset_max = true;
49 }
50 
52 {
53  while (_kmeter.size() > 0) {
54  delete (_kmeter.back());
55  delete (_iec1meter.back());
56  delete (_iec2meter.back());
57  delete (_vumeter.back());
58  _kmeter.pop_back();
59  _iec1meter.pop_back();
60  _iec2meter.pop_back();
61  _vumeter.pop_back();
62  }
63  while (_peak_power.size() > 0) {
64  _peak_buffer.pop_back();
65  _peak_power.pop_back();
66  _max_peak_signal.pop_back();
67  }
68 }
69 
70 
78 void
79 PeakMeter::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, pframes_t nframes, bool)
80 {
81  if (!_active && !_pending_active) {
82  return;
83  }
84  const bool do_reset_max = _reset_max;
85  const bool do_reset_dpm = _reset_dpm;
86  _reset_max = false;
87  _reset_dpm = false;
88 
89  // cerr << "meter " << name() << " runs with " << bufs.available() << " inputs\n";
90 
91  const uint32_t n_audio = min (current_meters.n_audio(), bufs.count().n_audio());
92  const uint32_t n_midi = min (current_meters.n_midi(), bufs.count().n_midi());
93 
94  uint32_t n = 0;
95 
96  const float falloff_dB = Config->get_meter_falloff() * nframes / _session.nominal_frame_rate();
97  const int zoh = _session.nominal_frame_rate() * .021;
98  _bufcnt += nframes;
99 
100  // Meter MIDI in to the first n_midi peaks
101  for (uint32_t i = 0; i < n_midi; ++i, ++n) {
102  float val = 0.0f;
103  const MidiBuffer& buf (bufs.get_midi(i));
104 
105  for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
106  const Evoral::MIDIEvent<framepos_t> ev(*e, false);
107  if (ev.is_note_on()) {
108  const float this_vel = ev.buffer()[2] / 127.0;
109  if (this_vel > val) {
110  val = this_vel;
111  }
112  } else {
113  val += 1.0 / bufs.get_midi(n).capacity();
114  if (val > 1.0) {
115  val = 1.0;
116  }
117  }
118  }
119  if (_peak_power[n] < (1.0 / 512.0)) {
120  _peak_power[n] = 0;
121  } else {
122  /* empirical algorithm WRT to audio falloff times */
123  _peak_power[n] -= sqrtf (_peak_power[n]) * falloff_dB * 0.045f;
124  }
125  _peak_power[n] = max(_peak_power[n], val);
126  _max_peak_signal[n] = 0;
127  }
128 
129  // Meter audio in to the rest of the peaks
130  for (uint32_t i = 0; i < n_audio; ++i, ++n) {
131  if (bufs.get_audio(i).silent()) {
132  ;
133  } else {
134  _peak_buffer[n] = compute_peak (bufs.get_audio(i).data(), nframes, _peak_buffer[n]);
135  _max_peak_signal[n] = std::max(_peak_buffer[n], _max_peak_signal[n]); // todo sync reset
136  }
137 
138  if (do_reset_max) {
139  _max_peak_signal[n] = 0;
140  }
141 
142  if (do_reset_dpm) {
143  _peak_buffer[n] = 0;
144  _peak_power[n] = -std::numeric_limits<float>::infinity();
145  } else {
146  // falloff
147  if (_peak_power[n] > -318.8f) {
148  _peak_power[n] -= falloff_dB;
149  } else {
150  _peak_power[n] = -std::numeric_limits<float>::infinity();
151  }
153  // integration buffer, retain peaks > 49Hz
154  if (_bufcnt > zoh) {
155  _peak_buffer[n] = 0;
156  }
157  }
158 
160  _kmeter[i]->process(bufs.get_audio(i).data(), nframes);
161  }
163  _iec1meter[i]->process(bufs.get_audio(i).data(), nframes);
164  }
166  _iec2meter[i]->process(bufs.get_audio(i).data(), nframes);
167  }
168  if (_meter_type & MeterVU) {
169  _vumeter[i]->process(bufs.get_audio(i).data(), nframes);
170  }
171  }
172 
173  // Zero any excess peaks
174  for (uint32_t i = n; i < _peak_power.size(); ++i) {
175  _peak_power[i] = -std::numeric_limits<float>::infinity();
176  _max_peak_signal[n] = 0;
177  }
178 
179  if (_bufcnt > zoh) {
180  _bufcnt = 0;
181  }
182 
184 }
185 
186 void
188 {
189  if (_active || _pending_active) {
190  _reset_dpm = true;
191  } else {
192  for (size_t i = 0; i < _peak_power.size(); ++i) {
193  _peak_power[i] = -std::numeric_limits<float>::infinity();
194  _peak_buffer[i] = 0;
195  }
196  }
197 
198  // these are handled async just fine.
199  for (size_t n = 0; n < _kmeter.size(); ++n) {
200  _kmeter[n]->reset();
201  _iec1meter[n]->reset();
202  _iec2meter[n]->reset();
203  _vumeter[n]->reset();
204  }
205 }
206 
207 void
209 {
210  if (_active || _pending_active) {
211  _reset_max = true;
212  return;
213  }
214  for (size_t i = 0; i < _max_peak_signal.size(); ++i) {
215  _max_peak_signal[i] = 0;
216  _peak_buffer[i] = 0;
217  }
218 }
219 
220 bool
222 {
223  out = in;
224  return true;
225 }
226 
227 bool
229 {
230  if (out != in) { // always 1:1
231  return false;
232  }
233 
234  current_meters = in;
235 
236  set_max_channels (in);
237 
238  return Processor::configure_io (in, out);
239 }
240 
241 void
243 {
244  reset();
245  current_meters = in;
246  reset_max();
247  // ConfigurationChanged() postponed
248 }
249 
250 void
253 }
254 
255 void
257 {
258  uint32_t const limit = chn.n_total();
259  const size_t n_audio = chn.n_audio();
260 
261  while (_peak_power.size() > limit) {
262  _peak_buffer.pop_back();
263  _peak_power.pop_back();
264  _max_peak_signal.pop_back();
265  }
266 
267  while (_peak_power.size() < limit) {
268  _peak_buffer.push_back(0);
269  _peak_power.push_back(-std::numeric_limits<float>::infinity());
270  _max_peak_signal.push_back(0);
271  }
272 
273  assert(_peak_buffer.size() == limit);
274  assert(_peak_power.size() == limit);
275  assert(_max_peak_signal.size() == limit);
276 
277  /* alloc/free other audio-only meter types. */
278  while (_kmeter.size() > n_audio) {
279  delete (_kmeter.back());
280  delete (_iec1meter.back());
281  delete (_iec2meter.back());
282  delete (_vumeter.back());
283  _kmeter.pop_back();
284  _iec1meter.pop_back();
285  _iec2meter.pop_back();
286  _vumeter.pop_back();
287  }
288  while (_kmeter.size() < n_audio) {
289  _kmeter.push_back(new Kmeterdsp());
290  _iec1meter.push_back(new Iec1ppmdsp());
291  _iec2meter.push_back(new Iec2ppmdsp());
292  _vumeter.push_back(new Vumeterdsp());
293  }
294  assert(_kmeter.size() == n_audio);
295  assert(_iec1meter.size() == n_audio);
296  assert(_iec2meter.size() == n_audio);
297  assert(_vumeter.size() == n_audio);
298 
299  reset();
300  reset_max();
301 }
302 
308 #define CHECKSIZE(MTR) (n < MTR.size() + n_midi && n >= n_midi)
309 
310 float
312  switch (type) {
313  case MeterKrms:
314  case MeterK20:
315  case MeterK14:
316  case MeterK12:
317  {
318  const uint32_t n_midi = current_meters.n_midi();
319  if (CHECKSIZE(_kmeter)) {
320  return accurate_coefficient_to_dB (_kmeter[n - n_midi]->read());
321  }
322  }
323  break;
324  case MeterIEC1DIN:
325  case MeterIEC1NOR:
326  {
327  const uint32_t n_midi = current_meters.n_midi();
328  if (CHECKSIZE(_iec1meter)) {
329  return accurate_coefficient_to_dB (_iec1meter[n - n_midi]->read());
330  }
331  }
332  break;
333  case MeterIEC2BBC:
334  case MeterIEC2EBU:
335  {
336  const uint32_t n_midi = current_meters.n_midi();
337  if (CHECKSIZE(_iec2meter)) {
338  return accurate_coefficient_to_dB (_iec2meter[n - n_midi]->read());
339  }
340  }
341  break;
342  case MeterVU:
343  {
344  const uint32_t n_midi = current_meters.n_midi();
345  if (CHECKSIZE(_vumeter)) {
346  return accurate_coefficient_to_dB (_vumeter[n - n_midi]->read());
347  }
348  }
349  break;
350  case MeterPeak:
351  case MeterPeak0dB:
352  if (n < _peak_power.size()) {
353  return _peak_power[n];
354  }
355  break;
356  case MeterMaxSignal:
357  assert(0);
358  break;
359  default:
360  case MeterMaxPeak:
361  if (n < _max_peak_signal.size()) {
363  }
364  break;
365  }
366  return minus_infinity();
367 }
368 
369 void
371 {
372  if (t == _meter_type) {
373  return;
374  }
375 
376  _meter_type = t;
377 
378  if (t & (MeterKrms | MeterK20 | MeterK14 | MeterK12)) {
379  const size_t n_audio = current_meters.n_audio();
380  for (size_t n = 0; n < n_audio; ++n) {
381  _kmeter[n]->reset();
382  }
383  }
384  if (t & (MeterIEC1DIN | MeterIEC1NOR)) {
385  const size_t n_audio = current_meters.n_audio();
386  for (size_t n = 0; n < n_audio; ++n) {
387  _iec1meter[n]->reset();
388  }
389  }
390  if (t & (MeterIEC2BBC | MeterIEC2EBU)) {
391  const size_t n_audio = current_meters.n_audio();
392  for (size_t n = 0; n < n_audio; ++n) {
393  _iec2meter[n]->reset();
394  }
395  }
396  if (t & MeterVU) {
397  const size_t n_audio = current_meters.n_audio();
398  for (size_t n = 0; n < n_audio; ++n) {
399  _vumeter[n]->reset();
400  }
401  }
402 
403  TypeChanged(t);
404 }
405 
406 XMLNode&
407 PeakMeter::state (bool full_state)
408 {
409  XMLNode& node (Processor::state (full_state));
410  node.add_property("type", "meter");
411  return node;
412 }
std::vector< float > _peak_buffer
Definition: meter.h:97
framecnt_t nominal_frame_rate() const
Definition: session.h:367
ARDOUR::Session & _session
std::vector< Kmeterdsp * > _kmeter
Definition: meter.h:101
void set_max_channels(const ChanCount &)
Definition: meter.cc:256
MidiBuffer & get_midi(size_t i)
Definition: buffer_set.h:107
bool _reset_dpm
Definition: meter.h:93
bool silent() const
Definition: buffer.h:57
bool is_note_on() const
Definition: MIDIEvent.hpp:68
void reflect_inputs(const ChanCount &in)
Definition: meter.cc:242
uint32_t pframes_t
Definition: types.h:61
uint32_t n_audio() const
Definition: chan_count.h:63
tuple f
Definition: signals.py:35
LIBARDOUR_API compute_peak_t compute_peak
Definition: globals.cc:129
Definition: Beats.hpp:239
static void init(int fsamp)
Definition: kmeterdsp.cc:40
PBD::Signal2< void, ChanCount, ChanCount > ConfigurationChanged
Definition: processor.h:113
void reset()
Definition: meter.cc:187
AudioBuffer & get_audio(size_t i)
Definition: buffer_set.h:100
uint32_t n_midi() const
Definition: chan_count.h:66
static float accurate_coefficient_to_dB(float coeff)
Definition: dB.h:38
std::vector< Vumeterdsp * > _vumeter
Definition: meter.h:104
uint32_t n_total() const
Definition: chan_count.h:69
static void init(float fsamp)
Definition: vumeterdsp.cc:87
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
static float minus_infinity(void)
Definition: fastlog.h:44
uint32_t _bufcnt
Definition: meter.h:96
void set_type(MeterType t)
Definition: meter.cc:370
MeterType
Definition: types.h:182
Definition: amp.h:29
MeterType _meter_type
Definition: meter.h:106
bool _reset_max
Definition: meter.h:94
virtual bool configure_io(ChanCount in, ChanCount out)
Definition: processor.cc:246
void run(BufferSet &bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool)
Definition: meter.cc:79
int64_t framepos_t
Definition: types.h:66
static void init(float fsamp)
Definition: iec1ppmdsp.cc:92
bool configure_io(ChanCount in, ChanCount out)
Definition: meter.cc:228
static void init(float fsamp)
Definition: iec2ppmdsp.cc:92
void reset_max()
Definition: meter.cc:208
std::vector< float > _peak_power
Definition: meter.h:98
XMLProperty * add_property(const char *name, const std::string &value)
size_t capacity() const
Definition: buffer.h:51
const char * name
std::vector< Iec2ppmdsp * > _iec2meter
Definition: meter.h:103
Definition: xml++.h:95
XMLNode & state(bool full)
Definition: meter.cc:407
const ChanCount & count() const
Definition: buffer_set.h:87
virtual XMLNode & state(bool full)
Definition: processor.cc:109
float meter_level(uint32_t n, MeterType type)
Definition: meter.cc:311
bool can_support_io_configuration(const ChanCount &in, ChanCount &out)
Definition: meter.cc:221
std::vector< float > _max_peak_signal
Definition: meter.h:99
PBD::Signal1< void, MeterType > TypeChanged
Definition: meter.h:82
const uint8_t * buffer() const
Definition: Event.hpp:135
void emit_configuration_changed()
Definition: meter.cc:251
const Sample * data(framecnt_t offset=0) const
Definition: audio_buffer.h:187
ChanCount current_meters
Definition: meter.h:91
std::vector< Iec1ppmdsp * > _iec1meter
Definition: meter.h:102
#define CHECKSIZE(MTR)
Definition: meter.cc:308
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208