xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp (revision a79b30c3b65a0035ccda843c6685accec08f833f)
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"
17*a79b30c3SStephan 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,
24*a79b30c3SStephan Aßmus 	float mixFrameRate, int32 mixFrameCount, int resamplingAlgorithm)
25a9cf57cfSAxel Dörfler 	:
26a9cf57cfSAxel Dörfler 	fCore(core),
272e9d6607Sbeveloper  	fInput(input),
2888777023Sbeveloper 	fInputByteSwap(0),
291c237c18Sbeveloper 	fEnabled(true),
302e9d6607Sbeveloper 	fInputChannelInfo(0),
312e9d6607Sbeveloper 	fInputChannelCount(0),
322e9d6607Sbeveloper 	fInputChannelMask(0),
332e9d6607Sbeveloper 	fMixerChannelInfo(0),
342e9d6607Sbeveloper 	fMixerChannelCount(0),
352e9d6607Sbeveloper 	fMixBuffer(0),
367b0daf5cSbeveloper 	fMixBufferFrameRate(0),
377b0daf5cSbeveloper 	fMixBufferFrameCount(0),
38e92593f4Sbeveloper 	fLastDataFrameWritten(-1),
39af8d0a4dSbeveloper 	fLastDataAvailableTime(-1),
40e92593f4Sbeveloper 	fFractionalFrames(0.0),
417b0daf5cSbeveloper 	fResampler(0),
42356855c3Sbeveloper 	fRtmPool(0),
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;
75b543dbc2SStephan Aßmus 			// will be set by UpdateInputChannelDestinationMask()
762e9d6607Sbeveloper 		fInputChannelInfo[i].gain = 1.0;
772e9d6607Sbeveloper 	}
782e9d6607Sbeveloper 
797b0daf5cSbeveloper 	// create resamplers
807b0daf5cSbeveloper 	fResampler = new Resampler * [fInputChannelCount];
814cc71346SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
82*a79b30c3SStephan Aßmus 		switch (resamplingAlgorithm) {
83*a79b30c3SStephan Aßmus 			case 2:
84*a79b30c3SStephan Aßmus 				fResampler[i] = new Interpolate(
85*a79b30c3SStephan Aßmus 					fInput.format.u.raw_audio.format,
86b543dbc2SStephan Aßmus 					media_raw_audio_format::B_AUDIO_FLOAT);
87*a79b30c3SStephan Aßmus 				break;
88*a79b30c3SStephan Aßmus 			default:
89*a79b30c3SStephan Aßmus 				fResampler[i] = new Resampler(
90*a79b30c3SStephan Aßmus 					fInput.format.u.raw_audio.format,
91*a79b30c3SStephan Aßmus 					media_raw_audio_format::B_AUDIO_FLOAT);
92*a79b30c3SStephan Aßmus 		}
934cc71346SStephan Aßmus 	}
947b0daf5cSbeveloper 
95b543dbc2SStephan Aßmus 	// fMixerChannelInfo and fMixerChannelCount will be initialized by
96b543dbc2SStephan Aßmus 	// UpdateInputChannelDestinations()
97bf7ab50dSStephan Aßmus 	SetMixBufferFormat((int32)mixFrameRate, mixFrameCount);
98678c2017Sbeveloper }
99678c2017Sbeveloper 
100a9cf57cfSAxel Dörfler 
101678c2017Sbeveloper MixerInput::~MixerInput()
102678c2017Sbeveloper {
1032e9d6607Sbeveloper 	if (fMixBuffer)
1042e9d6607Sbeveloper 		rtm_free(fMixBuffer);
105356855c3Sbeveloper 	if (fRtmPool)
106356855c3Sbeveloper 		rtm_delete_pool(fRtmPool);
1072e9d6607Sbeveloper 	delete [] fInputChannelInfo;
1082e9d6607Sbeveloper 	delete [] fMixerChannelInfo;
1097b0daf5cSbeveloper 
1107b0daf5cSbeveloper 	// delete resamplers
1117b0daf5cSbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
1127b0daf5cSbeveloper 		delete fResampler[i];
1137b0daf5cSbeveloper 	delete [] fResampler;
114db6f1135SJérôme Duval 	delete fInputByteSwap;
115678c2017Sbeveloper }
116678c2017Sbeveloper 
117a9cf57cfSAxel Dörfler 
118678c2017Sbeveloper void
119678c2017Sbeveloper MixerInput::BufferReceived(BBuffer *buffer)
120678c2017Sbeveloper {
12188777023Sbeveloper 	void *data;
12288777023Sbeveloper 	size_t size;
12388777023Sbeveloper 	bigtime_t start;
124e92593f4Sbeveloper 	bigtime_t buffer_duration;
12588777023Sbeveloper 
126d5848e21Sbeveloper 	if (!fMixBuffer) {
127b543dbc2SStephan Aßmus 		ERROR("MixerInput::BufferReceived: dropped incoming buffer as we "
128b543dbc2SStephan Aßmus 			"don't have a mix buffer\n");
129d5848e21Sbeveloper 		return;
130d5848e21Sbeveloper 	}
1312e9d6607Sbeveloper 
13288777023Sbeveloper 	data = buffer->Data();
13388777023Sbeveloper 	size = buffer->SizeUsed();
13488777023Sbeveloper 	start = buffer->Header()->start_time;
135b543dbc2SStephan Aßmus 	buffer_duration = duration_for_frames(fInput.format.u.raw_audio.frame_rate,
136b543dbc2SStephan Aßmus 		size / bytes_per_frame(fInput.format.u.raw_audio));
1378d28117fSbeveloper 	if (start < 0) {
138b543dbc2SStephan Aßmus 		ERROR("MixerInput::BufferReceived: buffer with negative start time of "
139b543dbc2SStephan Aßmus 			"%Ld dropped\n", start);
1408d28117fSbeveloper 		return;
1418d28117fSbeveloper 	}
14288777023Sbeveloper 
14388777023Sbeveloper 	// swap the byte order of this buffer, if necessary
14488777023Sbeveloper 	if (fInputByteSwap)
14588777023Sbeveloper 		fInputByteSwap->Swap(data, size);
14688777023Sbeveloper 
147b543dbc2SStephan Aßmus 	int offset = frames_for_duration(fMixBufferFrameRate, start)
148b543dbc2SStephan Aßmus 		% fMixBufferFrameCount;
1498d28117fSbeveloper 
150b543dbc2SStephan Aßmus 	PRINT(4, "MixerInput::BufferReceived: buffer start %10Ld, offset %6d\n",
151b543dbc2SStephan Aßmus 		start, offset);
1527b0daf5cSbeveloper 
153191033efSbeveloper 	int in_frames = size / bytes_per_frame(fInput.format.u.raw_audio);
154b543dbc2SStephan Aßmus 	double frames = double(in_frames * fMixBufferFrameRate)
155b543dbc2SStephan Aßmus 		/ fInput.format.u.raw_audio.frame_rate;
156e92593f4Sbeveloper 	int out_frames = int(frames);
157e92593f4Sbeveloper 	fFractionalFrames += frames - double(out_frames);
158e92593f4Sbeveloper 	if (fFractionalFrames >= 1.0) {
159e92593f4Sbeveloper 		fFractionalFrames -= 1.0;
1607619f562Sbeveloper 		out_frames++;
161e92593f4Sbeveloper 	}
162e92593f4Sbeveloper 
163e92593f4Sbeveloper 	// if fLastDataFrameWritten != -1, then we have a valid last position
164e92593f4Sbeveloper 	// and can do glitch compensation
165e92593f4Sbeveloper 	if (fLastDataFrameWritten >= 0) {
166b543dbc2SStephan Aßmus 		int expected_frame = (fLastDataFrameWritten + 1)
167b543dbc2SStephan Aßmus 			% fMixBufferFrameCount;
168e92593f4Sbeveloper 		if (offset != expected_frame) {
169e92593f4Sbeveloper 			// due to rounding and other errors, offset might be off by +/- 1
170e92593f4Sbeveloper 			// this is not really a bad glitch, we just adjust the position
171e92593f4Sbeveloper 			if (offset == fLastDataFrameWritten) {
172b543dbc2SStephan Aßmus //				printf("MixerInput::BufferReceived: -1 frame GLITCH! last "
173b543dbc2SStephan Aßmus //					"frame was %ld, expected frame was %d, new frame is %d\n",
174b543dbc2SStephan Aßmus //					fLastDataFrameWritten, expected_frame, offset);
175e92593f4Sbeveloper 				offset = expected_frame;
176b543dbc2SStephan Aßmus 			} else if (offset == ((fLastDataFrameWritten + 2)
177b543dbc2SStephan Aßmus 				% fMixBufferFrameCount)) {
178b543dbc2SStephan Aßmus //				printf("MixerInput::BufferReceived: +1 frame GLITCH! last "
179b543dbc2SStephan Aßmus //					"frame was %ld, expected frame was %d, new frame is %d\n",
180b543dbc2SStephan Aßmus //					fLastDataFrameWritten, expected_frame, offset);
181e92593f4Sbeveloper 				offset = expected_frame;
182e92593f4Sbeveloper 			} else {
183b543dbc2SStephan Aßmus 				printf("MixerInput::BufferReceived: GLITCH! last frame was "
184b543dbc2SStephan Aßmus 					"%4ld, expected frame was %4d, new frame is %4d\n",
185b543dbc2SStephan Aßmus 					fLastDataFrameWritten, expected_frame, offset);
186e92593f4Sbeveloper 
187e92593f4Sbeveloper 				if (start > fLastDataAvailableTime) {
188b543dbc2SStephan Aßmus 					if ((start - fLastDataAvailableTime)
189b543dbc2SStephan Aßmus 						< (buffer_duration / 10)) {
190e92593f4Sbeveloper 						// buffer is less than 10% of buffer duration too late
191b543dbc2SStephan Aßmus 						printf("short glitch, buffer too late, time delta "
192b543dbc2SStephan Aßmus 							"%Ld\n", start - fLastDataAvailableTime);
193e92593f4Sbeveloper 						offset = expected_frame;
194e92593f4Sbeveloper 						out_frames++;
195e92593f4Sbeveloper 					} else {
196e92593f4Sbeveloper 						// buffer more than 10% of buffer duration too late
197b543dbc2SStephan Aßmus 						// TODO: zerofill buffer
198b543dbc2SStephan Aßmus 						printf("MAJOR glitch, buffer too late, time delta "
199b543dbc2SStephan Aßmus 							"%Ld\n", start - fLastDataAvailableTime);
200e92593f4Sbeveloper 					}
201e92593f4Sbeveloper 				} else { // start <= fLastDataAvailableTime
202e92593f4Sbeveloper 					// the new buffer is too early
203b543dbc2SStephan Aßmus 					if ((fLastDataAvailableTime - start)
204b543dbc2SStephan Aßmus 						< (buffer_duration / 10)) {
205e92593f4Sbeveloper 						// buffer is less than 10% of buffer duration too early
206b543dbc2SStephan Aßmus 						printf("short glitch, buffer too early, time delta "
207b543dbc2SStephan Aßmus 							"%Ld\n", fLastDataAvailableTime - start);
208e92593f4Sbeveloper 						offset = expected_frame;
209e92593f4Sbeveloper 						out_frames--;
210e92593f4Sbeveloper 						if (out_frames < 1)
211e92593f4Sbeveloper 							out_frames = 1;
212e92593f4Sbeveloper 					} else {
213e92593f4Sbeveloper 						// buffer more than 10% of buffer duration too early
214b543dbc2SStephan Aßmus 						// TODO: zerofill buffer
215b543dbc2SStephan Aßmus 						printf("MAJOR glitch, buffer too early, time delta "
216b543dbc2SStephan Aßmus 							"%Ld\n", fLastDataAvailableTime - start);
217e92593f4Sbeveloper 					}
218e92593f4Sbeveloper 				}
219e92593f4Sbeveloper 			}
220e92593f4Sbeveloper 		}
221e92593f4Sbeveloper 	}
2227b0daf5cSbeveloper 
223b543dbc2SStephan Aßmus //	printf("data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n",
224b543dbc2SStephan Aßmus //		start,
225b543dbc2SStephan Aßmus //		start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
226b543dbc2SStephan Aßmus //		frames_per_buffer(fInput.format.u.raw_audio)), offset,
227b543dbc2SStephan Aßmus //		offset + out_frames);
2287b0daf5cSbeveloper 	if (offset + out_frames > fMixBufferFrameCount) {
2297b0daf5cSbeveloper 		int out_frames1 = fMixBufferFrameCount - offset;
2307b0daf5cSbeveloper 		int out_frames2 = out_frames - out_frames1;
2317b0daf5cSbeveloper 		int in_frames1 = (out_frames1 * in_frames) / out_frames;
2327b0daf5cSbeveloper 		int in_frames2 = in_frames - in_frames1;
2337b0daf5cSbeveloper 
234b543dbc2SStephan Aßmus //		printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at "
235b543dbc2SStephan Aßmus //			"frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(),
236b543dbc2SStephan Aßmus //			start,
237b543dbc2SStephan Aßmus //			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
238b543dbc2SStephan Aßmus //			frames_per_buffer(fInput.format.u.raw_audio)), offset,
239b543dbc2SStephan Aßmus //			offset + out_frames1 - 1, 0, out_frames2 - 1);
240b543dbc2SStephan Aßmus 		PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at "
241b543dbc2SStephan Aßmus 			"frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(),
242b543dbc2SStephan Aßmus 			start,
243b543dbc2SStephan Aßmus 			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
244b543dbc2SStephan Aßmus 			frames_per_buffer(fInput.format.u.raw_audio)), offset,
245b543dbc2SStephan Aßmus 			offset + out_frames1 - 1, 0, out_frames2 - 1);
246b543dbc2SStephan Aßmus 		PRINT(5, "  in_frames %5d, out_frames %5d, in_frames1 %5d, "
247b543dbc2SStephan Aßmus 			"out_frames1 %5d, in_frames2 %5d, out_frames2 %5d\n",
248b543dbc2SStephan Aßmus 			in_frames, out_frames, in_frames1, out_frames1, in_frames2,
249b543dbc2SStephan Aßmus 			out_frames2);
2507b0daf5cSbeveloper 
251e92593f4Sbeveloper 		fLastDataFrameWritten = out_frames2 - 1;
252e92593f4Sbeveloper 
253b543dbc2SStephan Aßmus 		// convert offset from frames into bytes
254b543dbc2SStephan Aßmus 		offset *= sizeof(float) * fInputChannelCount;
2558d28117fSbeveloper 
2567b0daf5cSbeveloper 		for (int i = 0; i < fInputChannelCount; i++) {
257b543dbc2SStephan Aßmus 			fResampler[i]->Resample(
258b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(data)
259b543dbc2SStephan Aßmus 					+ i * bytes_per_sample(fInput.format.u.raw_audio),
260b543dbc2SStephan Aßmus 				bytes_per_frame(fInput.format.u.raw_audio), in_frames1,
261b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base)
262b543dbc2SStephan Aßmus 					+ offset, fInputChannelCount * sizeof(float), out_frames1,
2637b0daf5cSbeveloper 				fInputChannelInfo[i].gain);
2647b0daf5cSbeveloper 
265b543dbc2SStephan Aßmus 			fResampler[i]->Resample(
266b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(data)
267b543dbc2SStephan Aßmus 					+ i * bytes_per_sample(fInput.format.u.raw_audio)
268b543dbc2SStephan Aßmus 					+ in_frames1 * bytes_per_frame(fInput.format.u.raw_audio),
269b543dbc2SStephan Aßmus 				bytes_per_frame(fInput.format.u.raw_audio), in_frames2,
2707b0daf5cSbeveloper 				reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base),
271b543dbc2SStephan Aßmus 				fInputChannelCount * sizeof(float), out_frames2,
2727b0daf5cSbeveloper 				fInputChannelInfo[i].gain);
273e92593f4Sbeveloper 
2747b0daf5cSbeveloper 		}
2757b0daf5cSbeveloper 	} else {
276b543dbc2SStephan Aßmus //		printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at "
277b543dbc2SStephan Aßmus //			"frames %ld to %ld\n", fCore->fTimeSource->Now(), start,
278b543dbc2SStephan Aßmus //			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
279b543dbc2SStephan Aßmus //			frames_per_buffer(fInput.format.u.raw_audio)), offset,
280b543dbc2SStephan Aßmus //			offset + out_frames - 1);
281b543dbc2SStephan Aßmus 		PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at "
282b543dbc2SStephan Aßmus 			"frames %ld to %ld\n", fCore->fTimeSource->Now(), start,
283b543dbc2SStephan Aßmus 			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
284b543dbc2SStephan Aßmus 			frames_per_buffer(fInput.format.u.raw_audio)), offset,
285b543dbc2SStephan Aßmus 			offset + out_frames - 1);
286191033efSbeveloper 		PRINT(5, "  in_frames %5d, out_frames %5d\n", in_frames, out_frames);
2878d28117fSbeveloper 
288e92593f4Sbeveloper 		fLastDataFrameWritten = offset + out_frames - 1;
289b543dbc2SStephan Aßmus 		// convert offset from frames into bytes
290b543dbc2SStephan Aßmus 		offset *= sizeof(float) * fInputChannelCount;
2917b0daf5cSbeveloper 		for (int i = 0; i < fInputChannelCount; i++) {
292b543dbc2SStephan Aßmus 			fResampler[i]->Resample(
293b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(data)
294b543dbc2SStephan Aßmus 					+ i * bytes_per_sample(fInput.format.u.raw_audio),
295b543dbc2SStephan Aßmus 				bytes_per_frame(fInput.format.u.raw_audio), in_frames,
296b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base)
297b543dbc2SStephan Aßmus 					+ offset, fInputChannelCount * sizeof(float),
298b543dbc2SStephan Aßmus 				out_frames, fInputChannelInfo[i].gain);
2997b0daf5cSbeveloper 		}
3007b0daf5cSbeveloper 	}
301e92593f4Sbeveloper 	fLastDataAvailableTime = start + buffer_duration;
302678c2017Sbeveloper }
3037ee2c804Sbeveloper 
304bf7ab50dSStephan Aßmus 
3057ee2c804Sbeveloper media_input &
3067ee2c804Sbeveloper MixerInput::MediaInput()
3077ee2c804Sbeveloper {
3087ee2c804Sbeveloper 	return fInput;
3097ee2c804Sbeveloper }
310e6c7c99fSbeveloper 
311bf7ab50dSStephan Aßmus 
312e6c7c99fSbeveloper int32
313e6c7c99fSbeveloper MixerInput::ID()
314e6c7c99fSbeveloper {
315e6c7c99fSbeveloper 	return fInput.destination.id;
316e6c7c99fSbeveloper }
317e6c7c99fSbeveloper 
318bf7ab50dSStephan Aßmus 
319d91580cdSbeveloper int
320fae6ce82Sbeveloper MixerInput::GetInputChannelCount()
321fae6ce82Sbeveloper {
322fae6ce82Sbeveloper 	return fInputChannelCount;
323fae6ce82Sbeveloper }
324fae6ce82Sbeveloper 
325bf7ab50dSStephan Aßmus 
3262e9d6607Sbeveloper void
3279c3be6a5Sbeveloper MixerInput::AddInputChannelDestination(int channel, int destination_type)
3282e9d6607Sbeveloper {
3299c3be6a5Sbeveloper 	uint32 mask = ChannelTypeToChannelMask(destination_type);
330e6c7c99fSbeveloper 
3312e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3322e9d6607Sbeveloper 		return;
3332e9d6607Sbeveloper 
3342e9d6607Sbeveloper 	// test if it is already set
3359c3be6a5Sbeveloper 	if (fInputChannelInfo[channel].destination_mask & mask)
3362e9d6607Sbeveloper 		return;
3372e9d6607Sbeveloper 
3389c3be6a5Sbeveloper 	// verify that no other channel has id
3399c3be6a5Sbeveloper 	if (-1 != GetInputChannelForDestination(destination_type)) {
340b543dbc2SStephan Aßmus 		ERROR("MixerInput::AddInputChannelDestination: destination_type %d "
341b543dbc2SStephan Aßmus 			"already assigned to channel %d\n", destination_type,
342b543dbc2SStephan Aßmus 			GetInputChannelForDestination(destination_type));
3439c3be6a5Sbeveloper 		return;
3449c3be6a5Sbeveloper 	}
3452e9d6607Sbeveloper 
3462e9d6607Sbeveloper 	// add it to specified channel
3479c3be6a5Sbeveloper 	fInputChannelInfo[channel].destination_mask |= mask;
3482e9d6607Sbeveloper 
3499c3be6a5Sbeveloper 	fUserOverridesChannelDestinations = true;
3509c3be6a5Sbeveloper 	UpdateInputChannelDestinations();
3512e9d6607Sbeveloper }
3522e9d6607Sbeveloper 
353a9cf57cfSAxel Dörfler 
3542e9d6607Sbeveloper void
3559c3be6a5Sbeveloper MixerInput::RemoveInputChannelDestination(int channel, int destination_type)
3562e9d6607Sbeveloper {
3579c3be6a5Sbeveloper 	uint32 mask = ChannelTypeToChannelMask(destination_type);
3582e9d6607Sbeveloper 
3592e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3602e9d6607Sbeveloper 		return;
3612e9d6607Sbeveloper 
3622e9d6607Sbeveloper 	// test if it is really set
3639c3be6a5Sbeveloper 	if ((fInputChannelInfo[channel].destination_mask & mask) == 0)
3642e9d6607Sbeveloper 		return;
3652e9d6607Sbeveloper 
3662e9d6607Sbeveloper 	// remove it from specified channel
3679c3be6a5Sbeveloper 	fInputChannelInfo[channel].destination_mask &= ~mask;
3682e9d6607Sbeveloper 
3699c3be6a5Sbeveloper 	fUserOverridesChannelDestinations = true;
3709c3be6a5Sbeveloper 	UpdateInputChannelDestinations();
3712e9d6607Sbeveloper }
3722e9d6607Sbeveloper 
373a9cf57cfSAxel Dörfler 
3749c3be6a5Sbeveloper bool
3759c3be6a5Sbeveloper MixerInput::HasInputChannelDestination(int channel, int destination_type)
3762e9d6607Sbeveloper {
3772e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3789c3be6a5Sbeveloper 		return false;
3799c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
3809c3be6a5Sbeveloper 		return false;
381b543dbc2SStephan Aßmus 	return fInputChannelInfo[channel].destination_mask
382b543dbc2SStephan Aßmus 		& ChannelTypeToChannelMask(destination_type);
3832e9d6607Sbeveloper }
3842e9d6607Sbeveloper 
385a9cf57cfSAxel Dörfler 
3869c3be6a5Sbeveloper int
3879c3be6a5Sbeveloper MixerInput::GetInputChannelForDestination(int destination_type)
3889c3be6a5Sbeveloper {
3899c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
3909c3be6a5Sbeveloper 		return -1;
3919c3be6a5Sbeveloper 	uint32 mask = ChannelTypeToChannelMask(destination_type);
3929c3be6a5Sbeveloper 	for (int chan = 0; chan < fInputChannelCount; chan++) {
3939c3be6a5Sbeveloper 		if (fInputChannelInfo[chan].destination_mask & mask)
3949c3be6a5Sbeveloper 			return chan;
3959c3be6a5Sbeveloper 	}
3969c3be6a5Sbeveloper 	return -1;
3979c3be6a5Sbeveloper }
3989c3be6a5Sbeveloper 
399a9cf57cfSAxel Dörfler 
4009c3be6a5Sbeveloper int
4012e9d6607Sbeveloper MixerInput::GetInputChannelType(int channel)
4022e9d6607Sbeveloper {
4032e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
4042e9d6607Sbeveloper 		return 0;
4059c3be6a5Sbeveloper 	return GetChannelType(channel, fInputChannelMask);
4062e9d6607Sbeveloper }
4072e9d6607Sbeveloper 
408a9cf57cfSAxel Dörfler 
4092e9d6607Sbeveloper void
4102e9d6607Sbeveloper MixerInput::SetInputChannelGain(int channel, float gain)
4112e9d6607Sbeveloper {
4122e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
4132e9d6607Sbeveloper 		return;
4142e9d6607Sbeveloper 	if (gain < 0.0f)
4152e9d6607Sbeveloper 		gain = 0.0f;
4162e9d6607Sbeveloper 
4172e9d6607Sbeveloper 	fInputChannelInfo[channel].gain = gain;
4182e9d6607Sbeveloper }
4192e9d6607Sbeveloper 
420a9cf57cfSAxel Dörfler 
4212e9d6607Sbeveloper float
4222e9d6607Sbeveloper MixerInput::GetInputChannelGain(int channel)
4232e9d6607Sbeveloper {
4242e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
4252e9d6607Sbeveloper 		return 0.0f;
4262e9d6607Sbeveloper 	return fInputChannelInfo[channel].gain;
4272e9d6607Sbeveloper }
4282e9d6607Sbeveloper 
429a9cf57cfSAxel Dörfler 
4302e9d6607Sbeveloper void
4319c3be6a5Sbeveloper MixerInput::UpdateInputChannelDestinationMask()
4322e9d6607Sbeveloper {
4332e9d6607Sbeveloper 	// is the user already messed with the assignmens, don't do anything.
4349c3be6a5Sbeveloper 	if (fUserOverridesChannelDestinations)
4352e9d6607Sbeveloper 		return;
4362e9d6607Sbeveloper 
4379c3be6a5Sbeveloper 	TRACE("UpdateInputChannelDestinationMask: enter\n");
4382e9d6607Sbeveloper 
439806cf560Sbeveloper 	// first apply a 1:1 mapping
440b543dbc2SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
441b543dbc2SStephan Aßmus 		fInputChannelInfo[i].destination_mask = GetChannelMask(i,
442b543dbc2SStephan Aßmus 			fInputChannelMask);
443b543dbc2SStephan Aßmus 	}
444806cf560Sbeveloper 
445806cf560Sbeveloper 	// specialize this, depending on the available physical output channels
446643e1b2eSbeveloper 	if (fCore->OutputChannelCount() <= 2) {
447643e1b2eSbeveloper 		// less or equal two channels
448b543dbc2SStephan Aßmus 		if (fInputChannelCount == 1
449b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask)
450b543dbc2SStephan Aßmus 				& (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
451ab276ac8Sbeveloper 			fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO;
452806cf560Sbeveloper 		}
453643e1b2eSbeveloper 	} else {
454643e1b2eSbeveloper 		// more than two channel output card
455b543dbc2SStephan Aßmus 		if (fInputChannelCount == 1
456b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask)
457b543dbc2SStephan Aßmus 				& (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
458ab276ac8Sbeveloper 			fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO;
459806cf560Sbeveloper 		}
460b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
461b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) {
462b543dbc2SStephan Aßmus 			fInputChannelInfo[0].destination_mask
463b543dbc2SStephan Aßmus 				= B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
464806cf560Sbeveloper 		}
465b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
466b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) {
467b543dbc2SStephan Aßmus 			fInputChannelInfo[0].destination_mask
468b543dbc2SStephan Aßmus 				= B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
469806cf560Sbeveloper 		}
470b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
471b543dbc2SStephan Aßmus 			&& (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) {
472b543dbc2SStephan Aßmus 			fInputChannelInfo[1].destination_mask
473b543dbc2SStephan Aßmus 				= B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
474806cf560Sbeveloper 		}
475b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
476b543dbc2SStephan Aßmus 			&& (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) {
477b543dbc2SStephan Aßmus 			fInputChannelInfo[1].destination_mask
478b543dbc2SStephan Aßmus 				= B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
479806cf560Sbeveloper 		}
4802e9d6607Sbeveloper 	}
4812e9d6607Sbeveloper 
482b543dbc2SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
483b543dbc2SStephan Aßmus 		TRACE("UpdateInputChannelDestinationMask: input channel %d, "
484b543dbc2SStephan Aßmus 			"destination_mask 0x%08lX, base %p, gain %.3f\n", i,
485b543dbc2SStephan Aßmus 			fInputChannelInfo[i].destination_mask,
486b543dbc2SStephan Aßmus 			fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
487b543dbc2SStephan Aßmus 	}
4889c3be6a5Sbeveloper 	TRACE("UpdateInputChannelDestinationMask: leave\n");
4892e9d6607Sbeveloper }
4902e9d6607Sbeveloper 
491a9cf57cfSAxel Dörfler 
4922e9d6607Sbeveloper void
4939c3be6a5Sbeveloper MixerInput::UpdateInputChannelDestinations()
4942e9d6607Sbeveloper {
495d91580cdSbeveloper 	int channel_count;
4962e9d6607Sbeveloper 	uint32 all_bits;
4972e9d6607Sbeveloper 	uint32 mask;
4982e9d6607Sbeveloper 
4999c3be6a5Sbeveloper 	TRACE("UpdateInputChannelDestinations: enter\n");
500b543dbc2SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
501b543dbc2SStephan Aßmus 		TRACE("UpdateInputChannelDestinations: input channel %d, "
502b543dbc2SStephan Aßmus 			"destination_mask 0x%08lX, base %p, gain %.3f\n", i,
503b543dbc2SStephan Aßmus 			fInputChannelInfo[i].destination_mask,
504b543dbc2SStephan Aßmus 			fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
505b543dbc2SStephan Aßmus 	}
5062e9d6607Sbeveloper 
5072e9d6607Sbeveloper 	all_bits = 0;
5082e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
5099c3be6a5Sbeveloper 		all_bits |= fInputChannelInfo[i].destination_mask;
5102e9d6607Sbeveloper 
511d91580cdSbeveloper 	TRACE("UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits);
5122e9d6607Sbeveloper 
5132e9d6607Sbeveloper 	channel_count = count_nonzero_bits(all_bits);
514b543dbc2SStephan Aßmus 	TRACE("UpdateInputChannelDestinations: %d input channels, %d mixer "
515b543dbc2SStephan Aßmus 		"channels (%d old)\n", fInputChannelCount, channel_count,
516b543dbc2SStephan Aßmus 		fMixerChannelCount);
5172e9d6607Sbeveloper 	if (channel_count != fMixerChannelCount) {
5189c3be6a5Sbeveloper 		delete [] fMixerChannelInfo;
5192e9d6607Sbeveloper 		fMixerChannelInfo = new mixer_chan_info[channel_count];
5202e9d6607Sbeveloper 		fMixerChannelCount = channel_count;
5212e9d6607Sbeveloper 	}
5222e9d6607Sbeveloper 
5232e9d6607Sbeveloper 	// assign each mixer channel one type
5249c3be6a5Sbeveloper 	// and the gain from the fChannelTypeGain[]
525d91580cdSbeveloper 	mask = 1;
526d91580cdSbeveloper 	for (int i = 0; i < fMixerChannelCount; i++) {
5272e9d6607Sbeveloper 		while (mask != 0 && (all_bits & mask) == 0)
5282e9d6607Sbeveloper 			mask <<= 1;
5299c3be6a5Sbeveloper 		fMixerChannelInfo[i].destination_type = ChannelMaskToChannelType(mask);
530b543dbc2SStephan Aßmus 		fMixerChannelInfo[i].destination_gain
531b543dbc2SStephan Aßmus 			= fChannelTypeGain[fMixerChannelInfo[i].destination_type];
5322e9d6607Sbeveloper 		mask <<= 1;
5332e9d6607Sbeveloper 	}
5342e9d6607Sbeveloper 
5352e9d6607Sbeveloper 	// assign buffer_base pointer for each mixer channel
5362e9d6607Sbeveloper 	for (int i = 0; i < fMixerChannelCount; i++) {
5372e9d6607Sbeveloper 		int j;
5382e9d6607Sbeveloper 		for (j = 0; j < fInputChannelCount; j++) {
539b543dbc2SStephan Aßmus 			if (fInputChannelInfo[j].destination_mask
540b543dbc2SStephan Aßmus 					& ChannelTypeToChannelMask(
541b543dbc2SStephan Aßmus 						fMixerChannelInfo[i].destination_type)) {
542b543dbc2SStephan Aßmus 				fMixerChannelInfo[i].buffer_base = fMixBuffer ? &fMixBuffer[j]
543b543dbc2SStephan Aßmus 					: 0;
5442e9d6607Sbeveloper 				break;
5452e9d6607Sbeveloper 			}
5462e9d6607Sbeveloper 		}
5472e9d6607Sbeveloper 		if (j == fInputChannelCount) {
548a2ca4723Sbeveloper 			ERROR("buffer assignment failed for mixer chan %d\n", i);
5492e9d6607Sbeveloper 			fMixerChannelInfo[i].buffer_base = fMixBuffer;
5502e9d6607Sbeveloper 		}
5512e9d6607Sbeveloper 	}
5522e9d6607Sbeveloper 
553b543dbc2SStephan Aßmus 	for (int i = 0; i < fMixerChannelCount; i++) {
554b543dbc2SStephan Aßmus 		TRACE("UpdateInputChannelDestinations: mixer channel %d, type %2d, "
555b543dbc2SStephan Aßmus 			"base %p, gain %.3f\n", i, fMixerChannelInfo[i].destination_type,
556b543dbc2SStephan Aßmus 			fMixerChannelInfo[i].buffer_base,
557b543dbc2SStephan Aßmus 			fMixerChannelInfo[i].destination_gain);
558b543dbc2SStephan Aßmus 	}
5592e9d6607Sbeveloper 
5609c3be6a5Sbeveloper 	TRACE("UpdateInputChannelDestinations: leave\n");
5612e9d6607Sbeveloper }
562bf7ab50dSStephan Aßmus 
563a9cf57cfSAxel Dörfler 
564bf7ab50dSStephan Aßmus // Note: The following code is outcommented on purpose
565bf7ab50dSStephan Aßmus // and is about to be modified at a later point
56669517c15Sbeveloper /*
5672e9d6607Sbeveloper void
568b543dbc2SStephan Aßmus MixerInput::SetInputChannelDestinationGain(int channel, int destination_type,
569b543dbc2SStephan Aßmus 	float gain)
5702e9d6607Sbeveloper {
571b543dbc2SStephan Aßmus 	TRACE("SetInputChannelDestinationGain: channel %d, destination_type %d,
572b543dbc2SStephan Aßmus 		gain %.4f\n", channel, destination_type, gain);
5739c3be6a5Sbeveloper 	// we don't need the channel, as each destination_type can only exist
5749c3be6a5Sbeveloper 	// once for each MixerInput, but we use it for parameter validation
5759c3be6a5Sbeveloper 	// and to have a interface similar to MixerOutput
5762e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
5772e9d6607Sbeveloper 		return;
5789c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
5799c3be6a5Sbeveloper 		return;
5802e9d6607Sbeveloper 	if (gain < 0.0f)
5812e9d6607Sbeveloper 		gain = 0.0f;
5829c3be6a5Sbeveloper 	fChannelTypeGain[destination_type] = gain;
5839c3be6a5Sbeveloper 	for (int i = 0; i < fMixerChannelCount; i++) {
5849c3be6a5Sbeveloper 		if (fMixerChannelInfo[i].destination_type == destination_type) {
5859c3be6a5Sbeveloper 			fMixerChannelInfo[i].destination_gain = gain;
5869c3be6a5Sbeveloper 			return;
5879c3be6a5Sbeveloper 		}
5889c3be6a5Sbeveloper 	}
5892e9d6607Sbeveloper }
5902e9d6607Sbeveloper 
591a9cf57cfSAxel Dörfler 
5922e9d6607Sbeveloper float
5939c3be6a5Sbeveloper MixerInput::GetInputChannelDestinationGain(int channel, int destination_type)
5942e9d6607Sbeveloper {
5959c3be6a5Sbeveloper 	// we don't need the channel, as each destination_type can only exist
5969c3be6a5Sbeveloper 	// once for each MixerInput, but we use it for parameter validation
5979c3be6a5Sbeveloper 	// and to have a interface similar to MixerOutput
5982e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
5999c3be6a5Sbeveloper 		return 0.0f;
6009c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
6019c3be6a5Sbeveloper 		return 0.0f;
6029c3be6a5Sbeveloper 	return fChannelTypeGain[destination_type];
6032e9d6607Sbeveloper }
60469517c15Sbeveloper */
60569517c15Sbeveloper 
606a9cf57cfSAxel Dörfler 
60769517c15Sbeveloper void
60869517c15Sbeveloper MixerInput::SetMixerChannelGain(int mixer_channel, float gain)
60969517c15Sbeveloper {
61069517c15Sbeveloper 	if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
61169517c15Sbeveloper 		return;
61269517c15Sbeveloper 	if (gain < 0.0f)
61369517c15Sbeveloper 		gain = 0.0f;
61469517c15Sbeveloper 
61569517c15Sbeveloper 	fMixerChannelInfo[mixer_channel].destination_gain = gain;
61669517c15Sbeveloper 	fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain;
61769517c15Sbeveloper }
61869517c15Sbeveloper 
619a9cf57cfSAxel Dörfler 
62069517c15Sbeveloper float
62169517c15Sbeveloper MixerInput::GetMixerChannelGain(int mixer_channel)
62269517c15Sbeveloper {
62369517c15Sbeveloper 	if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
62469517c15Sbeveloper 		return 0.0;
62569517c15Sbeveloper 	return fMixerChannelInfo[mixer_channel].destination_gain;
62669517c15Sbeveloper }
62769517c15Sbeveloper 
628a9cf57cfSAxel Dörfler 
62969517c15Sbeveloper int
63069517c15Sbeveloper MixerInput::GetMixerChannelType(int mixer_channel)
63169517c15Sbeveloper {
63269517c15Sbeveloper 	if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
63369517c15Sbeveloper 		return -1;
63469517c15Sbeveloper 	return fMixerChannelInfo[mixer_channel].destination_type;
63569517c15Sbeveloper }
6362e9d6607Sbeveloper 
637a9cf57cfSAxel Dörfler 
6382e9d6607Sbeveloper void
6391c237c18Sbeveloper MixerInput::SetEnabled(bool yesno)
6401c237c18Sbeveloper {
6411c237c18Sbeveloper 	fEnabled = yesno;
6421c237c18Sbeveloper }
6431c237c18Sbeveloper 
644a9cf57cfSAxel Dörfler 
6451c237c18Sbeveloper bool
6461c237c18Sbeveloper MixerInput::IsEnabled()
6471c237c18Sbeveloper {
6481c237c18Sbeveloper 	return fEnabled;
6491c237c18Sbeveloper }
6501c237c18Sbeveloper 
651a9cf57cfSAxel Dörfler 
6521c237c18Sbeveloper void
6538d28117fSbeveloper MixerInput::SetMixBufferFormat(int32 framerate, int32 frames)
6542e9d6607Sbeveloper {
655a9cf57cfSAxel Dörfler 	TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n",
656a9cf57cfSAxel Dörfler 		framerate, frames);
657d5848e21Sbeveloper 
6587b0daf5cSbeveloper 	fMixBufferFrameRate = framerate;
659a9cf57cfSAxel Dörfler 	fDebugMixBufferFrames = frames;
6602e9d6607Sbeveloper 
661d5848e21Sbeveloper 	// frames and/or framerate can be 0 (if no output is connected)
662d5848e21Sbeveloper 	if (framerate == 0 || frames == 0) {
663a9cf57cfSAxel Dörfler 		if (fMixBuffer != NULL) {
664d5848e21Sbeveloper 			rtm_free(fMixBuffer);
665a9cf57cfSAxel Dörfler 			fMixBuffer = NULL;
666d5848e21Sbeveloper 		}
667d5848e21Sbeveloper 		for (int i = 0; i < fInputChannelCount; i++)
668d5848e21Sbeveloper 			fInputChannelInfo[i].buffer_base = 0;
669d5848e21Sbeveloper 		fMixBufferFrameCount = 0;
670d5848e21Sbeveloper 
6719c3be6a5Sbeveloper 		UpdateInputChannelDestinationMask();
6729c3be6a5Sbeveloper 		UpdateInputChannelDestinations();
673d5848e21Sbeveloper 		return;
674d5848e21Sbeveloper 	}
6757b0daf5cSbeveloper 
6767b0daf5cSbeveloper 	// make fMixBufferFrameCount an integral multiple of frames,
6777b0daf5cSbeveloper 	// but at least 3 times duration of our input buffer
6787b0daf5cSbeveloper 	// and at least 2 times duration of the output buffer
679b543dbc2SStephan Aßmus 	bigtime_t inputBufferLength  = duration_for_frames(
680b543dbc2SStephan Aßmus 		fInput.format.u.raw_audio.frame_rate,
681b543dbc2SStephan Aßmus 		frames_per_buffer(fInput.format.u.raw_audio));
6827b0daf5cSbeveloper 	bigtime_t outputBufferLength = duration_for_frames(framerate, frames);
683b543dbc2SStephan Aßmus 	bigtime_t mixerBufferLength
684b543dbc2SStephan Aßmus 		= max_c(3 * inputBufferLength, 2 * outputBufferLength);
6857b0daf5cSbeveloper 	int temp = frames_for_duration(framerate, mixerBufferLength);
6867b0daf5cSbeveloper 	fMixBufferFrameCount = ((temp / frames) + 1) * frames;
6877b0daf5cSbeveloper 
688a2ca4723Sbeveloper 	TRACE("  inputBufferLength    %10Ld\n", inputBufferLength);
689a2ca4723Sbeveloper 	TRACE("  outputBufferLength   %10Ld\n", outputBufferLength);
690a2ca4723Sbeveloper 	TRACE("  mixerBufferLength    %10Ld\n", mixerBufferLength);
691d91580cdSbeveloper 	TRACE("  fMixBufferFrameCount %10d\n", fMixBufferFrameCount);
6927b0daf5cSbeveloper 
6938d28117fSbeveloper 	ASSERT((fMixBufferFrameCount % frames) == 0);
6948d28117fSbeveloper 
695e92593f4Sbeveloper 	fLastDataFrameWritten = -1;
696e92593f4Sbeveloper 	fFractionalFrames = 0.0;
697e92593f4Sbeveloper 
6982e9d6607Sbeveloper 	rtm_free(fMixBuffer);
699356855c3Sbeveloper 	rtm_delete_pool(fRtmPool);
700a9cf57cfSAxel Dörfler 
7017b0daf5cSbeveloper 	int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount;
702a9cf57cfSAxel Dörfler 	if (rtm_create_pool(&fRtmPool, size) != B_OK)
703a9cf57cfSAxel Dörfler 		fRtmPool = NULL;
704a9cf57cfSAxel Dörfler 
705356855c3Sbeveloper 	fMixBuffer = (float*)rtm_alloc(fRtmPool, size);
706a9cf57cfSAxel Dörfler 	if (fMixBuffer == NULL)
707a9cf57cfSAxel Dörfler 		return;
7087b0daf5cSbeveloper 
7097b0daf5cSbeveloper 	memset(fMixBuffer, 0, size);
7102e9d6607Sbeveloper 
7112e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
7127b0daf5cSbeveloper 		fInputChannelInfo[i].buffer_base = &fMixBuffer[i];
713d5848e21Sbeveloper 
7149c3be6a5Sbeveloper 	UpdateInputChannelDestinationMask();
7159c3be6a5Sbeveloper 	UpdateInputChannelDestinations();
7162e9d6607Sbeveloper }
717