2 * Copyright 2003-2010 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
10 #include "MixerCore.h"
14 #include <TimeSource.h> // TODO: debug only
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
)
30 fInputChannelInfo(NULL
),
31 fInputChannelCount(0),
34 fMixerChannelCount(0),
36 fMixBufferFrameRate(0),
37 fMixBufferFrameCount(0),
38 fLastDataFrameWritten(-1),
39 fLastDataAvailableTime(-1),
40 fFractionalFrames(0.0),
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()
92 rtm_delete_pool(fRtmPool
);
93 delete[] fInputChannelInfo
;
94 delete[] fMixerChannelInfo
;
97 if (fResampler
!= NULL
) {
98 for (int i
= 0; i
< fInputChannelCount
; i
++)
102 delete fInputByteSwap
;
109 return fInput
.destination
.id
;
114 MixerInput::MediaInput()
121 MixerInput::BufferReceived(BBuffer
* buffer
)
126 bigtime_t buffer_duration
;
129 ERROR("MixerInput::BufferReceived: dropped incoming buffer as we "
130 "don't have a mix buffer\n");
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
));
140 ERROR("MixerInput::BufferReceived: buffer with negative start time of "
141 "%Ld dropped\n", start
);
145 // swap the byte order of this buffer, if necessary
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",
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;
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
;
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
;
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
213 offset
= expected_frame
;
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
229 // printf("data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n",
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(),
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(),
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
,
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
);
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
;
312 MixerInput::UpdateResamplingAlgorithm()
314 if (fResampler
!= NULL
) {
315 for (int i
= 0; i
< fInputChannelCount
; i
++)
316 delete fResampler
[i
];
320 fResampler
= new Resampler
*[fInputChannelCount
];
321 for (int i
= 0; i
< fInputChannelCount
; i
++) {
322 switch (fCore
->Settings()->ResamplingAlgorithm()) {
324 fResampler
[i
] = new Interpolate(
325 fInput
.format
.u
.raw_audio
.format
,
326 media_raw_audio_format::B_AUDIO_FLOAT
);
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
;
345 MixerInput::AddInputChannelDestination(int channel
, int destination_type
)
347 uint32 mask
= ChannelTypeToChannelMask(destination_type
);
349 if (channel
< 0 || channel
>= fInputChannelCount
)
352 // test if it is already set
353 if (fInputChannelInfo
[channel
].destination_mask
& mask
)
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
));
364 // add it to specified channel
365 fInputChannelInfo
[channel
].destination_mask
|= mask
;
367 fUserOverridesChannelDestinations
= true;
368 _UpdateInputChannelDestinations();
373 MixerInput::RemoveInputChannelDestination(int channel
, int destination_type
)
375 uint32 mask
= ChannelTypeToChannelMask(destination_type
);
377 if (channel
< 0 || channel
>= fInputChannelCount
)
380 // test if it is really set
381 if ((fInputChannelInfo
[channel
].destination_mask
& mask
) == 0)
384 // remove it from specified channel
385 fInputChannelInfo
[channel
].destination_mask
&= ~mask
;
387 fUserOverridesChannelDestinations
= true;
388 _UpdateInputChannelDestinations();
393 MixerInput::HasInputChannelDestination(int channel
, int destination_type
)
395 if (channel
< 0 || channel
>= fInputChannelCount
)
397 if (destination_type
< 0 || destination_type
>= MAX_CHANNEL_TYPES
)
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
)
409 uint32 mask
= ChannelTypeToChannelMask(destination_type
);
410 for (int chan
= 0; chan
< fInputChannelCount
; chan
++) {
411 if (fInputChannelInfo
[chan
].destination_mask
& mask
)
419 MixerInput::GetInputChannelType(int channel
)
421 if (channel
< 0 || channel
>= fInputChannelCount
)
423 return GetChannelType(channel
, fInputChannelMask
);
428 MixerInput::SetInputChannelGain(int channel
, float gain
)
430 if (channel
< 0 || channel
>= fInputChannelCount
)
435 fInputChannelInfo
[channel
].gain
= gain
;
440 MixerInput::GetInputChannelGain(int channel
)
442 if (channel
< 0 || channel
>= fInputChannelCount
)
444 return fInputChannelInfo
[channel
].gain
;
449 MixerInput::_UpdateInputChannelDestinationMask()
451 // is the user already messed with the assignmens, don't do anything.
452 if (fUserOverridesChannelDestinations
)
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
,
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
;
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");
511 MixerInput::_UpdateInputChannelDestinations()
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
);
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
,
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[]
544 for (int i
= 0; i
< fMixerChannelCount
; i
++) {
545 while (mask
!= 0 && (all_bits
& mask
) == 0)
547 fMixerChannelInfo
[i
].destination_type
= ChannelMaskToChannelType(mask
);
548 fMixerChannelInfo
[i
].destination_gain
549 = fChannelTypeGain
[fMixerChannelInfo
[i
].destination_type
];
553 // assign buffer_base pointer for each mixer channel
554 for (int i
= 0; i
< fMixerChannelCount
; i
++) {
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
]
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
586 MixerInput::SetInputChannelDestinationGain(int channel, int destination_type,
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)
596 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
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;
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)
618 if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
620 return fChannelTypeGain[destination_type];
626 MixerInput::SetMixerChannelGain(int mixer_channel
, float gain
)
628 if (mixer_channel
< 0 || mixer_channel
>= fMixerChannelCount
)
633 fMixerChannelInfo
[mixer_channel
].destination_gain
= gain
;
634 fChannelTypeGain
[fMixerChannelInfo
[mixer_channel
].destination_type
] = gain
;
639 MixerInput::GetMixerChannelGain(int mixer_channel
)
641 if (mixer_channel
< 0 || mixer_channel
>= fMixerChannelCount
)
643 return fMixerChannelInfo
[mixer_channel
].destination_gain
;
648 MixerInput::GetMixerChannelType(int mixer_channel
)
650 if (mixer_channel
< 0 || mixer_channel
>= fMixerChannelCount
)
652 return fMixerChannelInfo
[mixer_channel
].destination_type
;
657 MixerInput::SetEnabled(bool yesno
)
664 MixerInput::IsEnabled()
671 MixerInput::SetMixBufferFormat(int32 framerate
, int32 frames
)
673 TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n",
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
);
685 for (int i
= 0; i
< fInputChannelCount
; i
++)
686 fInputChannelInfo
[i
].buffer_base
= 0;
687 fMixBufferFrameCount
= 0;
689 _UpdateInputChannelDestinationMask();
690 _UpdateInputChannelDestinations();
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
)
723 fMixBuffer
= (float*)rtm_alloc(fRtmPool
, size
);
724 if (fMixBuffer
== NULL
)
727 memset(fMixBuffer
, 0, size
);
729 for (int i
= 0; i
< fInputChannelCount
; i
++)
730 fInputChannelInfo
[i
].buffer_base
= &fMixBuffer
[i
];
732 _UpdateInputChannelDestinationMask();
733 _UpdateInputChannelDestinations();