3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / media / media-add-ons / mixer / MixerInput.cpp
blob420a2d728bf85d8c22ce04e0f293f3669ba8de57
1 /*
2 * Copyright 2003-2010 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Marcus Overhagen
7 */
10 #include "MixerCore.h"
12 #include <Buffer.h>
13 #include <string.h>
14 #include <TimeSource.h> // TODO: debug only
16 #include "ByteSwap.h"
17 #include "Interpolate.h"
18 #include "MixerInput.h"
19 #include "MixerUtils.h"
20 #include "Resampler.h"
23 MixerInput::MixerInput(MixerCore* core, const media_input& input,
24 float mixFrameRate, int32 mixFrameCount)
26 fCore(core),
27 fInput(input),
28 fInputByteSwap(NULL),
29 fEnabled(true),
30 fInputChannelInfo(NULL),
31 fInputChannelCount(0),
32 fInputChannelMask(0),
33 fMixerChannelInfo(0),
34 fMixerChannelCount(0),
35 fMixBuffer(NULL),
36 fMixBufferFrameRate(0),
37 fMixBufferFrameCount(0),
38 fLastDataFrameWritten(-1),
39 fLastDataAvailableTime(-1),
40 fFractionalFrames(0.0),
41 fResampler(NULL),
42 fRtmPool(NULL),
43 fUserOverridesChannelDestinations(false)
45 fix_multiaudio_format(&fInput.format.u.raw_audio);
46 PRINT_INPUT("MixerInput::MixerInput", fInput);
47 PRINT_CHANNEL_MASK(fInput.format);
49 ASSERT(fInput.format.u.raw_audio.channel_count > 0);
51 for (int i = 0; i < MAX_CHANNEL_TYPES; i++)
52 fChannelTypeGain[i] = 1.0f;
54 fInputChannelCount = fInput.format.u.raw_audio.channel_count;
55 fInputChannelMask = fInput.format.u.raw_audio.channel_mask;
56 fInputChannelInfo = new input_chan_info[fInputChannelCount];
58 // perhaps we need byte swapping
59 if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) {
60 if (fInput.format.u.raw_audio.format
61 == media_raw_audio_format::B_AUDIO_FLOAT
62 || fInput.format.u.raw_audio.format
63 == media_raw_audio_format::B_AUDIO_INT
64 || fInput.format.u.raw_audio.format
65 == media_raw_audio_format::B_AUDIO_SHORT) {
66 fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format);
70 // initialize fInputChannelInfo
71 for (int i = 0; i < fInputChannelCount; i++) {
72 fInputChannelInfo[i].buffer_base = 0;
73 // will be set by SetMixBufferFormat()
74 fInputChannelInfo[i].destination_mask = 0;
75 // will be set by _UpdateInputChannelDestinationMask()
76 fInputChannelInfo[i].gain = 1.0;
79 UpdateResamplingAlgorithm();
81 // fMixerChannelInfo and fMixerChannelCount will be initialized by
82 // _UpdateInputChannelDestinations()
83 SetMixBufferFormat((int32)mixFrameRate, mixFrameCount);
87 MixerInput::~MixerInput()
89 if (fMixBuffer)
90 rtm_free(fMixBuffer);
91 if (fRtmPool)
92 rtm_delete_pool(fRtmPool);
93 delete[] fInputChannelInfo;
94 delete[] fMixerChannelInfo;
96 // delete resamplers
97 if (fResampler != NULL) {
98 for (int i = 0; i < fInputChannelCount; i++)
99 delete fResampler[i];
100 delete[] fResampler;
102 delete fInputByteSwap;
106 int32
107 MixerInput::ID()
109 return fInput.destination.id;
113 media_input&
114 MixerInput::MediaInput()
116 return fInput;
120 void
121 MixerInput::BufferReceived(BBuffer* buffer)
123 void* data;
124 size_t size;
125 bigtime_t start;
126 bigtime_t buffer_duration;
128 if (!fMixBuffer) {
129 ERROR("MixerInput::BufferReceived: dropped incoming buffer as we "
130 "don't have a mix buffer\n");
131 return;
134 data = buffer->Data();
135 size = buffer->SizeUsed();
136 start = buffer->Header()->start_time;
137 buffer_duration = duration_for_frames(fInput.format.u.raw_audio.frame_rate,
138 size / bytes_per_frame(fInput.format.u.raw_audio));
139 if (start < 0) {
140 ERROR("MixerInput::BufferReceived: buffer with negative start time of "
141 "%Ld dropped\n", start);
142 return;
145 // swap the byte order of this buffer, if necessary
146 if (fInputByteSwap)
147 fInputByteSwap->Swap(data, size);
149 int offset = frames_for_duration(fMixBufferFrameRate, start)
150 % fMixBufferFrameCount;
152 PRINT(4, "MixerInput::BufferReceived: buffer start %10Ld, offset %6d\n",
153 start, offset);
155 int in_frames = size / bytes_per_frame(fInput.format.u.raw_audio);
156 double frames = ((double)in_frames * fMixBufferFrameRate)
157 / fInput.format.u.raw_audio.frame_rate;
158 int out_frames = int(frames);
159 fFractionalFrames += frames - double(out_frames);
160 if (fFractionalFrames >= 1.0) {
161 fFractionalFrames -= 1.0;
162 out_frames++;
165 // if fLastDataFrameWritten != -1, then we have a valid last position
166 // and can do glitch compensation
167 if (fLastDataFrameWritten >= 0) {
168 int expected_frame = (fLastDataFrameWritten + 1)
169 % fMixBufferFrameCount;
170 if (offset != expected_frame) {
171 // due to rounding and other errors, offset might be off by +/- 1
172 // this is not really a bad glitch, we just adjust the position
173 if (offset == fLastDataFrameWritten) {
174 // printf("MixerInput::BufferReceived: -1 frame GLITCH! last "
175 // "frame was %ld, expected frame was %d, new frame is %d\n",
176 // fLastDataFrameWritten, expected_frame, offset);
177 offset = expected_frame;
178 } else if (offset == ((fLastDataFrameWritten + 2)
179 % fMixBufferFrameCount)) {
180 // printf("MixerInput::BufferReceived: +1 frame GLITCH! last "
181 // "frame was %ld, expected frame was %d, new frame is %d\n",
182 // fLastDataFrameWritten, expected_frame, offset);
183 offset = expected_frame;
184 } else {
185 printf("MixerInput::BufferReceived: GLITCH! last frame was "
186 "%4" B_PRId32 ", expected frame was %4d, new frame is %4d"
187 "\n", fLastDataFrameWritten, expected_frame, offset);
189 if (start > fLastDataAvailableTime) {
190 if ((start - fLastDataAvailableTime)
191 < (buffer_duration / 10)) {
192 // buffer is less than 10% of buffer duration too late
193 printf("short glitch, buffer too late, time delta "
194 "%" B_PRIdBIGTIME "\n", start
195 - fLastDataAvailableTime);
196 offset = expected_frame;
197 out_frames++;
198 } else {
199 // buffer more than 10% of buffer duration too late
200 // TODO: zerofill buffer
201 printf("MAJOR glitch, buffer too late, time delta "
202 "%" B_PRIdBIGTIME "\n", start
203 - fLastDataAvailableTime);
205 } else { // start <= fLastDataAvailableTime
206 // the new buffer is too early
207 if ((fLastDataAvailableTime - start)
208 < (buffer_duration / 10)) {
209 // buffer is less than 10% of buffer duration too early
210 printf("short glitch, buffer too early, time delta "
211 "%" B_PRIdBIGTIME "\n", fLastDataAvailableTime
212 - start);
213 offset = expected_frame;
214 out_frames--;
215 if (out_frames < 1)
216 out_frames = 1;
217 } else {
218 // buffer more than 10% of buffer duration too early
219 // TODO: zerofill buffer
220 printf("MAJOR glitch, buffer too early, time delta "
221 "%" B_PRIdBIGTIME "\n", fLastDataAvailableTime
222 - start);
229 // printf("data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n",
230 // start,
231 // start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
232 // frames_per_buffer(fInput.format.u.raw_audio)), offset,
233 // offset + out_frames);
234 if (offset + out_frames > fMixBufferFrameCount) {
235 int out_frames1 = fMixBufferFrameCount - offset;
236 int out_frames2 = out_frames - out_frames1;
237 int in_frames1 = (out_frames1 * in_frames) / out_frames;
238 int in_frames2 = in_frames - in_frames1;
240 // printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at "
241 // "frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(),
242 // start,
243 // start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
244 // frames_per_buffer(fInput.format.u.raw_audio)), offset,
245 // offset + out_frames1 - 1, 0, out_frames2 - 1);
246 PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at "
247 "frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(),
248 start,
249 start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
250 frames_per_buffer(fInput.format.u.raw_audio)), offset,
251 offset + out_frames1 - 1, 0, out_frames2 - 1);
252 PRINT(5, " in_frames %5d, out_frames %5d, in_frames1 %5d, "
253 "out_frames1 %5d, in_frames2 %5d, out_frames2 %5d\n",
254 in_frames, out_frames, in_frames1, out_frames1, in_frames2,
255 out_frames2);
257 fLastDataFrameWritten = out_frames2 - 1;
259 // convert offset from frames into bytes
260 offset *= sizeof(float) * fInputChannelCount;
262 for (int i = 0; i < fInputChannelCount; i++) {
263 fResampler[i]->Resample(
264 reinterpret_cast<char*>(data)
265 + i * bytes_per_sample(fInput.format.u.raw_audio),
266 bytes_per_frame(fInput.format.u.raw_audio), in_frames1,
267 reinterpret_cast<char*>(fInputChannelInfo[i].buffer_base)
268 + offset, fInputChannelCount * sizeof(float), out_frames1,
269 fInputChannelInfo[i].gain);
271 fResampler[i]->Resample(
272 reinterpret_cast<char*>(data)
273 + i * bytes_per_sample(fInput.format.u.raw_audio)
274 + in_frames1 * bytes_per_frame(fInput.format.u.raw_audio),
275 bytes_per_frame(fInput.format.u.raw_audio), in_frames2,
276 reinterpret_cast<char*>(fInputChannelInfo[i].buffer_base),
277 fInputChannelCount * sizeof(float), out_frames2,
278 fInputChannelInfo[i].gain);
281 } else {
282 // printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at "
283 // "frames %ld to %ld\n", fCore->fTimeSource->Now(), start,
284 // start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
285 // frames_per_buffer(fInput.format.u.raw_audio)), offset,
286 // offset + out_frames - 1);
287 PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at "
288 "frames %ld to %ld\n", fCore->fTimeSource->Now(), start,
289 start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
290 frames_per_buffer(fInput.format.u.raw_audio)), offset,
291 offset + out_frames - 1);
292 PRINT(5, " in_frames %5d, out_frames %5d\n", in_frames, out_frames);
294 fLastDataFrameWritten = offset + out_frames - 1;
295 // convert offset from frames into bytes
296 offset *= sizeof(float) * fInputChannelCount;
297 for (int i = 0; i < fInputChannelCount; i++) {
298 fResampler[i]->Resample(
299 reinterpret_cast<char*>(data)
300 + i * bytes_per_sample(fInput.format.u.raw_audio),
301 bytes_per_frame(fInput.format.u.raw_audio), in_frames,
302 reinterpret_cast<char*>(fInputChannelInfo[i].buffer_base)
303 + offset, fInputChannelCount * sizeof(float),
304 out_frames, fInputChannelInfo[i].gain);
307 fLastDataAvailableTime = start + buffer_duration;
311 void
312 MixerInput::UpdateResamplingAlgorithm()
314 if (fResampler != NULL) {
315 for (int i = 0; i < fInputChannelCount; i++)
316 delete fResampler[i];
317 delete[] fResampler;
319 // create resamplers
320 fResampler = new Resampler*[fInputChannelCount];
321 for (int i = 0; i < fInputChannelCount; i++) {
322 switch (fCore->Settings()->ResamplingAlgorithm()) {
323 case 2:
324 fResampler[i] = new Interpolate(
325 fInput.format.u.raw_audio.format,
326 media_raw_audio_format::B_AUDIO_FLOAT);
327 break;
328 default:
329 fResampler[i] = new Resampler(
330 fInput.format.u.raw_audio.format,
331 media_raw_audio_format::B_AUDIO_FLOAT);
338 MixerInput::GetInputChannelCount()
340 return fInputChannelCount;
344 void
345 MixerInput::AddInputChannelDestination(int channel, int destination_type)
347 uint32 mask = ChannelTypeToChannelMask(destination_type);
349 if (channel < 0 || channel >= fInputChannelCount)
350 return;
352 // test if it is already set
353 if (fInputChannelInfo[channel].destination_mask & mask)
354 return;
356 // verify that no other channel has id
357 if (-1 != GetInputChannelForDestination(destination_type)) {
358 ERROR("MixerInput::AddInputChannelDestination: destination_type %d "
359 "already assigned to channel %d\n", destination_type,
360 GetInputChannelForDestination(destination_type));
361 return;
364 // add it to specified channel
365 fInputChannelInfo[channel].destination_mask |= mask;
367 fUserOverridesChannelDestinations = true;
368 _UpdateInputChannelDestinations();
372 void
373 MixerInput::RemoveInputChannelDestination(int channel, int destination_type)
375 uint32 mask = ChannelTypeToChannelMask(destination_type);
377 if (channel < 0 || channel >= fInputChannelCount)
378 return;
380 // test if it is really set
381 if ((fInputChannelInfo[channel].destination_mask & mask) == 0)
382 return;
384 // remove it from specified channel
385 fInputChannelInfo[channel].destination_mask &= ~mask;
387 fUserOverridesChannelDestinations = true;
388 _UpdateInputChannelDestinations();
392 bool
393 MixerInput::HasInputChannelDestination(int channel, int destination_type)
395 if (channel < 0 || channel >= fInputChannelCount)
396 return false;
397 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
398 return false;
399 return fInputChannelInfo[channel].destination_mask
400 & ChannelTypeToChannelMask(destination_type);
405 MixerInput::GetInputChannelForDestination(int destination_type)
407 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
408 return -1;
409 uint32 mask = ChannelTypeToChannelMask(destination_type);
410 for (int chan = 0; chan < fInputChannelCount; chan++) {
411 if (fInputChannelInfo[chan].destination_mask & mask)
412 return chan;
414 return -1;
419 MixerInput::GetInputChannelType(int channel)
421 if (channel < 0 || channel >= fInputChannelCount)
422 return 0;
423 return GetChannelType(channel, fInputChannelMask);
427 void
428 MixerInput::SetInputChannelGain(int channel, float gain)
430 if (channel < 0 || channel >= fInputChannelCount)
431 return;
432 if (gain < 0.0f)
433 gain = 0.0f;
435 fInputChannelInfo[channel].gain = gain;
439 float
440 MixerInput::GetInputChannelGain(int channel)
442 if (channel < 0 || channel >= fInputChannelCount)
443 return 0.0f;
444 return fInputChannelInfo[channel].gain;
448 void
449 MixerInput::_UpdateInputChannelDestinationMask()
451 // is the user already messed with the assignmens, don't do anything.
452 if (fUserOverridesChannelDestinations)
453 return;
455 TRACE("_UpdateInputChannelDestinationMask: enter\n");
457 // first apply a 1:1 mapping
458 for (int i = 0; i < fInputChannelCount; i++) {
459 fInputChannelInfo[i].destination_mask = GetChannelMask(i,
460 fInputChannelMask);
463 // specialize this, depending on the available physical output channels
464 if (fCore->OutputChannelCount() <= 2) {
465 // less or equal two channels
466 if (fInputChannelCount == 1
467 && (GetChannelMask(0, fInputChannelMask)
468 & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
469 fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO;
471 } else {
472 // more than two channel output card
473 if (fInputChannelCount == 1
474 && (GetChannelMask(0, fInputChannelMask)
475 & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
476 fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO;
478 if (fInputChannelCount == 2
479 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) {
480 fInputChannelInfo[0].destination_mask
481 = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
483 if (fInputChannelCount == 2
484 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) {
485 fInputChannelInfo[0].destination_mask
486 = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
488 if (fInputChannelCount == 2
489 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) {
490 fInputChannelInfo[1].destination_mask
491 = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
493 if (fInputChannelCount == 2
494 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) {
495 fInputChannelInfo[1].destination_mask
496 = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
500 for (int i = 0; i < fInputChannelCount; i++) {
501 TRACE("_UpdateInputChannelDestinationMask: input channel %d, "
502 "destination_mask 0x%08lX, base %p, gain %.3f\n", i,
503 fInputChannelInfo[i].destination_mask,
504 fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
506 TRACE("_UpdateInputChannelDestinationMask: leave\n");
510 void
511 MixerInput::_UpdateInputChannelDestinations()
513 int channel_count;
514 uint32 all_bits;
515 uint32 mask;
517 TRACE("_UpdateInputChannelDestinations: enter\n");
518 for (int i = 0; i < fInputChannelCount; i++) {
519 TRACE("_UpdateInputChannelDestinations: input channel %d, "
520 "destination_mask 0x%08lX, base %p, gain %.3f\n", i,
521 fInputChannelInfo[i].destination_mask,
522 fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
525 all_bits = 0;
526 for (int i = 0; i < fInputChannelCount; i++)
527 all_bits |= fInputChannelInfo[i].destination_mask;
529 TRACE("_UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits);
531 channel_count = count_nonzero_bits(all_bits);
532 TRACE("_UpdateInputChannelDestinations: %d input channels, %d mixer "
533 "channels (%d old)\n", fInputChannelCount, channel_count,
534 fMixerChannelCount);
535 if (channel_count != fMixerChannelCount) {
536 delete [] fMixerChannelInfo;
537 fMixerChannelInfo = new mixer_chan_info[channel_count];
538 fMixerChannelCount = channel_count;
541 // assign each mixer channel one type
542 // and the gain from the fChannelTypeGain[]
543 mask = 1;
544 for (int i = 0; i < fMixerChannelCount; i++) {
545 while (mask != 0 && (all_bits & mask) == 0)
546 mask <<= 1;
547 fMixerChannelInfo[i].destination_type = ChannelMaskToChannelType(mask);
548 fMixerChannelInfo[i].destination_gain
549 = fChannelTypeGain[fMixerChannelInfo[i].destination_type];
550 mask <<= 1;
553 // assign buffer_base pointer for each mixer channel
554 for (int i = 0; i < fMixerChannelCount; i++) {
555 int j;
556 for (j = 0; j < fInputChannelCount; j++) {
557 if (fInputChannelInfo[j].destination_mask
558 & ChannelTypeToChannelMask(
559 fMixerChannelInfo[i].destination_type)) {
560 fMixerChannelInfo[i].buffer_base = fMixBuffer ? &fMixBuffer[j]
561 : 0;
562 break;
565 if (j == fInputChannelCount) {
566 ERROR("buffer assignment failed for mixer chan %d\n", i);
567 fMixerChannelInfo[i].buffer_base = fMixBuffer;
571 for (int i = 0; i < fMixerChannelCount; i++) {
572 TRACE("_UpdateInputChannelDestinations: mixer channel %d, type %2d, "
573 "base %p, gain %.3f\n", i, fMixerChannelInfo[i].destination_type,
574 fMixerChannelInfo[i].buffer_base,
575 fMixerChannelInfo[i].destination_gain);
578 TRACE("_UpdateInputChannelDestinations: leave\n");
582 // Note: The following code is outcommented on purpose
583 // and is about to be modified at a later point
585 void
586 MixerInput::SetInputChannelDestinationGain(int channel, int destination_type,
587 float gain)
589 TRACE("SetInputChannelDestinationGain: channel %d, destination_type %d,
590 gain %.4f\n", channel, destination_type, gain);
591 // we don't need the channel, as each destination_type can only exist
592 // once for each MixerInput, but we use it for parameter validation
593 // and to have a interface similar to MixerOutput
594 if (channel < 0 || channel >= fMixerChannelCount)
595 return;
596 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
597 return;
598 if (gain < 0.0f)
599 gain = 0.0f;
600 fChannelTypeGain[destination_type] = gain;
601 for (int i = 0; i < fMixerChannelCount; i++) {
602 if (fMixerChannelInfo[i].destination_type == destination_type) {
603 fMixerChannelInfo[i].destination_gain = gain;
604 return;
610 float
611 MixerInput::GetInputChannelDestinationGain(int channel, int destination_type)
613 // we don't need the channel, as each destination_type can only exist
614 // once for each MixerInput, but we use it for parameter validation
615 // and to have a interface similar to MixerOutput
616 if (channel < 0 || channel >= fMixerChannelCount)
617 return 0.0f;
618 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
619 return 0.0f;
620 return fChannelTypeGain[destination_type];
625 void
626 MixerInput::SetMixerChannelGain(int mixer_channel, float gain)
628 if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
629 return;
630 if (gain < 0.0f)
631 gain = 0.0f;
633 fMixerChannelInfo[mixer_channel].destination_gain = gain;
634 fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain;
638 float
639 MixerInput::GetMixerChannelGain(int mixer_channel)
641 if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
642 return 0.0;
643 return fMixerChannelInfo[mixer_channel].destination_gain;
648 MixerInput::GetMixerChannelType(int mixer_channel)
650 if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
651 return -1;
652 return fMixerChannelInfo[mixer_channel].destination_type;
656 void
657 MixerInput::SetEnabled(bool yesno)
659 fEnabled = yesno;
663 bool
664 MixerInput::IsEnabled()
666 return fEnabled;
670 void
671 MixerInput::SetMixBufferFormat(int32 framerate, int32 frames)
673 TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n",
674 framerate, frames);
676 fMixBufferFrameRate = framerate;
677 fDebugMixBufferFrames = frames;
679 // frames and/or framerate can be 0 (if no output is connected)
680 if (framerate == 0 || frames == 0) {
681 if (fMixBuffer != NULL) {
682 rtm_free(fMixBuffer);
683 fMixBuffer = NULL;
685 for (int i = 0; i < fInputChannelCount; i++)
686 fInputChannelInfo[i].buffer_base = 0;
687 fMixBufferFrameCount = 0;
689 _UpdateInputChannelDestinationMask();
690 _UpdateInputChannelDestinations();
691 return;
694 // make fMixBufferFrameCount an integral multiple of frames,
695 // but at least 3 times duration of our input buffer
696 // and at least 2 times duration of the output buffer
697 bigtime_t inputBufferLength = duration_for_frames(
698 fInput.format.u.raw_audio.frame_rate,
699 frames_per_buffer(fInput.format.u.raw_audio));
700 bigtime_t outputBufferLength = duration_for_frames(framerate, frames);
701 bigtime_t mixerBufferLength
702 = max_c(3 * inputBufferLength, 2 * outputBufferLength);
703 int temp = frames_for_duration(framerate, mixerBufferLength);
704 fMixBufferFrameCount = ((temp / frames) + 1) * frames;
706 TRACE(" inputBufferLength %10Ld\n", inputBufferLength);
707 TRACE(" outputBufferLength %10Ld\n", outputBufferLength);
708 TRACE(" mixerBufferLength %10Ld\n", mixerBufferLength);
709 TRACE(" fMixBufferFrameCount %10d\n", fMixBufferFrameCount);
711 ASSERT((fMixBufferFrameCount % frames) == 0);
713 fLastDataFrameWritten = -1;
714 fFractionalFrames = 0.0;
716 rtm_free(fMixBuffer);
717 rtm_delete_pool(fRtmPool);
719 int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount;
720 if (rtm_create_pool(&fRtmPool, size) != B_OK)
721 fRtmPool = NULL;
723 fMixBuffer = (float*)rtm_alloc(fRtmPool, size);
724 if (fMixBuffer == NULL)
725 return;
727 memset(fMixBuffer, 0, size);
729 for (int i = 0; i < fInputChannelCount; i++)
730 fInputChannelInfo[i].buffer_base = &fMixBuffer[i];
732 _UpdateInputChannelDestinationMask();
733 _UpdateInputChannelDestinations();