1 /*
2 * Copyright 2003-2010 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 "Interpolate.h"
18 #include "MixerInput.h"
19 #include "MixerUtils.h"
20 #include "Resampler.h"
21
22
MixerInput(MixerCore * core,const media_input & input,float mixFrameRate,int32 mixFrameCount)23 MixerInput::MixerInput(MixerCore* core, const media_input& input,
24 float mixFrameRate, int32 mixFrameCount)
25 :
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)
44 {
45 fix_multiaudio_format(&fInput.format.u.raw_audio);
46 PRINT_INPUT("MixerInput::MixerInput", fInput);
47 PRINT_CHANNEL_MASK(fInput.format);
48
49 ASSERT(fInput.format.u.raw_audio.channel_count > 0);
50
51 for (int i = 0; i < MAX_CHANNEL_TYPES; i++)
52 fChannelTypeGain[i] = 1.0f;
53
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];
57
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);
67 }
68 }
69
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;
77 }
78
79 UpdateResamplingAlgorithm();
80
81 // fMixerChannelInfo and fMixerChannelCount will be initialized by
82 // _UpdateInputChannelDestinations()
83 SetMixBufferFormat((int32)mixFrameRate, mixFrameCount);
84 }
85
86
~MixerInput()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 if (fResampler != NULL) {
98 for (int i = 0; i < fInputChannelCount; i++)
99 delete fResampler[i];
100 delete[] fResampler;
101 }
102 delete fInputByteSwap;
103 }
104
105
106 int32
ID()107 MixerInput::ID()
108 {
109 return fInput.destination.id;
110 }
111
112
113 media_input&
MediaInput()114 MixerInput::MediaInput()
115 {
116 return fInput;
117 }
118
119
120 void
BufferReceived(BBuffer * buffer)121 MixerInput::BufferReceived(BBuffer* buffer)
122 {
123 void* data;
124 size_t size;
125 bigtime_t start;
126 bigtime_t buffer_duration;
127
128 if (!fMixBuffer) {
129 ERROR("MixerInput::BufferReceived: dropped incoming buffer as we "
130 "don't have a mix buffer\n");
131 return;
132 }
133
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 "%lld dropped\n", start);
142 return;
143 }
144
145 // swap the byte order of this buffer, if necessary
146 if (fInputByteSwap)
147 fInputByteSwap->Swap(data, size);
148
149 int offset = frames_for_duration(fMixBufferFrameRate, start)
150 % fMixBufferFrameCount;
151
152 PRINT(4, "MixerInput::BufferReceived: buffer start %10Ld, offset %6d\n",
153 start, offset);
154
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++;
163 }
164
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);
188
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);
204 }
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);
223 }
224 }
225 }
226 }
227 }
228
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;
239
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);
256
257 fLastDataFrameWritten = out_frames2 - 1;
258
259 // convert offset from frames into bytes
260 offset *= sizeof(float) * fInputChannelCount;
261
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);
270
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);
279
280 }
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);
293
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);
305 }
306 }
307 fLastDataAvailableTime = start + buffer_duration;
308 }
309
310
311 void
UpdateResamplingAlgorithm()312 MixerInput::UpdateResamplingAlgorithm()
313 {
314 if (fResampler != NULL) {
315 for (int i = 0; i < fInputChannelCount; i++)
316 delete fResampler[i];
317 delete[] fResampler;
318 }
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);
332 }
333 }
334 }
335
336
337 int
GetInputChannelCount()338 MixerInput::GetInputChannelCount()
339 {
340 return fInputChannelCount;
341 }
342
343
344 void
AddInputChannelDestination(int channel,int destination_type)345 MixerInput::AddInputChannelDestination(int channel, int destination_type)
346 {
347 uint32 mask = ChannelTypeToChannelMask(destination_type);
348
349 if (channel < 0 || channel >= fInputChannelCount)
350 return;
351
352 // test if it is already set
353 if (fInputChannelInfo[channel].destination_mask & mask)
354 return;
355
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;
362 }
363
364 // add it to specified channel
365 fInputChannelInfo[channel].destination_mask |= mask;
366
367 fUserOverridesChannelDestinations = true;
368 _UpdateInputChannelDestinations();
369 }
370
371
372 void
RemoveInputChannelDestination(int channel,int destination_type)373 MixerInput::RemoveInputChannelDestination(int channel, int destination_type)
374 {
375 uint32 mask = ChannelTypeToChannelMask(destination_type);
376
377 if (channel < 0 || channel >= fInputChannelCount)
378 return;
379
380 // test if it is really set
381 if ((fInputChannelInfo[channel].destination_mask & mask) == 0)
382 return;
383
384 // remove it from specified channel
385 fInputChannelInfo[channel].destination_mask &= ~mask;
386
387 fUserOverridesChannelDestinations = true;
388 _UpdateInputChannelDestinations();
389 }
390
391
392 bool
HasInputChannelDestination(int channel,int destination_type)393 MixerInput::HasInputChannelDestination(int channel, int destination_type)
394 {
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);
401 }
402
403
404 int
GetInputChannelForDestination(int destination_type)405 MixerInput::GetInputChannelForDestination(int destination_type)
406 {
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;
413 }
414 return -1;
415 }
416
417
418 int
GetInputChannelType(int channel)419 MixerInput::GetInputChannelType(int channel)
420 {
421 if (channel < 0 || channel >= fInputChannelCount)
422 return 0;
423 return GetChannelType(channel, fInputChannelMask);
424 }
425
426
427 void
SetInputChannelGain(int channel,float gain)428 MixerInput::SetInputChannelGain(int channel, float gain)
429 {
430 if (channel < 0 || channel >= fInputChannelCount)
431 return;
432 if (gain < 0.0f)
433 gain = 0.0f;
434
435 fInputChannelInfo[channel].gain = gain;
436 }
437
438
439 float
GetInputChannelGain(int channel)440 MixerInput::GetInputChannelGain(int channel)
441 {
442 if (channel < 0 || channel >= fInputChannelCount)
443 return 0.0f;
444 return fInputChannelInfo[channel].gain;
445 }
446
447
448 void
_UpdateInputChannelDestinationMask()449 MixerInput::_UpdateInputChannelDestinationMask()
450 {
451 // is the user already messed with the assignmens, don't do anything.
452 if (fUserOverridesChannelDestinations)
453 return;
454
455 TRACE("_UpdateInputChannelDestinationMask: enter\n");
456
457 // first apply a 1:1 mapping
458 for (int i = 0; i < fInputChannelCount; i++) {
459 fInputChannelInfo[i].destination_mask = GetChannelMask(i,
460 fInputChannelMask);
461 }
462
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;
470 }
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;
477 }
478 if (fInputChannelCount == 2
479 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) {
480 fInputChannelInfo[0].destination_mask
481 = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
482 }
483 if (fInputChannelCount == 2
484 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) {
485 fInputChannelInfo[0].destination_mask
486 = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
487 }
488 if (fInputChannelCount == 2
489 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) {
490 fInputChannelInfo[1].destination_mask
491 = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
492 }
493 if (fInputChannelCount == 2
494 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) {
495 fInputChannelInfo[1].destination_mask
496 = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
497 }
498 }
499
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);
505 }
506 TRACE("_UpdateInputChannelDestinationMask: leave\n");
507 }
508
509
510 void
_UpdateInputChannelDestinations()511 MixerInput::_UpdateInputChannelDestinations()
512 {
513 int channel_count;
514 uint32 all_bits;
515 uint32 mask;
516
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);
523 }
524
525 all_bits = 0;
526 for (int i = 0; i < fInputChannelCount; i++)
527 all_bits |= fInputChannelInfo[i].destination_mask;
528
529 TRACE("_UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits);
530
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;
539 }
540
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;
551 }
552
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;
563 }
564 }
565 if (j == fInputChannelCount) {
566 ERROR("buffer assignment failed for mixer chan %d\n", i);
567 fMixerChannelInfo[i].buffer_base = fMixBuffer;
568 }
569 }
570
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);
576 }
577
578 TRACE("_UpdateInputChannelDestinations: leave\n");
579 }
580
581
582 // Note: The following code is outcommented on purpose
583 // and is about to be modified at a later point
584 /*
585 void
586 MixerInput::SetInputChannelDestinationGain(int channel, int destination_type,
587 float gain)
588 {
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;
605 }
606 }
607 }
608
609
610 float
611 MixerInput::GetInputChannelDestinationGain(int channel, int destination_type)
612 {
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];
621 }
622 */
623
624
625 void
SetMixerChannelGain(int mixer_channel,float gain)626 MixerInput::SetMixerChannelGain(int mixer_channel, float gain)
627 {
628 if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
629 return;
630 if (gain < 0.0f)
631 gain = 0.0f;
632
633 fMixerChannelInfo[mixer_channel].destination_gain = gain;
634 fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain;
635 }
636
637
638 float
GetMixerChannelGain(int mixer_channel)639 MixerInput::GetMixerChannelGain(int mixer_channel)
640 {
641 if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
642 return 0.0;
643 return fMixerChannelInfo[mixer_channel].destination_gain;
644 }
645
646
647 int
GetMixerChannelType(int mixer_channel)648 MixerInput::GetMixerChannelType(int mixer_channel)
649 {
650 if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
651 return -1;
652 return fMixerChannelInfo[mixer_channel].destination_type;
653 }
654
655
656 void
SetEnabled(bool yesno)657 MixerInput::SetEnabled(bool yesno)
658 {
659 fEnabled = yesno;
660 }
661
662
663 bool
IsEnabled()664 MixerInput::IsEnabled()
665 {
666 return fEnabled;
667 }
668
669
670 void
SetMixBufferFormat(int32 framerate,int32 frames)671 MixerInput::SetMixBufferFormat(int32 framerate, int32 frames)
672 {
673 TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n",
674 framerate, frames);
675
676 fMixBufferFrameRate = framerate;
677 fDebugMixBufferFrames = frames;
678
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;
684 }
685 for (int i = 0; i < fInputChannelCount; i++)
686 fInputChannelInfo[i].buffer_base = 0;
687 fMixBufferFrameCount = 0;
688
689 _UpdateInputChannelDestinationMask();
690 _UpdateInputChannelDestinations();
691 return;
692 }
693
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;
705
706 TRACE(" inputBufferLength %10Ld\n", inputBufferLength);
707 TRACE(" outputBufferLength %10Ld\n", outputBufferLength);
708 TRACE(" mixerBufferLength %10Ld\n", mixerBufferLength);
709 TRACE(" fMixBufferFrameCount %10d\n", fMixBufferFrameCount);
710
711 ASSERT((fMixBufferFrameCount % frames) == 0);
712
713 fLastDataFrameWritten = -1;
714 fFractionalFrames = 0.0;
715
716 rtm_free(fMixBuffer);
717 rtm_delete_pool(fRtmPool);
718
719 int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount;
720 if (rtm_create_pool(&fRtmPool, size) != B_OK)
721 fRtmPool = NULL;
722
723 fMixBuffer = (float*)rtm_alloc(fRtmPool, size);
724 if (fMixBuffer == NULL)
725 return;
726
727 memset(fMixBuffer, 0, size);
728
729 for (int i = 0; i < fInputChannelCount; i++)
730 fInputChannelInfo[i].buffer_base = &fMixBuffer[i];
731
732 _UpdateInputChannelDestinationMask();
733 _UpdateInputChannelDestinations();
734 }
735