#ifndef _MIXER_INPUT_H
#define _MIXER_INPUT_H
#include <MediaNode.h>
#include <RealtimeAlloc.h>
#include "MixerCore.h"
#include "MixerDebug.h"
#include "MixerUtils.h"
class ByteSwap;
class Resampler;
class MixerInput {
public:
MixerInput(MixerCore* core,
const media_input& input,
float mixFrameRate, int32 mixFrameCount);
~MixerInput();
int32 ID();
media_input& MediaInput();
void BufferReceived(BBuffer* buffer);
void UpdateResamplingAlgorithm();
int GetInputChannelCount();
int GetInputChannelType(int channel);
void SetInputChannelGain(int channel, float gain);
float GetInputChannelGain(int channel);
void AddInputChannelDestination(int channel,
int destinationType);
void RemoveInputChannelDestination(int channel,
int destinationType);
bool HasInputChannelDestination(int channel,
int destinationType);
int GetInputChannelForDestination(
int destinationType);
int GetMixerChannelCount();
void SetMixerChannelGain(int mixerChannel,
float gain);
float GetMixerChannelGain(int mixerChannel);
int GetMixerChannelType(int mixerChannel);
void SetEnabled(bool enabled);
bool IsEnabled();
bool GetMixerChannelInfo(int mixerChannel,
int64 framepos, bigtime_t time,
const float** _buffer,
uint32* _sampleOffset, int* _type,
float* _gain);
protected:
friend class MixerCore;
void SetMixBufferFormat(int32 framerate,
int32 frames);
private:
void _UpdateInputChannelDestinationMask();
void _UpdateInputChannelDestinations();
struct input_chan_info {
float* buffer_base;
uint32 destination_mask;
float gain;
};
struct mixer_chan_info {
float* buffer_base;
int destination_type;
float destination_gain;
};
private:
MixerCore* fCore;
media_input fInput;
ByteSwap* fInputByteSwap;
float fChannelTypeGain[MAX_CHANNEL_TYPES];
bool fEnabled;
input_chan_info* fInputChannelInfo;
int fInputChannelCount;
uint32 fInputChannelMask;
mixer_chan_info* fMixerChannelInfo;
int fMixerChannelCount;
float* fMixBuffer;
int32 fMixBufferFrameRate;
int fMixBufferFrameCount;
int32 fLastDataFrameWritten;
bigtime_t fLastDataAvailableTime;
double fFractionalFrames;
Resampler** fResampler;
rtm_pool* fRtmPool;
bool fUserOverridesChannelDestinations;
int32 fDebugMixBufferFrames;
};
inline int
MixerInput::GetMixerChannelCount()
{
return fMixerChannelCount;
}
inline bool
MixerInput::GetMixerChannelInfo(int mixerChannel, int64 framepos,
bigtime_t time, const float** buffer, uint32* sampleOffset, int* type,
float* gain)
{
ASSERT(fMixBuffer != NULL);
ASSERT(mixerChannel >= 0 && mixerChannel < fMixerChannelCount);
if (!fEnabled)
return false;
#if DEBUG
if (time < (fLastDataAvailableTime - duration_for_frames(
fMixBufferFrameRate, fMixBufferFrameCount))
|| (time + duration_for_frames(fMixBufferFrameRate,
fDebugMixBufferFrames)) >= fLastDataAvailableTime) {
if (mixerChannel == 0) {
ERROR("MixerInput::GetMixerChannelInfo: reading wrong data, have %lld "
"to %lld, reading from %lld to %lld\n",
fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate,
fMixBufferFrameCount), fLastDataAvailableTime, time,
time + duration_for_frames(fMixBufferFrameRate,
fDebugMixBufferFrames));
}
}
#endif
if (time > fLastDataAvailableTime)
return false;
int32 offset = framepos % fMixBufferFrameCount;
if (mixerChannel == 0) {
PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset,
offset + fDebugMixBufferFrames - 1);
}
*buffer = reinterpret_cast<float*>(reinterpret_cast<char*>(
fMixerChannelInfo[mixerChannel].buffer_base)
+ (offset * sizeof(float) * fInputChannelCount));
*sampleOffset = sizeof(float) * fInputChannelCount;
*type = fMixerChannelInfo[mixerChannel].destination_type;
*gain = fMixerChannelInfo[mixerChannel].destination_gain;
return true;
}
#endif