xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp (revision 88777023cd6b39e9136e2b01b080c8456c677cf5)
1678c2017Sbeveloper #include <MediaNode.h>
22e9d6607Sbeveloper #include <Buffer.h>
32e9d6607Sbeveloper #include <RealtimeAlloc.h>
4678c2017Sbeveloper #include "MixerInput.h"
5678c2017Sbeveloper #include "MixerCore.h"
6e6c7c99fSbeveloper #include "MixerUtils.h"
7*88777023Sbeveloper #include "ByteSwap.h"
8e6c7c99fSbeveloper #include "debug.h"
9678c2017Sbeveloper 
102e9d6607Sbeveloper MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampleRate, int32 mixFramesCount, bigtime_t mixStartTime)
11e6c7c99fSbeveloper  :	fCore(core),
122e9d6607Sbeveloper  	fInput(input),
13*88777023Sbeveloper 	fInputByteSwap(0),
142e9d6607Sbeveloper 	fInputChannelInfo(0),
152e9d6607Sbeveloper 	fInputChannelCount(0),
162e9d6607Sbeveloper 	fInputChannelMask(0),
172e9d6607Sbeveloper 	fMixerChannelInfo(0),
182e9d6607Sbeveloper 	fMixerChannelCount(0),
192e9d6607Sbeveloper 	fMixBuffer(0),
202e9d6607Sbeveloper 	fMixBufferSampleRate(0),
212e9d6607Sbeveloper 	fMixBufferFrames(0),
222e9d6607Sbeveloper 	fMixBufferStartTime(0),
232e9d6607Sbeveloper 	fUserOverridesChannelDesignations(false)
24678c2017Sbeveloper {
25e6c7c99fSbeveloper 	fix_multiaudio_format(&fInput.format.u.raw_audio);
26e6c7c99fSbeveloper 	PRINT_INPUT("MixerInput::MixerInput", fInput);
27e6c7c99fSbeveloper 	PRINT_CHANNEL_MASK(fInput.format);
282e9d6607Sbeveloper 
292e9d6607Sbeveloper 	ASSERT(fInput.format.u.raw_audio.channel_count > 0);
302e9d6607Sbeveloper 
312e9d6607Sbeveloper 	fInputChannelCount = fInput.format.u.raw_audio.channel_count;
322e9d6607Sbeveloper 	fInputChannelMask = fInput.format.u.raw_audio.channel_mask;
332e9d6607Sbeveloper 	fInputChannelInfo = new input_chan_info[fInputChannelCount];
342e9d6607Sbeveloper 
35*88777023Sbeveloper 	// perhaps we need byte swapping
36*88777023Sbeveloper 	if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) {
37*88777023Sbeveloper 		if (	fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT
38*88777023Sbeveloper 			 ||	fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_INT
39*88777023Sbeveloper 			 ||	fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) {
40*88777023Sbeveloper 			fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format);
41*88777023Sbeveloper 		}
42*88777023Sbeveloper 	}
43*88777023Sbeveloper 
442e9d6607Sbeveloper 	// initialize fInputChannelInfo
452e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++) {
462e9d6607Sbeveloper 		fInputChannelInfo[i].buffer_base = 0;	// will be set by SetMixBufferFormat()
472e9d6607Sbeveloper 		fInputChannelInfo[i].designations = 0;	// will be set by UpdateChannelDesignations()
482e9d6607Sbeveloper 		fInputChannelInfo[i].gain = 1.0;
492e9d6607Sbeveloper 	}
502e9d6607Sbeveloper 
512e9d6607Sbeveloper 	// fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateMixerChannels()
522e9d6607Sbeveloper 
532e9d6607Sbeveloper 	SetMixBufferFormat(mixSampleRate, mixFramesCount, mixStartTime);
542e9d6607Sbeveloper 	UpdateChannelDesignations();
552e9d6607Sbeveloper 	UpdateMixerChannels();
562e9d6607Sbeveloper 
572e9d6607Sbeveloper 
582e9d6607Sbeveloper 	// XXX a test:
592e9d6607Sbeveloper 	SetMixerChannelGain(0, 0.222);
602e9d6607Sbeveloper 	SetMixerChannelGain(1, 0.444);
612e9d6607Sbeveloper 	AddInputChannelDesignation(0, B_CHANNEL_REARRIGHT);
622e9d6607Sbeveloper 	SetMixerChannelGain(2, 0.666);
632e9d6607Sbeveloper 	AddInputChannelDesignation(1, B_CHANNEL_REARLEFT);
64678c2017Sbeveloper }
65678c2017Sbeveloper 
66678c2017Sbeveloper MixerInput::~MixerInput()
67678c2017Sbeveloper {
682e9d6607Sbeveloper 	if (fMixBuffer)
692e9d6607Sbeveloper 		rtm_free(fMixBuffer);
702e9d6607Sbeveloper 	delete [] fInputChannelInfo;
712e9d6607Sbeveloper 	delete [] fMixerChannelInfo;
72678c2017Sbeveloper }
73678c2017Sbeveloper 
74678c2017Sbeveloper void
75678c2017Sbeveloper MixerInput::BufferReceived(BBuffer *buffer)
76678c2017Sbeveloper {
77*88777023Sbeveloper 	void *data;
78*88777023Sbeveloper 	size_t size;
79*88777023Sbeveloper 	bigtime_t start;
80*88777023Sbeveloper 
812e9d6607Sbeveloper 	ASSERT(fMixBuffer);
822e9d6607Sbeveloper 
83*88777023Sbeveloper 	data = buffer->Data();
84*88777023Sbeveloper 	size = buffer->SizeUsed();
85*88777023Sbeveloper 	start = buffer->Header()->start_time;
86*88777023Sbeveloper 
87*88777023Sbeveloper 	// swap the byte order of this buffer, if necessary
88*88777023Sbeveloper 	if (fInputByteSwap)
89*88777023Sbeveloper 		fInputByteSwap->Swap(data, size);
90*88777023Sbeveloper 
91*88777023Sbeveloper 
92*88777023Sbeveloper 	printf("mix buffer start %14Ld, buffer start %14Ld\n", fMixBufferStartTime, start);
93678c2017Sbeveloper }
947ee2c804Sbeveloper 
957ee2c804Sbeveloper media_input &
967ee2c804Sbeveloper MixerInput::MediaInput()
977ee2c804Sbeveloper {
987ee2c804Sbeveloper 	return fInput;
997ee2c804Sbeveloper }
100e6c7c99fSbeveloper 
101e6c7c99fSbeveloper int32
102e6c7c99fSbeveloper MixerInput::ID()
103e6c7c99fSbeveloper {
104e6c7c99fSbeveloper 	return fInput.destination.id;
105e6c7c99fSbeveloper }
106e6c7c99fSbeveloper 
1072e9d6607Sbeveloper void
1082e9d6607Sbeveloper MixerInput::AddInputChannelDesignation(int channel, uint32 des)
1092e9d6607Sbeveloper {
1102e9d6607Sbeveloper 	ASSERT(count_nonzero_bits(des) == 1);
111e6c7c99fSbeveloper 
1122e9d6607Sbeveloper 	// test if the channel is valid
1132e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
1142e9d6607Sbeveloper 		return;
1152e9d6607Sbeveloper 
1162e9d6607Sbeveloper 	// test if it is already set
1172e9d6607Sbeveloper 	if (fInputChannelInfo[channel].designations & des)
1182e9d6607Sbeveloper 		return;
1192e9d6607Sbeveloper 
1202e9d6607Sbeveloper 	// remove it from all other channels that might have it
1212e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
1222e9d6607Sbeveloper 		fInputChannelInfo[i].designations &= ~des;
1232e9d6607Sbeveloper 
1242e9d6607Sbeveloper 	// add it to specified channel
1252e9d6607Sbeveloper 	fInputChannelInfo[channel].designations |= des;
1262e9d6607Sbeveloper 
1272e9d6607Sbeveloper 	fUserOverridesChannelDesignations = true;
1282e9d6607Sbeveloper 	UpdateMixerChannels();
1292e9d6607Sbeveloper }
1302e9d6607Sbeveloper 
1312e9d6607Sbeveloper void
1322e9d6607Sbeveloper MixerInput::RemoveInputChannelDesignation(int channel, uint32 des)
1332e9d6607Sbeveloper {
1342e9d6607Sbeveloper 	ASSERT(count_nonzero_bits(des) == 1);
1352e9d6607Sbeveloper 
1362e9d6607Sbeveloper 	// test if the channel is valid
1372e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
1382e9d6607Sbeveloper 		return;
1392e9d6607Sbeveloper 
1402e9d6607Sbeveloper 	// test if it is really set
1412e9d6607Sbeveloper 	if ((fInputChannelInfo[channel].designations & des) == 0)
1422e9d6607Sbeveloper 		return;
1432e9d6607Sbeveloper 
1442e9d6607Sbeveloper 	// remove it from specified channel
1452e9d6607Sbeveloper 	fInputChannelInfo[channel].designations &= ~des;
1462e9d6607Sbeveloper 
1472e9d6607Sbeveloper 	fUserOverridesChannelDesignations = true;
1482e9d6607Sbeveloper 	UpdateMixerChannels();
1492e9d6607Sbeveloper }
1502e9d6607Sbeveloper 
1512e9d6607Sbeveloper uint32
1522e9d6607Sbeveloper MixerInput::GetInputChannelDesignations(int channel)
1532e9d6607Sbeveloper {
1542e9d6607Sbeveloper 	// test if the channel is valid
1552e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
1562e9d6607Sbeveloper 		return 0;
1572e9d6607Sbeveloper 	return fInputChannelInfo[channel].designations;
1582e9d6607Sbeveloper }
1592e9d6607Sbeveloper 
1602e9d6607Sbeveloper uint32
1612e9d6607Sbeveloper MixerInput::GetInputChannelType(int channel)
1622e9d6607Sbeveloper {
1632e9d6607Sbeveloper 	// test if the channel is valid
1642e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
1652e9d6607Sbeveloper 		return 0;
1662e9d6607Sbeveloper 	return GetChannelMask(channel, fInputChannelMask);
1672e9d6607Sbeveloper }
1682e9d6607Sbeveloper 
1692e9d6607Sbeveloper void
1702e9d6607Sbeveloper MixerInput::SetInputChannelGain(int channel, float gain)
1712e9d6607Sbeveloper {
1722e9d6607Sbeveloper 	// test if the channel is valid
1732e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
1742e9d6607Sbeveloper 		return;
1752e9d6607Sbeveloper 	if (gain < 0.0f)
1762e9d6607Sbeveloper 		gain = 0.0f;
1772e9d6607Sbeveloper 
1782e9d6607Sbeveloper 	fInputChannelInfo[channel].gain = gain;
1792e9d6607Sbeveloper }
1802e9d6607Sbeveloper 
1812e9d6607Sbeveloper float
1822e9d6607Sbeveloper MixerInput::GetInputChannelGain(int channel)
1832e9d6607Sbeveloper {
1842e9d6607Sbeveloper 	// test if the channel is valid
1852e9d6607Sbeveloper 	if (channel < 0 || channel >= fInputChannelCount)
1862e9d6607Sbeveloper 		return 0.0f;
1872e9d6607Sbeveloper 	return fInputChannelInfo[channel].gain;
1882e9d6607Sbeveloper }
1892e9d6607Sbeveloper 
1902e9d6607Sbeveloper void
1912e9d6607Sbeveloper MixerInput::UpdateChannelDesignations()
1922e9d6607Sbeveloper {
1932e9d6607Sbeveloper 	// is the user already messed with the assignmens, don't do anything.
1942e9d6607Sbeveloper 	if (fUserOverridesChannelDesignations)
1952e9d6607Sbeveloper 		return;
1962e9d6607Sbeveloper 
1972e9d6607Sbeveloper 	printf("UpdateChannelDesignations: enter\n");
1982e9d6607Sbeveloper 
1992e9d6607Sbeveloper 	if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
2002e9d6607Sbeveloper 		// a left or right channel get's output as stereo on both
2012e9d6607Sbeveloper 		fInputChannelInfo[0].designations = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
2022e9d6607Sbeveloper 	} else {
2032e9d6607Sbeveloper 		// everything else get's mapped 1:1
2042e9d6607Sbeveloper 		for (int i = 0; i < fInputChannelCount; i++)
2052e9d6607Sbeveloper 			fInputChannelInfo[i].designations = GetChannelMask(i, fInputChannelMask);
2062e9d6607Sbeveloper 	}
2072e9d6607Sbeveloper 
2082e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
2092e9d6607Sbeveloper 		printf("UpdateChannelDesignations: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
2102e9d6607Sbeveloper 
2112e9d6607Sbeveloper 	printf("UpdateChannelDesignations: enter\n");
2122e9d6607Sbeveloper }
2132e9d6607Sbeveloper 
2142e9d6607Sbeveloper void
2152e9d6607Sbeveloper MixerInput::UpdateMixerChannels()
2162e9d6607Sbeveloper {
2172e9d6607Sbeveloper 	uint32 channel_count;
2182e9d6607Sbeveloper 	uint32 all_bits;
2192e9d6607Sbeveloper 	uint32 mask;
2202e9d6607Sbeveloper 
2212e9d6607Sbeveloper 	mixer_chan_info *old_mixer_channel_info;
2222e9d6607Sbeveloper 	uint32 old_mixer_channel_count;
2232e9d6607Sbeveloper 
2242e9d6607Sbeveloper 	ASSERT(fMixBuffer);
2252e9d6607Sbeveloper 
2262e9d6607Sbeveloper 	printf("UpdateMixerChannels: enter\n");
2272e9d6607Sbeveloper 
2282e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
2292e9d6607Sbeveloper 		printf("UpdateMixerChannels: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
2302e9d6607Sbeveloper 
2312e9d6607Sbeveloper 	all_bits = 0;
2322e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
2332e9d6607Sbeveloper 		all_bits |= fInputChannelInfo[i].designations;
2342e9d6607Sbeveloper 
2352e9d6607Sbeveloper 	printf("UpdateMixerChannels: all_bits = %08x\n", all_bits);
2362e9d6607Sbeveloper 
2372e9d6607Sbeveloper 	channel_count = count_nonzero_bits(all_bits);
2382e9d6607Sbeveloper 
2392e9d6607Sbeveloper 	printf("UpdateMixerChannels: %ld input channels, %ld mixer channels (%ld old)\n", fInputChannelCount, channel_count, fMixerChannelCount);
2402e9d6607Sbeveloper 
2412e9d6607Sbeveloper 	// If we resize the channel info array, we preserve the gain setting
2422e9d6607Sbeveloper 	// by saving the old array until new assignments are finished, and
2432e9d6607Sbeveloper 	// then applying the old gains. New gains are set to 1.0
2442e9d6607Sbeveloper 	if (channel_count != fMixerChannelCount) {
2452e9d6607Sbeveloper 		old_mixer_channel_info = fMixerChannelInfo;
2462e9d6607Sbeveloper 		old_mixer_channel_count = fMixerChannelCount;
2472e9d6607Sbeveloper 		fMixerChannelInfo = new mixer_chan_info[channel_count];
2482e9d6607Sbeveloper 		fMixerChannelCount = channel_count;
2492e9d6607Sbeveloper 		for (int i = 0; i < fMixerChannelCount; i++)
2502e9d6607Sbeveloper 			fMixerChannelInfo[i].gain = 1.0;
2512e9d6607Sbeveloper 	} else {
2522e9d6607Sbeveloper 		old_mixer_channel_info = 0;
2532e9d6607Sbeveloper 		old_mixer_channel_count = 0;
2542e9d6607Sbeveloper 	}
2552e9d6607Sbeveloper 
2562e9d6607Sbeveloper 	// assign each mixer channel one type
2572e9d6607Sbeveloper 	for (int i  = 0, mask = 1; i < fMixerChannelCount; i++) {
2582e9d6607Sbeveloper 		while (mask != 0 && (all_bits & mask) == 0)
2592e9d6607Sbeveloper 			mask <<= 1;
260a4b8db85Sbeveloper 		fMixerChannelInfo[i].type = ChannelMaskToChannelType(mask);
2612e9d6607Sbeveloper 		mask <<= 1;
2622e9d6607Sbeveloper 	}
2632e9d6607Sbeveloper 
2642e9d6607Sbeveloper 	// assign buffer_base pointer for each mixer channel
2652e9d6607Sbeveloper 	for (int i  = 0; i < fMixerChannelCount; i++) {
2662e9d6607Sbeveloper 		int j;
2672e9d6607Sbeveloper 		for (j = 0; j < fInputChannelCount; j++) {
268a4b8db85Sbeveloper 			if (fInputChannelInfo[j].designations & ChannelTypeToChannelMask(fMixerChannelInfo[i].type)) {
2692e9d6607Sbeveloper 				fMixerChannelInfo[i].buffer_base = &fMixBuffer[j];
2702e9d6607Sbeveloper 				break;
2712e9d6607Sbeveloper 			}
2722e9d6607Sbeveloper 		}
2732e9d6607Sbeveloper 		if (j == fInputChannelCount) {
2742e9d6607Sbeveloper 			printf("buffer assignment failed for mixer chan %d\n", i);
2752e9d6607Sbeveloper 			fMixerChannelInfo[i].buffer_base = fMixBuffer;
2762e9d6607Sbeveloper 		}
2772e9d6607Sbeveloper 	}
2782e9d6607Sbeveloper 
2792e9d6607Sbeveloper 	// apply old gains, overriding the 1.0 defaults for the old channels
2802e9d6607Sbeveloper 	if (old_mixer_channel_info != 0) {
2812e9d6607Sbeveloper 		for (int i  = 0; i < fMixerChannelCount; i++) {
2822e9d6607Sbeveloper 			for (int j = 0; j < old_mixer_channel_count; j++) {
283a4b8db85Sbeveloper 				if (fMixerChannelInfo[i].type == old_mixer_channel_info[j].type) {
2842e9d6607Sbeveloper 					fMixerChannelInfo[i].gain = old_mixer_channel_info[j].gain;
2852e9d6607Sbeveloper 					break;
2862e9d6607Sbeveloper 				}
2872e9d6607Sbeveloper 			}
2882e9d6607Sbeveloper 		}
2892e9d6607Sbeveloper 		// also delete the old info array
2902e9d6607Sbeveloper 		delete [] old_mixer_channel_info;
2912e9d6607Sbeveloper 	}
2922e9d6607Sbeveloper 
2932e9d6607Sbeveloper 	for (int i = 0; i < fMixerChannelCount; i++)
294a4b8db85Sbeveloper 		printf("UpdateMixerChannels: mixer channel %d, type %2d, des 0x%08X, base %p, gain %.3f\n", i, fMixerChannelInfo[i].type, ChannelTypeToChannelMask(fMixerChannelInfo[i].type), fMixerChannelInfo[i].buffer_base, fMixerChannelInfo[i].gain);
2952e9d6607Sbeveloper 
2962e9d6607Sbeveloper 	printf("UpdateMixerChannels: leave\n");
2972e9d6607Sbeveloper }
2982e9d6607Sbeveloper 
2992e9d6607Sbeveloper uint32
3002e9d6607Sbeveloper MixerInput::GetMixerChannelCount()
3012e9d6607Sbeveloper {
3022e9d6607Sbeveloper 	return fMixerChannelCount;
3032e9d6607Sbeveloper }
3042e9d6607Sbeveloper 
3052e9d6607Sbeveloper void
306a4b8db85Sbeveloper MixerInput::GetMixerChannelInfo(int channel, const float **buffer, uint32 *sample_offset, int *type, float *gain)
3072e9d6607Sbeveloper {
3082e9d6607Sbeveloper 	ASSERT(fMixBuffer);
3092e9d6607Sbeveloper 	ASSERT(channel >= 0 && channel < fMixerChannelCount);
3102e9d6607Sbeveloper 	*buffer = fMixerChannelInfo[channel].buffer_base;
3112e9d6607Sbeveloper 	*sample_offset = sizeof(float) * fInputChannelCount;
312a4b8db85Sbeveloper 	*type = fMixerChannelInfo[channel].type;
3132e9d6607Sbeveloper 	*gain = fMixerChannelInfo[channel].gain;
3142e9d6607Sbeveloper }
3152e9d6607Sbeveloper 
3162e9d6607Sbeveloper void
3172e9d6607Sbeveloper MixerInput::SetMixerChannelGain(int channel, float gain)
3182e9d6607Sbeveloper {
3192e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
3202e9d6607Sbeveloper 		return;
3212e9d6607Sbeveloper 	if (gain < 0.0f)
3222e9d6607Sbeveloper 		gain = 0.0f;
3232e9d6607Sbeveloper 	fMixerChannelInfo[channel].gain = gain;
3242e9d6607Sbeveloper }
3252e9d6607Sbeveloper 
3262e9d6607Sbeveloper float
3272e9d6607Sbeveloper MixerInput::GetMixerChannelGain(int channel)
3282e9d6607Sbeveloper {
3292e9d6607Sbeveloper 	if (channel < 0 || channel >= fMixerChannelCount)
3302e9d6607Sbeveloper 		return 1.0;
3312e9d6607Sbeveloper 	return fMixerChannelInfo[channel].gain;
3322e9d6607Sbeveloper }
3332e9d6607Sbeveloper 
3342e9d6607Sbeveloper void
3352e9d6607Sbeveloper MixerInput::SetMixBufferFormat(float samplerate, int32 frames, bigtime_t starttime)
3362e9d6607Sbeveloper {
3372e9d6607Sbeveloper 	fMixBufferSampleRate = samplerate;
3382e9d6607Sbeveloper 	fMixBufferFrames = frames;
3392e9d6607Sbeveloper 	fMixBufferStartTime = starttime;
3402e9d6607Sbeveloper 
3412e9d6607Sbeveloper 	if (fMixBuffer)
3422e9d6607Sbeveloper 		rtm_free(fMixBuffer);
3432e9d6607Sbeveloper 	fMixBuffer = (float *)rtm_alloc(NULL, sizeof(float) * fInputChannelCount * fMixBufferFrames);
3442e9d6607Sbeveloper 
3452e9d6607Sbeveloper 	for (int i = 0; i < fInputChannelCount; i++)
3462e9d6607Sbeveloper 		fInputChannelInfo[i].buffer_base = &fMixBuffer[i * fMixBufferFrames];
3472e9d6607Sbeveloper }
348