2 Copyright (C) 2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "ardour/meter.h"
23 #include "ardour/logmeter.h"
24 #include "ardour/rc_configuration.h"
26 #include <gtkmm2ext/utils.h>
27 #include <gtkmm2ext/gui_thread.h>
29 #include "pbd/fastlog.h"
32 #include "canvas/box.h"
33 #include "canvas/meter.h"
35 #include "level_meter.h"
38 using namespace ARDOUR;
40 using namespace Gtkmm2ext;
42 using namespace ArdourSurface;
43 using namespace ArdourCanvas;
45 LevelMeter::LevelMeter (Push2& p, Item* parent, int len, Meter::Orientation o)
49 , _meter_orientation(o)
50 , regular_meter_width (6)
53 , max_peak (minus_infinity())
54 , meter_type (MeterPeak)
55 , visible_meter_type (MeterType(0))
58 , max_visible_meters (0)
60 Config->ParameterChanged.connect (_parameter_connection, invalidator(*this), boost::bind (&LevelMeter::parameter_changed, this, _1), &p2);
62 if (_meter_orientation == Meter::Vertical) {
63 meter_packer = new HBox (this);
65 meter_packer = new VBox (this);
68 meter_packer->set_collapse_on_hide (true);
71 LevelMeter::~LevelMeter ()
73 _configuration_connection.disconnect();
74 _meter_type_connection.disconnect();
75 _parameter_connection.disconnect();
76 for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); i++) {
83 LevelMeter::set_meter (PeakMeter* meter)
85 _configuration_connection.disconnect();
86 _meter_type_connection.disconnect();
91 _meter->ConfigurationChanged.connect (_configuration_connection, invalidator(*this), boost::bind (&LevelMeter::configuration_changed, this, _1, _2), &p2);
92 _meter->TypeChanged.connect (_meter_type_connection, invalidator (*this), boost::bind (&LevelMeter::meter_type_changed, this, _1), &p2);
95 setup_meters (meter_length, regular_meter_width, thin_meter_width);
98 static float meter_lineup_cfg(MeterLineUp lul, float offset) {
100 case MeteringLineUp24:
102 case MeteringLineUp20:
104 case MeteringLineUp18:
106 case MeteringLineUp15:
114 static float meter_lineup(float offset) {
115 return meter_lineup_cfg (MeteringLineUp24, offset);
116 //return meter_lineup_cfg (UIConfiguration::instance().get_meter_line_up_level(), offset);
119 static float vu_standard() {
122 // note - default meter config is +2dB (france)
123 switch (UIConfiguration::instance().get_meter_vu_standard()) {
125 case MeteringVUfrench: // 0VU = -2dBu
127 case MeteringVUamerican: // 0VU = 0dBu
129 case MeteringVUstandard: // 0VU = +4dBu
131 case MeteringVUeight: // 0VU = +8dBu
138 LevelMeter::update_meters ()
140 vector<MeterInfo>::iterator i;
147 uint32_t nmidi = _meter->input_streams().n_midi();
149 for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
151 const float mpeak = _meter->meter_level(n, MeterMaxPeak);
152 if (mpeak > (*i).max_peak) {
153 (*i).max_peak = mpeak;
154 //(*i).meter->set_highlight(mpeak >= UIConfiguration::instance().get_meter_peak());
155 (*i).meter->set_highlight (mpeak >= 2.0);
157 if (mpeak > max_peak) {
162 (*i).meter->set (_meter->meter_level (n, MeterPeak));
164 const float peak = _meter->meter_level (n, meter_type);
165 if (meter_type == MeterPeak) {
166 (*i).meter->set (log_meter (peak));
167 } else if (meter_type == MeterPeak0dB) {
168 (*i).meter->set (log_meter0dB (peak));
169 } else if (meter_type == MeterIEC1NOR) {
170 (*i).meter->set (meter_deflect_nordic (peak + meter_lineup(0)));
171 } else if (meter_type == MeterIEC1DIN) {
172 // (*i).meter->set (meter_deflect_din (peak + meter_lineup_cfg(UIConfiguration::instance().get_meter_line_up_din(), 3.0)));
173 } else if (meter_type == MeterIEC2BBC || meter_type == MeterIEC2EBU) {
174 (*i).meter->set (meter_deflect_ppm (peak + meter_lineup(0)));
175 } else if (meter_type == MeterVU) {
176 (*i).meter->set (meter_deflect_vu (peak + vu_standard() + meter_lineup(0)));
177 } else if (meter_type == MeterK12) {
178 (*i).meter->set (meter_deflect_k (peak, 12), meter_deflect_k(_meter->meter_level(n, MeterPeak), 12));
179 } else if (meter_type == MeterK14) {
180 (*i).meter->set (meter_deflect_k (peak, 14), meter_deflect_k(_meter->meter_level(n, MeterPeak), 14));
181 } else if (meter_type == MeterK20) {
182 (*i).meter->set (meter_deflect_k (peak, 20), meter_deflect_k(_meter->meter_level(n, MeterPeak), 20));
184 (*i).meter->set (log_meter (peak), log_meter(_meter->meter_level(n, MeterPeak)));
193 LevelMeter::parameter_changed (string p)
195 if (p == "meter-hold") {
196 vector<MeterInfo>::iterator i;
199 for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
200 //(*i).meter->set_hold_count ((uint32_t) floor(UIConfiguration::instance().get_meter_hold()));
201 (*i).meter->set_hold_count (20);
204 else if (p == "meter-line-up-level") {
205 setup_meters (meter_length, regular_meter_width, thin_meter_width);
207 else if (p == "meter-style-led") {
208 setup_meters (meter_length, regular_meter_width, thin_meter_width);
210 else if (p == "meter-peak") {
211 vector<MeterInfo>::iterator i;
214 for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
215 (*i).max_peak = minus_infinity();
221 LevelMeter::configuration_changed (ChanCount /*in*/, ChanCount /*out*/)
223 setup_meters (meter_length, regular_meter_width, thin_meter_width);
227 LevelMeter::meter_type_changed (MeterType t)
230 setup_meters (meter_length, regular_meter_width, thin_meter_width);
234 LevelMeter::hide_all_meters ()
236 for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); ++i) {
238 meter_packer->remove ((*i).meter);
246 LevelMeter::set_max_audio_meter_count (uint32_t cnt)
248 if (cnt == max_visible_meters) {
251 max_visible_meters = cnt;
252 setup_meters (meter_length, regular_meter_width, thin_meter_width);
256 LevelMeter::setup_meters (int len, int initial_width, int thin_width)
261 return; /* do it later or never */
264 uint32_t nmidi = _meter->input_streams().n_midi();
265 uint32_t nmeters = _meter->input_streams().n_total();
266 regular_meter_width = initial_width;
267 thin_meter_width = thin_width;
278 width = regular_meter_width;
280 width = thin_meter_width;
283 if ( meters.size() > 0
284 && nmidi == midi_count
285 && nmeters == meter_count
286 && meters[0].width == width
287 && meters[0].length == len
288 && meter_type == visible_meter_type) {
293 printf("Meter redraw: %s %s %s %s %s %s\n",
294 (meters.size() > 0) ? "yes" : "no",
295 (meters.size() > 0 && meters[0].width == width) ? "yes" : "no",
296 (meters.size() > 0 && meters[0].length == len) ? "yes" : "no",
297 (nmeters == meter_count) ? "yes" : "no",
298 (meter_type == visible_meter_type) ? "yes" : "no",
299 !color_changed ? "yes" : "no"
304 while (meters.size() < nmeters) {
305 meters.push_back (MeterInfo());
308 //cerr << "LevelMeter::setup_meters() called color_changed = " << color_changed << " colors: " << endl;//DEBUG
310 for (int32_t n = nmeters-1; nmeters && n >= 0 ; --n) {
315 int styleflags = UIConfiguration::instance().get_meter_style_led() ? 3 : 1;
316 b[0] = UIConfiguration::instance().color ("meter background bottom");
317 b[1] = UIConfiguration::instance().color ("meter background top");
318 b[2] = 0x991122ff; // red highlight gradient Bot
319 b[3] = 0x551111ff; // red highlight gradient Top
320 if ((uint32_t) n < nmidi) {
321 c[0] = UIConfiguration::instance().color ("midi meter color0");
322 c[1] = UIConfiguration::instance().color ("midi meter color1");
323 c[2] = UIConfiguration::instance().color ("midi meter color2");
324 c[3] = UIConfiguration::instance().color ("midi meter color3");
325 c[4] = UIConfiguration::instance().color ("midi meter color4");
326 c[5] = UIConfiguration::instance().color ("midi meter color5");
327 c[6] = UIConfiguration::instance().color ("midi meter color6");
328 c[7] = UIConfiguration::instance().color ("midi meter color7");
329 c[8] = UIConfiguration::instance().color ("midi meter color8");
330 c[9] = UIConfiguration::instance().color ("midi meter color9");
331 stp[0] = 115.0 * 32.0 / 128.0;
332 stp[1] = 115.0 * 64.0 / 128.0;
333 stp[2] = 115.0 * 100.0 / 128.0;
334 stp[3] = 115.0 * 112.0 / 128.0;
336 c[0] = UIConfiguration::instance().color ("meter color0");
337 c[1] = UIConfiguration::instance().color ("meter color1");
338 c[2] = UIConfiguration::instance().color ("meter color2");
339 c[3] = UIConfiguration::instance().color ("meter color3");
340 c[4] = UIConfiguration::instance().color ("meter color4");
341 c[5] = UIConfiguration::instance().color ("meter color5");
342 c[6] = UIConfiguration::instance().color ("meter color6");
343 c[7] = UIConfiguration::instance().color ("meter color7");
344 c[8] = UIConfiguration::instance().color ("meter color8");
345 c[9] = UIConfiguration::instance().color ("meter color9");
347 switch (meter_type) {
349 stp[0] = 115.0 * meter_deflect_k(-40, 20); //-20
350 stp[1] = 115.0 * meter_deflect_k(-20, 20); // 0
351 stp[2] = 115.0 * meter_deflect_k(-18, 20); // +2
352 stp[3] = 115.0 * meter_deflect_k(-16, 20); // +4
353 c[0] = c[1] = 0x008800ff;
354 c[2] = c[3] = 0x00ff00ff;
355 c[4] = c[5] = 0xffff00ff;
356 c[6] = c[7] = 0xffff00ff;
357 c[8] = c[9] = 0xff0000ff;
360 stp[0] = 115.0 * meter_deflect_k(-34, 14); //-20
361 stp[1] = 115.0 * meter_deflect_k(-14, 14); // 0
362 stp[2] = 115.0 * meter_deflect_k(-12, 14); // +2
363 stp[3] = 115.0 * meter_deflect_k(-10, 14); // +4
364 c[0] = c[1] = 0x008800ff;
365 c[2] = c[3] = 0x00ff00ff;
366 c[4] = c[5] = 0xffff00ff;
367 c[6] = c[7] = 0xffff00ff;
368 c[8] = c[9] = 0xff0000ff;
371 stp[0] = 115.0 * meter_deflect_k(-32, 12); //-20
372 stp[1] = 115.0 * meter_deflect_k(-12, 12); // 0
373 stp[2] = 115.0 * meter_deflect_k(-10, 12); // +2
374 stp[3] = 115.0 * meter_deflect_k( -8, 12); // +4
375 c[0] = c[1] = 0x008800ff;
376 c[2] = c[3] = 0x00ff00ff;
377 c[4] = c[5] = 0xffff00ff;
378 c[6] = c[7] = 0xffff00ff;
379 c[8] = c[9] = 0xff0000ff;
382 c[0] = c[1] = c[2] = c[3] = c[4] = c[5] = c[6] = c[7] = c[8] = c[9] =
383 UIConfiguration::instance().color ("meter color BBC");
384 stp[0] = stp[1] = stp[2] = stp[3] = 115.0;
387 stp[0] = 115.0 * meter_deflect_ppm(-24); // ignored
388 stp[1] = 115.0 * meter_deflect_ppm(-18);
389 stp[2] = 115.0 * meter_deflect_ppm( -9);
390 stp[3] = 115.0 * meter_deflect_ppm( 0); // ignored
392 c[6] = c[7] = c[8] = c[9];
395 stp[0] = 115.0 * meter_deflect_nordic(-30); // ignored
396 stp[1] = 115.0 * meter_deflect_nordic(-18);
397 stp[2] = 115.0 * meter_deflect_nordic(-12);
398 stp[3] = 115.0 * meter_deflect_nordic( -9); // ignored
399 c[0] = c[1] = c[2]; // bright-green
400 c[6] = c[7] = c[8] = c[9];
403 stp[0] = 115.0 * meter_deflect_din(-29); // ignored
404 stp[1] = 115.0 * meter_deflect_din(-18);
405 stp[2] = 115.0 * meter_deflect_din(-15); // ignored
406 stp[3] = 115.0 * meter_deflect_din( -9);
407 c[0] = c[2] = c[3] = c[1];
412 stp[0] = 115.0 * meter_deflect_vu(-26); // -6
413 stp[1] = 115.0 * meter_deflect_vu(-23); // -3
414 stp[2] = 115.0 * meter_deflect_vu(-20); // 0
415 stp[3] = 115.0 * meter_deflect_vu(-18); // +2
416 c[0] = c[2] = c[3] = c[4] = c[5] = c[1];
417 c[7] = c[8] = c[9] = c[6];
420 stp[1] = 89.125; // 115.0 * log_meter0dB(-9);
421 stp[2] = 106.375; // 115.0 * log_meter0dB(-3);
422 stp[3] = 115.0; // 115.0 * log_meter0dB(0);
423 switch (UIConfiguration::instance().get_meter_line_up_level()) {
424 case MeteringLineUp24:
425 stp[0] = 115.0 * log_meter0dB(-24);
427 case MeteringLineUp20:
428 stp[0] = 115.0 * log_meter0dB(-20);
431 case MeteringLineUp18:
432 stp[0] = 115.0 * log_meter0dB(-18);
434 case MeteringLineUp15:
435 stp[0] = 115.0 * log_meter0dB(-15);
438 default: // PEAK, RMS
439 stp[1] = 77.5; // 115 * log_meter(-9)
440 stp[2] = 92.5; // 115 * log_meter(-3)
441 stp[3] = 100.0; // 115 * log_meter(0)
442 switch (UIConfiguration::instance().get_meter_line_up_level()) {
443 case MeteringLineUp24:
446 case MeteringLineUp20:
450 case MeteringLineUp18:
453 case MeteringLineUp15:
461 if (meters[n].width != width || meters[n].length != len || meter_type != visible_meter_type || nmidi != midi_count) {
462 bool hl = meters[n].meter ? meters[n].meter->get_highlight() : false;
463 meters[n].packed = false;
464 delete meters[n].meter;
465 meters[n].meter = new Meter (this->canvas(), 32, width, _meter_orientation, len);
466 meters[n].meter->set_highlight(hl);
467 meters[n].width = width;
468 meters[n].length = len;
471 meter_packer->pack_start (meters[n].meter);
472 meters[n].packed = true;
473 if (max_visible_meters == 0 || (uint32_t) n < max_visible_meters + nmidi) {
474 meters[n].meter->show ();
476 meters[n].meter->hide ();
480 visible_meter_type = meter_type;
482 meter_count = nmeters;
486 LevelMeter::set_type(MeterType t)
492 void LevelMeter::clear_meters (bool reset_highlight)
494 for (vector<MeterInfo>::iterator i = meters.begin(); i < meters.end(); i++) {
496 (*i).max_peak = minus_infinity();
498 (*i).meter->set_highlight(false);
500 max_peak = minus_infinity();
503 void LevelMeter::hide_meters ()