remove some unnecessary and hard-to-compile-on-OSX debug stuff
[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 (double 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, framepos_t /*start_frame*/, framepos_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                 if (target_gain != _channels[chn]->current_gain || target_gain != 1.0f) {
280
281                         Amp::apply_gain (*b, nframes, _channels[chn]->current_gain, target_gain);
282                         _channels[chn]->current_gain = target_gain;
283                 }
284
285                 ++chn;
286         }
287
288         if (_mono) {
289                 DEBUG_TRACE (DEBUG::Monitor, "mono-izing\n");
290
291                 /* chn is now the number of channels, use as a scaling factor when mixing
292                  */
293                 gain_t scale = 1.0/chn;
294                 BufferSet::audio_iterator b = bufs.audio_begin();
295                 AudioBuffer& ab (*b);
296                 Sample* buf = ab.data();
297
298                 /* scale the first channel */
299
300                 for (nframes_t n = 0; n < nframes; ++n) {
301                         buf[n] *= scale;
302                 }
303
304                 /* add every other channel into the first channel's buffer */
305
306                 ++b;
307                 for (; b != bufs.audio_end(); ++b) {
308                         AudioBuffer& ob (*b);
309                         Sample* obuf = ob.data ();
310                         for (nframes_t n = 0; n < nframes; ++n) {
311                                 buf[n] += obuf[n] * scale;
312                         }
313                 }
314
315                 /* copy the first channel to every other channel's buffer */
316
317                 b = bufs.audio_begin();
318                 ++b;
319                 for (; b != bufs.audio_end(); ++b) {
320                         AudioBuffer& ob (*b);
321                         Sample* obuf = ob.data ();
322                         memcpy (obuf, buf, sizeof (Sample) * nframes);
323                 }
324         }
325 }
326
327 bool
328 MonitorProcessor::configure_io (ChanCount in, ChanCount out)
329 {
330         allocate_channels (in.n_audio());
331         return Processor::configure_io (in, out);
332 }
333
334 bool 
335 MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
336 {
337         return in == out;
338 }
339
340 void
341 MonitorProcessor::set_polarity (uint32_t chn, bool invert)
342 {
343         if (invert) {
344                 _channels[chn]->polarity = -1.0f;
345         } else {
346                 _channels[chn]->polarity = 1.0f;
347         }
348 }       
349
350 void
351 MonitorProcessor::set_dim (uint32_t chn, bool yn)
352 {
353         _channels[chn]->dim = yn;
354 }
355
356 void
357 MonitorProcessor::set_cut (uint32_t chn, bool yn)
358 {
359         if (yn) {
360                 _channels[chn]->cut = 0.0f;
361         } else {
362                 _channels[chn]->cut = 1.0f;
363         }
364 }
365
366 void
367 MonitorProcessor::set_solo (uint32_t chn, bool solo)
368 {
369         if (solo != _channels[chn]->soloed) {
370                 _channels[chn]->soloed = solo;
371                 
372                 if (solo) {
373                         solo_cnt++;
374                 } else {
375                         if (solo_cnt > 0) {
376                                 solo_cnt--;
377                         }
378                 }
379         }
380 }
381
382 void
383 MonitorProcessor::set_mono (bool yn)
384 {
385         _mono = yn;
386 }
387
388 void
389 MonitorProcessor::set_cut_all (bool yn)
390 {
391         _cut_all = yn;
392 }
393
394 void
395 MonitorProcessor::set_dim_all (bool yn)
396 {
397         _dim_all = yn;
398 }
399
400 bool
401 MonitorProcessor::display_to_user () const
402 {
403         return false;
404 }
405
406 void
407 MonitorProcessor::set_dim_level (gain_t val)
408 {
409         _dim_level = val;
410 }
411
412 void
413 MonitorProcessor::set_solo_boost_level (gain_t val)
414 {
415         _solo_boost_level = val;
416 }
417
418 bool 
419 MonitorProcessor::soloed (uint32_t chn) const
420 {
421         return _channels[chn]->soloed;
422 }
423
424
425 bool 
426 MonitorProcessor::inverted (uint32_t chn) const
427 {
428         return _channels[chn]->polarity < 0.0f;
429 }
430
431
432 bool 
433 MonitorProcessor::cut (uint32_t chn) const
434 {
435         return _channels[chn]->cut == 0.0f;
436 }
437
438 bool 
439 MonitorProcessor::dimmed (uint32_t chn) const
440 {
441         return _channels[chn]->dim;
442 }
443
444 bool
445 MonitorProcessor::mono () const
446 {
447         return _mono;
448 }
449
450 bool
451 MonitorProcessor::dim_all () const
452 {
453         return _dim_all;
454 }
455
456 bool
457 MonitorProcessor::cut_all () const
458 {
459         return _cut_all;
460 }
461
462 boost::shared_ptr<Controllable>
463 MonitorProcessor::channel_cut_control (uint32_t chn) const
464 {
465         if (chn < _channels.size()) {
466                 return _channels[chn]->cut_control;
467         }
468         return boost::shared_ptr<Controllable>();
469 }
470
471 boost::shared_ptr<Controllable>
472 MonitorProcessor::channel_dim_control (uint32_t chn) const
473 {
474         if (chn < _channels.size()) {
475                 return _channels[chn]->dim_control;
476         }
477         return boost::shared_ptr<Controllable>();
478 }
479
480 boost::shared_ptr<Controllable>
481 MonitorProcessor::channel_polarity_control (uint32_t chn) const
482 {
483         if (chn < _channels.size()) {
484                 return _channels[chn]->polarity_control;
485         }
486         return boost::shared_ptr<Controllable>();
487 }
488
489 boost::shared_ptr<Controllable>
490 MonitorProcessor::channel_solo_control (uint32_t chn) const
491 {
492         if (chn < _channels.size()) {
493                 return _channels[chn]->soloed_control;
494         }
495         return boost::shared_ptr<Controllable>();
496 }
497
498 MonitorProcessor::ChannelRecord::ChannelRecord (uint32_t chn)
499         : current_gain (1.0)
500         , cut_ptr (new MPControl<gain_t> (1.0, string_compose (_("cut control %1"), chn), PBD::Controllable::GainLike))
501         , dim_ptr (new MPControl<bool> (false, string_compose (_("dim control"), chn), PBD::Controllable::Toggle))
502         , polarity_ptr (new MPControl<gain_t> (1.0, string_compose (_("polarity control"), chn), PBD::Controllable::Toggle))
503         , soloed_ptr (new MPControl<bool> (false, string_compose (_("solo control"), chn), PBD::Controllable::Toggle))
504           
505         , cut_control (cut_ptr)
506         , dim_control (dim_ptr)
507         , polarity_control (polarity_ptr)
508         , soloed_control (soloed_ptr)
509           
510         , cut (*cut_ptr)
511         , dim (*dim_ptr)
512         , polarity (*polarity_ptr)
513         , soloed (*soloed_ptr)
514 {
515
516 }