3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / media / media-add-ons / mixer / MixerOutput.cpp
blob9827e5e6a59ae980f65f6de6eb5f6b6f634a6d38
1 /*
2 * Copyright 2003-2009 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Marcus Overhagen
7 */
10 #include "MixerOutput.h"
12 #include <MediaNode.h>
14 #include "MixerCore.h"
15 #include "MixerDebug.h"
16 #include "MixerUtils.h"
19 MixerOutput::MixerOutput(MixerCore *core, const media_output &output)
21 fCore(core),
22 fOutput(output),
23 fOutputChannelCount(0),
24 fOutputChannelInfo(0),
25 fOutputByteSwap(0),
26 fMuted(false)
28 fix_multiaudio_format(&fOutput.format.u.raw_audio);
29 PRINT_OUTPUT("MixerOutput::MixerOutput", fOutput);
30 PRINT_CHANNEL_MASK(fOutput.format);
32 UpdateOutputChannels();
33 UpdateByteOrderSwap();
37 MixerOutput::~MixerOutput()
39 delete fOutputChannelInfo;
40 delete fOutputByteSwap;
44 media_output &
45 MixerOutput::MediaOutput()
47 return fOutput;
51 void
52 MixerOutput::ChangeFormat(const media_multi_audio_format &format)
54 fOutput.format.u.raw_audio = format;
55 fix_multiaudio_format(&fOutput.format.u.raw_audio);
57 PRINT_OUTPUT("MixerOutput::ChangeFormat", fOutput);
58 PRINT_CHANNEL_MASK(fOutput.format);
60 UpdateOutputChannels();
61 UpdateByteOrderSwap();
65 void
66 MixerOutput::UpdateByteOrderSwap()
68 delete fOutputByteSwap;
69 fOutputByteSwap = 0;
71 // perhaps we need byte swapping
72 if (fOutput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) {
73 if ( fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT
74 || fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_INT
75 || fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) {
76 fOutputByteSwap = new ByteSwap(fOutput.format.u.raw_audio.format);
82 void
83 MixerOutput::UpdateOutputChannels()
85 output_chan_info *oldInfo = fOutputChannelInfo;
86 int oldCount = fOutputChannelCount;
88 fOutputChannelCount = fOutput.format.u.raw_audio.channel_count;
89 fOutputChannelInfo = new output_chan_info[fOutputChannelCount];
90 for (int i = 0; i < fOutputChannelCount; i++) {
91 fOutputChannelInfo[i].channel_type = GetChannelType(i, fOutput.format.u.raw_audio.channel_mask);
92 fOutputChannelInfo[i].channel_gain = 1.0;
93 fOutputChannelInfo[i].source_count = 1;
94 fOutputChannelInfo[i].source_gain[0] = 1.0;
95 fOutputChannelInfo[i].source_type[0] = fOutputChannelInfo[i].channel_type;
96 // all the cached values are 0.0 for a new channel
97 for (int j = 0; j < MAX_CHANNEL_TYPES; j++)
98 fOutputChannelInfo[i].source_gain_cache[j] = 0.0;
101 AssignDefaultSources();
103 // apply old gains and sources, overriding the 1.0 gain defaults for the old channels
104 if (oldInfo != 0 && oldCount != 0) {
105 for (int i = 0; i < fOutputChannelCount; i++) {
106 for (int j = 0; j < oldCount; j++) {
107 if (fOutputChannelInfo[i].channel_type == oldInfo[j].channel_type) {
108 fOutputChannelInfo[i].channel_gain = oldInfo[j].channel_gain;
109 fOutputChannelInfo[i].source_count = oldInfo[j].source_count;
110 for (int k = 0; k < fOutputChannelInfo[i].source_count; k++) {
111 fOutputChannelInfo[i].source_gain[k] = oldInfo[j].source_gain[k];
112 fOutputChannelInfo[i].source_type[k] = oldInfo[j].source_type[k];
114 // also copy the old gain cache
115 for (int k = 0; k < MAX_CHANNEL_TYPES; k++)
116 fOutputChannelInfo[i].source_gain_cache[k] = oldInfo[j].source_gain_cache[k];
117 break;
121 // also delete the old info array
122 delete [] oldInfo;
124 for (int i = 0; i < fOutputChannelCount; i++)
125 TRACE("UpdateOutputChannels: output channel %d, type %2d, gain %.3f\n", i, fOutputChannelInfo[i].channel_type, fOutputChannelInfo[i].channel_gain);
129 void
130 MixerOutput::AssignDefaultSources()
132 uint32 mask = fOutput.format.u.raw_audio.channel_mask;
133 int count = fOutputChannelCount;
135 // assign default sources for a few known setups,
136 // everything else is left unchanged (it already is 1:1)
137 if (count == 1 && mask & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT)) {
138 // we have only one phycial output channel, and use it as a mix of
139 // left, right, rear-left, rear-right, center and sub
140 TRACE("AssignDefaultSources: 1 channel setup\n");
141 fOutputChannelInfo[0].source_count = 9;
142 fOutputChannelInfo[0].source_gain[0] = 1.0;
143 fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT);
144 fOutputChannelInfo[0].source_gain[1] = 1.0;
145 fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_RIGHT);
146 fOutputChannelInfo[0].source_gain[2] = 0.8;
147 fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT);
148 fOutputChannelInfo[0].source_gain[3] = 0.8;
149 fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT);
150 fOutputChannelInfo[0].source_gain[4] = 0.7;
151 fOutputChannelInfo[0].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
152 fOutputChannelInfo[0].source_gain[5] = 0.6;
153 fOutputChannelInfo[0].source_type[5] = ChannelMaskToChannelType(B_CHANNEL_SUB);
154 fOutputChannelInfo[0].source_gain[6] = 1.0;
155 fOutputChannelInfo[0].source_type[6] = ChannelMaskToChannelType(B_CHANNEL_MONO);
156 fOutputChannelInfo[0].source_gain[7] = 0.7;
157 fOutputChannelInfo[0].source_type[7] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT);
158 fOutputChannelInfo[0].source_gain[8] = 0.7;
159 fOutputChannelInfo[0].source_type[8] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT);
160 } else if (count == 2 && mask == (B_CHANNEL_LEFT | B_CHANNEL_RIGHT)) {
161 // we have have two phycial output channels
162 TRACE("AssignDefaultSources: 2 channel setup\n");
163 // left channel:
164 fOutputChannelInfo[0].source_count = 6;
165 fOutputChannelInfo[0].source_gain[0] = 1.0;
166 fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT);
167 fOutputChannelInfo[0].source_gain[1] = 0.8;
168 fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT);
169 fOutputChannelInfo[0].source_gain[2] = 0.7;
170 fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
171 fOutputChannelInfo[0].source_gain[3] = 0.6;
172 fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SUB);
173 fOutputChannelInfo[0].source_gain[4] = 1.0;
174 fOutputChannelInfo[0].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_MONO);
175 fOutputChannelInfo[0].source_gain[5] = 0.7;
176 fOutputChannelInfo[0].source_type[5] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT);
177 // right channel:
178 fOutputChannelInfo[1].source_count = 6;
179 fOutputChannelInfo[1].source_gain[0] = 1.0;
180 fOutputChannelInfo[1].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_RIGHT);
181 fOutputChannelInfo[1].source_gain[1] = 0.8;
182 fOutputChannelInfo[1].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT);
183 fOutputChannelInfo[1].source_gain[2] = 0.7;
184 fOutputChannelInfo[1].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
185 fOutputChannelInfo[1].source_gain[3] = 0.6;
186 fOutputChannelInfo[1].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SUB);
187 fOutputChannelInfo[1].source_gain[4] = 1.0;
188 fOutputChannelInfo[1].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_MONO);
189 fOutputChannelInfo[1].source_gain[5] = 0.7;
190 fOutputChannelInfo[1].source_type[5] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT);
191 } else if (count == 4 && mask == (B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT)) {
192 TRACE("AssignDefaultSources: 4 channel setup\n");
193 // left channel:
194 fOutputChannelInfo[0].source_count = 5;
195 fOutputChannelInfo[0].source_gain[0] = 1.0;
196 fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT);
197 fOutputChannelInfo[0].source_gain[1] = 0.7;
198 fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
199 fOutputChannelInfo[0].source_gain[2] = 0.6;
200 fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_SUB);
201 fOutputChannelInfo[0].source_gain[3] = 1.0;
202 fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_MONO);
203 fOutputChannelInfo[0].source_gain[4] = 0.6;
204 fOutputChannelInfo[0].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT);
205 // right channel:
206 fOutputChannelInfo[1].source_count = 5;
207 fOutputChannelInfo[1].source_gain[0] = 1.0;
208 fOutputChannelInfo[1].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_RIGHT);
209 fOutputChannelInfo[1].source_gain[1] = 0.7;
210 fOutputChannelInfo[1].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
211 fOutputChannelInfo[1].source_gain[2] = 0.6;
212 fOutputChannelInfo[1].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_SUB);
213 fOutputChannelInfo[1].source_gain[3] = 1.0;
214 fOutputChannelInfo[1].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_MONO);
215 fOutputChannelInfo[1].source_gain[4] = 0.6;
216 fOutputChannelInfo[1].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT);
217 // rear-left channel:
218 fOutputChannelInfo[2].source_count = 4;
219 fOutputChannelInfo[2].source_gain[0] = 1.0;
220 fOutputChannelInfo[2].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT);
221 fOutputChannelInfo[2].source_gain[1] = 0.6;
222 fOutputChannelInfo[2].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
223 fOutputChannelInfo[2].source_gain[2] = 0.9;
224 fOutputChannelInfo[2].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO);
225 fOutputChannelInfo[2].source_gain[3] = 0.6;
226 fOutputChannelInfo[2].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT);
227 // rear-right channel:
228 fOutputChannelInfo[3].source_count = 4;
229 fOutputChannelInfo[3].source_gain[0] = 1.0;
230 fOutputChannelInfo[3].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT);
231 fOutputChannelInfo[3].source_gain[1] = 0.6;
232 fOutputChannelInfo[3].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
233 fOutputChannelInfo[3].source_gain[2] = 0.9;
234 fOutputChannelInfo[3].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO);
235 fOutputChannelInfo[3].source_gain[3] = 0.6;
236 fOutputChannelInfo[3].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT);
237 } else if (count == 5 && mask == (B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT | B_CHANNEL_CENTER)) {
238 TRACE("AssignDefaultSources: 5 channel setup\n");
239 // left channel:
240 fOutputChannelInfo[0].source_count = 4;
241 fOutputChannelInfo[0].source_gain[0] = 1.0;
242 fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT);
243 fOutputChannelInfo[0].source_gain[1] = 0.6;
244 fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
245 fOutputChannelInfo[0].source_gain[2] = 1.0;
246 fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO);
247 fOutputChannelInfo[0].source_gain[3] = 0.6;
248 fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT);
249 // right channel:
250 fOutputChannelInfo[1].source_count = 4;
251 fOutputChannelInfo[1].source_gain[0] = 1.0;
252 fOutputChannelInfo[1].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_RIGHT);
253 fOutputChannelInfo[1].source_gain[1] = 0.6;
254 fOutputChannelInfo[1].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
255 fOutputChannelInfo[1].source_gain[2] = 1.0;
256 fOutputChannelInfo[1].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO);
257 fOutputChannelInfo[1].source_gain[3] = 0.6;
258 fOutputChannelInfo[1].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT);
259 // rear-left channel:
260 fOutputChannelInfo[2].source_count = 4;
261 fOutputChannelInfo[2].source_gain[0] = 1.0;
262 fOutputChannelInfo[2].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT);
263 fOutputChannelInfo[2].source_gain[1] = 0.6;
264 fOutputChannelInfo[2].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
265 fOutputChannelInfo[2].source_gain[2] = 0.9;
266 fOutputChannelInfo[2].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO);
267 fOutputChannelInfo[2].source_gain[3] = 0.6;
268 fOutputChannelInfo[2].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT);
269 // rear-right channel:
270 fOutputChannelInfo[3].source_count = 4;
271 fOutputChannelInfo[3].source_gain[0] = 1.0;
272 fOutputChannelInfo[3].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT);
273 fOutputChannelInfo[3].source_gain[1] = 0.6;
274 fOutputChannelInfo[3].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
275 fOutputChannelInfo[3].source_gain[2] = 0.9;
276 fOutputChannelInfo[3].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO);
277 fOutputChannelInfo[3].source_gain[3] = 0.6;
278 fOutputChannelInfo[3].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT);
279 // center channel:
280 fOutputChannelInfo[4].source_count = 3;
281 fOutputChannelInfo[4].source_gain[0] = 1.0;
282 fOutputChannelInfo[4].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
283 fOutputChannelInfo[4].source_gain[1] = 0.5;
284 fOutputChannelInfo[4].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
285 fOutputChannelInfo[4].source_gain[2] = 0.8;
286 fOutputChannelInfo[4].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO);
287 } else {
288 TRACE("AssignDefaultSources: no default setup, adding mono channel to first two channels\n");
289 if (count >= 1) {
290 // this is not a left channel, but we add the mono channel anyway
291 fOutputChannelInfo[0].source_gain[fOutputChannelInfo[0].source_count] = 1.0;
292 fOutputChannelInfo[0].source_type[fOutputChannelInfo[0].source_count] = ChannelMaskToChannelType(B_CHANNEL_MONO);
293 fOutputChannelInfo[0].source_count++;
295 if (count >= 2) {
296 // this is not a right channel, but we add the mono channel anyway
297 fOutputChannelInfo[1].source_gain[fOutputChannelInfo[1].source_count] = 1.0;
298 fOutputChannelInfo[1].source_type[fOutputChannelInfo[1].source_count] = ChannelMaskToChannelType(B_CHANNEL_MONO);
299 fOutputChannelInfo[1].source_count++;
303 for (int i = 0; i < fOutputChannelCount; i++) {
304 for (int j = 0; j < fOutputChannelInfo[i].source_count; j++) {
305 TRACE("AssignDefaultSources: output channel %d, source index %d: source_type %2d, source_gain %.3f\n", i, j, fOutputChannelInfo[i].source_type[j], fOutputChannelInfo[i].source_gain[j]);
312 MixerOutput::GetOutputChannelType(int channel)
314 if (channel < 0 || channel >= fOutputChannelCount)
315 return 0;
316 return fOutputChannelInfo[channel].channel_type;
320 void
321 MixerOutput::SetOutputChannelGain(int channel, float gain)
323 TRACE("SetOutputChannelGain chan %d, gain %.5f\n", channel, gain);
324 if (channel < 0 || channel >= fOutputChannelCount)
325 return;
326 fOutputChannelInfo[channel].channel_gain = gain;
330 void
331 MixerOutput::AddOutputChannelSource(int channel, int source_type)
333 if (channel < 0 || channel >= fOutputChannelCount)
334 return;
335 if (source_type < 0 || source_type >= MAX_CHANNEL_TYPES)
336 return;
337 if (fOutputChannelInfo[channel].source_count == MAX_SOURCE_ENTRIES)
338 return;
339 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
340 if (fOutputChannelInfo[channel].source_type[i] == source_type)
341 return;
343 // when adding a new source, use the current gain value from cache
344 float source_gain = fOutputChannelInfo[channel].source_gain_cache[source_type];
345 fOutputChannelInfo[channel].source_type[fOutputChannelInfo[channel].source_count] = source_type;
346 fOutputChannelInfo[channel].source_gain[fOutputChannelInfo[channel].source_count] = source_gain;
347 fOutputChannelInfo[channel].source_count++;
351 void
352 MixerOutput::RemoveOutputChannelSource(int channel, int source_type)
354 if (channel < 0 || channel >= fOutputChannelCount)
355 return;
356 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
357 if (fOutputChannelInfo[channel].source_type[i] == source_type) {
358 // when removing a source, save the current gain value into the cache
359 fOutputChannelInfo[channel].source_gain_cache[source_type] = fOutputChannelInfo[channel].source_gain[i];
360 // remove the entry
361 fOutputChannelInfo[channel].source_type[i] = fOutputChannelInfo[channel].source_type[fOutputChannelInfo[channel].source_count - 1];
362 fOutputChannelInfo[channel].source_gain[i] = fOutputChannelInfo[channel].source_gain[fOutputChannelInfo[channel].source_count - 1];
363 fOutputChannelInfo[channel].source_count--;
364 return;
370 void
371 MixerOutput::SetOutputChannelSourceGain(int channel, int source_type, float source_gain)
373 if (channel < 0 || channel >= fOutputChannelCount)
374 return;
375 // set gain for active source
376 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
377 if (fOutputChannelInfo[channel].source_type[i] == source_type) {
378 fOutputChannelInfo[channel].source_gain[i] = source_gain;
379 return;
382 // we don't have an active source of that type, save gain in cache
383 if (source_type < 0 || source_type >= MAX_CHANNEL_TYPES)
384 return;
385 fOutputChannelInfo[channel].source_gain_cache[source_type] = source_gain;
389 float
390 MixerOutput::GetOutputChannelSourceGain(int channel, int source_type)
392 if (channel < 0 || channel >= fOutputChannelCount)
393 return 0.0;
394 // get gain for active source
395 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
396 if (fOutputChannelInfo[channel].source_type[i] == source_type) {
397 return fOutputChannelInfo[channel].source_gain[i];
400 // we don't have an active source of that type, get gain from cache
401 if (source_type < 0 || source_type >= MAX_CHANNEL_TYPES)
402 return 0.0;
403 return fOutputChannelInfo[channel].source_gain_cache[source_type];
407 bool
408 MixerOutput::HasOutputChannelSource(int channel, int source_type)
410 if (channel < 0 || channel >= fOutputChannelCount)
411 return false;
412 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
413 if (fOutputChannelInfo[channel].source_type[i] == source_type) {
414 return true;
417 return false;
421 void
422 MixerOutput::SetMuted(bool yesno)
424 fMuted = yesno;