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
2088777023Sbeveloperclass ByteSwap;
217b0daf5cSbeveloperclass Resampler;
22678c2017Sbeveloper
23a9cf57cfSAxel Dörfler
24a9cf57cfSAxel Dörflerclass MixerInput {
25a9cf57cfSAxel Dörflerpublic:
26a9cf57cfSAxel Dörfler								MixerInput(MixerCore* core,
27a9cf57cfSAxel Dörfler									const media_input& input,
28b006bbe1SStephan Aßmus									float mixFrameRate, int32 mixFrameCount);
29a9cf57cfSAxel Dörfler								~MixerInput();
30a9cf57cfSAxel Dörfler
31a9cf57cfSAxel Dörfler			int32				ID();
32a9cf57cfSAxel Dörfler			media_input&		MediaInput();
33a9cf57cfSAxel Dörfler
34b006bbe1SStephan Aßmus			void				BufferReceived(BBuffer* buffer);
35b006bbe1SStephan Aßmus
36b006bbe1SStephan Aßmus			void				UpdateResamplingAlgorithm();
37b006bbe1SStephan Aßmus
38a9cf57cfSAxel Dörfler	// The physical input channels
39a9cf57cfSAxel Dörfler			int					GetInputChannelCount();
40a9cf57cfSAxel Dörfler			int					GetInputChannelType(int channel);
41a9cf57cfSAxel Dörfler			void				SetInputChannelGain(int channel, float gain);
42a9cf57cfSAxel Dörfler			float				GetInputChannelGain(int channel);
43a9cf57cfSAxel Dörfler
44a9cf57cfSAxel Dörfler	// 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);
51a9cf57cfSAxel Dörfler			int 				GetInputChannelForDestination(
52a9cf57cfSAxel Dörfler									int destinationType);
53a9cf57cfSAxel Dörfler				// returns -1 if not found
54a9cf57cfSAxel Dörfler
55a9cf57cfSAxel Dörfler	// The virtual mixer channels that are generated from destinations
56a9cf57cfSAxel Dörfler			int					GetMixerChannelCount();
57a9cf57cfSAxel Dörfler			void				SetMixerChannelGain(int mixerChannel,
58a9cf57cfSAxel Dörfler									float gain);
59a9cf57cfSAxel Dörfler			float				GetMixerChannelGain(int mixerChannel);
60a9cf57cfSAxel Dörfler			int					GetMixerChannelType(int mixerChannel);
61a9cf57cfSAxel Dörfler
62a9cf57cfSAxel Dörfler			void				SetEnabled(bool enabled);
63a9cf57cfSAxel Dörfler			bool				IsEnabled();
64a9cf57cfSAxel Dörfler
65a9cf57cfSAxel Dörfler	// 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);
71a9cf57cfSAxel Dörfler
72a9cf57cfSAxel Dörflerprotected:
73a9cf57cfSAxel Dörfler	friend class MixerCore;
74a9cf57cfSAxel Dörfler
75a9cf57cfSAxel Dörfler			void				SetMixBufferFormat(int32 framerate,
76a9cf57cfSAxel Dörfler									int32 frames);
77a9cf57cfSAxel Dörfler
78a9cf57cfSAxel Dörflerprivate:
79b006bbe1SStephan Aßmus			void				_UpdateInputChannelDestinationMask();
80b006bbe1SStephan Aßmus			void				_UpdateInputChannelDestinations();
81a9cf57cfSAxel Dörfler
82a9cf57cfSAxel Dörfler	struct input_chan_info {
83a9cf57cfSAxel Dörfler		float*					buffer_base;
84a9cf57cfSAxel Dörfler		uint32					destination_mask;	// multiple or no bits sets
85a9cf57cfSAxel Dörfler		float					gain;
86a9cf57cfSAxel Dörfler	};
87a9cf57cfSAxel Dörfler
88a9cf57cfSAxel Dörfler	struct mixer_chan_info {
89a9cf57cfSAxel Dörfler		float*					buffer_base;
90a9cf57cfSAxel Dörfler		int						destination_type;
91a9cf57cfSAxel Dörfler		float					destination_gain;
92a9cf57cfSAxel Dörfler	};
93a9cf57cfSAxel Dörfler
94a9cf57cfSAxel Dörflerprivate:
95a9cf57cfSAxel Dörfler			MixerCore*			fCore;
96a9cf57cfSAxel Dörfler			media_input			fInput;
97a9cf57cfSAxel Dörfler			ByteSwap*			fInputByteSwap;
98a9cf57cfSAxel Dörfler			float				fChannelTypeGain[MAX_CHANNEL_TYPES];
99a9cf57cfSAxel Dörfler			bool				fEnabled;
100a9cf57cfSAxel Dörfler			input_chan_info*	fInputChannelInfo; // array
101a9cf57cfSAxel Dörfler			int					fInputChannelCount;
102a9cf57cfSAxel Dörfler			uint32				fInputChannelMask;
103a9cf57cfSAxel Dörfler			mixer_chan_info*	fMixerChannelInfo; // array
104a9cf57cfSAxel Dörfler			int					fMixerChannelCount;
105a9cf57cfSAxel Dörfler			float*				fMixBuffer;
106a9cf57cfSAxel Dörfler			int32				fMixBufferFrameRate;
107a9cf57cfSAxel Dörfler			int					fMixBufferFrameCount;
108a9cf57cfSAxel Dörfler			int32				fLastDataFrameWritten;
109a9cf57cfSAxel Dörfler			bigtime_t			fLastDataAvailableTime;
110a9cf57cfSAxel Dörfler			double				fFractionalFrames;
111a9cf57cfSAxel Dörfler			Resampler**			fResampler; // array
112a9cf57cfSAxel Dörfler			rtm_pool*			fRtmPool;
113a9cf57cfSAxel Dörfler			bool				fUserOverridesChannelDestinations;
114a9cf57cfSAxel Dörfler			int32				fDebugMixBufferFrames;
115678c2017Sbeveloper};
116678c2017Sbeveloper
117a9cf57cfSAxel Dörfler
118d91580cdSbeveloperinline int
1199c3be6a5SbeveloperMixerInput::GetMixerChannelCount()
1209c3be6a5Sbeveloper{
1219c3be6a5Sbeveloper	return fMixerChannelCount;
1229c3be6a5Sbeveloper}
1239c3be6a5Sbeveloper
124a9cf57cfSAxel Dörfler
125af8d0a4dSbeveloperinline bool
1260960b6d0SStephan AßmusMixerInput::GetMixerChannelInfo(int mixerChannel, int64 framepos,
1270960b6d0SStephan Aßmus	bigtime_t time, const float** buffer, uint32* sampleOffset, int* type,
1280960b6d0SStephan Aßmus	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) {
143a6e0f877SStephan Aßmus			ERROR("MixerInput::GetMixerChannelInfo: reading wrong data, have %Ld "
144a6e0f877SStephan Aßmus				"to %Ld, reading from %Ld to %Ld\n",
145a6e0f877SStephan Aßmus				fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate,
146a6e0f877SStephan Aßmus					fMixBufferFrameCount), fLastDataAvailableTime, time,
147a6e0f877SStephan Aßmus				time + duration_for_frames(fMixBufferFrameRate,
148a6e0f877SStephan Aßmus				fDebugMixBufferFrames));
149a6e0f877SStephan Aßmus		}
1500960b6d0SStephan Aßmus	}
151f91503b9Sbeveloper#endif
152f91503b9Sbeveloper
153f91503b9Sbeveloper	if (time > fLastDataAvailableTime)
154af8d0a4dSbeveloper		return false;
155a9cf57cfSAxel Dörfler
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