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