boo/lib/audiodev/AudioMatrix.hpp

165 lines
4.4 KiB
C++
Raw Normal View History

2018-10-07 03:36:44 +00:00
#pragma once
#include "boo/audiodev/IAudioVoice.hpp"
#include <vector>
2017-12-29 07:54:26 +00:00
#include <cstdint>
2016-05-07 04:28:32 +00:00
#include <limits.h>
2017-12-29 07:54:26 +00:00
#include <cfloat>
2016-05-22 08:37:16 +00:00
#if __SSE__
#include <immintrin.h>
2016-05-22 08:37:16 +00:00
#endif
namespace boo
{
struct AudioVoiceEngineMixInfo;
2016-05-07 04:28:32 +00:00
static inline int16_t Clamp16(float in)
{
if (in < SHRT_MIN)
return SHRT_MIN;
else if (in > SHRT_MAX)
return SHRT_MAX;
return in;
}
static inline int32_t Clamp32(float in)
{
if (in < INT_MIN)
return INT_MIN;
else if (in > INT_MAX)
return INT_MAX;
return in;
}
class AudioMatrixMono
{
2016-05-22 08:37:16 +00:00
union Coefs
{
float v[8];
#if __SSE__
__m128 q[2];
__m64 d[4];
#endif
};
Coefs m_coefs = {};
Coefs m_oldCoefs = {};
2016-05-21 21:45:55 +00:00
size_t m_slewFrames = 0;
2018-09-03 00:44:38 +00:00
size_t m_curSlewFrame = ~size_t(0);
public:
AudioMatrixMono() {setDefaultMatrixCoefficients(AudioChannelSet::Stereo);}
void setDefaultMatrixCoefficients(AudioChannelSet acSet);
2016-05-21 21:45:55 +00:00
void setMatrixCoefficients(const float coefs[8], size_t slewFrames=0)
{
2016-05-21 21:45:55 +00:00
m_slewFrames = slewFrames;
2016-05-22 08:37:16 +00:00
#if __SSE__
2018-09-03 00:44:38 +00:00
if (m_curSlewFrame != 0)
{
m_oldCoefs.q[0] = m_coefs.q[0];
m_oldCoefs.q[1] = m_coefs.q[1];
}
2016-05-22 08:37:16 +00:00
m_coefs.q[0] = _mm_loadu_ps(coefs);
m_coefs.q[1] = _mm_loadu_ps(&coefs[4]);
#else
for (int i=0 ; i<8 ; ++i)
2016-05-21 21:45:55 +00:00
{
2018-09-03 00:44:38 +00:00
if (m_curSlewFrame != 0)
m_oldCoefs.v[i] = m_coefs.v[i];
2016-05-22 08:37:16 +00:00
m_coefs.v[i] = coefs[i];
2016-05-21 21:45:55 +00:00
}
2016-05-22 08:37:16 +00:00
#endif
2018-09-03 00:44:38 +00:00
m_curSlewFrame = 0;
}
int16_t* mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
2016-05-21 21:45:55 +00:00
const int16_t* dataIn, int16_t* dataOut, size_t samples);
int32_t* mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
2016-05-21 21:45:55 +00:00
const int32_t* dataIn, int32_t* dataOut, size_t samples);
float* mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
2016-05-21 21:45:55 +00:00
const float* dataIn, float* dataOut, size_t samples);
2017-11-28 03:38:02 +00:00
bool isSilent() const
{
if (m_curSlewFrame < m_slewFrames)
for (int i=0 ; i<8 ; ++i)
if (m_oldCoefs.v[i] > FLT_EPSILON)
return false;
for (int i=0 ; i<8 ; ++i)
if (m_coefs.v[i] > FLT_EPSILON)
return false;
return true;
}
};
class AudioMatrixStereo
{
2016-05-22 08:37:16 +00:00
union Coefs
{
float v[8][2];
#if __SSE__
__m128 q[4];
__m64 d[8];
#endif
};
Coefs m_coefs = {};
Coefs m_oldCoefs = {};
2016-05-21 21:45:55 +00:00
size_t m_slewFrames = 0;
2018-09-03 00:44:38 +00:00
size_t m_curSlewFrame = ~size_t(0);
public:
AudioMatrixStereo() {setDefaultMatrixCoefficients(AudioChannelSet::Stereo);}
void setDefaultMatrixCoefficients(AudioChannelSet acSet);
2016-05-21 21:45:55 +00:00
void setMatrixCoefficients(const float coefs[8][2], size_t slewFrames=0)
{
2016-05-21 21:45:55 +00:00
m_slewFrames = slewFrames;
2016-05-22 08:37:16 +00:00
#if __SSE__
2018-09-03 00:44:38 +00:00
if (m_curSlewFrame != 0)
{
m_oldCoefs.q[0] = m_coefs.q[0];
m_oldCoefs.q[1] = m_coefs.q[1];
m_oldCoefs.q[2] = m_coefs.q[2];
m_oldCoefs.q[3] = m_coefs.q[3];
}
2016-05-22 08:37:16 +00:00
m_coefs.q[0] = _mm_loadu_ps(coefs[0]);
m_coefs.q[1] = _mm_loadu_ps(coefs[2]);
m_coefs.q[2] = _mm_loadu_ps(coefs[4]);
m_coefs.q[3] = _mm_loadu_ps(coefs[6]);
#else
for (int i=0 ; i<8 ; ++i)
{
2018-09-03 00:44:38 +00:00
if (m_curSlewFrame != 0)
{
m_oldCoefs.v[i][0] = m_coefs.v[i][0];
m_oldCoefs.v[i][1] = m_coefs.v[i][1];
}
2018-10-07 02:49:22 +00:00
m_coefs.v[i][0] = coefs[i][0];
m_coefs.v[i][1] = coefs[i][1];
}
2016-05-22 08:37:16 +00:00
#endif
2018-09-03 00:44:38 +00:00
m_curSlewFrame = 0;
}
int16_t* mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
2016-05-21 21:45:55 +00:00
const int16_t* dataIn, int16_t* dataOut, size_t frames);
int32_t* mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
2016-05-21 21:45:55 +00:00
const int32_t* dataIn, int32_t* dataOut, size_t frames);
float* mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
2016-05-21 21:45:55 +00:00
const float* dataIn, float* dataOut, size_t frames);
2017-11-28 03:38:02 +00:00
bool isSilent() const
{
if (m_curSlewFrame < m_slewFrames)
for (int i=0 ; i<8 ; ++i)
if (m_oldCoefs.v[i][0] > FLT_EPSILON || m_oldCoefs.v[i][1] > FLT_EPSILON)
return false;
for (int i=0 ; i<8 ; ++i)
if (m_coefs.v[i][0] > FLT_EPSILON || m_coefs.v[i][1] > FLT_EPSILON)
return false;
return true;
}
};
}