1 #include <MediaNode.h> 2 #include "MixerOutput.h" 3 #include "MixerCore.h" 4 #include "MixerUtils.h" 5 #include "debug.h" 6 7 MixerOutput::MixerOutput(MixerCore *core, const media_output &output) 8 : fCore(core), 9 fOutput(output), 10 fOutputChannelCount(0), 11 fOutputChannelInfo(0), 12 fOutputByteSwap(0), 13 fMuted(false) 14 { 15 fix_multiaudio_format(&fOutput.format.u.raw_audio); 16 PRINT_OUTPUT("MixerOutput::MixerOutput", fOutput); 17 PRINT_CHANNEL_MASK(fOutput.format); 18 19 UpdateOutputChannels(); 20 UpdateByteOrderSwap(); 21 } 22 23 MixerOutput::~MixerOutput() 24 { 25 delete fOutputChannelInfo; 26 delete fOutputByteSwap; 27 } 28 29 media_output & 30 MixerOutput::MediaOutput() 31 { 32 return fOutput; 33 } 34 35 void 36 MixerOutput::ChangeFormat(const media_multi_audio_format &format) 37 { 38 fOutput.format.u.raw_audio = format; 39 fix_multiaudio_format(&fOutput.format.u.raw_audio); 40 41 PRINT_OUTPUT("MixerOutput::ChangeFormat", fOutput); 42 PRINT_CHANNEL_MASK(fOutput.format); 43 44 UpdateOutputChannels(); 45 UpdateByteOrderSwap(); 46 } 47 48 void 49 MixerOutput::UpdateByteOrderSwap() 50 { 51 delete fOutputByteSwap; 52 fOutputByteSwap = 0; 53 54 // perhaps we need byte swapping 55 if (fOutput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) { 56 if ( fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT 57 || fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_INT 58 || fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) { 59 fOutputByteSwap = new ByteSwap(fOutput.format.u.raw_audio.format); 60 } 61 } 62 } 63 64 void 65 MixerOutput::UpdateOutputChannels() 66 { 67 output_chan_info *oldInfo = fOutputChannelInfo; 68 int oldCount = fOutputChannelCount; 69 70 fOutputChannelCount = fOutput.format.u.raw_audio.channel_count; 71 fOutputChannelInfo = new output_chan_info[fOutputChannelCount]; 72 for (int i = 0; i < fOutputChannelCount; i++) { 73 fOutputChannelInfo[i].channel_type = GetChannelType(i, fOutput.format.u.raw_audio.channel_mask); 74 fOutputChannelInfo[i].channel_gain = 1.0; 75 fOutputChannelInfo[i].source_count = 1; 76 fOutputChannelInfo[i].source_gain[0] = 1.0; 77 fOutputChannelInfo[i].source_type[0] = fOutputChannelInfo[i].channel_type; 78 // all the cached values are 0.0 for a new channel 79 for (int j = 0; j < MAX_CHANNEL_TYPES; j++) 80 fOutputChannelInfo[i].source_gain_cache[j] = 0.0; 81 } 82 83 AssignDefaultSources(); 84 85 // apply old gains and sources, overriding the 1.0 gain defaults for the old channels 86 if (oldInfo != 0 && oldCount != 0) { 87 for (int i = 0; i < fOutputChannelCount; i++) { 88 for (int j = 0; j < oldCount; j++) { 89 if (fOutputChannelInfo[i].channel_type == oldInfo[j].channel_type) { 90 fOutputChannelInfo[i].channel_gain = oldInfo[j].channel_gain; 91 fOutputChannelInfo[i].source_count = oldInfo[j].source_count; 92 for (int k = 0; k < fOutputChannelInfo[i].source_count; k++) { 93 fOutputChannelInfo[i].source_gain[k] = oldInfo[j].source_gain[k]; 94 fOutputChannelInfo[i].source_type[k] = oldInfo[j].source_type[k]; 95 } 96 // also copy the old gain cache 97 for (int k = 0; k < MAX_CHANNEL_TYPES; k++) 98 fOutputChannelInfo[i].source_gain_cache[k] = oldInfo[j].source_gain_cache[k]; 99 break; 100 } 101 } 102 } 103 // also delete the old info array 104 delete [] oldInfo; 105 } 106 for (int i = 0; i < fOutputChannelCount; i++) 107 TRACE("UpdateOutputChannels: output channel %d, type %2d, gain %.3f\n", i, fOutputChannelInfo[i].channel_type, fOutputChannelInfo[i].channel_gain); 108 } 109 110 void 111 MixerOutput::AssignDefaultSources() 112 { 113 uint32 mask = fOutput.format.u.raw_audio.channel_mask; 114 int count = fOutputChannelCount; 115 116 // assign default sources for a few known setups, 117 // everything else is left unchanged (it already is 1:1) 118 119 if (count == 1 && mask & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT)) { 120 // we have only one phycial output channel, and use it as a mix of 121 // left, right, rear-left, rear-right, center and sub 122 TRACE("AssignDefaultSources: 1 channel setup\n"); 123 fOutputChannelInfo[0].source_count = 9; 124 fOutputChannelInfo[0].source_gain[0] = 1.0; 125 fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT); 126 fOutputChannelInfo[0].source_gain[1] = 1.0; 127 fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_RIGHT); 128 fOutputChannelInfo[0].source_gain[2] = 0.8; 129 fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT); 130 fOutputChannelInfo[0].source_gain[3] = 0.8; 131 fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT); 132 fOutputChannelInfo[0].source_gain[4] = 0.7; 133 fOutputChannelInfo[0].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_CENTER); 134 fOutputChannelInfo[0].source_gain[5] = 0.6; 135 fOutputChannelInfo[0].source_type[5] = ChannelMaskToChannelType(B_CHANNEL_SUB); 136 fOutputChannelInfo[0].source_gain[6] = 1.0; 137 fOutputChannelInfo[0].source_type[6] = ChannelMaskToChannelType(B_CHANNEL_MONO); 138 fOutputChannelInfo[0].source_gain[7] = 0.7; 139 fOutputChannelInfo[0].source_type[7] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT); 140 fOutputChannelInfo[0].source_gain[8] = 0.7; 141 fOutputChannelInfo[0].source_type[8] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT); 142 } else if (count == 2 && mask == (B_CHANNEL_LEFT | B_CHANNEL_RIGHT)) { 143 // we have have two phycial output channels 144 TRACE("AssignDefaultSources: 2 channel setup\n"); 145 // left channel: 146 fOutputChannelInfo[0].source_count = 6; 147 fOutputChannelInfo[0].source_gain[0] = 1.0; 148 fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT); 149 fOutputChannelInfo[0].source_gain[1] = 0.8; 150 fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT); 151 fOutputChannelInfo[0].source_gain[2] = 0.7; 152 fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_CENTER); 153 fOutputChannelInfo[0].source_gain[3] = 0.6; 154 fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SUB); 155 fOutputChannelInfo[0].source_gain[4] = 1.0; 156 fOutputChannelInfo[0].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_MONO); 157 fOutputChannelInfo[0].source_gain[5] = 0.7; 158 fOutputChannelInfo[0].source_type[5] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT); 159 // right channel: 160 fOutputChannelInfo[1].source_count = 6; 161 fOutputChannelInfo[1].source_gain[0] = 1.0; 162 fOutputChannelInfo[1].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_RIGHT); 163 fOutputChannelInfo[1].source_gain[1] = 0.8; 164 fOutputChannelInfo[1].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT); 165 fOutputChannelInfo[1].source_gain[2] = 0.7; 166 fOutputChannelInfo[1].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_CENTER); 167 fOutputChannelInfo[1].source_gain[3] = 0.6; 168 fOutputChannelInfo[1].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SUB); 169 fOutputChannelInfo[1].source_gain[4] = 1.0; 170 fOutputChannelInfo[1].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_MONO); 171 fOutputChannelInfo[1].source_gain[5] = 0.7; 172 fOutputChannelInfo[1].source_type[5] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT); 173 } else if (count == 4 && mask == (B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT)) { 174 TRACE("AssignDefaultSources: 4 channel setup\n"); 175 // left channel: 176 fOutputChannelInfo[0].source_count = 5; 177 fOutputChannelInfo[0].source_gain[0] = 1.0; 178 fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT); 179 fOutputChannelInfo[0].source_gain[1] = 0.7; 180 fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_CENTER); 181 fOutputChannelInfo[0].source_gain[2] = 0.6; 182 fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_SUB); 183 fOutputChannelInfo[0].source_gain[3] = 1.0; 184 fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_MONO); 185 fOutputChannelInfo[0].source_gain[4] = 0.6; 186 fOutputChannelInfo[0].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT); 187 // right channel: 188 fOutputChannelInfo[1].source_count = 5; 189 fOutputChannelInfo[1].source_gain[0] = 1.0; 190 fOutputChannelInfo[1].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_RIGHT); 191 fOutputChannelInfo[1].source_gain[1] = 0.7; 192 fOutputChannelInfo[1].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_CENTER); 193 fOutputChannelInfo[1].source_gain[2] = 0.6; 194 fOutputChannelInfo[1].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_SUB); 195 fOutputChannelInfo[1].source_gain[3] = 1.0; 196 fOutputChannelInfo[1].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_MONO); 197 fOutputChannelInfo[1].source_gain[4] = 0.6; 198 fOutputChannelInfo[1].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT); 199 // rear-left channel: 200 fOutputChannelInfo[2].source_count = 4; 201 fOutputChannelInfo[2].source_gain[0] = 1.0; 202 fOutputChannelInfo[2].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT); 203 fOutputChannelInfo[2].source_gain[1] = 0.6; 204 fOutputChannelInfo[2].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB); 205 fOutputChannelInfo[2].source_gain[2] = 0.9; 206 fOutputChannelInfo[2].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO); 207 fOutputChannelInfo[2].source_gain[3] = 0.6; 208 fOutputChannelInfo[2].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT); 209 // rear-right channel: 210 fOutputChannelInfo[3].source_count = 4; 211 fOutputChannelInfo[3].source_gain[0] = 1.0; 212 fOutputChannelInfo[3].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT); 213 fOutputChannelInfo[3].source_gain[1] = 0.6; 214 fOutputChannelInfo[3].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB); 215 fOutputChannelInfo[3].source_gain[2] = 0.9; 216 fOutputChannelInfo[3].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO); 217 fOutputChannelInfo[3].source_gain[3] = 0.6; 218 fOutputChannelInfo[3].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT); 219 } else if (count == 5 && mask == (B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT | B_CHANNEL_CENTER)) { 220 TRACE("AssignDefaultSources: 5 channel setup\n"); 221 // left channel: 222 fOutputChannelInfo[0].source_count = 4; 223 fOutputChannelInfo[0].source_gain[0] = 1.0; 224 fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT); 225 fOutputChannelInfo[0].source_gain[1] = 0.6; 226 fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB); 227 fOutputChannelInfo[0].source_gain[2] = 1.0; 228 fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO); 229 fOutputChannelInfo[0].source_gain[3] = 0.6; 230 fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT); 231 // right channel: 232 fOutputChannelInfo[1].source_count = 4; 233 fOutputChannelInfo[1].source_gain[0] = 1.0; 234 fOutputChannelInfo[1].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_RIGHT); 235 fOutputChannelInfo[1].source_gain[1] = 0.6; 236 fOutputChannelInfo[1].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB); 237 fOutputChannelInfo[1].source_gain[2] = 1.0; 238 fOutputChannelInfo[1].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO); 239 fOutputChannelInfo[1].source_gain[3] = 0.6; 240 fOutputChannelInfo[1].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT); 241 // rear-left channel: 242 fOutputChannelInfo[2].source_count = 4; 243 fOutputChannelInfo[2].source_gain[0] = 1.0; 244 fOutputChannelInfo[2].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT); 245 fOutputChannelInfo[2].source_gain[1] = 0.6; 246 fOutputChannelInfo[2].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB); 247 fOutputChannelInfo[2].source_gain[2] = 0.9; 248 fOutputChannelInfo[2].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO); 249 fOutputChannelInfo[2].source_gain[3] = 0.6; 250 fOutputChannelInfo[2].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_LEFT); 251 // rear-right channel: 252 fOutputChannelInfo[3].source_count = 4; 253 fOutputChannelInfo[3].source_gain[0] = 1.0; 254 fOutputChannelInfo[3].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT); 255 fOutputChannelInfo[3].source_gain[1] = 0.6; 256 fOutputChannelInfo[3].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB); 257 fOutputChannelInfo[3].source_gain[2] = 0.9; 258 fOutputChannelInfo[3].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO); 259 fOutputChannelInfo[3].source_gain[3] = 0.6; 260 fOutputChannelInfo[3].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SIDE_RIGHT); 261 // center channel: 262 fOutputChannelInfo[4].source_count = 3; 263 fOutputChannelInfo[4].source_gain[0] = 1.0; 264 fOutputChannelInfo[4].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_CENTER); 265 fOutputChannelInfo[4].source_gain[1] = 0.5; 266 fOutputChannelInfo[4].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB); 267 fOutputChannelInfo[4].source_gain[2] = 0.8; 268 fOutputChannelInfo[4].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_MONO); 269 } else { 270 TRACE("AssignDefaultSources: no default setup, adding mono channel to first two channels\n"); 271 if (count >= 1) { 272 // this is not a left channel, but we add the mono channel anyway 273 fOutputChannelInfo[0].source_gain[fOutputChannelInfo[0].source_count] = 1.0; 274 fOutputChannelInfo[0].source_type[fOutputChannelInfo[0].source_count] = ChannelMaskToChannelType(B_CHANNEL_MONO); 275 fOutputChannelInfo[0].source_count++; 276 } 277 if (count >= 2) { 278 // this is not a right channel, but we add the mono channel anyway 279 fOutputChannelInfo[1].source_gain[fOutputChannelInfo[1].source_count] = 1.0; 280 fOutputChannelInfo[1].source_type[fOutputChannelInfo[1].source_count] = ChannelMaskToChannelType(B_CHANNEL_MONO); 281 fOutputChannelInfo[1].source_count++; 282 } 283 } 284 285 for (int i = 0; i < fOutputChannelCount; i++) { 286 for (int j = 0; j < fOutputChannelInfo[i].source_count; j++) { 287 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]); 288 } 289 } 290 } 291 292 int 293 MixerOutput::GetOutputChannelType(int channel) 294 { 295 if (channel < 0 || channel >= fOutputChannelCount) 296 return 0; 297 return fOutputChannelInfo[channel].channel_type; 298 } 299 300 void 301 MixerOutput::SetOutputChannelGain(int channel, float gain) 302 { 303 TRACE("SetOutputChannelGain chan %d, gain %.5f\n", channel, gain); 304 if (channel < 0 || channel >= fOutputChannelCount) 305 return; 306 fOutputChannelInfo[channel].channel_gain = gain; 307 } 308 309 void 310 MixerOutput::AddOutputChannelSource(int channel, int source_type) 311 { 312 if (channel < 0 || channel >= fOutputChannelCount) 313 return; 314 if (source_type < 0 || source_type >= MAX_CHANNEL_TYPES) 315 return; 316 if (fOutputChannelInfo[channel].source_count == MAX_SOURCE_ENTRIES) 317 return; 318 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) { 319 if (fOutputChannelInfo[channel].source_type[i] == source_type) 320 return; 321 } 322 // when adding a new source, use the current gain value from cache 323 float source_gain = fOutputChannelInfo[channel].source_gain_cache[source_type]; 324 fOutputChannelInfo[channel].source_type[fOutputChannelInfo[channel].source_count] = source_type; 325 fOutputChannelInfo[channel].source_gain[fOutputChannelInfo[channel].source_count] = source_gain; 326 fOutputChannelInfo[channel].source_count++; 327 } 328 329 void 330 MixerOutput::RemoveOutputChannelSource(int channel, int source_type) 331 { 332 if (channel < 0 || channel >= fOutputChannelCount) 333 return; 334 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) { 335 if (fOutputChannelInfo[channel].source_type[i] == source_type) { 336 // when removing a source, save the current gain value into the cache 337 fOutputChannelInfo[channel].source_gain_cache[source_type] = fOutputChannelInfo[channel].source_gain[i]; 338 // remove the entry 339 fOutputChannelInfo[channel].source_type[i] = fOutputChannelInfo[channel].source_type[fOutputChannelInfo[channel].source_count - 1]; 340 fOutputChannelInfo[channel].source_gain[i] = fOutputChannelInfo[channel].source_gain[fOutputChannelInfo[channel].source_count - 1]; 341 fOutputChannelInfo[channel].source_count--; 342 return; 343 } 344 } 345 } 346 347 void 348 MixerOutput::SetOutputChannelSourceGain(int channel, int source_type, float source_gain) 349 { 350 if (channel < 0 || channel >= fOutputChannelCount) 351 return; 352 // set gain for active source 353 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) { 354 if (fOutputChannelInfo[channel].source_type[i] == source_type) { 355 fOutputChannelInfo[channel].source_gain[i] = source_gain; 356 return; 357 } 358 } 359 // we don't have an active source of that type, save gain in cache 360 if (source_type < 0 || source_type >= MAX_CHANNEL_TYPES) 361 return; 362 fOutputChannelInfo[channel].source_gain_cache[source_type] = source_gain; 363 } 364 365 float 366 MixerOutput::GetOutputChannelSourceGain(int channel, int source_type) 367 { 368 if (channel < 0 || channel >= fOutputChannelCount) 369 return 0.0; 370 // get gain for active source 371 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) { 372 if (fOutputChannelInfo[channel].source_type[i] == source_type) { 373 return fOutputChannelInfo[channel].source_gain[i]; 374 } 375 } 376 // we don't have an active source of that type, get gain from cache 377 if (source_type < 0 || source_type >= MAX_CHANNEL_TYPES) 378 return 0.0; 379 return fOutputChannelInfo[channel].source_gain_cache[source_type]; 380 } 381 382 bool 383 MixerOutput::HasOutputChannelSource(int channel, int source_type) 384 { 385 if (channel < 0 || channel >= fOutputChannelCount) 386 return false; 387 for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) { 388 if (fOutputChannelInfo[channel].source_type[i] == source_type) { 389 return true; 390 } 391 } 392 return false; 393 } 394 395 void 396 MixerOutput::SetMuted(bool yesno) 397 { 398 fMuted = yesno; 399 } 400