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