monitor section: make sip/afl/pfl buttons work, add rude solo, mono function, rearrange
[ardour.git] / libs / ardour / monitor_processor.cc
1 #include "pbd/xml++.h"
2
3 #include "ardour/amp.h"
4 #include "ardour/dB.h"
5 #include "ardour/audio_buffer.h"
6 #include "ardour/monitor_processor.h"
7 #include "ardour/session.h"
8
9 #include "i18n.h"
10
11 using namespace ARDOUR;
12 using namespace std;
13
14 MonitorProcessor::MonitorProcessor (Session& s)
15         : Processor (s, X_("MonitorOut"))
16 {
17         solo_cnt = 0;
18         _cut_all = false;
19         _dim_all = false;
20         _dim_level = 0.2;
21         _solo_boost_level = 1.0;
22 }
23
24 MonitorProcessor::MonitorProcessor (Session& s, const XMLNode& node)
25         : Processor (s, node)
26 {
27         set_state (node, Stateful::loading_state_version);
28 }
29
30 int
31 MonitorProcessor::set_state (const XMLNode& node, int version)
32 {
33         return Processor::set_state (node, version);
34 }
35
36 XMLNode&
37 MonitorProcessor::state (bool full)
38 {
39         XMLNode& node (Processor::state (full));
40
41         /* this replaces any existing "type" property */
42
43         node.add_property (X_("type"), X_("monitor"));
44
45         return node;
46 }
47
48 void
49 MonitorProcessor::run (BufferSet& bufs, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t nframes, bool /*result_required*/)
50 {
51         uint32_t chn = 0;
52         gain_t target_gain;
53         gain_t dim_level_this_time = _dim_level;
54         gain_t global_cut = (_cut_all ? 0.0f : 1.0f);
55         gain_t global_dim = (_dim_all ? dim_level_this_time : 1.0f);
56         gain_t solo_boost;
57
58         if (_session.listening() || _session.soloing()) {
59                 solo_boost = _solo_boost_level;
60         } else {
61                 solo_boost = 1.0;
62         }
63
64         for (BufferSet::audio_iterator b = bufs.audio_begin(); b != bufs.audio_end(); ++b) {
65
66                 /* don't double-scale by both track dim and global dim coefficients */
67
68                 gain_t dim_level = (global_dim == 1.0 ? (_dim[chn] ? dim_level_this_time : 1.0) : 1.0);
69
70                 if (_soloed[chn]) {
71                         target_gain = _polarity[chn] * _cut[chn] * dim_level * global_cut * global_dim * solo_boost;
72                 } else {
73                         if (solo_cnt == 0) {
74                                 target_gain = _polarity[chn] * _cut[chn] * dim_level * global_cut * global_dim * solo_boost;
75                         } else {
76                                 target_gain = 0.0;
77                         }
78                 }
79
80                 if (target_gain != current_gain[chn] || target_gain != 1.0f) {
81
82                         Amp::apply_gain (*b, nframes, current_gain[chn], target_gain);
83                         current_gain[chn] = target_gain;
84                 }
85
86                 ++chn;
87         }
88
89         if (_mono) {
90                 /* chn is now the number of channels, use as a scaling factor when mixing
91                  */
92                 gain_t scale = 1.0/chn;
93                 BufferSet::audio_iterator b = bufs.audio_begin();
94                 AudioBuffer& ab (*b);
95                 Sample* buf = ab.data();
96
97                 /* scale the first channel */
98
99                 for (nframes_t n = 0; n < nframes; ++n) {
100                         buf[n] *= scale;
101                 }
102
103                 /* add every other channel into the first channel's buffer */
104
105                 ++b;
106                 for (; b != bufs.audio_end(); ++b) {
107                         AudioBuffer& ob (*b);
108                         Sample* obuf = ob.data ();
109                         for (nframes_t n = 0; n < nframes; ++n) {
110                                 buf[n] += obuf[n] * scale;
111                         }
112                 }
113
114                 /* copy the first channel to every other channel's buffer */
115
116                 b = bufs.audio_begin();
117                 ++b;
118                 for (; b != bufs.audio_end(); ++b) {
119                         AudioBuffer& ob (*b);
120                         Sample* obuf = ob.data ();
121                         memcpy (obuf, buf, sizeof (Sample) * nframes);
122                 }
123         }
124 }
125
126 bool
127 MonitorProcessor::configure_io (ChanCount in, ChanCount out)
128 {
129         uint32_t needed = in.n_audio();
130
131         while (current_gain.size() > needed) {
132                 current_gain.pop_back ();
133                 _dim.pop_back ();
134                 _cut.pop_back ();
135                 _polarity.pop_back ();
136
137                 if (_soloed.back()) {
138                         if (solo_cnt > 0) {
139                                 --solo_cnt;
140                         }
141                 }
142
143                 _soloed.pop_back ();
144         }
145         
146         while (current_gain.size() < needed) {
147                 current_gain.push_back (1.0);
148                 _dim.push_back (false);
149                 _cut.push_back (1.0);
150                 _polarity.push_back (1.0);
151                 _soloed.push_back (false);
152         }
153
154         return Processor::configure_io (in, out);
155 }
156
157 bool 
158 MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
159 {
160         return in == out;
161 }
162
163 void
164 MonitorProcessor::set_polarity (uint32_t chn, bool invert)
165 {
166         if (invert) {
167                 _polarity[chn] = -1.0f;
168         } else {
169                 _polarity[chn] = 1.0f;
170         }
171 }       
172
173 void
174 MonitorProcessor::set_dim (uint32_t chn, bool yn)
175 {
176         _dim[chn] = yn;
177 }
178
179 void
180 MonitorProcessor::set_cut (uint32_t chn, bool yn)
181 {
182         if (yn) {
183                 _cut[chn] = 0.0f;
184         } else {
185                 _cut[chn] = 1.0f;
186         }
187 }
188
189 void
190 MonitorProcessor::set_solo (uint32_t chn, bool solo)
191 {
192         _soloed[chn] = solo;
193
194         if (solo) {
195                 solo_cnt++;
196         } else {
197                 if (solo_cnt > 0) {
198                         solo_cnt--;
199                 }
200         }
201 }
202
203 void
204 MonitorProcessor::set_mono (bool yn)
205 {
206         _mono = yn;
207 }
208
209 void
210 MonitorProcessor::set_cut_all (bool yn)
211 {
212         _cut_all = yn;
213 }
214
215 void
216 MonitorProcessor::set_dim_all (bool yn)
217 {
218         _dim_all = yn;
219 }
220
221 bool
222 MonitorProcessor::display_to_user () const
223 {
224         return false;
225 }
226
227 void
228 MonitorProcessor::set_dim_level (gain_t val)
229 {
230         _dim_level = val;
231 }
232
233 void
234 MonitorProcessor::set_solo_boost_level (gain_t val)
235 {
236         _solo_boost_level = val;
237 }
238
239 bool 
240 MonitorProcessor::soloed (uint32_t chn) const
241 {
242         return _soloed[chn];
243 }
244
245
246 bool 
247 MonitorProcessor::inverted (uint32_t chn) const
248 {
249         return _polarity[chn] < 0.0f;
250 }
251
252
253 bool 
254 MonitorProcessor::cut (uint32_t chn) const
255 {
256         return _cut[chn] == 0.0f;
257 }
258
259 bool 
260 MonitorProcessor::dimmed (uint32_t chn) const
261 {
262         return _dim[chn];
263 }
264
265 bool
266 MonitorProcessor::mono () const
267 {
268         return _mono;
269 }