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