Fix broken whitespace. I'd apologize for the compile times if it was my fault :D
[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*/, pframes_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 (pframes_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 (pframes_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         out = in;
338         return true;
339 }
340
341 void
342 MonitorProcessor::set_polarity (uint32_t chn, bool invert)
343 {
344         if (invert) {
345                 _channels[chn]->polarity = -1.0f;
346         } else {
347                 _channels[chn]->polarity = 1.0f;
348         }
349 }
350
351 void
352 MonitorProcessor::set_dim (uint32_t chn, bool yn)
353 {
354         _channels[chn]->dim = yn;
355 }
356
357 void
358 MonitorProcessor::set_cut (uint32_t chn, bool yn)
359 {
360         if (yn) {
361                 _channels[chn]->cut = 0.0f;
362         } else {
363                 _channels[chn]->cut = 1.0f;
364         }
365 }
366
367 void
368 MonitorProcessor::set_solo (uint32_t chn, bool solo)
369 {
370         if (solo != _channels[chn]->soloed) {
371                 _channels[chn]->soloed = solo;
372
373                 if (solo) {
374                         solo_cnt++;
375                 } else {
376                         if (solo_cnt > 0) {
377                                 solo_cnt--;
378                         }
379                 }
380         }
381 }
382
383 void
384 MonitorProcessor::set_mono (bool yn)
385 {
386         _mono = yn;
387 }
388
389 void
390 MonitorProcessor::set_cut_all (bool yn)
391 {
392         _cut_all = yn;
393 }
394
395 void
396 MonitorProcessor::set_dim_all (bool yn)
397 {
398         _dim_all = yn;
399 }
400
401 bool
402 MonitorProcessor::display_to_user () const
403 {
404         return false;
405 }
406
407 bool
408 MonitorProcessor::soloed (uint32_t chn) const
409 {
410         return _channels[chn]->soloed;
411 }
412
413
414 bool
415 MonitorProcessor::inverted (uint32_t chn) const
416 {
417         return _channels[chn]->polarity < 0.0f;
418 }
419
420
421 bool
422 MonitorProcessor::cut (uint32_t chn) const
423 {
424         return _channels[chn]->cut == 0.0f;
425 }
426
427 bool
428 MonitorProcessor::dimmed (uint32_t chn) const
429 {
430         return _channels[chn]->dim;
431 }
432
433 bool
434 MonitorProcessor::mono () const
435 {
436         return _mono;
437 }
438
439 bool
440 MonitorProcessor::dim_all () const
441 {
442         return _dim_all;
443 }
444
445 bool
446 MonitorProcessor::cut_all () const
447 {
448         return _cut_all;
449 }
450
451 boost::shared_ptr<Controllable>
452 MonitorProcessor::channel_cut_control (uint32_t chn) const
453 {
454         if (chn < _channels.size()) {
455                 return _channels[chn]->cut_control;
456         }
457         return boost::shared_ptr<Controllable>();
458 }
459
460 boost::shared_ptr<Controllable>
461 MonitorProcessor::channel_dim_control (uint32_t chn) const
462 {
463         if (chn < _channels.size()) {
464                 return _channels[chn]->dim_control;
465         }
466         return boost::shared_ptr<Controllable>();
467 }
468
469 boost::shared_ptr<Controllable>
470 MonitorProcessor::channel_polarity_control (uint32_t chn) const
471 {
472         if (chn < _channels.size()) {
473                 return _channels[chn]->polarity_control;
474         }
475         return boost::shared_ptr<Controllable>();
476 }
477
478 boost::shared_ptr<Controllable>
479 MonitorProcessor::channel_solo_control (uint32_t chn) const
480 {
481         if (chn < _channels.size()) {
482                 return _channels[chn]->soloed_control;
483         }
484         return boost::shared_ptr<Controllable>();
485 }
486
487 MonitorProcessor::ChannelRecord::ChannelRecord (uint32_t chn)
488         : current_gain (1.0)
489         , cut_ptr (new MPControl<gain_t> (1.0, string_compose (_("cut control %1"), chn), PBD::Controllable::GainLike))
490         , dim_ptr (new MPControl<bool> (false, string_compose (_("dim control"), chn), PBD::Controllable::Toggle))
491         , polarity_ptr (new MPControl<gain_t> (1.0, string_compose (_("polarity control"), chn), PBD::Controllable::Toggle))
492         , soloed_ptr (new MPControl<bool> (false, string_compose (_("solo control"), chn), PBD::Controllable::Toggle))
493
494         , cut_control (cut_ptr)
495         , dim_control (dim_ptr)
496         , polarity_control (polarity_ptr)
497         , soloed_control (soloed_ptr)
498
499         , cut (*cut_ptr)
500         , dim (*dim_ptr)
501         , polarity (*polarity_ptr)
502         , soloed (*soloed_ptr)
503 {
504
505 }