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