xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp (revision 23bfcc5517a125afb3223927483e317b8b3561bb)
1bf7ab50dSStephan Aßmus /*
2b543dbc2SStephan Aßmus  * Copyright 2003-2010 Haiku Inc. All rights reserved.
3bf7ab50dSStephan Aßmus  * Distributed under the terms of the MIT License.
4bf7ab50dSStephan Aßmus  *
5bf7ab50dSStephan Aßmus  * Authors:
6bf7ab50dSStephan Aßmus  *		Marcus Overhagen
7bf7ab50dSStephan Aßmus  */
8a9cf57cfSAxel Dörfler 
9a9cf57cfSAxel Dörfler 
10bf7ab50dSStephan Aßmus #include "MixerCore.h"
11a9cf57cfSAxel Dörfler 
12a9cf57cfSAxel Dörfler #include <Buffer.h>
13a9cf57cfSAxel Dörfler #include <string.h>
14a9cf57cfSAxel Dörfler #include <TimeSource.h> // TODO: debug only
15a9cf57cfSAxel Dörfler 
16a9cf57cfSAxel Dörfler #include "ByteSwap.h"
17a79b30c3SStephan Aßmus #include "Interpolate.h"
18bf7ab50dSStephan Aßmus #include "MixerInput.h"
19bf7ab50dSStephan Aßmus #include "MixerUtils.h"
20bf7ab50dSStephan Aßmus #include "Resampler.h"
21bf7ab50dSStephan Aßmus 
22678c2017Sbeveloper 
23a9cf57cfSAxel Dörfler MixerInput::MixerInput(MixerCore* core, const media_input& input,
24b006bbe1SStephan Aßmus 	float mixFrameRate, int32 mixFrameCount)
25a9cf57cfSAxel Dörfler 	:
26a9cf57cfSAxel Dörfler 	fCore(core),
272e9d6607Sbeveloper  	fInput(input),
28b006bbe1SStephan Aßmus 	fInputByteSwap(NULL),
291c237c18Sbeveloper 	fEnabled(true),
30b006bbe1SStephan Aßmus 	fInputChannelInfo(NULL),
312e9d6607Sbeveloper 	fInputChannelCount(0),
322e9d6607Sbeveloper 	fInputChannelMask(0),
332e9d6607Sbeveloper 	fMixerChannelInfo(0),
342e9d6607Sbeveloper 	fMixerChannelCount(0),
35b006bbe1SStephan Aßmus 	fMixBuffer(NULL),
367b0daf5cSbeveloper 	fMixBufferFrameRate(0),
377b0daf5cSbeveloper 	fMixBufferFrameCount(0),
38e92593f4Sbeveloper 	fLastDataFrameWritten(-1),
39af8d0a4dSbeveloper 	fLastDataAvailableTime(-1),
40e92593f4Sbeveloper 	fFractionalFrames(0.0),
41b006bbe1SStephan Aßmus 	fResampler(NULL),
42b006bbe1SStephan Aßmus 	fRtmPool(NULL),
439c3be6a5Sbeveloper 	fUserOverridesChannelDestinations(false)
44678c2017Sbeveloper {
45e6c7c99fSbeveloper 	fix_multiaudio_format(&fInput.format.u.raw_audio);
46e6c7c99fSbeveloper 	PRINT_INPUT("MixerInput::MixerInput", fInput);
47e6c7c99fSbeveloper 	PRINT_CHANNEL_MASK(fInput.format);
482e9d6607Sbeveloper 
492e9d6607Sbeveloper 	ASSERT(fInput.format.u.raw_audio.channel_count > 0);
502e9d6607Sbeveloper 
519c3be6a5Sbeveloper 	for (int i = 0; i <	MAX_CHANNEL_TYPES; i++)
529c3be6a5Sbeveloper 		fChannelTypeGain[i] = 1.0f;
539c3be6a5Sbeveloper 
542e9d6607Sbeveloper 	fInputChannelCount = fInput.format.u.raw_audio.channel_count;
552e9d6607Sbeveloper 	fInputChannelMask = fInput.format.u.raw_audio.channel_mask;
562e9d6607Sbeveloper 	fInputChannelInfo = new input_chan_info[fInputChannelCount];
572e9d6607Sbeveloper 
5888777023Sbeveloper 	// perhaps we need byte swapping
5988777023Sbeveloper 	if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) {
60a9cf57cfSAxel Dörfler 		if (fInput.format.u.raw_audio.format
61a9cf57cfSAxel Dörfler 				== media_raw_audio_format::B_AUDIO_FLOAT
62a9cf57cfSAxel Dörfler 			|| fInput.format.u.raw_audio.format
63a9cf57cfSAxel Dörfler 				== media_raw_audio_format::B_AUDIO_INT
64a9cf57cfSAxel Dörfler 			|| fInput.format.u.raw_audio.format
65a9cf57cfSAxel Dörfler 				== media_raw_audio_format::B_AUDIO_SHORT) {
6688777023Sbeveloper 			fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format);
6788777023Sbeveloper 		}
6888777023Sbeveloper 	}
6988777023Sbeveloper 
702e9d6607Sbeveloper 	// initialize fInputChannelInfo
712e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++) {
72b543dbc2SStephan Aßmus 		fInputChannelInfo[i].buffer_base = 0;
73b543dbc2SStephan Aßmus 			// will be set by SetMixBufferFormat()
74b543dbc2SStephan Aßmus 		fInputChannelInfo[i].destination_mask = 0;
75b006bbe1SStephan Aßmus 			// will be set by _UpdateInputChannelDestinationMask()
762e9d6607Sbeveloper 		fInputChannelInfo[i].gain = 1.0;
772e9d6607Sbeveloper 	}
782e9d6607Sbeveloper 
79b006bbe1SStephan Aßmus 	UpdateResamplingAlgorithm();
807b0daf5cSbeveloper 
81b543dbc2SStephan Aßmus 	// fMixerChannelInfo and fMixerChannelCount will be initialized by
82b006bbe1SStephan Aßmus 	// _UpdateInputChannelDestinations()
83bf7ab50dSStephan Aßmus 	SetMixBufferFormat((int32)mixFrameRate, mixFrameCount);
84678c2017Sbeveloper }
85678c2017Sbeveloper 
86a9cf57cfSAxel Dörfler 
87678c2017Sbeveloper MixerInput::~MixerInput()
88678c2017Sbeveloper {
892e9d6607Sbeveloper 	if (fMixBuffer)
902e9d6607Sbeveloper 		rtm_free(fMixBuffer);
91356855c3Sbeveloper 	if (fRtmPool)
92356855c3Sbeveloper 		rtm_delete_pool(fRtmPool);
932e9d6607Sbeveloper 	delete[] fInputChannelInfo;
942e9d6607Sbeveloper 	delete[] fMixerChannelInfo;
957b0daf5cSbeveloper 
967b0daf5cSbeveloper 	// delete resamplers
97b006bbe1SStephan Aßmus 	if (fResampler != NULL) {
987b0daf5cSbeveloper 		for (int i = 0; i < fInputChannelCount; i++)
997b0daf5cSbeveloper 			delete fResampler[i];
1007b0daf5cSbeveloper 		delete[] fResampler;
101b006bbe1SStephan Aßmus 	}
102db6f1135SJérôme Duval 	delete fInputByteSwap;
103678c2017Sbeveloper }
104678c2017Sbeveloper 
105a9cf57cfSAxel Dörfler 
106b006bbe1SStephan Aßmus int32
107b006bbe1SStephan Aßmus MixerInput::ID()
108b006bbe1SStephan Aßmus {
109b006bbe1SStephan Aßmus 	return fInput.destination.id;
110b006bbe1SStephan Aßmus }
111b006bbe1SStephan Aßmus 
112b006bbe1SStephan Aßmus 
113b006bbe1SStephan Aßmus media_input&
114b006bbe1SStephan Aßmus MixerInput::MediaInput()
115b006bbe1SStephan Aßmus {
116b006bbe1SStephan Aßmus 	return fInput;
117b006bbe1SStephan Aßmus }
118b006bbe1SStephan Aßmus 
119b006bbe1SStephan Aßmus 
120678c2017Sbeveloper void
121678c2017Sbeveloper MixerInput::BufferReceived(BBuffer* buffer)
122678c2017Sbeveloper {
12388777023Sbeveloper 	void* data;
12488777023Sbeveloper 	size_t size;
12588777023Sbeveloper 	bigtime_t start;
126e92593f4Sbeveloper 	bigtime_t buffer_duration;
12788777023Sbeveloper 
128d5848e21Sbeveloper 	if (!fMixBuffer) {
129b543dbc2SStephan Aßmus 		ERROR("MixerInput::BufferReceived: dropped incoming buffer as we "
130b543dbc2SStephan Aßmus 			"don't have a mix buffer\n");
131d5848e21Sbeveloper 		return;
132d5848e21Sbeveloper 	}
1332e9d6607Sbeveloper 
13488777023Sbeveloper 	data = buffer->Data();
13588777023Sbeveloper 	size = buffer->SizeUsed();
13688777023Sbeveloper 	start = buffer->Header()->start_time;
137b543dbc2SStephan Aßmus 	buffer_duration = duration_for_frames(fInput.format.u.raw_audio.frame_rate,
138b543dbc2SStephan Aßmus 		size / bytes_per_frame(fInput.format.u.raw_audio));
1398d28117fSbeveloper 	if (start < 0) {
140b543dbc2SStephan Aßmus 		ERROR("MixerInput::BufferReceived: buffer with negative start time of "
141b543dbc2SStephan Aßmus 			"%Ld dropped\n", start);
1428d28117fSbeveloper 		return;
1438d28117fSbeveloper 	}
14488777023Sbeveloper 
14588777023Sbeveloper 	// swap the byte order of this buffer, if necessary
14688777023Sbeveloper 	if (fInputByteSwap)
14788777023Sbeveloper 		fInputByteSwap->Swap(data, size);
14888777023Sbeveloper 
149b543dbc2SStephan Aßmus 	int offset = frames_for_duration(fMixBufferFrameRate, start)
150b543dbc2SStephan Aßmus 		% fMixBufferFrameCount;
1518d28117fSbeveloper 
152b543dbc2SStephan Aßmus 	PRINT(4, "MixerInput::BufferReceived: buffer start %10Ld, offset %6d\n",
153b543dbc2SStephan Aßmus 		start, offset);
1547b0daf5cSbeveloper 
155191033efSbeveloper 	int in_frames = size / bytes_per_frame(fInput.format.u.raw_audio);
156*23bfcc55SJulian Harnath 	double frames = ((double)in_frames * fMixBufferFrameRate)
157b543dbc2SStephan Aßmus 		/ fInput.format.u.raw_audio.frame_rate;
158e92593f4Sbeveloper 	int out_frames = int(frames);
159e92593f4Sbeveloper 	fFractionalFrames += frames - double(out_frames);
160e92593f4Sbeveloper 	if (fFractionalFrames >= 1.0) {
161e92593f4Sbeveloper 		fFractionalFrames -= 1.0;
1627619f562Sbeveloper 		out_frames++;
163e92593f4Sbeveloper 	}
164e92593f4Sbeveloper 
165e92593f4Sbeveloper 	// if fLastDataFrameWritten != -1, then we have a valid last position
166e92593f4Sbeveloper 	// and can do glitch compensation
167e92593f4Sbeveloper 	if (fLastDataFrameWritten >= 0) {
168b543dbc2SStephan Aßmus 		int expected_frame = (fLastDataFrameWritten + 1)
169b543dbc2SStephan Aßmus 			% fMixBufferFrameCount;
170e92593f4Sbeveloper 		if (offset != expected_frame) {
171e92593f4Sbeveloper 			// due to rounding and other errors, offset might be off by +/- 1
172e92593f4Sbeveloper 			// this is not really a bad glitch, we just adjust the position
173e92593f4Sbeveloper 			if (offset == fLastDataFrameWritten) {
174b543dbc2SStephan Aßmus //				printf("MixerInput::BufferReceived: -1 frame GLITCH! last "
175b543dbc2SStephan Aßmus //					"frame was %ld, expected frame was %d, new frame is %d\n",
176b543dbc2SStephan Aßmus //					fLastDataFrameWritten, expected_frame, offset);
177e92593f4Sbeveloper 				offset = expected_frame;
178b543dbc2SStephan Aßmus 			} else if (offset == ((fLastDataFrameWritten + 2)
179b543dbc2SStephan Aßmus 				% fMixBufferFrameCount)) {
180b543dbc2SStephan Aßmus //				printf("MixerInput::BufferReceived: +1 frame GLITCH! last "
181b543dbc2SStephan Aßmus //					"frame was %ld, expected frame was %d, new frame is %d\n",
182b543dbc2SStephan Aßmus //					fLastDataFrameWritten, expected_frame, offset);
183e92593f4Sbeveloper 				offset = expected_frame;
184e92593f4Sbeveloper 			} else {
185b543dbc2SStephan Aßmus 				printf("MixerInput::BufferReceived: GLITCH! last frame was "
186b543dbc2SStephan Aßmus 					"%4ld, expected frame was %4d, new frame is %4d\n",
187b543dbc2SStephan Aßmus 					fLastDataFrameWritten, expected_frame, offset);
188e92593f4Sbeveloper 
189e92593f4Sbeveloper 				if (start > fLastDataAvailableTime) {
190b543dbc2SStephan Aßmus 					if ((start - fLastDataAvailableTime)
191b543dbc2SStephan Aßmus 						< (buffer_duration / 10)) {
192e92593f4Sbeveloper 						// buffer is less than 10% of buffer duration too late
193b543dbc2SStephan Aßmus 						printf("short glitch, buffer too late, time delta "
194b543dbc2SStephan Aßmus 							"%Ld\n", start - fLastDataAvailableTime);
195e92593f4Sbeveloper 						offset = expected_frame;
196e92593f4Sbeveloper 						out_frames++;
197e92593f4Sbeveloper 					} else {
198e92593f4Sbeveloper 						// buffer more than 10% of buffer duration too late
199b543dbc2SStephan Aßmus 						// TODO: zerofill buffer
200b543dbc2SStephan Aßmus 						printf("MAJOR glitch, buffer too late, time delta "
201b543dbc2SStephan Aßmus 							"%Ld\n", start - fLastDataAvailableTime);
202e92593f4Sbeveloper 					}
203e92593f4Sbeveloper 				} else { // start <= fLastDataAvailableTime
204e92593f4Sbeveloper 					// the new buffer is too early
205b543dbc2SStephan Aßmus 					if ((fLastDataAvailableTime - start)
206b543dbc2SStephan Aßmus 						< (buffer_duration / 10)) {
207e92593f4Sbeveloper 						// buffer is less than 10% of buffer duration too early
208b543dbc2SStephan Aßmus 						printf("short glitch, buffer too early, time delta "
209b543dbc2SStephan Aßmus 							"%Ld\n", fLastDataAvailableTime - start);
210e92593f4Sbeveloper 						offset = expected_frame;
211e92593f4Sbeveloper 						out_frames--;
212e92593f4Sbeveloper 						if (out_frames < 1)
213e92593f4Sbeveloper 							out_frames = 1;
214e92593f4Sbeveloper 					} else {
215e92593f4Sbeveloper 						// buffer more than 10% of buffer duration too early
216b543dbc2SStephan Aßmus 						// TODO: zerofill buffer
217b543dbc2SStephan Aßmus 						printf("MAJOR glitch, buffer too early, time delta "
218b543dbc2SStephan Aßmus 							"%Ld\n", fLastDataAvailableTime - start);
219e92593f4Sbeveloper 					}
220e92593f4Sbeveloper 				}
221e92593f4Sbeveloper 			}
222e92593f4Sbeveloper 		}
223e92593f4Sbeveloper 	}
2247b0daf5cSbeveloper 
225b543dbc2SStephan Aßmus //	printf("data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n",
226b543dbc2SStephan Aßmus //		start,
227b543dbc2SStephan Aßmus //		start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
228b543dbc2SStephan Aßmus //		frames_per_buffer(fInput.format.u.raw_audio)), offset,
229b543dbc2SStephan Aßmus //		offset + out_frames);
2307b0daf5cSbeveloper 	if (offset + out_frames > fMixBufferFrameCount) {
2317b0daf5cSbeveloper 		int out_frames1 = fMixBufferFrameCount - offset;
2327b0daf5cSbeveloper 		int out_frames2 = out_frames - out_frames1;
2337b0daf5cSbeveloper 		int in_frames1 = (out_frames1 * in_frames) / out_frames;
2347b0daf5cSbeveloper 		int in_frames2 = in_frames - in_frames1;
2357b0daf5cSbeveloper 
236b543dbc2SStephan Aßmus //		printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at "
237b543dbc2SStephan Aßmus //			"frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(),
238b543dbc2SStephan Aßmus //			start,
239b543dbc2SStephan Aßmus //			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
240b543dbc2SStephan Aßmus //			frames_per_buffer(fInput.format.u.raw_audio)), offset,
241b543dbc2SStephan Aßmus //			offset + out_frames1 - 1, 0, out_frames2 - 1);
242b543dbc2SStephan Aßmus 		PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at "
243b543dbc2SStephan Aßmus 			"frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(),
244b543dbc2SStephan Aßmus 			start,
245b543dbc2SStephan Aßmus 			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
246b543dbc2SStephan Aßmus 			frames_per_buffer(fInput.format.u.raw_audio)), offset,
247b543dbc2SStephan Aßmus 			offset + out_frames1 - 1, 0, out_frames2 - 1);
248b543dbc2SStephan Aßmus 		PRINT(5, "  in_frames %5d, out_frames %5d, in_frames1 %5d, "
249b543dbc2SStephan Aßmus 			"out_frames1 %5d, in_frames2 %5d, out_frames2 %5d\n",
250b543dbc2SStephan Aßmus 			in_frames, out_frames, in_frames1, out_frames1, in_frames2,
251b543dbc2SStephan Aßmus 			out_frames2);
2527b0daf5cSbeveloper 
253e92593f4Sbeveloper 		fLastDataFrameWritten = out_frames2 - 1;
254e92593f4Sbeveloper 
255b543dbc2SStephan Aßmus 		// convert offset from frames into bytes
256b543dbc2SStephan Aßmus 		offset *= sizeof(float) * fInputChannelCount;
2578d28117fSbeveloper 
2587b0daf5cSbeveloper 		for (int i = 0; i < fInputChannelCount; i++) {
259b543dbc2SStephan Aßmus 			fResampler[i]->Resample(
260b543dbc2SStephan Aßmus 				reinterpret_cast<char*>(data)
261b543dbc2SStephan Aßmus 					+ i * bytes_per_sample(fInput.format.u.raw_audio),
262b543dbc2SStephan Aßmus 				bytes_per_frame(fInput.format.u.raw_audio), in_frames1,
263b543dbc2SStephan Aßmus 				reinterpret_cast<char*>(fInputChannelInfo[i].buffer_base)
264b543dbc2SStephan Aßmus 					+ offset, fInputChannelCount * sizeof(float), out_frames1,
2657b0daf5cSbeveloper 				fInputChannelInfo[i].gain);
2667b0daf5cSbeveloper 
267b543dbc2SStephan Aßmus 			fResampler[i]->Resample(
268b543dbc2SStephan Aßmus 				reinterpret_cast<char*>(data)
269b543dbc2SStephan Aßmus 					+ i * bytes_per_sample(fInput.format.u.raw_audio)
270b543dbc2SStephan Aßmus 					+ in_frames1 * bytes_per_frame(fInput.format.u.raw_audio),
271b543dbc2SStephan Aßmus 				bytes_per_frame(fInput.format.u.raw_audio), in_frames2,
2727b0daf5cSbeveloper 				reinterpret_cast<char*>(fInputChannelInfo[i].buffer_base),
273b543dbc2SStephan Aßmus 				fInputChannelCount * sizeof(float), out_frames2,
2747b0daf5cSbeveloper 				fInputChannelInfo[i].gain);
275e92593f4Sbeveloper 
2767b0daf5cSbeveloper 		}
2777b0daf5cSbeveloper 	} else {
278b543dbc2SStephan Aßmus //		printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at "
279b543dbc2SStephan Aßmus //			"frames %ld to %ld\n", fCore->fTimeSource->Now(), start,
280b543dbc2SStephan Aßmus //			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
281b543dbc2SStephan Aßmus //			frames_per_buffer(fInput.format.u.raw_audio)), offset,
282b543dbc2SStephan Aßmus //			offset + out_frames - 1);
283b543dbc2SStephan Aßmus 		PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at "
284b543dbc2SStephan Aßmus 			"frames %ld to %ld\n", fCore->fTimeSource->Now(), start,
285b543dbc2SStephan Aßmus 			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
286b543dbc2SStephan Aßmus 			frames_per_buffer(fInput.format.u.raw_audio)), offset,
287b543dbc2SStephan Aßmus 			offset + out_frames - 1);
288191033efSbeveloper 		PRINT(5, "  in_frames %5d, out_frames %5d\n", in_frames, out_frames);
2898d28117fSbeveloper 
290e92593f4Sbeveloper 		fLastDataFrameWritten = offset + out_frames - 1;
291b543dbc2SStephan Aßmus 		// convert offset from frames into bytes
292b543dbc2SStephan Aßmus 		offset *= sizeof(float) * fInputChannelCount;
2937b0daf5cSbeveloper 		for (int i = 0; i < fInputChannelCount; i++) {
294b543dbc2SStephan Aßmus 			fResampler[i]->Resample(
295b543dbc2SStephan Aßmus 				reinterpret_cast<char*>(data)
296b543dbc2SStephan Aßmus 					+ i * bytes_per_sample(fInput.format.u.raw_audio),
297b543dbc2SStephan Aßmus 				bytes_per_frame(fInput.format.u.raw_audio), in_frames,
298b543dbc2SStephan Aßmus 				reinterpret_cast<char*>(fInputChannelInfo[i].buffer_base)
299b543dbc2SStephan Aßmus 					+ offset, fInputChannelCount * sizeof(float),
300b543dbc2SStephan Aßmus 				out_frames, fInputChannelInfo[i].gain);
3017b0daf5cSbeveloper 		}
3027b0daf5cSbeveloper 	}
303e92593f4Sbeveloper 	fLastDataAvailableTime = start + buffer_duration;
304678c2017Sbeveloper }
3057ee2c804Sbeveloper 
306bf7ab50dSStephan Aßmus 
307b006bbe1SStephan Aßmus void
308b006bbe1SStephan Aßmus MixerInput::UpdateResamplingAlgorithm()
3097ee2c804Sbeveloper {
310b006bbe1SStephan Aßmus 	if (fResampler != NULL) {
311b006bbe1SStephan Aßmus 		for (int i = 0; i < fInputChannelCount; i++)
312b006bbe1SStephan Aßmus 			delete fResampler[i];
313b006bbe1SStephan Aßmus 		delete[] fResampler;
3147ee2c804Sbeveloper 	}
315b006bbe1SStephan Aßmus 	// create resamplers
316b006bbe1SStephan Aßmus 	fResampler = new Resampler*[fInputChannelCount];
317b006bbe1SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
318b006bbe1SStephan Aßmus 		switch (fCore->Settings()->ResamplingAlgorithm()) {
319b006bbe1SStephan Aßmus 			case 2:
320b006bbe1SStephan Aßmus 				fResampler[i] = new Interpolate(
321b006bbe1SStephan Aßmus 					fInput.format.u.raw_audio.format,
322b006bbe1SStephan Aßmus 					media_raw_audio_format::B_AUDIO_FLOAT);
323b006bbe1SStephan Aßmus 				break;
324b006bbe1SStephan Aßmus 			default:
325b006bbe1SStephan Aßmus 				fResampler[i] = new Resampler(
326b006bbe1SStephan Aßmus 					fInput.format.u.raw_audio.format,
327b006bbe1SStephan Aßmus 					media_raw_audio_format::B_AUDIO_FLOAT);
328b006bbe1SStephan Aßmus 		}
329b006bbe1SStephan Aßmus 	}
330e6c7c99fSbeveloper }
331e6c7c99fSbeveloper 
332bf7ab50dSStephan Aßmus 
333d91580cdSbeveloper int
334fae6ce82Sbeveloper MixerInput::GetInputChannelCount()
335fae6ce82Sbeveloper {
336fae6ce82Sbeveloper 	return fInputChannelCount;
337fae6ce82Sbeveloper }
338fae6ce82Sbeveloper 
339bf7ab50dSStephan Aßmus 
3402e9d6607Sbeveloper void
3419c3be6a5Sbeveloper MixerInput::AddInputChannelDestination(int channel, int destination_type)
3422e9d6607Sbeveloper {
3439c3be6a5Sbeveloper 	uint32 mask = ChannelTypeToChannelMask(destination_type);
344e6c7c99fSbeveloper 
3452e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3462e9d6607Sbeveloper 		return;
3472e9d6607Sbeveloper 
3482e9d6607Sbeveloper 	// test if it is already set
3499c3be6a5Sbeveloper 	if (fInputChannelInfo[channel].destination_mask & mask)
3502e9d6607Sbeveloper 		return;
3512e9d6607Sbeveloper 
3529c3be6a5Sbeveloper 	// verify that no other channel has id
3539c3be6a5Sbeveloper 	if (-1 != GetInputChannelForDestination(destination_type)) {
354b543dbc2SStephan Aßmus 		ERROR("MixerInput::AddInputChannelDestination: destination_type %d "
355b543dbc2SStephan Aßmus 			"already assigned to channel %d\n", destination_type,
356b543dbc2SStephan Aßmus 			GetInputChannelForDestination(destination_type));
3579c3be6a5Sbeveloper 		return;
3589c3be6a5Sbeveloper 	}
3592e9d6607Sbeveloper 
3602e9d6607Sbeveloper 	// add it to specified channel
3619c3be6a5Sbeveloper 	fInputChannelInfo[channel].destination_mask |= mask;
3622e9d6607Sbeveloper 
3639c3be6a5Sbeveloper 	fUserOverridesChannelDestinations = true;
364b006bbe1SStephan Aßmus 	_UpdateInputChannelDestinations();
3652e9d6607Sbeveloper }
3662e9d6607Sbeveloper 
367a9cf57cfSAxel Dörfler 
3682e9d6607Sbeveloper void
3699c3be6a5Sbeveloper MixerInput::RemoveInputChannelDestination(int channel, int destination_type)
3702e9d6607Sbeveloper {
3719c3be6a5Sbeveloper 	uint32 mask = ChannelTypeToChannelMask(destination_type);
3722e9d6607Sbeveloper 
3732e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3742e9d6607Sbeveloper 		return;
3752e9d6607Sbeveloper 
3762e9d6607Sbeveloper 	// test if it is really set
3779c3be6a5Sbeveloper 	if ((fInputChannelInfo[channel].destination_mask & mask) == 0)
3782e9d6607Sbeveloper 		return;
3792e9d6607Sbeveloper 
3802e9d6607Sbeveloper 	// remove it from specified channel
3819c3be6a5Sbeveloper 	fInputChannelInfo[channel].destination_mask &= ~mask;
3822e9d6607Sbeveloper 
3839c3be6a5Sbeveloper 	fUserOverridesChannelDestinations = true;
384b006bbe1SStephan Aßmus 	_UpdateInputChannelDestinations();
3852e9d6607Sbeveloper }
3862e9d6607Sbeveloper 
387a9cf57cfSAxel Dörfler 
3889c3be6a5Sbeveloper bool
3899c3be6a5Sbeveloper MixerInput::HasInputChannelDestination(int channel, int destination_type)
3902e9d6607Sbeveloper {
3912e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3929c3be6a5Sbeveloper 		return false;
3939c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
3949c3be6a5Sbeveloper 		return false;
395b543dbc2SStephan Aßmus 	return fInputChannelInfo[channel].destination_mask
396b543dbc2SStephan Aßmus 		& ChannelTypeToChannelMask(destination_type);
3972e9d6607Sbeveloper }
3982e9d6607Sbeveloper 
399a9cf57cfSAxel Dörfler 
4009c3be6a5Sbeveloper int
4019c3be6a5Sbeveloper MixerInput::GetInputChannelForDestination(int destination_type)
4029c3be6a5Sbeveloper {
4039c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
4049c3be6a5Sbeveloper 		return -1;
4059c3be6a5Sbeveloper 	uint32 mask = ChannelTypeToChannelMask(destination_type);
4069c3be6a5Sbeveloper 	for (int chan = 0; chan < fInputChannelCount; chan++) {
4079c3be6a5Sbeveloper 		if (fInputChannelInfo[chan].destination_mask & mask)
4089c3be6a5Sbeveloper 			return chan;
4099c3be6a5Sbeveloper 	}
4109c3be6a5Sbeveloper 	return -1;
4119c3be6a5Sbeveloper }
4129c3be6a5Sbeveloper 
413a9cf57cfSAxel Dörfler 
4149c3be6a5Sbeveloper int
4152e9d6607Sbeveloper MixerInput::GetInputChannelType(int channel)
4162e9d6607Sbeveloper {
4172e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
4182e9d6607Sbeveloper 		return 0;
4199c3be6a5Sbeveloper 	return GetChannelType(channel, fInputChannelMask);
4202e9d6607Sbeveloper }
4212e9d6607Sbeveloper 
422a9cf57cfSAxel Dörfler 
4232e9d6607Sbeveloper void
4242e9d6607Sbeveloper MixerInput::SetInputChannelGain(int channel, float gain)
4252e9d6607Sbeveloper {
4262e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
4272e9d6607Sbeveloper 		return;
4282e9d6607Sbeveloper 	if (gain < 0.0f)
4292e9d6607Sbeveloper 		gain = 0.0f;
4302e9d6607Sbeveloper 
4312e9d6607Sbeveloper 	fInputChannelInfo[channel].gain = gain;
4322e9d6607Sbeveloper }
4332e9d6607Sbeveloper 
434a9cf57cfSAxel Dörfler 
4352e9d6607Sbeveloper float
4362e9d6607Sbeveloper MixerInput::GetInputChannelGain(int channel)
4372e9d6607Sbeveloper {
4382e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
4392e9d6607Sbeveloper 		return 0.0f;
4402e9d6607Sbeveloper 	return fInputChannelInfo[channel].gain;
4412e9d6607Sbeveloper }
4422e9d6607Sbeveloper 
443a9cf57cfSAxel Dörfler 
4442e9d6607Sbeveloper void
445b006bbe1SStephan Aßmus MixerInput::_UpdateInputChannelDestinationMask()
4462e9d6607Sbeveloper {
4472e9d6607Sbeveloper 	// is the user already messed with the assignmens, don't do anything.
4489c3be6a5Sbeveloper 	if (fUserOverridesChannelDestinations)
4492e9d6607Sbeveloper 		return;
4502e9d6607Sbeveloper 
451b006bbe1SStephan Aßmus 	TRACE("_UpdateInputChannelDestinationMask: enter\n");
4522e9d6607Sbeveloper 
453806cf560Sbeveloper 	// first apply a 1:1 mapping
454b543dbc2SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
455b543dbc2SStephan Aßmus 		fInputChannelInfo[i].destination_mask = GetChannelMask(i,
456b543dbc2SStephan Aßmus 			fInputChannelMask);
457b543dbc2SStephan Aßmus 	}
458806cf560Sbeveloper 
459806cf560Sbeveloper 	// specialize this, depending on the available physical output channels
460643e1b2eSbeveloper 	if (fCore->OutputChannelCount() <= 2) {
461643e1b2eSbeveloper 		// less or equal two channels
462b543dbc2SStephan Aßmus 		if (fInputChannelCount == 1
463b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask)
464b543dbc2SStephan Aßmus 				& (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
465ab276ac8Sbeveloper 			fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO;
466806cf560Sbeveloper 		}
467643e1b2eSbeveloper 	} else {
468643e1b2eSbeveloper 		// more than two channel output card
469b543dbc2SStephan Aßmus 		if (fInputChannelCount == 1
470b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask)
471b543dbc2SStephan Aßmus 				& (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
472ab276ac8Sbeveloper 			fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO;
473806cf560Sbeveloper 		}
474b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
475b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) {
476b543dbc2SStephan Aßmus 			fInputChannelInfo[0].destination_mask
477b543dbc2SStephan Aßmus 				= B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
478806cf560Sbeveloper 		}
479b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
480b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) {
481b543dbc2SStephan Aßmus 			fInputChannelInfo[0].destination_mask
482b543dbc2SStephan Aßmus 				= B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
483806cf560Sbeveloper 		}
484b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
485b543dbc2SStephan Aßmus 			&& (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) {
486b543dbc2SStephan Aßmus 			fInputChannelInfo[1].destination_mask
487b543dbc2SStephan Aßmus 				= B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
488806cf560Sbeveloper 		}
489b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
490b543dbc2SStephan Aßmus 			&& (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) {
491b543dbc2SStephan Aßmus 			fInputChannelInfo[1].destination_mask
492b543dbc2SStephan Aßmus 				= B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
493806cf560Sbeveloper 		}
4942e9d6607Sbeveloper 	}
4952e9d6607Sbeveloper 
496b543dbc2SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
497b006bbe1SStephan Aßmus 		TRACE("_UpdateInputChannelDestinationMask: input channel %d, "
498b543dbc2SStephan Aßmus 			"destination_mask 0x%08lX, base %p, gain %.3f\n", i,
499b543dbc2SStephan Aßmus 			fInputChannelInfo[i].destination_mask,
500b543dbc2SStephan Aßmus 			fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
501b543dbc2SStephan Aßmus 	}
502b006bbe1SStephan Aßmus 	TRACE("_UpdateInputChannelDestinationMask: leave\n");
5032e9d6607Sbeveloper }
5042e9d6607Sbeveloper 
505a9cf57cfSAxel Dörfler 
5062e9d6607Sbeveloper void
507b006bbe1SStephan Aßmus MixerInput::_UpdateInputChannelDestinations()
5082e9d6607Sbeveloper {
509d91580cdSbeveloper 	int channel_count;
5102e9d6607Sbeveloper 	uint32 all_bits;
5112e9d6607Sbeveloper 	uint32 mask;
5122e9d6607Sbeveloper 
513b006bbe1SStephan Aßmus 	TRACE("_UpdateInputChannelDestinations: enter\n");
514b543dbc2SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
515b006bbe1SStephan Aßmus 		TRACE("_UpdateInputChannelDestinations: input channel %d, "
516b543dbc2SStephan Aßmus 			"destination_mask 0x%08lX, base %p, gain %.3f\n", i,
517b543dbc2SStephan Aßmus 			fInputChannelInfo[i].destination_mask,
518b543dbc2SStephan Aßmus 			fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
519b543dbc2SStephan Aßmus 	}
5202e9d6607Sbeveloper 
5212e9d6607Sbeveloper 	all_bits = 0;
5222e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
5239c3be6a5Sbeveloper 		all_bits |= fInputChannelInfo[i].destination_mask;
5242e9d6607Sbeveloper 
525b006bbe1SStephan Aßmus 	TRACE("_UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits);
5262e9d6607Sbeveloper 
5272e9d6607Sbeveloper 	channel_count = count_nonzero_bits(all_bits);
528b006bbe1SStephan Aßmus 	TRACE("_UpdateInputChannelDestinations: %d input channels, %d mixer "
529b543dbc2SStephan Aßmus 		"channels (%d old)\n", fInputChannelCount, channel_count,
530b543dbc2SStephan Aßmus 		fMixerChannelCount);
5312e9d6607Sbeveloper 	if (channel_count != fMixerChannelCount) {
5329c3be6a5Sbeveloper 		delete [] fMixerChannelInfo;
5332e9d6607Sbeveloper 		fMixerChannelInfo = new mixer_chan_info[channel_count];
5342e9d6607Sbeveloper 		fMixerChannelCount = channel_count;
5352e9d6607Sbeveloper 	}
5362e9d6607Sbeveloper 
5372e9d6607Sbeveloper 	// assign each mixer channel one type
5389c3be6a5Sbeveloper 	// and the gain from the fChannelTypeGain[]
539d91580cdSbeveloper 	mask = 1;
540d91580cdSbeveloper 	for (int i = 0; i < fMixerChannelCount; i++) {
5412e9d6607Sbeveloper 		while (mask != 0 && (all_bits & mask) == 0)
5422e9d6607Sbeveloper 			mask <<= 1;
5439c3be6a5Sbeveloper 		fMixerChannelInfo[i].destination_type = ChannelMaskToChannelType(mask);
544b543dbc2SStephan Aßmus 		fMixerChannelInfo[i].destination_gain
545b543dbc2SStephan Aßmus 			= fChannelTypeGain[fMixerChannelInfo[i].destination_type];
5462e9d6607Sbeveloper 		mask <<= 1;
5472e9d6607Sbeveloper 	}
5482e9d6607Sbeveloper 
5492e9d6607Sbeveloper 	// assign buffer_base pointer for each mixer channel
5502e9d6607Sbeveloper 	for (int i = 0; i < fMixerChannelCount; i++) {
5512e9d6607Sbeveloper 		int j;
5522e9d6607Sbeveloper 		for (j = 0; j < fInputChannelCount; j++) {
553b543dbc2SStephan Aßmus 			if (fInputChannelInfo[j].destination_mask
554b543dbc2SStephan Aßmus 					& ChannelTypeToChannelMask(
555b543dbc2SStephan Aßmus 						fMixerChannelInfo[i].destination_type)) {
556b543dbc2SStephan Aßmus 				fMixerChannelInfo[i].buffer_base = fMixBuffer ? &fMixBuffer[j]
557b543dbc2SStephan Aßmus 					: 0;
5582e9d6607Sbeveloper 				break;
5592e9d6607Sbeveloper 			}
5602e9d6607Sbeveloper 		}
5612e9d6607Sbeveloper 		if (j == fInputChannelCount) {
562a2ca4723Sbeveloper 			ERROR("buffer assignment failed for mixer chan %d\n", i);
5632e9d6607Sbeveloper 			fMixerChannelInfo[i].buffer_base = fMixBuffer;
5642e9d6607Sbeveloper 		}
5652e9d6607Sbeveloper 	}
5662e9d6607Sbeveloper 
567b543dbc2SStephan Aßmus 	for (int i = 0; i < fMixerChannelCount; i++) {
568b006bbe1SStephan Aßmus 		TRACE("_UpdateInputChannelDestinations: mixer channel %d, type %2d, "
569b543dbc2SStephan Aßmus 			"base %p, gain %.3f\n", i, fMixerChannelInfo[i].destination_type,
570b543dbc2SStephan Aßmus 			fMixerChannelInfo[i].buffer_base,
571b543dbc2SStephan Aßmus 			fMixerChannelInfo[i].destination_gain);
572b543dbc2SStephan Aßmus 	}
5732e9d6607Sbeveloper 
574b006bbe1SStephan Aßmus 	TRACE("_UpdateInputChannelDestinations: leave\n");
5752e9d6607Sbeveloper }
576bf7ab50dSStephan Aßmus 
577a9cf57cfSAxel Dörfler 
578bf7ab50dSStephan Aßmus // Note: The following code is outcommented on purpose
579bf7ab50dSStephan Aßmus // and is about to be modified at a later point
58069517c15Sbeveloper /*
5812e9d6607Sbeveloper void
582b543dbc2SStephan Aßmus MixerInput::SetInputChannelDestinationGain(int channel, int destination_type,
583b543dbc2SStephan Aßmus 	float gain)
5842e9d6607Sbeveloper {
585b543dbc2SStephan Aßmus 	TRACE("SetInputChannelDestinationGain: channel %d, destination_type %d,
586b543dbc2SStephan Aßmus 		gain %.4f\n", channel, destination_type, gain);
5879c3be6a5Sbeveloper 	// we don't need the channel, as each destination_type can only exist
5889c3be6a5Sbeveloper 	// once for each MixerInput, but we use it for parameter validation
5899c3be6a5Sbeveloper 	// and to have a interface similar to MixerOutput
5902e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
5912e9d6607Sbeveloper 		return;
5929c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
5939c3be6a5Sbeveloper 		return;
5942e9d6607Sbeveloper 	if (gain < 0.0f)
5952e9d6607Sbeveloper 		gain = 0.0f;
5969c3be6a5Sbeveloper 	fChannelTypeGain[destination_type] = gain;
5979c3be6a5Sbeveloper 	for (int i = 0; i < fMixerChannelCount; i++) {
5989c3be6a5Sbeveloper 		if (fMixerChannelInfo[i].destination_type == destination_type) {
5999c3be6a5Sbeveloper 			fMixerChannelInfo[i].destination_gain = gain;
6009c3be6a5Sbeveloper 			return;
6019c3be6a5Sbeveloper 		}
6029c3be6a5Sbeveloper 	}
6032e9d6607Sbeveloper }
6042e9d6607Sbeveloper 
605a9cf57cfSAxel Dörfler 
6062e9d6607Sbeveloper float
6079c3be6a5Sbeveloper MixerInput::GetInputChannelDestinationGain(int channel, int destination_type)
6082e9d6607Sbeveloper {
6099c3be6a5Sbeveloper 	// we don't need the channel, as each destination_type can only exist
6109c3be6a5Sbeveloper 	// once for each MixerInput, but we use it for parameter validation
6119c3be6a5Sbeveloper 	// and to have a interface similar to MixerOutput
6122e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
6139c3be6a5Sbeveloper 		return 0.0f;
6149c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
6159c3be6a5Sbeveloper 		return 0.0f;
6169c3be6a5Sbeveloper 	return fChannelTypeGain[destination_type];
6172e9d6607Sbeveloper }
61869517c15Sbeveloper */
61969517c15Sbeveloper 
620a9cf57cfSAxel Dörfler 
62169517c15Sbeveloper void
62269517c15Sbeveloper MixerInput::SetMixerChannelGain(int mixer_channel, float gain)
62369517c15Sbeveloper {
62469517c15Sbeveloper 	if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
62569517c15Sbeveloper 		return;
62669517c15Sbeveloper 	if (gain < 0.0f)
62769517c15Sbeveloper 		gain = 0.0f;
62869517c15Sbeveloper 
62969517c15Sbeveloper 	fMixerChannelInfo[mixer_channel].destination_gain = gain;
63069517c15Sbeveloper 	fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain;
63169517c15Sbeveloper }
63269517c15Sbeveloper 
633a9cf57cfSAxel Dörfler 
63469517c15Sbeveloper float
63569517c15Sbeveloper MixerInput::GetMixerChannelGain(int mixer_channel)
63669517c15Sbeveloper {
63769517c15Sbeveloper 	if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
63869517c15Sbeveloper 		return 0.0;
63969517c15Sbeveloper 	return fMixerChannelInfo[mixer_channel].destination_gain;
64069517c15Sbeveloper }
64169517c15Sbeveloper 
642a9cf57cfSAxel Dörfler 
64369517c15Sbeveloper int
64469517c15Sbeveloper MixerInput::GetMixerChannelType(int mixer_channel)
64569517c15Sbeveloper {
64669517c15Sbeveloper 	if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
64769517c15Sbeveloper 		return -1;
64869517c15Sbeveloper 	return fMixerChannelInfo[mixer_channel].destination_type;
64969517c15Sbeveloper }
6502e9d6607Sbeveloper 
651a9cf57cfSAxel Dörfler 
6522e9d6607Sbeveloper void
6531c237c18Sbeveloper MixerInput::SetEnabled(bool yesno)
6541c237c18Sbeveloper {
6551c237c18Sbeveloper 	fEnabled = yesno;
6561c237c18Sbeveloper }
6571c237c18Sbeveloper 
658a9cf57cfSAxel Dörfler 
6591c237c18Sbeveloper bool
6601c237c18Sbeveloper MixerInput::IsEnabled()
6611c237c18Sbeveloper {
6621c237c18Sbeveloper 	return fEnabled;
6631c237c18Sbeveloper }
6641c237c18Sbeveloper 
665a9cf57cfSAxel Dörfler 
6661c237c18Sbeveloper void
6678d28117fSbeveloper MixerInput::SetMixBufferFormat(int32 framerate, int32 frames)
6682e9d6607Sbeveloper {
669a9cf57cfSAxel Dörfler 	TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n",
670a9cf57cfSAxel Dörfler 		framerate, frames);
671d5848e21Sbeveloper 
6727b0daf5cSbeveloper 	fMixBufferFrameRate = framerate;
673a9cf57cfSAxel Dörfler 	fDebugMixBufferFrames = frames;
6742e9d6607Sbeveloper 
675d5848e21Sbeveloper 	// frames and/or framerate can be 0 (if no output is connected)
676d5848e21Sbeveloper 	if (framerate == 0 || frames == 0) {
677a9cf57cfSAxel Dörfler 		if (fMixBuffer != NULL) {
678d5848e21Sbeveloper 			rtm_free(fMixBuffer);
679a9cf57cfSAxel Dörfler 			fMixBuffer = NULL;
680d5848e21Sbeveloper 		}
681d5848e21Sbeveloper 		for (int i = 0; i < fInputChannelCount; i++)
682d5848e21Sbeveloper 			fInputChannelInfo[i].buffer_base = 0;
683d5848e21Sbeveloper 		fMixBufferFrameCount = 0;
684d5848e21Sbeveloper 
685b006bbe1SStephan Aßmus 		_UpdateInputChannelDestinationMask();
686b006bbe1SStephan Aßmus 		_UpdateInputChannelDestinations();
687d5848e21Sbeveloper 		return;
688d5848e21Sbeveloper 	}
6897b0daf5cSbeveloper 
6907b0daf5cSbeveloper 	// make fMixBufferFrameCount an integral multiple of frames,
6917b0daf5cSbeveloper 	// but at least 3 times duration of our input buffer
6927b0daf5cSbeveloper 	// and at least 2 times duration of the output buffer
693b543dbc2SStephan Aßmus 	bigtime_t inputBufferLength  = duration_for_frames(
694b543dbc2SStephan Aßmus 		fInput.format.u.raw_audio.frame_rate,
695b543dbc2SStephan Aßmus 		frames_per_buffer(fInput.format.u.raw_audio));
6967b0daf5cSbeveloper 	bigtime_t outputBufferLength = duration_for_frames(framerate, frames);
697b543dbc2SStephan Aßmus 	bigtime_t mixerBufferLength
698b543dbc2SStephan Aßmus 		= max_c(3 * inputBufferLength, 2 * outputBufferLength);
6997b0daf5cSbeveloper 	int temp = frames_for_duration(framerate, mixerBufferLength);
7007b0daf5cSbeveloper 	fMixBufferFrameCount = ((temp / frames) + 1) * frames;
7017b0daf5cSbeveloper 
702a2ca4723Sbeveloper 	TRACE("  inputBufferLength    %10Ld\n", inputBufferLength);
703a2ca4723Sbeveloper 	TRACE("  outputBufferLength   %10Ld\n", outputBufferLength);
704a2ca4723Sbeveloper 	TRACE("  mixerBufferLength    %10Ld\n", mixerBufferLength);
705d91580cdSbeveloper 	TRACE("  fMixBufferFrameCount %10d\n", fMixBufferFrameCount);
7067b0daf5cSbeveloper 
7078d28117fSbeveloper 	ASSERT((fMixBufferFrameCount % frames) == 0);
7088d28117fSbeveloper 
709e92593f4Sbeveloper 	fLastDataFrameWritten = -1;
710e92593f4Sbeveloper 	fFractionalFrames = 0.0;
711e92593f4Sbeveloper 
7122e9d6607Sbeveloper 	rtm_free(fMixBuffer);
713356855c3Sbeveloper 	rtm_delete_pool(fRtmPool);
714a9cf57cfSAxel Dörfler 
7157b0daf5cSbeveloper 	int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount;
716a9cf57cfSAxel Dörfler 	if (rtm_create_pool(&fRtmPool, size) != B_OK)
717a9cf57cfSAxel Dörfler 		fRtmPool = NULL;
718a9cf57cfSAxel Dörfler 
719356855c3Sbeveloper 	fMixBuffer = (float*)rtm_alloc(fRtmPool, size);
720a9cf57cfSAxel Dörfler 	if (fMixBuffer == NULL)
721a9cf57cfSAxel Dörfler 		return;
7227b0daf5cSbeveloper 
7237b0daf5cSbeveloper 	memset(fMixBuffer, 0, size);
7242e9d6607Sbeveloper 
7252e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
7267b0daf5cSbeveloper 		fInputChannelInfo[i].buffer_base = &fMixBuffer[i];
727d5848e21Sbeveloper 
728b006bbe1SStephan Aßmus 	_UpdateInputChannelDestinationMask();
729b006bbe1SStephan Aßmus 	_UpdateInputChannelDestinations();
7302e9d6607Sbeveloper }
731