xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp (revision 2e9d660756e64ccd9bd2b779020a167b8c7a5824)
1678c2017Sbeveloper #include <MediaNode.h>
2*2e9d6607Sbeveloper #include <Buffer.h>
3*2e9d6607Sbeveloper #include <RealtimeAlloc.h>
4678c2017Sbeveloper #include "MixerInput.h"
5678c2017Sbeveloper #include "MixerCore.h"
6e6c7c99fSbeveloper #include "MixerUtils.h"
7e6c7c99fSbeveloper #include "debug.h"
8678c2017Sbeveloper 
9*2e9d6607Sbeveloper MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampleRate, int32 mixFramesCount, bigtime_t mixStartTime)
10e6c7c99fSbeveloper  :	fCore(core),
11*2e9d6607Sbeveloper  	fInput(input),
12*2e9d6607Sbeveloper 	fInputChannelInfo(0),
13*2e9d6607Sbeveloper 	fInputChannelCount(0),
14*2e9d6607Sbeveloper 	fInputChannelMask(0),
15*2e9d6607Sbeveloper 	fMixerChannelInfo(0),
16*2e9d6607Sbeveloper 	fMixerChannelCount(0),
17*2e9d6607Sbeveloper 	fMixBuffer(0),
18*2e9d6607Sbeveloper 	fMixBufferSampleRate(0),
19*2e9d6607Sbeveloper 	fMixBufferFrames(0),
20*2e9d6607Sbeveloper 	fMixBufferStartTime(0),
21*2e9d6607Sbeveloper 	fUserOverridesChannelDesignations(false)
22678c2017Sbeveloper {
23e6c7c99fSbeveloper 	fix_multiaudio_format(&fInput.format.u.raw_audio);
24e6c7c99fSbeveloper 	PRINT_INPUT("MixerInput::MixerInput", fInput);
25e6c7c99fSbeveloper 	PRINT_CHANNEL_MASK(fInput.format);
26*2e9d6607Sbeveloper 
27*2e9d6607Sbeveloper 	ASSERT(fInput.format.u.raw_audio.channel_count > 0);
28*2e9d6607Sbeveloper 
29*2e9d6607Sbeveloper 	fInputChannelCount = fInput.format.u.raw_audio.channel_count;
30*2e9d6607Sbeveloper 	fInputChannelMask = fInput.format.u.raw_audio.channel_mask;
31*2e9d6607Sbeveloper 	fInputChannelInfo = new input_chan_info[fInputChannelCount];
32*2e9d6607Sbeveloper 
33*2e9d6607Sbeveloper 	// initialize fInputChannelInfo
34*2e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++) {
35*2e9d6607Sbeveloper 		fInputChannelInfo[i].buffer_base = 0;	// will be set by SetMixBufferFormat()
36*2e9d6607Sbeveloper 		fInputChannelInfo[i].designations = 0;	// will be set by UpdateChannelDesignations()
37*2e9d6607Sbeveloper 		fInputChannelInfo[i].gain = 1.0;
38*2e9d6607Sbeveloper 	}
39*2e9d6607Sbeveloper 
40*2e9d6607Sbeveloper 	// fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateMixerChannels()
41*2e9d6607Sbeveloper 
42*2e9d6607Sbeveloper 	SetMixBufferFormat(mixSampleRate, mixFramesCount, mixStartTime);
43*2e9d6607Sbeveloper 	UpdateChannelDesignations();
44*2e9d6607Sbeveloper 	UpdateMixerChannels();
45*2e9d6607Sbeveloper 
46*2e9d6607Sbeveloper 
47*2e9d6607Sbeveloper 	// XXX a test:
48*2e9d6607Sbeveloper 	SetMixerChannelGain(0, 0.222);
49*2e9d6607Sbeveloper 	SetMixerChannelGain(1, 0.444);
50*2e9d6607Sbeveloper 	AddInputChannelDesignation(0, B_CHANNEL_REARRIGHT);
51*2e9d6607Sbeveloper 	SetMixerChannelGain(2, 0.666);
52*2e9d6607Sbeveloper 	AddInputChannelDesignation(1, B_CHANNEL_REARLEFT);
53678c2017Sbeveloper }
54678c2017Sbeveloper 
55678c2017Sbeveloper MixerInput::~MixerInput()
56678c2017Sbeveloper {
57*2e9d6607Sbeveloper 	if (fMixBuffer)
58*2e9d6607Sbeveloper 		rtm_free(fMixBuffer);
59*2e9d6607Sbeveloper 	delete [] fInputChannelInfo;
60*2e9d6607Sbeveloper 	delete [] fMixerChannelInfo;
61678c2017Sbeveloper }
62678c2017Sbeveloper 
63678c2017Sbeveloper void
64678c2017Sbeveloper MixerInput::BufferReceived(BBuffer *buffer)
65678c2017Sbeveloper {
66*2e9d6607Sbeveloper 	ASSERT(fMixBuffer);
67*2e9d6607Sbeveloper 
68*2e9d6607Sbeveloper 	printf("mix buffer start %14Ld, buffer start %14Ld\n", fMixBufferStartTime, buffer->Header()->start_time);
69678c2017Sbeveloper }
707ee2c804Sbeveloper 
717ee2c804Sbeveloper media_input &
727ee2c804Sbeveloper MixerInput::MediaInput()
737ee2c804Sbeveloper {
747ee2c804Sbeveloper 	return fInput;
757ee2c804Sbeveloper }
76e6c7c99fSbeveloper 
77e6c7c99fSbeveloper int32
78e6c7c99fSbeveloper MixerInput::ID()
79e6c7c99fSbeveloper {
80e6c7c99fSbeveloper 	return fInput.destination.id;
81e6c7c99fSbeveloper }
82e6c7c99fSbeveloper 
83*2e9d6607Sbeveloper void
84*2e9d6607Sbeveloper MixerInput::AddInputChannelDesignation(int channel, uint32 des)
85*2e9d6607Sbeveloper {
86*2e9d6607Sbeveloper 	ASSERT(count_nonzero_bits(des) == 1);
87e6c7c99fSbeveloper 
88*2e9d6607Sbeveloper 	// test if the channel is valid
89*2e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
90*2e9d6607Sbeveloper 		return;
91*2e9d6607Sbeveloper 
92*2e9d6607Sbeveloper 	// test if it is already set
93*2e9d6607Sbeveloper 	if (fInputChannelInfo[channel].designations & des)
94*2e9d6607Sbeveloper 		return;
95*2e9d6607Sbeveloper 
96*2e9d6607Sbeveloper 	// remove it from all other channels that might have it
97*2e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
98*2e9d6607Sbeveloper 		fInputChannelInfo[i].designations &= ~des;
99*2e9d6607Sbeveloper 
100*2e9d6607Sbeveloper 	// add it to specified channel
101*2e9d6607Sbeveloper 	fInputChannelInfo[channel].designations |= des;
102*2e9d6607Sbeveloper 
103*2e9d6607Sbeveloper 	fUserOverridesChannelDesignations = true;
104*2e9d6607Sbeveloper 	UpdateMixerChannels();
105*2e9d6607Sbeveloper }
106*2e9d6607Sbeveloper 
107*2e9d6607Sbeveloper void
108*2e9d6607Sbeveloper MixerInput::RemoveInputChannelDesignation(int channel, uint32 des)
109*2e9d6607Sbeveloper {
110*2e9d6607Sbeveloper 	ASSERT(count_nonzero_bits(des) == 1);
111*2e9d6607Sbeveloper 
112*2e9d6607Sbeveloper 	// test if the channel is valid
113*2e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
114*2e9d6607Sbeveloper 		return;
115*2e9d6607Sbeveloper 
116*2e9d6607Sbeveloper 	// test if it is really set
117*2e9d6607Sbeveloper 	if ((fInputChannelInfo[channel].designations & des) == 0)
118*2e9d6607Sbeveloper 		return;
119*2e9d6607Sbeveloper 
120*2e9d6607Sbeveloper 	// remove it from specified channel
121*2e9d6607Sbeveloper 	fInputChannelInfo[channel].designations &= ~des;
122*2e9d6607Sbeveloper 
123*2e9d6607Sbeveloper 	fUserOverridesChannelDesignations = true;
124*2e9d6607Sbeveloper 	UpdateMixerChannels();
125*2e9d6607Sbeveloper }
126*2e9d6607Sbeveloper 
127*2e9d6607Sbeveloper uint32
128*2e9d6607Sbeveloper MixerInput::GetInputChannelDesignations(int channel)
129*2e9d6607Sbeveloper {
130*2e9d6607Sbeveloper 	// test if the channel is valid
131*2e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
132*2e9d6607Sbeveloper 		return 0;
133*2e9d6607Sbeveloper 	return fInputChannelInfo[channel].designations;
134*2e9d6607Sbeveloper }
135*2e9d6607Sbeveloper 
136*2e9d6607Sbeveloper uint32
137*2e9d6607Sbeveloper MixerInput::GetInputChannelType(int channel)
138*2e9d6607Sbeveloper {
139*2e9d6607Sbeveloper 	// test if the channel is valid
140*2e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
141*2e9d6607Sbeveloper 		return 0;
142*2e9d6607Sbeveloper 	return GetChannelMask(channel, fInputChannelMask);
143*2e9d6607Sbeveloper }
144*2e9d6607Sbeveloper 
145*2e9d6607Sbeveloper void
146*2e9d6607Sbeveloper MixerInput::SetInputChannelGain(int channel, float gain)
147*2e9d6607Sbeveloper {
148*2e9d6607Sbeveloper 	// test if the channel is valid
149*2e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
150*2e9d6607Sbeveloper 		return;
151*2e9d6607Sbeveloper 	if (gain < 0.0f)
152*2e9d6607Sbeveloper 		gain = 0.0f;
153*2e9d6607Sbeveloper 
154*2e9d6607Sbeveloper 	fInputChannelInfo[channel].gain = gain;
155*2e9d6607Sbeveloper }
156*2e9d6607Sbeveloper 
157*2e9d6607Sbeveloper float
158*2e9d6607Sbeveloper MixerInput::GetInputChannelGain(int channel)
159*2e9d6607Sbeveloper {
160*2e9d6607Sbeveloper 	// test if the channel is valid
161*2e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
162*2e9d6607Sbeveloper 		return 0.0f;
163*2e9d6607Sbeveloper 	return fInputChannelInfo[channel].gain;
164*2e9d6607Sbeveloper }
165*2e9d6607Sbeveloper 
166*2e9d6607Sbeveloper void
167*2e9d6607Sbeveloper MixerInput::UpdateChannelDesignations()
168*2e9d6607Sbeveloper {
169*2e9d6607Sbeveloper 	// is the user already messed with the assignmens, don't do anything.
170*2e9d6607Sbeveloper 	if (fUserOverridesChannelDesignations)
171*2e9d6607Sbeveloper 		return;
172*2e9d6607Sbeveloper 
173*2e9d6607Sbeveloper 	printf("UpdateChannelDesignations: enter\n");
174*2e9d6607Sbeveloper 
175*2e9d6607Sbeveloper 	if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
176*2e9d6607Sbeveloper 		// a left or right channel get's output as stereo on both
177*2e9d6607Sbeveloper 		fInputChannelInfo[0].designations = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
178*2e9d6607Sbeveloper 	} else {
179*2e9d6607Sbeveloper 		// everything else get's mapped 1:1
180*2e9d6607Sbeveloper 		for (int i = 0; i < fInputChannelCount; i++)
181*2e9d6607Sbeveloper 			fInputChannelInfo[i].designations = GetChannelMask(i, fInputChannelMask);
182*2e9d6607Sbeveloper 	}
183*2e9d6607Sbeveloper 
184*2e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
185*2e9d6607Sbeveloper 		printf("UpdateChannelDesignations: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
186*2e9d6607Sbeveloper 
187*2e9d6607Sbeveloper 	printf("UpdateChannelDesignations: enter\n");
188*2e9d6607Sbeveloper }
189*2e9d6607Sbeveloper 
190*2e9d6607Sbeveloper void
191*2e9d6607Sbeveloper MixerInput::UpdateMixerChannels()
192*2e9d6607Sbeveloper {
193*2e9d6607Sbeveloper 	uint32 channel_count;
194*2e9d6607Sbeveloper 	uint32 all_bits;
195*2e9d6607Sbeveloper 	uint32 mask;
196*2e9d6607Sbeveloper 
197*2e9d6607Sbeveloper 	mixer_chan_info *old_mixer_channel_info;
198*2e9d6607Sbeveloper 	uint32 old_mixer_channel_count;
199*2e9d6607Sbeveloper 
200*2e9d6607Sbeveloper 	ASSERT(fMixBuffer);
201*2e9d6607Sbeveloper 
202*2e9d6607Sbeveloper 	printf("UpdateMixerChannels: enter\n");
203*2e9d6607Sbeveloper 
204*2e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
205*2e9d6607Sbeveloper 		printf("UpdateMixerChannels: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
206*2e9d6607Sbeveloper 
207*2e9d6607Sbeveloper 	all_bits = 0;
208*2e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
209*2e9d6607Sbeveloper 		all_bits |= fInputChannelInfo[i].designations;
210*2e9d6607Sbeveloper 
211*2e9d6607Sbeveloper 	printf("UpdateMixerChannels: all_bits = %08x\n", all_bits);
212*2e9d6607Sbeveloper 
213*2e9d6607Sbeveloper 	channel_count = count_nonzero_bits(all_bits);
214*2e9d6607Sbeveloper 
215*2e9d6607Sbeveloper 	printf("UpdateMixerChannels: %ld input channels, %ld mixer channels (%ld old)\n", fInputChannelCount, channel_count, fMixerChannelCount);
216*2e9d6607Sbeveloper 
217*2e9d6607Sbeveloper 	// If we resize the channel info array, we preserve the gain setting
218*2e9d6607Sbeveloper 	// by saving the old array until new assignments are finished, and
219*2e9d6607Sbeveloper 	// then applying the old gains. New gains are set to 1.0
220*2e9d6607Sbeveloper 	if (channel_count != fMixerChannelCount) {
221*2e9d6607Sbeveloper 		old_mixer_channel_info = fMixerChannelInfo;
222*2e9d6607Sbeveloper 		old_mixer_channel_count = fMixerChannelCount;
223*2e9d6607Sbeveloper 		fMixerChannelInfo = new mixer_chan_info[channel_count];
224*2e9d6607Sbeveloper 		fMixerChannelCount = channel_count;
225*2e9d6607Sbeveloper 		for (int i = 0; i < fMixerChannelCount; i++)
226*2e9d6607Sbeveloper 			fMixerChannelInfo[i].gain = 1.0;
227*2e9d6607Sbeveloper 	} else {
228*2e9d6607Sbeveloper 		old_mixer_channel_info = 0;
229*2e9d6607Sbeveloper 		old_mixer_channel_count = 0;
230*2e9d6607Sbeveloper 	}
231*2e9d6607Sbeveloper 
232*2e9d6607Sbeveloper 	// assign each mixer channel one type
233*2e9d6607Sbeveloper 	for (int i  = 0, mask = 1; i < fMixerChannelCount; i++) {
234*2e9d6607Sbeveloper 		while (mask != 0 && (all_bits & mask) == 0)
235*2e9d6607Sbeveloper 			mask <<= 1;
236*2e9d6607Sbeveloper 		fMixerChannelInfo[i].designation = mask;
237*2e9d6607Sbeveloper 		mask <<= 1;
238*2e9d6607Sbeveloper 	}
239*2e9d6607Sbeveloper 
240*2e9d6607Sbeveloper 	// assign buffer_base pointer for each mixer channel
241*2e9d6607Sbeveloper 	for (int i  = 0; i < fMixerChannelCount; i++) {
242*2e9d6607Sbeveloper 		int j;
243*2e9d6607Sbeveloper 		for (j = 0; j < fInputChannelCount; j++) {
244*2e9d6607Sbeveloper 			if (fInputChannelInfo[j].designations & fMixerChannelInfo[i].designation) {
245*2e9d6607Sbeveloper 				fMixerChannelInfo[i].buffer_base = &fMixBuffer[j];
246*2e9d6607Sbeveloper 				break;
247*2e9d6607Sbeveloper 			}
248*2e9d6607Sbeveloper 		}
249*2e9d6607Sbeveloper 		if (j == fInputChannelCount) {
250*2e9d6607Sbeveloper 			printf("buffer assignment failed for mixer chan %d\n", i);
251*2e9d6607Sbeveloper 			fMixerChannelInfo[i].buffer_base = fMixBuffer;
252*2e9d6607Sbeveloper 		}
253*2e9d6607Sbeveloper 	}
254*2e9d6607Sbeveloper 
255*2e9d6607Sbeveloper 	// apply old gains, overriding the 1.0 defaults for the old channels
256*2e9d6607Sbeveloper 	if (old_mixer_channel_info != 0) {
257*2e9d6607Sbeveloper 		for (int i  = 0; i < fMixerChannelCount; i++) {
258*2e9d6607Sbeveloper 			for (int j = 0; j < old_mixer_channel_count; j++) {
259*2e9d6607Sbeveloper 				if (fMixerChannelInfo[i].designation == old_mixer_channel_info[j].designation) {
260*2e9d6607Sbeveloper 					fMixerChannelInfo[i].gain = old_mixer_channel_info[j].gain;
261*2e9d6607Sbeveloper 					break;
262*2e9d6607Sbeveloper 				}
263*2e9d6607Sbeveloper 			}
264*2e9d6607Sbeveloper 		}
265*2e9d6607Sbeveloper 		// also delete the old info array
266*2e9d6607Sbeveloper 		delete [] old_mixer_channel_info;
267*2e9d6607Sbeveloper 	}
268*2e9d6607Sbeveloper 
269*2e9d6607Sbeveloper 	for (int i = 0; i < fMixerChannelCount; i++)
270*2e9d6607Sbeveloper 		printf("UpdateMixerChannels: mixer channel %d, designation  0x%08X, base %p, gain %.3f\n", i, fMixerChannelInfo[i].designation, fMixerChannelInfo[i].buffer_base, fMixerChannelInfo[i].gain);
271*2e9d6607Sbeveloper 
272*2e9d6607Sbeveloper 	printf("UpdateMixerChannels: leave\n");
273*2e9d6607Sbeveloper }
274*2e9d6607Sbeveloper 
275*2e9d6607Sbeveloper uint32
276*2e9d6607Sbeveloper MixerInput::GetMixerChannelCount()
277*2e9d6607Sbeveloper {
278*2e9d6607Sbeveloper 	return fMixerChannelCount;
279*2e9d6607Sbeveloper }
280*2e9d6607Sbeveloper 
281*2e9d6607Sbeveloper void
282*2e9d6607Sbeveloper MixerInput::GetMixerChannelInfo(int channel, const float **buffer, uint32 *sample_offset, uint32 *type, float *gain)
283*2e9d6607Sbeveloper {
284*2e9d6607Sbeveloper 	ASSERT(fMixBuffer);
285*2e9d6607Sbeveloper 	ASSERT(channel >= 0 && channel < fMixerChannelCount);
286*2e9d6607Sbeveloper 	*buffer = fMixerChannelInfo[channel].buffer_base;
287*2e9d6607Sbeveloper 	*sample_offset = sizeof(float) * fInputChannelCount;
288*2e9d6607Sbeveloper 	*type = fMixerChannelInfo[channel].designation;
289*2e9d6607Sbeveloper 	*gain = fMixerChannelInfo[channel].gain;
290*2e9d6607Sbeveloper }
291*2e9d6607Sbeveloper 
292*2e9d6607Sbeveloper void
293*2e9d6607Sbeveloper MixerInput::SetMixerChannelGain(int channel, float gain)
294*2e9d6607Sbeveloper {
295*2e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
296*2e9d6607Sbeveloper 		return;
297*2e9d6607Sbeveloper 	if (gain < 0.0f)
298*2e9d6607Sbeveloper 		gain = 0.0f;
299*2e9d6607Sbeveloper 	fMixerChannelInfo[channel].gain = gain;
300*2e9d6607Sbeveloper }
301*2e9d6607Sbeveloper 
302*2e9d6607Sbeveloper float
303*2e9d6607Sbeveloper MixerInput::GetMixerChannelGain(int channel)
304*2e9d6607Sbeveloper {
305*2e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
306*2e9d6607Sbeveloper 		return 1.0;
307*2e9d6607Sbeveloper 	return fMixerChannelInfo[channel].gain;
308*2e9d6607Sbeveloper }
309*2e9d6607Sbeveloper 
310*2e9d6607Sbeveloper void
311*2e9d6607Sbeveloper MixerInput::SetMixBufferFormat(float samplerate, int32 frames, bigtime_t starttime)
312*2e9d6607Sbeveloper {
313*2e9d6607Sbeveloper 	fMixBufferSampleRate = samplerate;
314*2e9d6607Sbeveloper 	fMixBufferFrames = frames;
315*2e9d6607Sbeveloper 	fMixBufferStartTime = starttime;
316*2e9d6607Sbeveloper 
317*2e9d6607Sbeveloper 	if (fMixBuffer)
318*2e9d6607Sbeveloper 		rtm_free(fMixBuffer);
319*2e9d6607Sbeveloper 	fMixBuffer = (float *)rtm_alloc(NULL, sizeof(float) * fInputChannelCount * fMixBufferFrames);
320*2e9d6607Sbeveloper 
321*2e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
322*2e9d6607Sbeveloper 		fInputChannelInfo[i].buffer_base = &fMixBuffer[i * fMixBufferFrames];
323*2e9d6607Sbeveloper }
324