1 /* 2 * Copyright 2003-2009 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marcus Overhagen 7 */ 8 9 10 #include "MixerOutput.h" 11 12 #include <MediaNode.h> 13 14 #include "MixerCore.h" 15 #include "MixerDebug.h" 16 #include "MixerUtils.h" 17 18 19 MixerOutput::MixerOutput(MixerCore *core, const media_output &output) 20 : 21 fCore(core), 22 fOutput(output), 23 fOutputChannelCount(0), 24 fOutputChannelInfo(0), 25 fOutputByteSwap(0), 26 fMuted(false) 27 { 28 fix_multiaudio_format(&fOutput.format.u.raw_audio); 29 PRINT_OUTPUT("MixerOutput::MixerOutput", fOutput); 30 PRINT_CHANNEL_MASK(fOutput.format); 31 32 UpdateOutputChannels(); 33 UpdateByteOrderSwap(); 34 } 35 36 37 MixerOutput::~MixerOutput() 38 { 39 delete fOutputChannelInfo; 40 delete fOutputByteSwap; 41 } 42 43 44 media_output & 45 MixerOutput::MediaOutput() 46 { 47 return fOutput; 48 } 49 50 51 void 52 MixerOutput::ChangeFormat(const media_multi_audio_format &format) 53 { 54 fOutput.format.u.raw_audio = format; 55 fix_multiaudio_format(&fOutput.format.u.raw_audio); 56 57 PRINT_OUTPUT("MixerOutput::ChangeFormat", fOutput); 58 PRINT_CHANNEL_MASK(fOutput.format); 59 60 UpdateOutputChannels(); 61 UpdateByteOrderSwap(); 62 } 63 64 65 void 66 MixerOutput::UpdateByteOrderSwap() 67 { 68 delete fOutputByteSwap; 69 fOutputByteSwap = 0; 70 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); 77 } 78 } 79 } 80 81 82 void 83 MixerOutput::UpdateOutputChannels() 84 { 85 output_chan_info *oldInfo = fOutputChannelInfo; 86 int oldCount = fOutputChannelCount; 87 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; 99 } 100 101 AssignDefaultSources(); 102 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]; 113 } 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; 118 } 119 } 120 } 121 // also delete the old info array 122 delete [] oldInfo; 123 } 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); 126 } 127 128 129 void 130 MixerOutput::AssignDefaultSources() 131 { 132 uint32 mask = fOutput.format.u.raw_audio.channel_mask; 133 int count = fOutputChannelCount; 134 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++; 294 } 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++; 300 } 301 } 302 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]); 306 } 307 } 308 } 309 310 311 int 312 MixerOutput::GetOutputChannelType(int channel) 313 { 314 if (channel < 0 || channel >= fOutputChannelCount) 315 return 0; 316 return fOutputChannelInfo[channel].channel_type; 317 } 318 319 320 void 321 MixerOutput::SetOutputChannelGain(int channel, float gain) 322 { 323 TRACE("SetOutputChannelGain chan %d, gain %.5f\n", channel, gain); 324 if (channel < 0 || channel >= fOutputChannelCount) 325 return; 326 fOutputChannelInfo[channel].channel_gain = gain; 327 } 328 329 330 void 331 MixerOutput::AddOutputChannelSource(int channel, int source_type) 332 { 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; 342 } 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++; 348 } 349 350 351 void 352 MixerOutput::RemoveOutputChannelSource(int channel, int source_type) 353 { 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; 365 } 366 } 367 } 368 369 370 void 371 MixerOutput::SetOutputChannelSourceGain(int channel, int source_type, float source_gain) 372 { 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; 380 } 381 } 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; 386 } 387 388 389 float 390 MixerOutput::GetOutputChannelSourceGain(int channel, int source_type) 391 { 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]; 398 } 399 } 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]; 404 } 405 406 407 bool 408 MixerOutput::HasOutputChannelSource(int channel, int source_type) 409 { 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; 415 } 416 } 417 return false; 418 } 419 420 421 void 422 MixerOutput::SetMuted(bool yesno) 423 { 424 fMuted = yesno; 425 } 426