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