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