Only show user-presets in favorite sidebar
[ardour.git] / libs / ardour / monitor_processor.cc
1 /*
2     Copyright (C) 2010 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #include "pbd/error.h"
21 #include "pbd/xml++.h"
22
23 #include "ardour/amp.h"
24 #include "ardour/debug.h"
25 #include "ardour/audio_buffer.h"
26 #include "ardour/monitor_processor.h"
27 #include "ardour/session.h"
28
29 #include "pbd/i18n.h"
30
31 using namespace ARDOUR;
32 using namespace PBD;
33 using namespace std;
34
35 /* specialize for bool because of set_value() semantics */
36
37 namespace ARDOUR {
38         template<> void MPControl<bool>::set_value (double v, PBD::Controllable::GroupControlDisposition gcd) {
39                 bool newval = fabs (v) >= 0.5;
40                 if (newval != _value) {
41                         _value = newval;
42                         Changed (true, gcd); /* EMIT SIGNAL */
43                 }
44         }
45 }
46
47 MonitorProcessor::MonitorProcessor (Session& s)
48         : Processor (s, X_("MonitorOut"))
49         , solo_cnt (0)
50         , _monitor_active (false)
51
52         , _dim_all_ptr (new MPControl<bool> (false, _("monitor dim"), Controllable::Toggle))
53         , _cut_all_ptr (new MPControl<bool> (false, _("monitor cut"), Controllable::Toggle))
54         , _mono_ptr (new MPControl<bool> (false, _("monitor mono"), Controllable::Toggle))
55         , _dim_level_ptr (new MPControl<volatile gain_t>
56                           /* default is -12dB, range is -20dB to 0dB */
57                           (dB_to_coefficient(-12.0), _("monitor dim level"), Controllable::Flag (0),
58                            dB_to_coefficient(-20.0), dB_to_coefficient (0.0)))
59         , _solo_boost_level_ptr (new MPControl<volatile gain_t>
60                                  /* default is 0dB, range is 0dB to +20dB */
61                                  (dB_to_coefficient(0.0), _("monitor solo boost level"), Controllable::Flag (0),
62                                   dB_to_coefficient(0.0), dB_to_coefficient(10.0)))
63         , _dim_all_control (_dim_all_ptr)
64         , _cut_all_control (_cut_all_ptr)
65         , _mono_control (_mono_ptr)
66         , _dim_level_control (_dim_level_ptr)
67         , _solo_boost_level_control (_solo_boost_level_ptr)
68
69         , _dim_all (*_dim_all_ptr)
70         , _cut_all (*_cut_all_ptr)
71         , _mono (*_mono_ptr)
72         , _dim_level (*_dim_level_ptr)
73         , _solo_boost_level (*_solo_boost_level_ptr)
74
75 {
76 }
77
78 MonitorProcessor::~MonitorProcessor ()
79 {
80         allocate_channels (0);
81 }
82
83 void
84 MonitorProcessor::allocate_channels (uint32_t size)
85 {
86         while (_channels.size() > size) {
87                 if (_channels.back()->soloed) {
88                         if (solo_cnt > 0) {
89                                 --solo_cnt;
90                         }
91                 }
92                 ChannelRecord* cr = _channels.back();
93                 _channels.pop_back();
94                 delete cr;
95         }
96
97         uint32_t n = _channels.size() + 1;
98
99         while (_channels.size() < size) {
100                 _channels.push_back (new ChannelRecord (n));
101         }
102 }
103
104 int
105 MonitorProcessor::set_state (const XMLNode& node, int version)
106 {
107         int ret = Processor::set_state (node, version);
108
109         if (ret != 0) {
110                 return ret;
111         }
112
113         std::string type_name;
114         if (!node.get_property (X_("type"), type_name)) {
115                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor XML settings have no type information"))
116                       << endmsg;
117                 return -1;
118         }
119
120         if (type_name != X_("monitor")) {
121                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor given unknown XML settings"))
122                       << endmsg;
123                 return -1;
124         }
125
126         uint32_t channels = 0;
127         if (!node.get_property (X_("channels"), channels)) {
128                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor XML settings are missing a channel cnt"))
129                       << endmsg;
130                 return -1;
131         }
132
133         allocate_channels (channels);
134
135         // need to check that these conversions are working as expected
136         gain_t val;
137         if (node.get_property (X_("dim-level"), val)) {
138                 _dim_level = val;
139         }
140
141         if (node.get_property (X_("solo-boost-level"), val)) {
142                 _solo_boost_level = val;
143         }
144
145         bool bool_val;
146         if (node.get_property (X_("cut-all"), bool_val)) {
147                 _cut_all = bool_val;
148         }
149
150         if (node.get_property (X_("dim-all"), bool_val)) {
151                 _dim_all = bool_val;
152         }
153
154         if (node.get_property (X_("mono"), bool_val)) {
155                 _mono = bool_val;
156         }
157
158         for (XMLNodeList::const_iterator i = node.children().begin(); i != node.children().end(); ++i) {
159
160                 if ((*i)->name() == X_("Channel")) {
161
162                         uint32_t chn;
163                         if (!(*i)->get_property (X_("id"), chn)) {
164                                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor XML settings are missing an ID"))
165                                       << endmsg;
166                                 return -1;
167                         }
168
169                         if (chn >= _channels.size()) {
170                                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor XML settings has an illegal channel count"))
171                                       << endmsg;
172                                 return -1;
173                         }
174                         ChannelRecord& cr (*_channels[chn]);
175
176                         bool gain_coeff_zero;
177                         if ((*i)->get_property ("cut", gain_coeff_zero)) {
178                                 if (gain_coeff_zero) {
179                                         cr.cut = GAIN_COEFF_ZERO;
180                                 } else {
181                                         cr.cut = GAIN_COEFF_UNITY;
182                                 }
183                         }
184
185                         bool dim;
186                         if ((*i)->get_property ("dim", dim)) {
187                                 cr.dim = dim;
188                         }
189
190                         bool invert_polarity;
191                         if ((*i)->get_property ("invert", invert_polarity)) {
192                                 if (invert_polarity) {
193                                         cr.polarity = -1.0f;
194                                 } else {
195                                         cr.polarity = 1.0f;
196                                 }
197                         }
198
199                         bool soloed;
200                         if ((*i)->get_property ("solo", soloed)) {
201                                 cr.soloed = soloed;
202                         }
203                 }
204         }
205
206         /* reset solo cnt */
207
208         solo_cnt = 0;
209
210         for (vector<ChannelRecord*>::const_iterator x = _channels.begin(); x != _channels.end(); ++x) {
211                 if ((*x)->soloed) {
212                         solo_cnt++;
213                 }
214         }
215
216         update_monitor_state ();
217         return 0;
218 }
219
220 XMLNode&
221 MonitorProcessor::state ()
222 {
223         XMLNode& node(Processor::state ());
224
225         /* this replaces any existing "type" property */
226
227         node.set_property (X_("type"), X_("monitor"));
228
229         node.set_property (X_ ("dim-level"), (float)_dim_level.val ());
230         node.set_property (X_ ("solo-boost-level"), (float)_solo_boost_level.val ());
231
232         node.set_property (X_("cut-all"), _cut_all.val());
233         node.set_property (X_("dim-all"), _dim_all.val());
234         node.set_property (X_("mono"), _mono.val());
235
236         node.set_property (X_("channels"), (uint32_t)_channels.size ());
237
238         XMLNode* chn_node;
239         uint32_t chn = 0;
240
241         for (vector<ChannelRecord*>::const_iterator x = _channels.begin (); x != _channels.end ();
242              ++x, ++chn) {
243                 chn_node = new XMLNode (X_("Channel"));
244
245                 chn_node->set_property ("id", chn);
246
247                 // implicitly cast these to bool
248                 chn_node->set_property (X_("cut"), (*x)->cut != GAIN_COEFF_UNITY);
249                 chn_node->set_property (X_("invert"), (*x)->polarity != GAIN_COEFF_UNITY);
250                 chn_node->set_property (X_("dim"), (*x)->dim == true);
251                 chn_node->set_property (X_("solo"), (*x)->soloed == true);
252
253                 node.add_child_nocopy (*chn_node);
254         }
255
256         return node;
257 }
258
259 void
260 MonitorProcessor::run (BufferSet& bufs, samplepos_t /*start_sample*/, samplepos_t /*end_sample*/, double /*speed*/, pframes_t nframes, bool /*result_required*/)
261 {
262         uint32_t chn = 0;
263         gain_t target_gain;
264         gain_t dim_level_this_time = _dim_level;
265         gain_t global_cut = (_cut_all ? GAIN_COEFF_ZERO : GAIN_COEFF_UNITY);
266         gain_t global_dim = (_dim_all ? dim_level_this_time : GAIN_COEFF_UNITY);
267         gain_t solo_boost;
268
269         if (_session.listening() || _session.soloing()) {
270                 solo_boost = _solo_boost_level;
271         } else {
272                 solo_boost = GAIN_COEFF_UNITY;
273         }
274
275         for (BufferSet::audio_iterator b = bufs.audio_begin(); b != bufs.audio_end(); ++b) {
276
277                 /* don't double-scale by both track dim and global dim coefficients */
278
279                 gain_t dim_level = (global_dim == GAIN_COEFF_UNITY ? (_channels[chn]->dim ? dim_level_this_time : GAIN_COEFF_UNITY) : GAIN_COEFF_UNITY);
280
281                 if (_channels[chn]->soloed) {
282                         target_gain = _channels[chn]->polarity * _channels[chn]->cut * dim_level * global_cut * global_dim * solo_boost;
283                 } else {
284                         if (solo_cnt == 0) {
285                                 target_gain = _channels[chn]->polarity * _channels[chn]->cut * dim_level * global_cut * global_dim * solo_boost;
286                         } else {
287                                 target_gain = GAIN_COEFF_ZERO;
288                         }
289                 }
290
291                 if (target_gain != _channels[chn]->current_gain || target_gain != GAIN_COEFF_UNITY) {
292
293                         _channels[chn]->current_gain = Amp::apply_gain (*b, _session.nominal_sample_rate(), nframes, _channels[chn]->current_gain, target_gain);
294                 }
295
296                 ++chn;
297         }
298
299         if (_mono) {
300                 DEBUG_TRACE (DEBUG::Monitor, "mono-izing\n");
301
302                 /* chn is now the number of channels, use as a scaling factor when mixing
303                  */
304                 gain_t scale = 1.f / (float)chn;
305                 BufferSet::audio_iterator b = bufs.audio_begin();
306                 AudioBuffer& ab (*b);
307                 Sample* buf = ab.data();
308
309                 /* scale the first channel */
310
311                 for (pframes_t n = 0; n < nframes; ++n) {
312                         buf[n] *= scale;
313                 }
314
315                 /* add every other channel into the first channel's buffer */
316
317                 ++b;
318                 for (; b != bufs.audio_end(); ++b) {
319                         AudioBuffer& ob (*b);
320                         Sample* obuf = ob.data ();
321                         for (pframes_t n = 0; n < nframes; ++n) {
322                                 buf[n] += obuf[n] * scale;
323                         }
324                 }
325
326                 /* copy the first channel to every other channel's buffer */
327
328                 b = bufs.audio_begin();
329                 ++b;
330                 for (; b != bufs.audio_end(); ++b) {
331                         AudioBuffer& ob (*b);
332                         Sample* obuf = ob.data ();
333                         memcpy (obuf, buf, sizeof (Sample) * nframes);
334                 }
335         }
336 }
337
338 bool
339 MonitorProcessor::configure_io (ChanCount in, ChanCount out)
340 {
341         allocate_channels (in.n_audio());
342         return Processor::configure_io (in, out);
343 }
344
345 bool
346 MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out)
347 {
348         out = in;
349         return true;
350 }
351
352 void
353 MonitorProcessor::set_polarity (uint32_t chn, bool invert)
354 {
355         if (invert) {
356                 _channels[chn]->polarity = -1.0f;
357         } else {
358                 _channels[chn]->polarity = 1.0f;
359         }
360         update_monitor_state ();
361 }
362
363 void
364 MonitorProcessor::set_dim (uint32_t chn, bool yn)
365 {
366         _channels[chn]->dim = yn;
367         update_monitor_state ();
368 }
369
370 void
371 MonitorProcessor::set_cut (uint32_t chn, bool yn)
372 {
373         if (yn) {
374                 _channels[chn]->cut = GAIN_COEFF_ZERO;
375         } else {
376                 _channels[chn]->cut = GAIN_COEFF_UNITY;
377         }
378         update_monitor_state ();
379 }
380
381 void
382 MonitorProcessor::set_solo (uint32_t chn, bool solo)
383 {
384         if (solo != _channels[chn]->soloed) {
385                 _channels[chn]->soloed = solo;
386
387                 if (solo) {
388                         solo_cnt++;
389                 } else {
390                         if (solo_cnt > 0) {
391                                 solo_cnt--;
392                         }
393                 }
394         }
395         update_monitor_state ();
396 }
397
398 void
399 MonitorProcessor::set_mono (bool yn)
400 {
401         _mono = yn;
402         update_monitor_state ();
403 }
404
405 void
406 MonitorProcessor::set_cut_all (bool yn)
407 {
408         _cut_all = yn;
409         update_monitor_state ();
410 }
411
412 void
413 MonitorProcessor::set_dim_all (bool yn)
414 {
415         _dim_all = yn;
416         update_monitor_state ();
417 }
418
419 bool
420 MonitorProcessor::display_to_user () const
421 {
422         return false;
423 }
424
425 bool
426 MonitorProcessor::soloed (uint32_t chn) const
427 {
428         return _channels[chn]->soloed;
429 }
430
431
432 bool
433 MonitorProcessor::inverted (uint32_t chn) const
434 {
435         return _channels[chn]->polarity < 0.0f;
436 }
437
438
439 bool
440 MonitorProcessor::cut (uint32_t chn) const
441 {
442         return _channels[chn]->cut == GAIN_COEFF_ZERO;
443 }
444
445 bool
446 MonitorProcessor::dimmed (uint32_t chn) const
447 {
448         return _channels[chn]->dim;
449 }
450
451 bool
452 MonitorProcessor::mono () const
453 {
454         return _mono;
455 }
456
457 bool
458 MonitorProcessor::dim_all () const
459 {
460         return _dim_all;
461 }
462
463 bool
464 MonitorProcessor::cut_all () const
465 {
466         return _cut_all;
467 }
468
469 void
470 MonitorProcessor::update_monitor_state ()
471 {
472         bool en = false;
473
474         if (_cut_all || _dim_all || _mono) {
475                 en = true;
476         }
477
478         const uint32_t nchans = _channels.size();
479         for (uint32_t i = 0; i < nchans && !en; ++i) {
480                 if (cut (i) || dimmed (i) || soloed (i) || inverted (i)) {
481                         en = true;
482                         break;
483                 }
484         }
485
486         if (_monitor_active != en) {
487                 _monitor_active = en;
488                 _session.MonitorChanged();
489         }
490 }
491
492 boost::shared_ptr<Controllable>
493 MonitorProcessor::channel_cut_control (uint32_t chn) const
494 {
495         if (chn < _channels.size()) {
496                 return _channels[chn]->cut_control;
497         }
498         return boost::shared_ptr<Controllable>();
499 }
500
501 boost::shared_ptr<Controllable>
502 MonitorProcessor::channel_dim_control (uint32_t chn) const
503 {
504         if (chn < _channels.size()) {
505                 return _channels[chn]->dim_control;
506         }
507         return boost::shared_ptr<Controllable>();
508 }
509
510 boost::shared_ptr<Controllable>
511 MonitorProcessor::channel_polarity_control (uint32_t chn) const
512 {
513         if (chn < _channels.size()) {
514                 return _channels[chn]->polarity_control;
515         }
516         return boost::shared_ptr<Controllable>();
517 }
518
519 boost::shared_ptr<Controllable>
520 MonitorProcessor::channel_solo_control (uint32_t chn) const
521 {
522         if (chn < _channels.size()) {
523                 return _channels[chn]->soloed_control;
524         }
525         return boost::shared_ptr<Controllable>();
526 }
527
528 MonitorProcessor::ChannelRecord::ChannelRecord (uint32_t chn)
529         : current_gain (GAIN_COEFF_UNITY)
530         , cut_ptr (new MPControl<gain_t> (1.0, string_compose (_("cut control %1"), chn), PBD::Controllable::GainLike))
531         , dim_ptr (new MPControl<bool> (false, string_compose (_("dim control"), chn), PBD::Controllable::Toggle))
532         , polarity_ptr (new MPControl<gain_t> (1.0, string_compose (_("polarity control"), chn), PBD::Controllable::Toggle, -1, 1))
533         , soloed_ptr (new MPControl<bool> (false, string_compose (_("solo control"), chn), PBD::Controllable::Toggle))
534
535         , cut_control (cut_ptr)
536         , dim_control (dim_ptr)
537         , polarity_control (polarity_ptr)
538         , soloed_control (soloed_ptr)
539
540         , cut (*cut_ptr)
541         , dim (*dim_ptr)
542         , polarity (*polarity_ptr)
543         , soloed (*soloed_ptr)
544 {
545
546 }