1/*
2 * Copyright 2003-2010 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Marcus Overhagen
7 */
8#ifndef _MIXER_INPUT_H
9#define _MIXER_INPUT_H
10
11
12#include <MediaNode.h>
13#include <RealtimeAlloc.h>
14
15#include "MixerCore.h"
16#include "MixerDebug.h"
17#include "MixerUtils.h"
18
19
20class ByteSwap;
21class Resampler;
22
23
24class MixerInput {
25public:
26								MixerInput(MixerCore* core,
27									const media_input& input,
28									float mixFrameRate, int32 mixFrameCount);
29								~MixerInput();
30
31			int32				ID();
32			media_input&		MediaInput();
33
34			void				BufferReceived(BBuffer* buffer);
35
36			void				UpdateResamplingAlgorithm();
37
38	// The physical input channels
39			int					GetInputChannelCount();
40			int					GetInputChannelType(int channel);
41			void				SetInputChannelGain(int channel, float gain);
42			float				GetInputChannelGain(int channel);
43
44	// The destinations for each channel
45			void				AddInputChannelDestination(int channel,
46									int destinationType);
47			void				RemoveInputChannelDestination(int channel,
48									int destinationType);
49			bool				HasInputChannelDestination(int channel,
50									int destinationType);
51			int 				GetInputChannelForDestination(
52									int destinationType);
53				// returns -1 if not found
54
55	// The virtual mixer channels that are generated from destinations
56			int					GetMixerChannelCount();
57			void				SetMixerChannelGain(int mixerChannel,
58									float gain);
59			float				GetMixerChannelGain(int mixerChannel);
60			int					GetMixerChannelType(int mixerChannel);
61
62			void				SetEnabled(bool enabled);
63			bool				IsEnabled();
64
65	// only for use by MixerCore
66			bool				GetMixerChannelInfo(int mixerChannel,
67									int64 framepos, bigtime_t time,
68									const float** _buffer,
69									uint32* _sampleOffset, int* _type,
70									float* _gain);
71
72protected:
73	friend class MixerCore;
74
75			void				SetMixBufferFormat(int32 framerate,
76									int32 frames);
77
78private:
79			void				_UpdateInputChannelDestinationMask();
80			void				_UpdateInputChannelDestinations();
81
82	struct input_chan_info {
83		float*					buffer_base;
84		uint32					destination_mask;	// multiple or no bits sets
85		float					gain;
86	};
87
88	struct mixer_chan_info {
89		float*					buffer_base;
90		int						destination_type;
91		float					destination_gain;
92	};
93
94private:
95			MixerCore*			fCore;
96			media_input			fInput;
97			ByteSwap*			fInputByteSwap;
98			float				fChannelTypeGain[MAX_CHANNEL_TYPES];
99			bool				fEnabled;
100			input_chan_info*	fInputChannelInfo; // array
101			int					fInputChannelCount;
102			uint32				fInputChannelMask;
103			mixer_chan_info*	fMixerChannelInfo; // array
104			int					fMixerChannelCount;
105			float*				fMixBuffer;
106			int32				fMixBufferFrameRate;
107			int					fMixBufferFrameCount;
108			int32				fLastDataFrameWritten;
109			bigtime_t			fLastDataAvailableTime;
110			double				fFractionalFrames;
111			Resampler**			fResampler; // array
112			rtm_pool*			fRtmPool;
113			bool				fUserOverridesChannelDestinations;
114			int32				fDebugMixBufferFrames;
115};
116
117
118inline int
119MixerInput::GetMixerChannelCount()
120{
121	return fMixerChannelCount;
122}
123
124
125inline bool
126MixerInput::GetMixerChannelInfo(int mixerChannel, int64 framepos,
127	bigtime_t time, const float** buffer, uint32* sampleOffset, int* type,
128	float* gain)
129{
130	// this function should not be called if we don't have a mix buffer!
131	ASSERT(fMixBuffer != NULL);
132	ASSERT(mixerChannel >= 0 && mixerChannel < fMixerChannelCount);
133	if (!fEnabled)
134		return false;
135
136#if DEBUG
137	if (time < (fLastDataAvailableTime - duration_for_frames(
138			fMixBufferFrameRate, fMixBufferFrameCount))
139		|| (time + duration_for_frames(fMixBufferFrameRate,
140			fDebugMixBufferFrames)) >= fLastDataAvailableTime) {
141		// Print this error for the first channel only.
142		if (mixerChannel == 0) {
143			ERROR("MixerInput::GetMixerChannelInfo: reading wrong data, have %lld "
144				"to %lld, reading from %lld to %lld\n",
145				fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate,
146					fMixBufferFrameCount), fLastDataAvailableTime, time,
147				time + duration_for_frames(fMixBufferFrameRate,
148				fDebugMixBufferFrames));
149		}
150	}
151#endif
152
153	if (time > fLastDataAvailableTime)
154		return false;
155
156	int32 offset = framepos % fMixBufferFrameCount;
157	if (mixerChannel == 0) {
158		PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset,
159			offset + fDebugMixBufferFrames - 1);
160	}
161	*buffer = reinterpret_cast<float*>(reinterpret_cast<char*>(
162		fMixerChannelInfo[mixerChannel].buffer_base)
163		+ (offset * sizeof(float) * fInputChannelCount));
164	*sampleOffset = sizeof(float) * fInputChannelCount;
165	*type = fMixerChannelInfo[mixerChannel].destination_type;
166	*gain = fMixerChannelInfo[mixerChannel].destination_gain;
167	return true;
168}
169
170#endif	// _MIXER_INPUT_H
171