xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerInput.h (revision 24159a0c7d6d6dcba9f2a0c1a7c08d2c8167f21b)
1 #ifndef _MIXER_INPUT_H
2 #define _MIXER_INPUT_H
3 
4 #include <RealtimeAlloc.h>
5 #include <MediaNode.h>
6 #include "MixerCore.h"
7 #include "MixerUtils.h" // DEBUG only
8 #include "debug.h"
9 
10 class ByteSwap;
11 class Resampler;
12 
13 class MixerInput
14 {
15 public:
16 	MixerInput(MixerCore *core, const media_input &input, float mixFrameRate, int32 mixFrameCount);
17 	~MixerInput();
18 
19 	int32	ID();
20 
21 	void	BufferReceived(BBuffer *buffer);
22 
23 	media_input & MediaInput();
24 
25 	// The physical input channels
26 	int		GetInputChannelCount();
27 	int		GetInputChannelType(int channel);
28 	void	SetInputChannelGain(int channel, float gain);
29 	float	GetInputChannelGain(int channel);
30 
31 	// The destinations for each channel
32 	void 	AddInputChannelDestination(int channel, int destination_type);
33 	void 	RemoveInputChannelDestination(int channel, int destination_type);
34 //	void 	SetInputChannelDestinationGain(int channel, int destination_type, float gain);
35 //	float	GetInputChannelDestinationGain(int channel, int destination_type);
36 	bool 	HasInputChannelDestination(int channel, int destination_type);
37 	int 	GetInputChannelForDestination(int destination_type); // returns -1 if not found
38 
39 	// The virtual mixer channels that are generated from destinations
40 	int		GetMixerChannelCount();
41 	void 	SetMixerChannelGain(int mixer_channel, float gain);
42 	float	GetMixerChannelGain(int mixer_channel);
43 	int		GetMixerChannelType(int mixer_channel);
44 
45 	void	SetEnabled(bool yesno);
46 	bool	IsEnabled();
47 
48 	// only for use by MixerCore
49 	bool	GetMixerChannelInfo(int mixer_channel, int64 framepos, bigtime_t time, const float **buffer, uint32 *sample_offset, int *type, float *gain);
50 
51 protected:
52 	friend class MixerCore;
53 	void SetMixBufferFormat(int32 framerate, int32 frames);
54 
55 private:
56 	void UpdateInputChannelDestinationMask();
57 	void UpdateInputChannelDestinations();
58 
59 private:
60 	struct input_chan_info {
61 		float	*buffer_base;
62 		uint32	destination_mask;	// multiple or no bits sets
63 		float	gain;
64 	};
65 	struct mixer_chan_info {
66 		float	*buffer_base;
67 		int		destination_type;
68 		float	destination_gain;
69 	};
70 
71 private:
72 	MixerCore		*fCore;
73 	media_input		fInput;
74 	ByteSwap		*fInputByteSwap;
75 
76 	float			fChannelTypeGain[MAX_CHANNEL_TYPES];
77 
78 	bool			fEnabled;
79 
80 	input_chan_info *fInputChannelInfo; // array
81 	int				fInputChannelCount;
82 	uint32			fInputChannelMask;
83 
84 	mixer_chan_info *fMixerChannelInfo; // array
85 	int				fMixerChannelCount;
86 
87 	float 			*fMixBuffer;
88 
89 	int32 			fMixBufferFrameRate;
90 	int				fMixBufferFrameCount;
91 
92 	int32			fLastDataFrameWritten;
93 	bigtime_t		fLastDataAvailableTime;
94 
95 	double			fFractionalFrames;
96 
97 	Resampler		**fResampler; // array
98 	rtm_pool		*fRtmPool;
99 
100 	bool			fUserOverridesChannelDestinations;
101 
102 	int32			debugMixBufferFrames;
103 };
104 
105 inline int
106 MixerInput::GetMixerChannelCount()
107 {
108 	return fMixerChannelCount;
109 }
110 
111 inline bool
112 MixerInput::GetMixerChannelInfo(int mixer_channel, int64 framepos, bigtime_t time, const float **buffer, uint32 *sample_offset, int *type, float *gain)
113 {
114 	ASSERT(fMixBuffer); // this function should not be called if we don't have a mix buffer!
115 	ASSERT(mixer_channel >= 0 && mixer_channel < fMixerChannelCount);
116 	if (!fEnabled)
117 		return false;
118 
119 #if 1
120 	if (time < (fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate, fMixBufferFrameCount))
121 		|| (time + duration_for_frames(fMixBufferFrameRate, debugMixBufferFrames)) >= fLastDataAvailableTime)
122 		ERROR("MixerInput::GetMixerChannelInfo: reading wrong data, have %Ld to %Ld, reading from %Ld to %Ld\n",
123 				fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate, fMixBufferFrameCount), fLastDataAvailableTime, time, time + duration_for_frames(fMixBufferFrameRate, debugMixBufferFrames));
124 #endif
125 
126 	if (time > fLastDataAvailableTime)
127 		return false;
128 
129 	int32 offset = framepos % fMixBufferFrameCount;
130 	if (mixer_channel == 0) PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset, offset + debugMixBufferFrames - 1);
131 	*buffer = reinterpret_cast<float *>(reinterpret_cast<char *>(fMixerChannelInfo[mixer_channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount));
132 	*sample_offset = sizeof(float) * fInputChannelCount;
133 	*type = fMixerChannelInfo[mixer_channel].destination_type;
134 	*gain = fMixerChannelInfo[mixer_channel].destination_gain;
135 	return true;
136 }
137 
138 #endif
139