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