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