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