1 /* 2 * Copyright 2003-2010 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 "MixerCore.h" 11 12 #include <Buffer.h> 13 #include <string.h> 14 #include <TimeSource.h> // TODO: debug only 15 16 #include "ByteSwap.h" 17 #include "Interpolate.h" 18 #include "MixerInput.h" 19 #include "MixerUtils.h" 20 #include "Resampler.h" 21 22 23 MixerInput::MixerInput(MixerCore* core, const media_input& input, 24 float mixFrameRate, int32 mixFrameCount) 25 : 26 fCore(core), 27 fInput(input), 28 fInputByteSwap(NULL), 29 fEnabled(true), 30 fInputChannelInfo(NULL), 31 fInputChannelCount(0), 32 fInputChannelMask(0), 33 fMixerChannelInfo(0), 34 fMixerChannelCount(0), 35 fMixBuffer(NULL), 36 fMixBufferFrameRate(0), 37 fMixBufferFrameCount(0), 38 fLastDataFrameWritten(-1), 39 fLastDataAvailableTime(-1), 40 fFractionalFrames(0.0), 41 fResampler(NULL), 42 fRtmPool(NULL), 43 fUserOverridesChannelDestinations(false) 44 { 45 fix_multiaudio_format(&fInput.format.u.raw_audio); 46 PRINT_INPUT("MixerInput::MixerInput", fInput); 47 PRINT_CHANNEL_MASK(fInput.format); 48 49 ASSERT(fInput.format.u.raw_audio.channel_count > 0); 50 51 for (int i = 0; i < MAX_CHANNEL_TYPES; i++) 52 fChannelTypeGain[i] = 1.0f; 53 54 fInputChannelCount = fInput.format.u.raw_audio.channel_count; 55 fInputChannelMask = fInput.format.u.raw_audio.channel_mask; 56 fInputChannelInfo = new input_chan_info[fInputChannelCount]; 57 58 // perhaps we need byte swapping 59 if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) { 60 if (fInput.format.u.raw_audio.format 61 == media_raw_audio_format::B_AUDIO_FLOAT 62 || fInput.format.u.raw_audio.format 63 == media_raw_audio_format::B_AUDIO_INT 64 || fInput.format.u.raw_audio.format 65 == media_raw_audio_format::B_AUDIO_SHORT) { 66 fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format); 67 } 68 } 69 70 // initialize fInputChannelInfo 71 for (int i = 0; i < fInputChannelCount; i++) { 72 fInputChannelInfo[i].buffer_base = 0; 73 // will be set by SetMixBufferFormat() 74 fInputChannelInfo[i].destination_mask = 0; 75 // will be set by _UpdateInputChannelDestinationMask() 76 fInputChannelInfo[i].gain = 1.0; 77 } 78 79 UpdateResamplingAlgorithm(); 80 81 // fMixerChannelInfo and fMixerChannelCount will be initialized by 82 // _UpdateInputChannelDestinations() 83 SetMixBufferFormat((int32)mixFrameRate, mixFrameCount); 84 } 85 86 87 MixerInput::~MixerInput() 88 { 89 if (fMixBuffer) 90 rtm_free(fMixBuffer); 91 if (fRtmPool) 92 rtm_delete_pool(fRtmPool); 93 delete[] fInputChannelInfo; 94 delete[] fMixerChannelInfo; 95 96 // delete resamplers 97 if (fResampler != NULL) { 98 for (int i = 0; i < fInputChannelCount; i++) 99 delete fResampler[i]; 100 delete[] fResampler; 101 } 102 delete fInputByteSwap; 103 } 104 105 106 int32 107 MixerInput::ID() 108 { 109 return fInput.destination.id; 110 } 111 112 113 media_input& 114 MixerInput::MediaInput() 115 { 116 return fInput; 117 } 118 119 120 void 121 MixerInput::BufferReceived(BBuffer* buffer) 122 { 123 void* data; 124 size_t size; 125 bigtime_t start; 126 bigtime_t buffer_duration; 127 128 if (!fMixBuffer) { 129 ERROR("MixerInput::BufferReceived: dropped incoming buffer as we " 130 "don't have a mix buffer\n"); 131 return; 132 } 133 134 data = buffer->Data(); 135 size = buffer->SizeUsed(); 136 start = buffer->Header()->start_time; 137 buffer_duration = duration_for_frames(fInput.format.u.raw_audio.frame_rate, 138 size / bytes_per_frame(fInput.format.u.raw_audio)); 139 if (start < 0) { 140 ERROR("MixerInput::BufferReceived: buffer with negative start time of " 141 "%lld dropped\n", start); 142 return; 143 } 144 145 // swap the byte order of this buffer, if necessary 146 if (fInputByteSwap) 147 fInputByteSwap->Swap(data, size); 148 149 int offset = frames_for_duration(fMixBufferFrameRate, start) 150 % fMixBufferFrameCount; 151 152 PRINT(4, "MixerInput::BufferReceived: buffer start %10Ld, offset %6d\n", 153 start, offset); 154 155 int in_frames = size / bytes_per_frame(fInput.format.u.raw_audio); 156 double frames = ((double)in_frames * fMixBufferFrameRate) 157 / fInput.format.u.raw_audio.frame_rate; 158 int out_frames = int(frames); 159 fFractionalFrames += frames - double(out_frames); 160 if (fFractionalFrames >= 1.0) { 161 fFractionalFrames -= 1.0; 162 out_frames++; 163 } 164 165 // if fLastDataFrameWritten != -1, then we have a valid last position 166 // and can do glitch compensation 167 if (fLastDataFrameWritten >= 0) { 168 int expected_frame = (fLastDataFrameWritten + 1) 169 % fMixBufferFrameCount; 170 if (offset != expected_frame) { 171 // due to rounding and other errors, offset might be off by +/- 1 172 // this is not really a bad glitch, we just adjust the position 173 if (offset == fLastDataFrameWritten) { 174 // printf("MixerInput::BufferReceived: -1 frame GLITCH! last " 175 // "frame was %ld, expected frame was %d, new frame is %d\n", 176 // fLastDataFrameWritten, expected_frame, offset); 177 offset = expected_frame; 178 } else if (offset == ((fLastDataFrameWritten + 2) 179 % fMixBufferFrameCount)) { 180 // printf("MixerInput::BufferReceived: +1 frame GLITCH! last " 181 // "frame was %ld, expected frame was %d, new frame is %d\n", 182 // fLastDataFrameWritten, expected_frame, offset); 183 offset = expected_frame; 184 } else { 185 printf("MixerInput::BufferReceived: GLITCH! last frame was " 186 "%4" B_PRId32 ", expected frame was %4d, new frame is %4d" 187 "\n", fLastDataFrameWritten, expected_frame, offset); 188 189 if (start > fLastDataAvailableTime) { 190 if ((start - fLastDataAvailableTime) 191 < (buffer_duration / 10)) { 192 // buffer is less than 10% of buffer duration too late 193 printf("short glitch, buffer too late, time delta " 194 "%" B_PRIdBIGTIME "\n", start 195 - fLastDataAvailableTime); 196 offset = expected_frame; 197 out_frames++; 198 } else { 199 // buffer more than 10% of buffer duration too late 200 // TODO: zerofill buffer 201 printf("MAJOR glitch, buffer too late, time delta " 202 "%" B_PRIdBIGTIME "\n", start 203 - fLastDataAvailableTime); 204 } 205 } else { // start <= fLastDataAvailableTime 206 // the new buffer is too early 207 if ((fLastDataAvailableTime - start) 208 < (buffer_duration / 10)) { 209 // buffer is less than 10% of buffer duration too early 210 printf("short glitch, buffer too early, time delta " 211 "%" B_PRIdBIGTIME "\n", fLastDataAvailableTime 212 - start); 213 offset = expected_frame; 214 out_frames--; 215 if (out_frames < 1) 216 out_frames = 1; 217 } else { 218 // buffer more than 10% of buffer duration too early 219 // TODO: zerofill buffer 220 printf("MAJOR glitch, buffer too early, time delta " 221 "%" B_PRIdBIGTIME "\n", fLastDataAvailableTime 222 - start); 223 } 224 } 225 } 226 } 227 } 228 229 // printf("data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n", 230 // start, 231 // start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, 232 // frames_per_buffer(fInput.format.u.raw_audio)), offset, 233 // offset + out_frames); 234 if (offset + out_frames > fMixBufferFrameCount) { 235 int out_frames1 = fMixBufferFrameCount - offset; 236 int out_frames2 = out_frames - out_frames1; 237 int in_frames1 = (out_frames1 * in_frames) / out_frames; 238 int in_frames2 = in_frames - in_frames1; 239 240 // printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at " 241 // "frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(), 242 // start, 243 // start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, 244 // frames_per_buffer(fInput.format.u.raw_audio)), offset, 245 // offset + out_frames1 - 1, 0, out_frames2 - 1); 246 PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at " 247 "frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(), 248 start, 249 start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, 250 frames_per_buffer(fInput.format.u.raw_audio)), offset, 251 offset + out_frames1 - 1, 0, out_frames2 - 1); 252 PRINT(5, " in_frames %5d, out_frames %5d, in_frames1 %5d, " 253 "out_frames1 %5d, in_frames2 %5d, out_frames2 %5d\n", 254 in_frames, out_frames, in_frames1, out_frames1, in_frames2, 255 out_frames2); 256 257 fLastDataFrameWritten = out_frames2 - 1; 258 259 // convert offset from frames into bytes 260 offset *= sizeof(float) * fInputChannelCount; 261 262 for (int i = 0; i < fInputChannelCount; i++) { 263 fResampler[i]->Resample( 264 reinterpret_cast<char*>(data) 265 + i * bytes_per_sample(fInput.format.u.raw_audio), 266 bytes_per_frame(fInput.format.u.raw_audio), in_frames1, 267 reinterpret_cast<char*>(fInputChannelInfo[i].buffer_base) 268 + offset, fInputChannelCount * sizeof(float), out_frames1, 269 fInputChannelInfo[i].gain); 270 271 fResampler[i]->Resample( 272 reinterpret_cast<char*>(data) 273 + i * bytes_per_sample(fInput.format.u.raw_audio) 274 + in_frames1 * bytes_per_frame(fInput.format.u.raw_audio), 275 bytes_per_frame(fInput.format.u.raw_audio), in_frames2, 276 reinterpret_cast<char*>(fInputChannelInfo[i].buffer_base), 277 fInputChannelCount * sizeof(float), out_frames2, 278 fInputChannelInfo[i].gain); 279 280 } 281 } else { 282 // printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at " 283 // "frames %ld to %ld\n", fCore->fTimeSource->Now(), start, 284 // start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, 285 // frames_per_buffer(fInput.format.u.raw_audio)), offset, 286 // offset + out_frames - 1); 287 PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at " 288 "frames %ld to %ld\n", fCore->fTimeSource->Now(), start, 289 start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, 290 frames_per_buffer(fInput.format.u.raw_audio)), offset, 291 offset + out_frames - 1); 292 PRINT(5, " in_frames %5d, out_frames %5d\n", in_frames, out_frames); 293 294 fLastDataFrameWritten = offset + out_frames - 1; 295 // convert offset from frames into bytes 296 offset *= sizeof(float) * fInputChannelCount; 297 for (int i = 0; i < fInputChannelCount; i++) { 298 fResampler[i]->Resample( 299 reinterpret_cast<char*>(data) 300 + i * bytes_per_sample(fInput.format.u.raw_audio), 301 bytes_per_frame(fInput.format.u.raw_audio), in_frames, 302 reinterpret_cast<char*>(fInputChannelInfo[i].buffer_base) 303 + offset, fInputChannelCount * sizeof(float), 304 out_frames, fInputChannelInfo[i].gain); 305 } 306 } 307 fLastDataAvailableTime = start + buffer_duration; 308 } 309 310 311 void 312 MixerInput::UpdateResamplingAlgorithm() 313 { 314 if (fResampler != NULL) { 315 for (int i = 0; i < fInputChannelCount; i++) 316 delete fResampler[i]; 317 delete[] fResampler; 318 } 319 // create resamplers 320 fResampler = new Resampler*[fInputChannelCount]; 321 for (int i = 0; i < fInputChannelCount; i++) { 322 switch (fCore->Settings()->ResamplingAlgorithm()) { 323 case 2: 324 fResampler[i] = new Interpolate( 325 fInput.format.u.raw_audio.format, 326 media_raw_audio_format::B_AUDIO_FLOAT); 327 break; 328 default: 329 fResampler[i] = new Resampler( 330 fInput.format.u.raw_audio.format, 331 media_raw_audio_format::B_AUDIO_FLOAT); 332 } 333 } 334 } 335 336 337 int 338 MixerInput::GetInputChannelCount() 339 { 340 return fInputChannelCount; 341 } 342 343 344 void 345 MixerInput::AddInputChannelDestination(int channel, int destination_type) 346 { 347 uint32 mask = ChannelTypeToChannelMask(destination_type); 348 349 if (channel < 0 || channel >= fInputChannelCount) 350 return; 351 352 // test if it is already set 353 if (fInputChannelInfo[channel].destination_mask & mask) 354 return; 355 356 // verify that no other channel has id 357 if (-1 != GetInputChannelForDestination(destination_type)) { 358 ERROR("MixerInput::AddInputChannelDestination: destination_type %d " 359 "already assigned to channel %d\n", destination_type, 360 GetInputChannelForDestination(destination_type)); 361 return; 362 } 363 364 // add it to specified channel 365 fInputChannelInfo[channel].destination_mask |= mask; 366 367 fUserOverridesChannelDestinations = true; 368 _UpdateInputChannelDestinations(); 369 } 370 371 372 void 373 MixerInput::RemoveInputChannelDestination(int channel, int destination_type) 374 { 375 uint32 mask = ChannelTypeToChannelMask(destination_type); 376 377 if (channel < 0 || channel >= fInputChannelCount) 378 return; 379 380 // test if it is really set 381 if ((fInputChannelInfo[channel].destination_mask & mask) == 0) 382 return; 383 384 // remove it from specified channel 385 fInputChannelInfo[channel].destination_mask &= ~mask; 386 387 fUserOverridesChannelDestinations = true; 388 _UpdateInputChannelDestinations(); 389 } 390 391 392 bool 393 MixerInput::HasInputChannelDestination(int channel, int destination_type) 394 { 395 if (channel < 0 || channel >= fInputChannelCount) 396 return false; 397 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 398 return false; 399 return fInputChannelInfo[channel].destination_mask 400 & ChannelTypeToChannelMask(destination_type); 401 } 402 403 404 int 405 MixerInput::GetInputChannelForDestination(int destination_type) 406 { 407 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 408 return -1; 409 uint32 mask = ChannelTypeToChannelMask(destination_type); 410 for (int chan = 0; chan < fInputChannelCount; chan++) { 411 if (fInputChannelInfo[chan].destination_mask & mask) 412 return chan; 413 } 414 return -1; 415 } 416 417 418 int 419 MixerInput::GetInputChannelType(int channel) 420 { 421 if (channel < 0 || channel >= fInputChannelCount) 422 return 0; 423 return GetChannelType(channel, fInputChannelMask); 424 } 425 426 427 void 428 MixerInput::SetInputChannelGain(int channel, float gain) 429 { 430 if (channel < 0 || channel >= fInputChannelCount) 431 return; 432 if (gain < 0.0f) 433 gain = 0.0f; 434 435 fInputChannelInfo[channel].gain = gain; 436 } 437 438 439 float 440 MixerInput::GetInputChannelGain(int channel) 441 { 442 if (channel < 0 || channel >= fInputChannelCount) 443 return 0.0f; 444 return fInputChannelInfo[channel].gain; 445 } 446 447 448 void 449 MixerInput::_UpdateInputChannelDestinationMask() 450 { 451 // is the user already messed with the assignmens, don't do anything. 452 if (fUserOverridesChannelDestinations) 453 return; 454 455 TRACE("_UpdateInputChannelDestinationMask: enter\n"); 456 457 // first apply a 1:1 mapping 458 for (int i = 0; i < fInputChannelCount; i++) { 459 fInputChannelInfo[i].destination_mask = GetChannelMask(i, 460 fInputChannelMask); 461 } 462 463 // specialize this, depending on the available physical output channels 464 if (fCore->OutputChannelCount() <= 2) { 465 // less or equal two channels 466 if (fInputChannelCount == 1 467 && (GetChannelMask(0, fInputChannelMask) 468 & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { 469 fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO; 470 } 471 } else { 472 // more than two channel output card 473 if (fInputChannelCount == 1 474 && (GetChannelMask(0, fInputChannelMask) 475 & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { 476 fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO; 477 } 478 if (fInputChannelCount == 2 479 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) { 480 fInputChannelInfo[0].destination_mask 481 = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT; 482 } 483 if (fInputChannelCount == 2 484 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) { 485 fInputChannelInfo[0].destination_mask 486 = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT; 487 } 488 if (fInputChannelCount == 2 489 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) { 490 fInputChannelInfo[1].destination_mask 491 = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT; 492 } 493 if (fInputChannelCount == 2 494 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) { 495 fInputChannelInfo[1].destination_mask 496 = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT; 497 } 498 } 499 500 for (int i = 0; i < fInputChannelCount; i++) { 501 TRACE("_UpdateInputChannelDestinationMask: input channel %d, " 502 "destination_mask 0x%08lX, base %p, gain %.3f\n", i, 503 fInputChannelInfo[i].destination_mask, 504 fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); 505 } 506 TRACE("_UpdateInputChannelDestinationMask: leave\n"); 507 } 508 509 510 void 511 MixerInput::_UpdateInputChannelDestinations() 512 { 513 int channel_count; 514 uint32 all_bits; 515 uint32 mask; 516 517 TRACE("_UpdateInputChannelDestinations: enter\n"); 518 for (int i = 0; i < fInputChannelCount; i++) { 519 TRACE("_UpdateInputChannelDestinations: input channel %d, " 520 "destination_mask 0x%08lX, base %p, gain %.3f\n", i, 521 fInputChannelInfo[i].destination_mask, 522 fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); 523 } 524 525 all_bits = 0; 526 for (int i = 0; i < fInputChannelCount; i++) 527 all_bits |= fInputChannelInfo[i].destination_mask; 528 529 TRACE("_UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits); 530 531 channel_count = count_nonzero_bits(all_bits); 532 TRACE("_UpdateInputChannelDestinations: %d input channels, %d mixer " 533 "channels (%d old)\n", fInputChannelCount, channel_count, 534 fMixerChannelCount); 535 if (channel_count != fMixerChannelCount) { 536 delete [] fMixerChannelInfo; 537 fMixerChannelInfo = new mixer_chan_info[channel_count]; 538 fMixerChannelCount = channel_count; 539 } 540 541 // assign each mixer channel one type 542 // and the gain from the fChannelTypeGain[] 543 mask = 1; 544 for (int i = 0; i < fMixerChannelCount; i++) { 545 while (mask != 0 && (all_bits & mask) == 0) 546 mask <<= 1; 547 fMixerChannelInfo[i].destination_type = ChannelMaskToChannelType(mask); 548 fMixerChannelInfo[i].destination_gain 549 = fChannelTypeGain[fMixerChannelInfo[i].destination_type]; 550 mask <<= 1; 551 } 552 553 // assign buffer_base pointer for each mixer channel 554 for (int i = 0; i < fMixerChannelCount; i++) { 555 int j; 556 for (j = 0; j < fInputChannelCount; j++) { 557 if (fInputChannelInfo[j].destination_mask 558 & ChannelTypeToChannelMask( 559 fMixerChannelInfo[i].destination_type)) { 560 fMixerChannelInfo[i].buffer_base = fMixBuffer ? &fMixBuffer[j] 561 : 0; 562 break; 563 } 564 } 565 if (j == fInputChannelCount) { 566 ERROR("buffer assignment failed for mixer chan %d\n", i); 567 fMixerChannelInfo[i].buffer_base = fMixBuffer; 568 } 569 } 570 571 for (int i = 0; i < fMixerChannelCount; i++) { 572 TRACE("_UpdateInputChannelDestinations: mixer channel %d, type %2d, " 573 "base %p, gain %.3f\n", i, fMixerChannelInfo[i].destination_type, 574 fMixerChannelInfo[i].buffer_base, 575 fMixerChannelInfo[i].destination_gain); 576 } 577 578 TRACE("_UpdateInputChannelDestinations: leave\n"); 579 } 580 581 582 // Note: The following code is outcommented on purpose 583 // and is about to be modified at a later point 584 /* 585 void 586 MixerInput::SetInputChannelDestinationGain(int channel, int destination_type, 587 float gain) 588 { 589 TRACE("SetInputChannelDestinationGain: channel %d, destination_type %d, 590 gain %.4f\n", channel, destination_type, gain); 591 // we don't need the channel, as each destination_type can only exist 592 // once for each MixerInput, but we use it for parameter validation 593 // and to have a interface similar to MixerOutput 594 if (channel < 0 || channel >= fMixerChannelCount) 595 return; 596 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 597 return; 598 if (gain < 0.0f) 599 gain = 0.0f; 600 fChannelTypeGain[destination_type] = gain; 601 for (int i = 0; i < fMixerChannelCount; i++) { 602 if (fMixerChannelInfo[i].destination_type == destination_type) { 603 fMixerChannelInfo[i].destination_gain = gain; 604 return; 605 } 606 } 607 } 608 609 610 float 611 MixerInput::GetInputChannelDestinationGain(int channel, int destination_type) 612 { 613 // we don't need the channel, as each destination_type can only exist 614 // once for each MixerInput, but we use it for parameter validation 615 // and to have a interface similar to MixerOutput 616 if (channel < 0 || channel >= fMixerChannelCount) 617 return 0.0f; 618 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES) 619 return 0.0f; 620 return fChannelTypeGain[destination_type]; 621 } 622 */ 623 624 625 void 626 MixerInput::SetMixerChannelGain(int mixer_channel, float gain) 627 { 628 if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount) 629 return; 630 if (gain < 0.0f) 631 gain = 0.0f; 632 633 fMixerChannelInfo[mixer_channel].destination_gain = gain; 634 fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain; 635 } 636 637 638 float 639 MixerInput::GetMixerChannelGain(int mixer_channel) 640 { 641 if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount) 642 return 0.0; 643 return fMixerChannelInfo[mixer_channel].destination_gain; 644 } 645 646 647 int 648 MixerInput::GetMixerChannelType(int mixer_channel) 649 { 650 if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount) 651 return -1; 652 return fMixerChannelInfo[mixer_channel].destination_type; 653 } 654 655 656 void 657 MixerInput::SetEnabled(bool yesno) 658 { 659 fEnabled = yesno; 660 } 661 662 663 bool 664 MixerInput::IsEnabled() 665 { 666 return fEnabled; 667 } 668 669 670 void 671 MixerInput::SetMixBufferFormat(int32 framerate, int32 frames) 672 { 673 TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n", 674 framerate, frames); 675 676 fMixBufferFrameRate = framerate; 677 fDebugMixBufferFrames = frames; 678 679 // frames and/or framerate can be 0 (if no output is connected) 680 if (framerate == 0 || frames == 0) { 681 if (fMixBuffer != NULL) { 682 rtm_free(fMixBuffer); 683 fMixBuffer = NULL; 684 } 685 for (int i = 0; i < fInputChannelCount; i++) 686 fInputChannelInfo[i].buffer_base = 0; 687 fMixBufferFrameCount = 0; 688 689 _UpdateInputChannelDestinationMask(); 690 _UpdateInputChannelDestinations(); 691 return; 692 } 693 694 // make fMixBufferFrameCount an integral multiple of frames, 695 // but at least 3 times duration of our input buffer 696 // and at least 2 times duration of the output buffer 697 bigtime_t inputBufferLength = duration_for_frames( 698 fInput.format.u.raw_audio.frame_rate, 699 frames_per_buffer(fInput.format.u.raw_audio)); 700 bigtime_t outputBufferLength = duration_for_frames(framerate, frames); 701 bigtime_t mixerBufferLength 702 = max_c(3 * inputBufferLength, 2 * outputBufferLength); 703 int temp = frames_for_duration(framerate, mixerBufferLength); 704 fMixBufferFrameCount = ((temp / frames) + 1) * frames; 705 706 TRACE(" inputBufferLength %10Ld\n", inputBufferLength); 707 TRACE(" outputBufferLength %10Ld\n", outputBufferLength); 708 TRACE(" mixerBufferLength %10Ld\n", mixerBufferLength); 709 TRACE(" fMixBufferFrameCount %10d\n", fMixBufferFrameCount); 710 711 ASSERT((fMixBufferFrameCount % frames) == 0); 712 713 fLastDataFrameWritten = -1; 714 fFractionalFrames = 0.0; 715 716 rtm_free(fMixBuffer); 717 rtm_delete_pool(fRtmPool); 718 719 int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount; 720 if (rtm_create_pool(&fRtmPool, size) != B_OK) 721 fRtmPool = NULL; 722 723 fMixBuffer = (float*)rtm_alloc(fRtmPool, size); 724 if (fMixBuffer == NULL) 725 return; 726 727 memset(fMixBuffer, 0, size); 728 729 for (int i = 0; i < fInputChannelCount; i++) 730 fInputChannelInfo[i].buffer_base = &fMixBuffer[i]; 731 732 _UpdateInputChannelDestinationMask(); 733 _UpdateInputChannelDestinations(); 734 } 735