xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerInput.h (revision 425ac1b60a56f4df7a0e88bd784545c0ec4fa01f)
1bf7ab50dSStephan Aßmus /*
2c21a83bbSStephan Aßmus  * Copyright 2003-2010 Haiku Inc. All rights reserved.
3bf7ab50dSStephan Aßmus  * Distributed under the terms of the MIT License.
4a9cf57cfSAxel Dörfler  *
5a9cf57cfSAxel Dörfler  * Authors:
6a9cf57cfSAxel Dörfler  *		Marcus Overhagen
7bf7ab50dSStephan Aßmus  */
8678c2017Sbeveloper #ifndef _MIXER_INPUT_H
9678c2017Sbeveloper #define _MIXER_INPUT_H
10678c2017Sbeveloper 
11a9cf57cfSAxel Dörfler 
12a9cf57cfSAxel Dörfler #include <MediaNode.h>
13a9cf57cfSAxel Dörfler #include <RealtimeAlloc.h>
14a9cf57cfSAxel Dörfler 
159c3be6a5Sbeveloper #include "MixerCore.h"
16f916862cSMarcus Overhagen #include "MixerDebug.h"
17bf7ab50dSStephan Aßmus #include "MixerUtils.h"
18bf7ab50dSStephan Aßmus 
19fae6ce82Sbeveloper 
2088777023Sbeveloper class ByteSwap;
217b0daf5cSbeveloper class Resampler;
22678c2017Sbeveloper 
23a9cf57cfSAxel Dörfler 
24a9cf57cfSAxel Dörfler class MixerInput {
25678c2017Sbeveloper public:
26bf7ab50dSStephan Aßmus 								MixerInput(MixerCore* core,
27bf7ab50dSStephan Aßmus 									const media_input& input,
28b006bbe1SStephan Aßmus 									float mixFrameRate, int32 mixFrameCount);
29678c2017Sbeveloper 								~MixerInput();
30678c2017Sbeveloper 
31e6c7c99fSbeveloper 			int32				ID();
32be2a2489Sbeveloper 			media_input&		MediaInput();
33be2a2489Sbeveloper 
34b006bbe1SStephan Aßmus 			void				BufferReceived(BBuffer* buffer);
35b006bbe1SStephan Aßmus 
36b006bbe1SStephan Aßmus 			void				UpdateResamplingAlgorithm();
37b006bbe1SStephan Aßmus 
389c3be6a5Sbeveloper 	// The physical input channels
39d91580cdSbeveloper 			int					GetInputChannelCount();
409c3be6a5Sbeveloper 			int					GetInputChannelType(int channel);
41a9cf57cfSAxel Dörfler 			void				SetInputChannelGain(int channel, float gain);
424224efc3Sbeveloper 			float				GetInputChannelGain(int channel);
432e9d6607Sbeveloper 
449c3be6a5Sbeveloper 	// The destinations for each channel
45a9cf57cfSAxel Dörfler 			void				AddInputChannelDestination(int channel,
46a9cf57cfSAxel Dörfler 									int destinationType);
47a9cf57cfSAxel Dörfler 			void				RemoveInputChannelDestination(int channel,
48a9cf57cfSAxel Dörfler 									int destinationType);
49a9cf57cfSAxel Dörfler 			bool				HasInputChannelDestination(int channel,
50a9cf57cfSAxel Dörfler 									int destinationType);
51bf7ab50dSStephan Aßmus 			int 				GetInputChannelForDestination(
52a9cf57cfSAxel Dörfler 									int destinationType);
53bf7ab50dSStephan Aßmus 				// returns -1 if not found
549c3be6a5Sbeveloper 
5569517c15Sbeveloper 	// The virtual mixer channels that are generated from destinations
56d91580cdSbeveloper 			int					GetMixerChannelCount();
57a9cf57cfSAxel Dörfler 			void				SetMixerChannelGain(int mixerChannel,
58bf7ab50dSStephan Aßmus 									float gain);
59a9cf57cfSAxel Dörfler 			float				GetMixerChannelGain(int mixerChannel);
60a9cf57cfSAxel Dörfler 			int					GetMixerChannelType(int mixerChannel);
6169517c15Sbeveloper 
62a9cf57cfSAxel Dörfler 			void				SetEnabled(bool enabled);
631c237c18Sbeveloper 			bool				IsEnabled();
641c237c18Sbeveloper 
65fae6ce82Sbeveloper 	// only for use by MixerCore
66a9cf57cfSAxel Dörfler 			bool				GetMixerChannelInfo(int mixerChannel,
67a9cf57cfSAxel Dörfler 									int64 framepos, bigtime_t time,
68a9cf57cfSAxel Dörfler 									const float** _buffer,
69a9cf57cfSAxel Dörfler 									uint32* _sampleOffset, int* _type,
70a9cf57cfSAxel Dörfler 									float* _gain);
71fae6ce82Sbeveloper 
722e9d6607Sbeveloper protected:
732e9d6607Sbeveloper 	friend class MixerCore;
74a9cf57cfSAxel Dörfler 
75bf7ab50dSStephan Aßmus 			void				SetMixBufferFormat(int32 framerate,
76bf7ab50dSStephan Aßmus 									int32 frames);
772e9d6607Sbeveloper 
782e9d6607Sbeveloper private:
79b006bbe1SStephan Aßmus 			void				_UpdateInputChannelDestinationMask();
80b006bbe1SStephan Aßmus 			void				_UpdateInputChannelDestinations();
812e9d6607Sbeveloper 
822e9d6607Sbeveloper 	struct input_chan_info {
832e9d6607Sbeveloper 		float*					buffer_base;
849c3be6a5Sbeveloper 		uint32					destination_mask;	// multiple or no bits sets
852e9d6607Sbeveloper 		float					gain;
862e9d6607Sbeveloper 	};
87a9cf57cfSAxel Dörfler 
882e9d6607Sbeveloper 	struct mixer_chan_info {
892e9d6607Sbeveloper 		float*					buffer_base;
909c3be6a5Sbeveloper 		int						destination_type;
919c3be6a5Sbeveloper 		float					destination_gain;
922e9d6607Sbeveloper 	};
932e9d6607Sbeveloper 
94678c2017Sbeveloper private:
95678c2017Sbeveloper 			MixerCore*			fCore;
967ee2c804Sbeveloper 			media_input			fInput;
9788777023Sbeveloper 			ByteSwap*			fInputByteSwap;
989c3be6a5Sbeveloper 			float				fChannelTypeGain[MAX_CHANNEL_TYPES];
991c237c18Sbeveloper 			bool				fEnabled;
1002e9d6607Sbeveloper 			input_chan_info*	fInputChannelInfo; // array
101d91580cdSbeveloper 			int					fInputChannelCount;
1022e9d6607Sbeveloper 			uint32				fInputChannelMask;
1032e9d6607Sbeveloper 			mixer_chan_info*	fMixerChannelInfo; // array
104d91580cdSbeveloper 			int					fMixerChannelCount;
1052e9d6607Sbeveloper 			float*				fMixBuffer;
1067619f562Sbeveloper 			int32				fMixBufferFrameRate;
107d91580cdSbeveloper 			int					fMixBufferFrameCount;
108e92593f4Sbeveloper 			int32				fLastDataFrameWritten;
109af8d0a4dSbeveloper 			bigtime_t			fLastDataAvailableTime;
110e92593f4Sbeveloper 			double				fFractionalFrames;
1117b0daf5cSbeveloper 			Resampler**			fResampler; // array
112356855c3Sbeveloper 			rtm_pool*			fRtmPool;
1139c3be6a5Sbeveloper 			bool				fUserOverridesChannelDestinations;
114a9cf57cfSAxel Dörfler 			int32				fDebugMixBufferFrames;
115678c2017Sbeveloper };
116678c2017Sbeveloper 
117a9cf57cfSAxel Dörfler 
118d91580cdSbeveloper inline int
GetMixerChannelCount()1199c3be6a5Sbeveloper MixerInput::GetMixerChannelCount()
1209c3be6a5Sbeveloper {
1219c3be6a5Sbeveloper 	return fMixerChannelCount;
1229c3be6a5Sbeveloper }
1239c3be6a5Sbeveloper 
124a9cf57cfSAxel Dörfler 
125af8d0a4dSbeveloper inline bool
GetMixerChannelInfo(int mixerChannel,int64 framepos,bigtime_t time,const float ** buffer,uint32 * sampleOffset,int * type,float * gain)1260960b6d0SStephan Aßmus MixerInput::GetMixerChannelInfo(int mixerChannel, int64 framepos,
1270960b6d0SStephan Aßmus 	bigtime_t time, const float** buffer, uint32* sampleOffset, int* type,
128a9cf57cfSAxel Dörfler 	float* gain)
129fae6ce82Sbeveloper {
130bf7ab50dSStephan Aßmus 	// this function should not be called if we don't have a mix buffer!
1310960b6d0SStephan Aßmus 	ASSERT(fMixBuffer != NULL);
1320960b6d0SStephan Aßmus 	ASSERT(mixerChannel >= 0 && mixerChannel < fMixerChannelCount);
133f91503b9Sbeveloper 	if (!fEnabled)
134f91503b9Sbeveloper 		return false;
135f91503b9Sbeveloper 
136a6e0f877SStephan Aßmus #if DEBUG
1370960b6d0SStephan Aßmus 	if (time < (fLastDataAvailableTime - duration_for_frames(
1380960b6d0SStephan Aßmus 			fMixBufferFrameRate, fMixBufferFrameCount))
1390960b6d0SStephan Aßmus 		|| (time + duration_for_frames(fMixBufferFrameRate,
1400960b6d0SStephan Aßmus 			fDebugMixBufferFrames)) >= fLastDataAvailableTime) {
141a6e0f877SStephan Aßmus 		// Print this error for the first channel only.
142a6e0f877SStephan Aßmus 		if (mixerChannel == 0) {
143*425ac1b6SAlexander von Gluck IV 			ERROR("MixerInput::GetMixerChannelInfo: reading wrong data, have %lld "
144*425ac1b6SAlexander von Gluck IV 				"to %lld, reading from %lld to %lld\n",
1450960b6d0SStephan Aßmus 				fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate,
1460960b6d0SStephan Aßmus 					fMixBufferFrameCount), fLastDataAvailableTime, time,
1470960b6d0SStephan Aßmus 				time + duration_for_frames(fMixBufferFrameRate,
1480960b6d0SStephan Aßmus 				fDebugMixBufferFrames));
1490960b6d0SStephan Aßmus 		}
150a6e0f877SStephan Aßmus 	}
151f91503b9Sbeveloper #endif
152f91503b9Sbeveloper 
153f91503b9Sbeveloper 	if (time > fLastDataAvailableTime)
154af8d0a4dSbeveloper 		return false;
155af8d0a4dSbeveloper 
156fae6ce82Sbeveloper 	int32 offset = framepos % fMixBufferFrameCount;
1570960b6d0SStephan Aßmus 	if (mixerChannel == 0) {
1580960b6d0SStephan Aßmus 		PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset,
1590960b6d0SStephan Aßmus 			offset + fDebugMixBufferFrames - 1);
1600960b6d0SStephan Aßmus 	}
1610960b6d0SStephan Aßmus 	*buffer = reinterpret_cast<float*>(reinterpret_cast<char*>(
1620960b6d0SStephan Aßmus 		fMixerChannelInfo[mixerChannel].buffer_base)
1630960b6d0SStephan Aßmus 		+ (offset * sizeof(float) * fInputChannelCount));
1640960b6d0SStephan Aßmus 	*sampleOffset = sizeof(float) * fInputChannelCount;
1650960b6d0SStephan Aßmus 	*type = fMixerChannelInfo[mixerChannel].destination_type;
1660960b6d0SStephan Aßmus 	*gain = fMixerChannelInfo[mixerChannel].destination_gain;
167af8d0a4dSbeveloper 	return true;
168fae6ce82Sbeveloper }
169a9cf57cfSAxel Dörfler 
170a9cf57cfSAxel Dörfler #endif	// _MIXER_INPUT_H
171