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