xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp (revision b543dbc293a9f03c29ed5c9b3d6a678fba44b769)
1bf7ab50dSStephan Aßmus /*
2*b543dbc2SStephan 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"
17bf7ab50dSStephan Aßmus #include "MixerInput.h"
18bf7ab50dSStephan Aßmus #include "MixerUtils.h"
19bf7ab50dSStephan Aßmus #include "Resampler.h"
20bf7ab50dSStephan Aßmus 
21678c2017Sbeveloper 
22a9cf57cfSAxel Dörfler MixerInput::MixerInput(MixerCore *core, const media_input &input,
23a9cf57cfSAxel Dörfler 	float mixFrameRate, int32 mixFrameCount)
24a9cf57cfSAxel Dörfler 	:
25a9cf57cfSAxel Dörfler 	fCore(core),
262e9d6607Sbeveloper  	fInput(input),
2788777023Sbeveloper 	fInputByteSwap(0),
281c237c18Sbeveloper 	fEnabled(true),
292e9d6607Sbeveloper 	fInputChannelInfo(0),
302e9d6607Sbeveloper 	fInputChannelCount(0),
312e9d6607Sbeveloper 	fInputChannelMask(0),
322e9d6607Sbeveloper 	fMixerChannelInfo(0),
332e9d6607Sbeveloper 	fMixerChannelCount(0),
342e9d6607Sbeveloper 	fMixBuffer(0),
357b0daf5cSbeveloper 	fMixBufferFrameRate(0),
367b0daf5cSbeveloper 	fMixBufferFrameCount(0),
37e92593f4Sbeveloper 	fLastDataFrameWritten(-1),
38af8d0a4dSbeveloper 	fLastDataAvailableTime(-1),
39e92593f4Sbeveloper 	fFractionalFrames(0.0),
407b0daf5cSbeveloper 	fResampler(0),
41356855c3Sbeveloper 	fRtmPool(0),
429c3be6a5Sbeveloper 	fUserOverridesChannelDestinations(false)
43678c2017Sbeveloper {
44e6c7c99fSbeveloper 	fix_multiaudio_format(&fInput.format.u.raw_audio);
45e6c7c99fSbeveloper 	PRINT_INPUT("MixerInput::MixerInput", fInput);
46e6c7c99fSbeveloper 	PRINT_CHANNEL_MASK(fInput.format);
472e9d6607Sbeveloper 
482e9d6607Sbeveloper 	ASSERT(fInput.format.u.raw_audio.channel_count > 0);
492e9d6607Sbeveloper 
509c3be6a5Sbeveloper 	for (int i = 0; i <	MAX_CHANNEL_TYPES; i++)
519c3be6a5Sbeveloper 		fChannelTypeGain[i] = 1.0f;
529c3be6a5Sbeveloper 
532e9d6607Sbeveloper 	fInputChannelCount = fInput.format.u.raw_audio.channel_count;
542e9d6607Sbeveloper 	fInputChannelMask = fInput.format.u.raw_audio.channel_mask;
552e9d6607Sbeveloper 	fInputChannelInfo = new input_chan_info[fInputChannelCount];
562e9d6607Sbeveloper 
5788777023Sbeveloper 	// perhaps we need byte swapping
5888777023Sbeveloper 	if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) {
59a9cf57cfSAxel Dörfler 		if (fInput.format.u.raw_audio.format
60a9cf57cfSAxel Dörfler 				== media_raw_audio_format::B_AUDIO_FLOAT
61a9cf57cfSAxel Dörfler 			|| fInput.format.u.raw_audio.format
62a9cf57cfSAxel Dörfler 				== media_raw_audio_format::B_AUDIO_INT
63a9cf57cfSAxel Dörfler 			|| fInput.format.u.raw_audio.format
64a9cf57cfSAxel Dörfler 				== media_raw_audio_format::B_AUDIO_SHORT) {
6588777023Sbeveloper 			fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format);
6688777023Sbeveloper 		}
6788777023Sbeveloper 	}
6888777023Sbeveloper 
692e9d6607Sbeveloper 	// initialize fInputChannelInfo
702e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++) {
71*b543dbc2SStephan Aßmus 		fInputChannelInfo[i].buffer_base = 0;
72*b543dbc2SStephan Aßmus 			// will be set by SetMixBufferFormat()
73*b543dbc2SStephan Aßmus 		fInputChannelInfo[i].destination_mask = 0;
74*b543dbc2SStephan Aßmus 			// will be set by UpdateInputChannelDestinationMask()
752e9d6607Sbeveloper 		fInputChannelInfo[i].gain = 1.0;
762e9d6607Sbeveloper 	}
772e9d6607Sbeveloper 
787b0daf5cSbeveloper 	// create resamplers
797b0daf5cSbeveloper 	fResampler = new Resampler * [fInputChannelCount];
804cc71346SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
81ff617a11SAdrien Destugues 		// TODO create Interpolate instead of Resampler if the settings says so
82*b543dbc2SStephan Aßmus 		fResampler[i] = new Resampler(fInput.format.u.raw_audio.format,
83*b543dbc2SStephan Aßmus 			media_raw_audio_format::B_AUDIO_FLOAT);
844cc71346SStephan Aßmus 	}
857b0daf5cSbeveloper 
86*b543dbc2SStephan Aßmus 	// fMixerChannelInfo and fMixerChannelCount will be initialized by
87*b543dbc2SStephan Aßmus 	// UpdateInputChannelDestinations()
88bf7ab50dSStephan Aßmus 	SetMixBufferFormat((int32)mixFrameRate, mixFrameCount);
89678c2017Sbeveloper }
90678c2017Sbeveloper 
91a9cf57cfSAxel Dörfler 
92678c2017Sbeveloper MixerInput::~MixerInput()
93678c2017Sbeveloper {
942e9d6607Sbeveloper 	if (fMixBuffer)
952e9d6607Sbeveloper 		rtm_free(fMixBuffer);
96356855c3Sbeveloper 	if (fRtmPool)
97356855c3Sbeveloper 		rtm_delete_pool(fRtmPool);
982e9d6607Sbeveloper 	delete [] fInputChannelInfo;
992e9d6607Sbeveloper 	delete [] fMixerChannelInfo;
1007b0daf5cSbeveloper 
1017b0daf5cSbeveloper 	// delete resamplers
1027b0daf5cSbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
1037b0daf5cSbeveloper 		delete fResampler[i];
1047b0daf5cSbeveloper 	delete [] fResampler;
105db6f1135SJérôme Duval 	delete fInputByteSwap;
106678c2017Sbeveloper }
107678c2017Sbeveloper 
108a9cf57cfSAxel Dörfler 
109678c2017Sbeveloper void
110678c2017Sbeveloper MixerInput::BufferReceived(BBuffer *buffer)
111678c2017Sbeveloper {
11288777023Sbeveloper 	void *data;
11388777023Sbeveloper 	size_t size;
11488777023Sbeveloper 	bigtime_t start;
115e92593f4Sbeveloper 	bigtime_t buffer_duration;
11688777023Sbeveloper 
117d5848e21Sbeveloper 	if (!fMixBuffer) {
118*b543dbc2SStephan Aßmus 		ERROR("MixerInput::BufferReceived: dropped incoming buffer as we "
119*b543dbc2SStephan Aßmus 			"don't have a mix buffer\n");
120d5848e21Sbeveloper 		return;
121d5848e21Sbeveloper 	}
1222e9d6607Sbeveloper 
12388777023Sbeveloper 	data = buffer->Data();
12488777023Sbeveloper 	size = buffer->SizeUsed();
12588777023Sbeveloper 	start = buffer->Header()->start_time;
126*b543dbc2SStephan Aßmus 	buffer_duration = duration_for_frames(fInput.format.u.raw_audio.frame_rate,
127*b543dbc2SStephan Aßmus 		size / bytes_per_frame(fInput.format.u.raw_audio));
1288d28117fSbeveloper 	if (start < 0) {
129*b543dbc2SStephan Aßmus 		ERROR("MixerInput::BufferReceived: buffer with negative start time of "
130*b543dbc2SStephan Aßmus 			"%Ld dropped\n", start);
1318d28117fSbeveloper 		return;
1328d28117fSbeveloper 	}
13388777023Sbeveloper 
13488777023Sbeveloper 	// swap the byte order of this buffer, if necessary
13588777023Sbeveloper 	if (fInputByteSwap)
13688777023Sbeveloper 		fInputByteSwap->Swap(data, size);
13788777023Sbeveloper 
138*b543dbc2SStephan Aßmus 	int offset = frames_for_duration(fMixBufferFrameRate, start)
139*b543dbc2SStephan Aßmus 		% fMixBufferFrameCount;
1408d28117fSbeveloper 
141*b543dbc2SStephan Aßmus 	PRINT(4, "MixerInput::BufferReceived: buffer start %10Ld, offset %6d\n",
142*b543dbc2SStephan Aßmus 		start, offset);
1437b0daf5cSbeveloper 
144191033efSbeveloper 	int in_frames = size / bytes_per_frame(fInput.format.u.raw_audio);
145*b543dbc2SStephan Aßmus 	double frames = double(in_frames * fMixBufferFrameRate)
146*b543dbc2SStephan Aßmus 		/ fInput.format.u.raw_audio.frame_rate;
147e92593f4Sbeveloper 	int out_frames = int(frames);
148e92593f4Sbeveloper 	fFractionalFrames += frames - double(out_frames);
149e92593f4Sbeveloper 	if (fFractionalFrames >= 1.0) {
150e92593f4Sbeveloper 		fFractionalFrames -= 1.0;
1517619f562Sbeveloper 		out_frames++;
152e92593f4Sbeveloper 	}
153e92593f4Sbeveloper 
154e92593f4Sbeveloper 	// if fLastDataFrameWritten != -1, then we have a valid last position
155e92593f4Sbeveloper 	// and can do glitch compensation
156e92593f4Sbeveloper 	if (fLastDataFrameWritten >= 0) {
157*b543dbc2SStephan Aßmus 		int expected_frame = (fLastDataFrameWritten + 1)
158*b543dbc2SStephan Aßmus 			% fMixBufferFrameCount;
159e92593f4Sbeveloper 		if (offset != expected_frame) {
160e92593f4Sbeveloper 			// due to rounding and other errors, offset might be off by +/- 1
161e92593f4Sbeveloper 			// this is not really a bad glitch, we just adjust the position
162e92593f4Sbeveloper 			if (offset == fLastDataFrameWritten) {
163*b543dbc2SStephan Aßmus //				printf("MixerInput::BufferReceived: -1 frame GLITCH! last "
164*b543dbc2SStephan Aßmus //					"frame was %ld, expected frame was %d, new frame is %d\n",
165*b543dbc2SStephan Aßmus //					fLastDataFrameWritten, expected_frame, offset);
166e92593f4Sbeveloper 				offset = expected_frame;
167*b543dbc2SStephan Aßmus 			} else if (offset == ((fLastDataFrameWritten + 2)
168*b543dbc2SStephan Aßmus 				% fMixBufferFrameCount)) {
169*b543dbc2SStephan Aßmus //				printf("MixerInput::BufferReceived: +1 frame GLITCH! last "
170*b543dbc2SStephan Aßmus //					"frame was %ld, expected frame was %d, new frame is %d\n",
171*b543dbc2SStephan Aßmus //					fLastDataFrameWritten, expected_frame, offset);
172e92593f4Sbeveloper 				offset = expected_frame;
173e92593f4Sbeveloper 			} else {
174*b543dbc2SStephan Aßmus 				printf("MixerInput::BufferReceived: GLITCH! last frame was "
175*b543dbc2SStephan Aßmus 					"%4ld, expected frame was %4d, new frame is %4d\n",
176*b543dbc2SStephan Aßmus 					fLastDataFrameWritten, expected_frame, offset);
177e92593f4Sbeveloper 
178e92593f4Sbeveloper 				if (start > fLastDataAvailableTime) {
179*b543dbc2SStephan Aßmus 					if ((start - fLastDataAvailableTime)
180*b543dbc2SStephan Aßmus 						< (buffer_duration / 10)) {
181e92593f4Sbeveloper 						// buffer is less than 10% of buffer duration too late
182*b543dbc2SStephan Aßmus 						printf("short glitch, buffer too late, time delta "
183*b543dbc2SStephan Aßmus 							"%Ld\n", start - fLastDataAvailableTime);
184e92593f4Sbeveloper 						offset = expected_frame;
185e92593f4Sbeveloper 						out_frames++;
186e92593f4Sbeveloper 					} else {
187e92593f4Sbeveloper 						// buffer more than 10% of buffer duration too late
188*b543dbc2SStephan Aßmus 						// TODO: zerofill buffer
189*b543dbc2SStephan Aßmus 						printf("MAJOR glitch, buffer too late, time delta "
190*b543dbc2SStephan Aßmus 							"%Ld\n", start - fLastDataAvailableTime);
191e92593f4Sbeveloper 					}
192e92593f4Sbeveloper 				} else { // start <= fLastDataAvailableTime
193e92593f4Sbeveloper 					// the new buffer is too early
194*b543dbc2SStephan Aßmus 					if ((fLastDataAvailableTime - start)
195*b543dbc2SStephan Aßmus 						< (buffer_duration / 10)) {
196e92593f4Sbeveloper 						// buffer is less than 10% of buffer duration too early
197*b543dbc2SStephan Aßmus 						printf("short glitch, buffer too early, time delta "
198*b543dbc2SStephan Aßmus 							"%Ld\n", fLastDataAvailableTime - start);
199e92593f4Sbeveloper 						offset = expected_frame;
200e92593f4Sbeveloper 						out_frames--;
201e92593f4Sbeveloper 						if (out_frames < 1)
202e92593f4Sbeveloper 							out_frames = 1;
203e92593f4Sbeveloper 					} else {
204e92593f4Sbeveloper 						// buffer more than 10% of buffer duration too early
205*b543dbc2SStephan Aßmus 						// TODO: zerofill buffer
206*b543dbc2SStephan Aßmus 						printf("MAJOR glitch, buffer too early, time delta "
207*b543dbc2SStephan Aßmus 							"%Ld\n", fLastDataAvailableTime - start);
208e92593f4Sbeveloper 					}
209e92593f4Sbeveloper 				}
210e92593f4Sbeveloper 			}
211e92593f4Sbeveloper 		}
212e92593f4Sbeveloper 	}
2137b0daf5cSbeveloper 
214*b543dbc2SStephan Aßmus //	printf("data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n",
215*b543dbc2SStephan Aßmus //		start,
216*b543dbc2SStephan Aßmus //		start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
217*b543dbc2SStephan Aßmus //		frames_per_buffer(fInput.format.u.raw_audio)), offset,
218*b543dbc2SStephan Aßmus //		offset + out_frames);
2197b0daf5cSbeveloper 	if (offset + out_frames > fMixBufferFrameCount) {
2207b0daf5cSbeveloper 		int out_frames1 = fMixBufferFrameCount - offset;
2217b0daf5cSbeveloper 		int out_frames2 = out_frames - out_frames1;
2227b0daf5cSbeveloper 		int in_frames1 = (out_frames1 * in_frames) / out_frames;
2237b0daf5cSbeveloper 		int in_frames2 = in_frames - in_frames1;
2247b0daf5cSbeveloper 
225*b543dbc2SStephan Aßmus //		printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at "
226*b543dbc2SStephan Aßmus //			"frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(),
227*b543dbc2SStephan Aßmus //			start,
228*b543dbc2SStephan Aßmus //			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
229*b543dbc2SStephan Aßmus //			frames_per_buffer(fInput.format.u.raw_audio)), offset,
230*b543dbc2SStephan Aßmus //			offset + out_frames1 - 1, 0, out_frames2 - 1);
231*b543dbc2SStephan Aßmus 		PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at "
232*b543dbc2SStephan Aßmus 			"frames %ld to %ld and %ld to %ld\n", fCore->fTimeSource->Now(),
233*b543dbc2SStephan Aßmus 			start,
234*b543dbc2SStephan Aßmus 			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
235*b543dbc2SStephan Aßmus 			frames_per_buffer(fInput.format.u.raw_audio)), offset,
236*b543dbc2SStephan Aßmus 			offset + out_frames1 - 1, 0, out_frames2 - 1);
237*b543dbc2SStephan Aßmus 		PRINT(5, "  in_frames %5d, out_frames %5d, in_frames1 %5d, "
238*b543dbc2SStephan Aßmus 			"out_frames1 %5d, in_frames2 %5d, out_frames2 %5d\n",
239*b543dbc2SStephan Aßmus 			in_frames, out_frames, in_frames1, out_frames1, in_frames2,
240*b543dbc2SStephan Aßmus 			out_frames2);
2417b0daf5cSbeveloper 
242e92593f4Sbeveloper 		fLastDataFrameWritten = out_frames2 - 1;
243e92593f4Sbeveloper 
244*b543dbc2SStephan Aßmus 		// convert offset from frames into bytes
245*b543dbc2SStephan Aßmus 		offset *= sizeof(float) * fInputChannelCount;
2468d28117fSbeveloper 
2477b0daf5cSbeveloper 		for (int i = 0; i < fInputChannelCount; i++) {
248*b543dbc2SStephan Aßmus 			fResampler[i]->Resample(
249*b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(data)
250*b543dbc2SStephan Aßmus 					+ i * bytes_per_sample(fInput.format.u.raw_audio),
251*b543dbc2SStephan Aßmus 				bytes_per_frame(fInput.format.u.raw_audio), in_frames1,
252*b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base)
253*b543dbc2SStephan Aßmus 					+ offset, fInputChannelCount * sizeof(float), out_frames1,
2547b0daf5cSbeveloper 				fInputChannelInfo[i].gain);
2557b0daf5cSbeveloper 
256*b543dbc2SStephan Aßmus 			fResampler[i]->Resample(
257*b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(data)
258*b543dbc2SStephan Aßmus 					+ i * bytes_per_sample(fInput.format.u.raw_audio)
259*b543dbc2SStephan Aßmus 					+ in_frames1 * bytes_per_frame(fInput.format.u.raw_audio),
260*b543dbc2SStephan Aßmus 				bytes_per_frame(fInput.format.u.raw_audio), in_frames2,
2617b0daf5cSbeveloper 				reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base),
262*b543dbc2SStephan Aßmus 				fInputChannelCount * sizeof(float), out_frames2,
2637b0daf5cSbeveloper 				fInputChannelInfo[i].gain);
264e92593f4Sbeveloper 
2657b0daf5cSbeveloper 		}
2667b0daf5cSbeveloper 	} else {
267*b543dbc2SStephan Aßmus //		printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at "
268*b543dbc2SStephan Aßmus //			"frames %ld to %ld\n", fCore->fTimeSource->Now(), start,
269*b543dbc2SStephan Aßmus //			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
270*b543dbc2SStephan Aßmus //			frames_per_buffer(fInput.format.u.raw_audio)), offset,
271*b543dbc2SStephan Aßmus //			offset + out_frames - 1);
272*b543dbc2SStephan Aßmus 		PRINT(3, "at %10Ld, data arrived for %10Ld to %10Ld, storing at "
273*b543dbc2SStephan Aßmus 			"frames %ld to %ld\n", fCore->fTimeSource->Now(), start,
274*b543dbc2SStephan Aßmus 			start + duration_for_frames(fInput.format.u.raw_audio.frame_rate,
275*b543dbc2SStephan Aßmus 			frames_per_buffer(fInput.format.u.raw_audio)), offset,
276*b543dbc2SStephan Aßmus 			offset + out_frames - 1);
277191033efSbeveloper 		PRINT(5, "  in_frames %5d, out_frames %5d\n", in_frames, out_frames);
2788d28117fSbeveloper 
279e92593f4Sbeveloper 		fLastDataFrameWritten = offset + out_frames - 1;
280*b543dbc2SStephan Aßmus 		// convert offset from frames into bytes
281*b543dbc2SStephan Aßmus 		offset *= sizeof(float) * fInputChannelCount;
2827b0daf5cSbeveloper 		for (int i = 0; i < fInputChannelCount; i++) {
283*b543dbc2SStephan Aßmus 			fResampler[i]->Resample(
284*b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(data)
285*b543dbc2SStephan Aßmus 					+ i * bytes_per_sample(fInput.format.u.raw_audio),
286*b543dbc2SStephan Aßmus 				bytes_per_frame(fInput.format.u.raw_audio), in_frames,
287*b543dbc2SStephan Aßmus 				reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base)
288*b543dbc2SStephan Aßmus 					+ offset, fInputChannelCount * sizeof(float),
289*b543dbc2SStephan Aßmus 				out_frames, fInputChannelInfo[i].gain);
2907b0daf5cSbeveloper 		}
2917b0daf5cSbeveloper 	}
292e92593f4Sbeveloper 	fLastDataAvailableTime = start + buffer_duration;
293678c2017Sbeveloper }
2947ee2c804Sbeveloper 
295bf7ab50dSStephan Aßmus 
2967ee2c804Sbeveloper media_input &
2977ee2c804Sbeveloper MixerInput::MediaInput()
2987ee2c804Sbeveloper {
2997ee2c804Sbeveloper 	return fInput;
3007ee2c804Sbeveloper }
301e6c7c99fSbeveloper 
302bf7ab50dSStephan Aßmus 
303e6c7c99fSbeveloper int32
304e6c7c99fSbeveloper MixerInput::ID()
305e6c7c99fSbeveloper {
306e6c7c99fSbeveloper 	return fInput.destination.id;
307e6c7c99fSbeveloper }
308e6c7c99fSbeveloper 
309bf7ab50dSStephan Aßmus 
310d91580cdSbeveloper int
311fae6ce82Sbeveloper MixerInput::GetInputChannelCount()
312fae6ce82Sbeveloper {
313fae6ce82Sbeveloper 	return fInputChannelCount;
314fae6ce82Sbeveloper }
315fae6ce82Sbeveloper 
316bf7ab50dSStephan Aßmus 
3172e9d6607Sbeveloper void
3189c3be6a5Sbeveloper MixerInput::AddInputChannelDestination(int channel, int destination_type)
3192e9d6607Sbeveloper {
3209c3be6a5Sbeveloper 	uint32 mask = ChannelTypeToChannelMask(destination_type);
321e6c7c99fSbeveloper 
3222e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3232e9d6607Sbeveloper 		return;
3242e9d6607Sbeveloper 
3252e9d6607Sbeveloper 	// test if it is already set
3269c3be6a5Sbeveloper 	if (fInputChannelInfo[channel].destination_mask & mask)
3272e9d6607Sbeveloper 		return;
3282e9d6607Sbeveloper 
3299c3be6a5Sbeveloper 	// verify that no other channel has id
3309c3be6a5Sbeveloper 	if (-1 != GetInputChannelForDestination(destination_type)) {
331*b543dbc2SStephan Aßmus 		ERROR("MixerInput::AddInputChannelDestination: destination_type %d "
332*b543dbc2SStephan Aßmus 			"already assigned to channel %d\n", destination_type,
333*b543dbc2SStephan Aßmus 			GetInputChannelForDestination(destination_type));
3349c3be6a5Sbeveloper 		return;
3359c3be6a5Sbeveloper 	}
3362e9d6607Sbeveloper 
3372e9d6607Sbeveloper 	// add it to specified channel
3389c3be6a5Sbeveloper 	fInputChannelInfo[channel].destination_mask |= mask;
3392e9d6607Sbeveloper 
3409c3be6a5Sbeveloper 	fUserOverridesChannelDestinations = true;
3419c3be6a5Sbeveloper 	UpdateInputChannelDestinations();
3422e9d6607Sbeveloper }
3432e9d6607Sbeveloper 
344a9cf57cfSAxel Dörfler 
3452e9d6607Sbeveloper void
3469c3be6a5Sbeveloper MixerInput::RemoveInputChannelDestination(int channel, int destination_type)
3472e9d6607Sbeveloper {
3489c3be6a5Sbeveloper 	uint32 mask = ChannelTypeToChannelMask(destination_type);
3492e9d6607Sbeveloper 
3502e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3512e9d6607Sbeveloper 		return;
3522e9d6607Sbeveloper 
3532e9d6607Sbeveloper 	// test if it is really set
3549c3be6a5Sbeveloper 	if ((fInputChannelInfo[channel].destination_mask & mask) == 0)
3552e9d6607Sbeveloper 		return;
3562e9d6607Sbeveloper 
3572e9d6607Sbeveloper 	// remove it from specified channel
3589c3be6a5Sbeveloper 	fInputChannelInfo[channel].destination_mask &= ~mask;
3592e9d6607Sbeveloper 
3609c3be6a5Sbeveloper 	fUserOverridesChannelDestinations = true;
3619c3be6a5Sbeveloper 	UpdateInputChannelDestinations();
3622e9d6607Sbeveloper }
3632e9d6607Sbeveloper 
364a9cf57cfSAxel Dörfler 
3659c3be6a5Sbeveloper bool
3669c3be6a5Sbeveloper MixerInput::HasInputChannelDestination(int channel, int destination_type)
3672e9d6607Sbeveloper {
3682e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3699c3be6a5Sbeveloper 		return false;
3709c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
3719c3be6a5Sbeveloper 		return false;
372*b543dbc2SStephan Aßmus 	return fInputChannelInfo[channel].destination_mask
373*b543dbc2SStephan Aßmus 		& ChannelTypeToChannelMask(destination_type);
3742e9d6607Sbeveloper }
3752e9d6607Sbeveloper 
376a9cf57cfSAxel Dörfler 
3779c3be6a5Sbeveloper int
3789c3be6a5Sbeveloper MixerInput::GetInputChannelForDestination(int destination_type)
3799c3be6a5Sbeveloper {
3809c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
3819c3be6a5Sbeveloper 		return -1;
3829c3be6a5Sbeveloper 	uint32 mask = ChannelTypeToChannelMask(destination_type);
3839c3be6a5Sbeveloper 	for (int chan = 0; chan < fInputChannelCount; chan++) {
3849c3be6a5Sbeveloper 		if (fInputChannelInfo[chan].destination_mask & mask)
3859c3be6a5Sbeveloper 			return chan;
3869c3be6a5Sbeveloper 	}
3879c3be6a5Sbeveloper 	return -1;
3889c3be6a5Sbeveloper }
3899c3be6a5Sbeveloper 
390a9cf57cfSAxel Dörfler 
3919c3be6a5Sbeveloper int
3922e9d6607Sbeveloper MixerInput::GetInputChannelType(int channel)
3932e9d6607Sbeveloper {
3942e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
3952e9d6607Sbeveloper 		return 0;
3969c3be6a5Sbeveloper 	return GetChannelType(channel, fInputChannelMask);
3972e9d6607Sbeveloper }
3982e9d6607Sbeveloper 
399a9cf57cfSAxel Dörfler 
4002e9d6607Sbeveloper void
4012e9d6607Sbeveloper MixerInput::SetInputChannelGain(int channel, float gain)
4022e9d6607Sbeveloper {
4032e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
4042e9d6607Sbeveloper 		return;
4052e9d6607Sbeveloper 	if (gain < 0.0f)
4062e9d6607Sbeveloper 		gain = 0.0f;
4072e9d6607Sbeveloper 
4082e9d6607Sbeveloper 	fInputChannelInfo[channel].gain = gain;
4092e9d6607Sbeveloper }
4102e9d6607Sbeveloper 
411a9cf57cfSAxel Dörfler 
4122e9d6607Sbeveloper float
4132e9d6607Sbeveloper MixerInput::GetInputChannelGain(int channel)
4142e9d6607Sbeveloper {
4152e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
4162e9d6607Sbeveloper 		return 0.0f;
4172e9d6607Sbeveloper 	return fInputChannelInfo[channel].gain;
4182e9d6607Sbeveloper }
4192e9d6607Sbeveloper 
420a9cf57cfSAxel Dörfler 
4212e9d6607Sbeveloper void
4229c3be6a5Sbeveloper MixerInput::UpdateInputChannelDestinationMask()
4232e9d6607Sbeveloper {
4242e9d6607Sbeveloper 	// is the user already messed with the assignmens, don't do anything.
4259c3be6a5Sbeveloper 	if (fUserOverridesChannelDestinations)
4262e9d6607Sbeveloper 		return;
4272e9d6607Sbeveloper 
4289c3be6a5Sbeveloper 	TRACE("UpdateInputChannelDestinationMask: enter\n");
4292e9d6607Sbeveloper 
430806cf560Sbeveloper 	// first apply a 1:1 mapping
431*b543dbc2SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
432*b543dbc2SStephan Aßmus 		fInputChannelInfo[i].destination_mask = GetChannelMask(i,
433*b543dbc2SStephan Aßmus 			fInputChannelMask);
434*b543dbc2SStephan Aßmus 	}
435806cf560Sbeveloper 
436806cf560Sbeveloper 	// specialize this, depending on the available physical output channels
437643e1b2eSbeveloper 	if (fCore->OutputChannelCount() <= 2) {
438643e1b2eSbeveloper 		// less or equal two channels
439*b543dbc2SStephan Aßmus 		if (fInputChannelCount == 1
440*b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask)
441*b543dbc2SStephan Aßmus 				& (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
442ab276ac8Sbeveloper 			fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO;
443806cf560Sbeveloper 		}
444643e1b2eSbeveloper 	} else {
445643e1b2eSbeveloper 		// more than two channel output card
446*b543dbc2SStephan Aßmus 		if (fInputChannelCount == 1
447*b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask)
448*b543dbc2SStephan Aßmus 				& (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
449ab276ac8Sbeveloper 			fInputChannelInfo[0].destination_mask = B_CHANNEL_MONO;
450806cf560Sbeveloper 		}
451*b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
452*b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) {
453*b543dbc2SStephan Aßmus 			fInputChannelInfo[0].destination_mask
454*b543dbc2SStephan Aßmus 				= B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
455806cf560Sbeveloper 		}
456*b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
457*b543dbc2SStephan Aßmus 			&& (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) {
458*b543dbc2SStephan Aßmus 			fInputChannelInfo[0].destination_mask
459*b543dbc2SStephan Aßmus 				= B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
460806cf560Sbeveloper 		}
461*b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
462*b543dbc2SStephan Aßmus 			&& (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) {
463*b543dbc2SStephan Aßmus 			fInputChannelInfo[1].destination_mask
464*b543dbc2SStephan Aßmus 				= B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
465806cf560Sbeveloper 		}
466*b543dbc2SStephan Aßmus 		if (fInputChannelCount == 2
467*b543dbc2SStephan Aßmus 			&& (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) {
468*b543dbc2SStephan Aßmus 			fInputChannelInfo[1].destination_mask
469*b543dbc2SStephan Aßmus 				= B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
470806cf560Sbeveloper 		}
4712e9d6607Sbeveloper 	}
4722e9d6607Sbeveloper 
473*b543dbc2SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
474*b543dbc2SStephan Aßmus 		TRACE("UpdateInputChannelDestinationMask: input channel %d, "
475*b543dbc2SStephan Aßmus 			"destination_mask 0x%08lX, base %p, gain %.3f\n", i,
476*b543dbc2SStephan Aßmus 			fInputChannelInfo[i].destination_mask,
477*b543dbc2SStephan Aßmus 			fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
478*b543dbc2SStephan Aßmus 	}
4799c3be6a5Sbeveloper 	TRACE("UpdateInputChannelDestinationMask: leave\n");
4802e9d6607Sbeveloper }
4812e9d6607Sbeveloper 
482a9cf57cfSAxel Dörfler 
4832e9d6607Sbeveloper void
4849c3be6a5Sbeveloper MixerInput::UpdateInputChannelDestinations()
4852e9d6607Sbeveloper {
486d91580cdSbeveloper 	int channel_count;
4872e9d6607Sbeveloper 	uint32 all_bits;
4882e9d6607Sbeveloper 	uint32 mask;
4892e9d6607Sbeveloper 
4909c3be6a5Sbeveloper 	TRACE("UpdateInputChannelDestinations: enter\n");
491*b543dbc2SStephan Aßmus 	for (int i = 0; i < fInputChannelCount; i++) {
492*b543dbc2SStephan Aßmus 		TRACE("UpdateInputChannelDestinations: input channel %d, "
493*b543dbc2SStephan Aßmus 			"destination_mask 0x%08lX, base %p, gain %.3f\n", i,
494*b543dbc2SStephan Aßmus 			fInputChannelInfo[i].destination_mask,
495*b543dbc2SStephan Aßmus 			fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
496*b543dbc2SStephan Aßmus 	}
4972e9d6607Sbeveloper 
4982e9d6607Sbeveloper 	all_bits = 0;
4992e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
5009c3be6a5Sbeveloper 		all_bits |= fInputChannelInfo[i].destination_mask;
5012e9d6607Sbeveloper 
502d91580cdSbeveloper 	TRACE("UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits);
5032e9d6607Sbeveloper 
5042e9d6607Sbeveloper 	channel_count = count_nonzero_bits(all_bits);
505*b543dbc2SStephan Aßmus 	TRACE("UpdateInputChannelDestinations: %d input channels, %d mixer "
506*b543dbc2SStephan Aßmus 		"channels (%d old)\n", fInputChannelCount, channel_count,
507*b543dbc2SStephan Aßmus 		fMixerChannelCount);
5082e9d6607Sbeveloper 	if (channel_count != fMixerChannelCount) {
5099c3be6a5Sbeveloper 		delete [] fMixerChannelInfo;
5102e9d6607Sbeveloper 		fMixerChannelInfo = new mixer_chan_info[channel_count];
5112e9d6607Sbeveloper 		fMixerChannelCount = channel_count;
5122e9d6607Sbeveloper 	}
5132e9d6607Sbeveloper 
5142e9d6607Sbeveloper 	// assign each mixer channel one type
5159c3be6a5Sbeveloper 	// and the gain from the fChannelTypeGain[]
516d91580cdSbeveloper 	mask = 1;
517d91580cdSbeveloper 	for (int i = 0; i < fMixerChannelCount; i++) {
5182e9d6607Sbeveloper 		while (mask != 0 && (all_bits & mask) == 0)
5192e9d6607Sbeveloper 			mask <<= 1;
5209c3be6a5Sbeveloper 		fMixerChannelInfo[i].destination_type = ChannelMaskToChannelType(mask);
521*b543dbc2SStephan Aßmus 		fMixerChannelInfo[i].destination_gain
522*b543dbc2SStephan Aßmus 			= fChannelTypeGain[fMixerChannelInfo[i].destination_type];
5232e9d6607Sbeveloper 		mask <<= 1;
5242e9d6607Sbeveloper 	}
5252e9d6607Sbeveloper 
5262e9d6607Sbeveloper 	// assign buffer_base pointer for each mixer channel
5272e9d6607Sbeveloper 	for (int i = 0; i < fMixerChannelCount; i++) {
5282e9d6607Sbeveloper 		int j;
5292e9d6607Sbeveloper 		for (j = 0; j < fInputChannelCount; j++) {
530*b543dbc2SStephan Aßmus 			if (fInputChannelInfo[j].destination_mask
531*b543dbc2SStephan Aßmus 					& ChannelTypeToChannelMask(
532*b543dbc2SStephan Aßmus 						fMixerChannelInfo[i].destination_type)) {
533*b543dbc2SStephan Aßmus 				fMixerChannelInfo[i].buffer_base = fMixBuffer ? &fMixBuffer[j]
534*b543dbc2SStephan Aßmus 					: 0;
5352e9d6607Sbeveloper 				break;
5362e9d6607Sbeveloper 			}
5372e9d6607Sbeveloper 		}
5382e9d6607Sbeveloper 		if (j == fInputChannelCount) {
539a2ca4723Sbeveloper 			ERROR("buffer assignment failed for mixer chan %d\n", i);
5402e9d6607Sbeveloper 			fMixerChannelInfo[i].buffer_base = fMixBuffer;
5412e9d6607Sbeveloper 		}
5422e9d6607Sbeveloper 	}
5432e9d6607Sbeveloper 
544*b543dbc2SStephan Aßmus 	for (int i = 0; i < fMixerChannelCount; i++) {
545*b543dbc2SStephan Aßmus 		TRACE("UpdateInputChannelDestinations: mixer channel %d, type %2d, "
546*b543dbc2SStephan Aßmus 			"base %p, gain %.3f\n", i, fMixerChannelInfo[i].destination_type,
547*b543dbc2SStephan Aßmus 			fMixerChannelInfo[i].buffer_base,
548*b543dbc2SStephan Aßmus 			fMixerChannelInfo[i].destination_gain);
549*b543dbc2SStephan Aßmus 	}
5502e9d6607Sbeveloper 
5519c3be6a5Sbeveloper 	TRACE("UpdateInputChannelDestinations: leave\n");
5522e9d6607Sbeveloper }
553bf7ab50dSStephan Aßmus 
554a9cf57cfSAxel Dörfler 
555bf7ab50dSStephan Aßmus // Note: The following code is outcommented on purpose
556bf7ab50dSStephan Aßmus // and is about to be modified at a later point
55769517c15Sbeveloper /*
5582e9d6607Sbeveloper void
559*b543dbc2SStephan Aßmus MixerInput::SetInputChannelDestinationGain(int channel, int destination_type,
560*b543dbc2SStephan Aßmus 	float gain)
5612e9d6607Sbeveloper {
562*b543dbc2SStephan Aßmus 	TRACE("SetInputChannelDestinationGain: channel %d, destination_type %d,
563*b543dbc2SStephan Aßmus 		gain %.4f\n", channel, destination_type, gain);
5649c3be6a5Sbeveloper 	// we don't need the channel, as each destination_type can only exist
5659c3be6a5Sbeveloper 	// once for each MixerInput, but we use it for parameter validation
5669c3be6a5Sbeveloper 	// and to have a interface similar to MixerOutput
5672e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
5682e9d6607Sbeveloper 		return;
5699c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
5709c3be6a5Sbeveloper 		return;
5712e9d6607Sbeveloper 	if (gain < 0.0f)
5722e9d6607Sbeveloper 		gain = 0.0f;
5739c3be6a5Sbeveloper 	fChannelTypeGain[destination_type] = gain;
5749c3be6a5Sbeveloper 	for (int i = 0; i < fMixerChannelCount; i++) {
5759c3be6a5Sbeveloper 		if (fMixerChannelInfo[i].destination_type == destination_type) {
5769c3be6a5Sbeveloper 			fMixerChannelInfo[i].destination_gain = gain;
5779c3be6a5Sbeveloper 			return;
5789c3be6a5Sbeveloper 		}
5799c3be6a5Sbeveloper 	}
5802e9d6607Sbeveloper }
5812e9d6607Sbeveloper 
582a9cf57cfSAxel Dörfler 
5832e9d6607Sbeveloper float
5849c3be6a5Sbeveloper MixerInput::GetInputChannelDestinationGain(int channel, int destination_type)
5852e9d6607Sbeveloper {
5869c3be6a5Sbeveloper 	// we don't need the channel, as each destination_type can only exist
5879c3be6a5Sbeveloper 	// once for each MixerInput, but we use it for parameter validation
5889c3be6a5Sbeveloper 	// and to have a interface similar to MixerOutput
5892e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
5909c3be6a5Sbeveloper 		return 0.0f;
5919c3be6a5Sbeveloper 	if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
5929c3be6a5Sbeveloper 		return 0.0f;
5939c3be6a5Sbeveloper 	return fChannelTypeGain[destination_type];
5942e9d6607Sbeveloper }
59569517c15Sbeveloper */
59669517c15Sbeveloper 
597a9cf57cfSAxel Dörfler 
59869517c15Sbeveloper void
59969517c15Sbeveloper MixerInput::SetMixerChannelGain(int mixer_channel, float gain)
60069517c15Sbeveloper {
60169517c15Sbeveloper 	if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
60269517c15Sbeveloper 		return;
60369517c15Sbeveloper 	if (gain < 0.0f)
60469517c15Sbeveloper 		gain = 0.0f;
60569517c15Sbeveloper 
60669517c15Sbeveloper 	fMixerChannelInfo[mixer_channel].destination_gain = gain;
60769517c15Sbeveloper 	fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain;
60869517c15Sbeveloper }
60969517c15Sbeveloper 
610a9cf57cfSAxel Dörfler 
61169517c15Sbeveloper float
61269517c15Sbeveloper MixerInput::GetMixerChannelGain(int mixer_channel)
61369517c15Sbeveloper {
61469517c15Sbeveloper 	if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
61569517c15Sbeveloper 		return 0.0;
61669517c15Sbeveloper 	return fMixerChannelInfo[mixer_channel].destination_gain;
61769517c15Sbeveloper }
61869517c15Sbeveloper 
619a9cf57cfSAxel Dörfler 
62069517c15Sbeveloper int
62169517c15Sbeveloper MixerInput::GetMixerChannelType(int mixer_channel)
62269517c15Sbeveloper {
62369517c15Sbeveloper 	if (mixer_channel < 0 || mixer_channel >= fMixerChannelCount)
62469517c15Sbeveloper 		return -1;
62569517c15Sbeveloper 	return fMixerChannelInfo[mixer_channel].destination_type;
62669517c15Sbeveloper }
6272e9d6607Sbeveloper 
628a9cf57cfSAxel Dörfler 
6292e9d6607Sbeveloper void
6301c237c18Sbeveloper MixerInput::SetEnabled(bool yesno)
6311c237c18Sbeveloper {
6321c237c18Sbeveloper 	fEnabled = yesno;
6331c237c18Sbeveloper }
6341c237c18Sbeveloper 
635a9cf57cfSAxel Dörfler 
6361c237c18Sbeveloper bool
6371c237c18Sbeveloper MixerInput::IsEnabled()
6381c237c18Sbeveloper {
6391c237c18Sbeveloper 	return fEnabled;
6401c237c18Sbeveloper }
6411c237c18Sbeveloper 
642a9cf57cfSAxel Dörfler 
6431c237c18Sbeveloper void
6448d28117fSbeveloper MixerInput::SetMixBufferFormat(int32 framerate, int32 frames)
6452e9d6607Sbeveloper {
646a9cf57cfSAxel Dörfler 	TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n",
647a9cf57cfSAxel Dörfler 		framerate, frames);
648d5848e21Sbeveloper 
6497b0daf5cSbeveloper 	fMixBufferFrameRate = framerate;
650a9cf57cfSAxel Dörfler 	fDebugMixBufferFrames = frames;
6512e9d6607Sbeveloper 
652d5848e21Sbeveloper 	// frames and/or framerate can be 0 (if no output is connected)
653d5848e21Sbeveloper 	if (framerate == 0 || frames == 0) {
654a9cf57cfSAxel Dörfler 		if (fMixBuffer != NULL) {
655d5848e21Sbeveloper 			rtm_free(fMixBuffer);
656a9cf57cfSAxel Dörfler 			fMixBuffer = NULL;
657d5848e21Sbeveloper 		}
658d5848e21Sbeveloper 		for (int i = 0; i < fInputChannelCount; i++)
659d5848e21Sbeveloper 			fInputChannelInfo[i].buffer_base = 0;
660d5848e21Sbeveloper 		fMixBufferFrameCount = 0;
661d5848e21Sbeveloper 
6629c3be6a5Sbeveloper 		UpdateInputChannelDestinationMask();
6639c3be6a5Sbeveloper 		UpdateInputChannelDestinations();
664d5848e21Sbeveloper 		return;
665d5848e21Sbeveloper 	}
6667b0daf5cSbeveloper 
6677b0daf5cSbeveloper 	// make fMixBufferFrameCount an integral multiple of frames,
6687b0daf5cSbeveloper 	// but at least 3 times duration of our input buffer
6697b0daf5cSbeveloper 	// and at least 2 times duration of the output buffer
670*b543dbc2SStephan Aßmus 	bigtime_t inputBufferLength  = duration_for_frames(
671*b543dbc2SStephan Aßmus 		fInput.format.u.raw_audio.frame_rate,
672*b543dbc2SStephan Aßmus 		frames_per_buffer(fInput.format.u.raw_audio));
6737b0daf5cSbeveloper 	bigtime_t outputBufferLength = duration_for_frames(framerate, frames);
674*b543dbc2SStephan Aßmus 	bigtime_t mixerBufferLength
675*b543dbc2SStephan Aßmus 		= max_c(3 * inputBufferLength, 2 * outputBufferLength);
6767b0daf5cSbeveloper 	int temp = frames_for_duration(framerate, mixerBufferLength);
6777b0daf5cSbeveloper 	fMixBufferFrameCount = ((temp / frames) + 1) * frames;
6787b0daf5cSbeveloper 
679a2ca4723Sbeveloper 	TRACE("  inputBufferLength    %10Ld\n", inputBufferLength);
680a2ca4723Sbeveloper 	TRACE("  outputBufferLength   %10Ld\n", outputBufferLength);
681a2ca4723Sbeveloper 	TRACE("  mixerBufferLength    %10Ld\n", mixerBufferLength);
682d91580cdSbeveloper 	TRACE("  fMixBufferFrameCount %10d\n", fMixBufferFrameCount);
6837b0daf5cSbeveloper 
6848d28117fSbeveloper 	ASSERT((fMixBufferFrameCount % frames) == 0);
6858d28117fSbeveloper 
686e92593f4Sbeveloper 	fLastDataFrameWritten = -1;
687e92593f4Sbeveloper 	fFractionalFrames = 0.0;
688e92593f4Sbeveloper 
6892e9d6607Sbeveloper 	rtm_free(fMixBuffer);
690356855c3Sbeveloper 	rtm_delete_pool(fRtmPool);
691a9cf57cfSAxel Dörfler 
6927b0daf5cSbeveloper 	int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount;
693a9cf57cfSAxel Dörfler 	if (rtm_create_pool(&fRtmPool, size) != B_OK)
694a9cf57cfSAxel Dörfler 		fRtmPool = NULL;
695a9cf57cfSAxel Dörfler 
696356855c3Sbeveloper 	fMixBuffer = (float*)rtm_alloc(fRtmPool, size);
697a9cf57cfSAxel Dörfler 	if (fMixBuffer == NULL)
698a9cf57cfSAxel Dörfler 		return;
6997b0daf5cSbeveloper 
7007b0daf5cSbeveloper 	memset(fMixBuffer, 0, size);
7012e9d6607Sbeveloper 
7022e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
7037b0daf5cSbeveloper 		fInputChannelInfo[i].buffer_base = &fMixBuffer[i];
704d5848e21Sbeveloper 
7059c3be6a5Sbeveloper 	UpdateInputChannelDestinationMask();
7069c3be6a5Sbeveloper 	UpdateInputChannelDestinations();
7072e9d6607Sbeveloper }
708