2018-10-07 03:36:44 +00:00
|
|
|
#pragma once
|
2016-03-24 00:01:57 +00:00
|
|
|
|
|
|
|
#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-03-24 00:01:57 +00:00
|
|
|
|
2016-05-22 08:37:16 +00:00
|
|
|
#if __SSE__
|
2017-12-19 03:04:47 +00:00
|
|
|
#include <immintrin.h>
|
2016-05-22 08:37:16 +00:00
|
|
|
#endif
|
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
namespace boo {
|
2016-03-24 00:01:57 +00:00
|
|
|
struct AudioVoiceEngineMixInfo;
|
|
|
|
|
2018-12-08 05:17:51 +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;
|
2016-05-07 04:28:32 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
static inline int32_t Clamp32(float in) {
|
|
|
|
if (in < INT_MIN)
|
|
|
|
return INT_MIN;
|
|
|
|
else if (in > INT_MAX)
|
|
|
|
return INT_MAX;
|
|
|
|
return in;
|
2016-05-07 04:28:32 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
class AudioMatrixMono {
|
|
|
|
union Coefs {
|
|
|
|
float v[8];
|
2016-05-22 08:37:16 +00:00
|
|
|
#if __SSE__
|
2018-12-08 05:17:51 +00:00
|
|
|
__m128 q[2];
|
|
|
|
__m64 d[4];
|
2016-05-22 08:37:16 +00:00
|
|
|
#endif
|
2018-12-08 05:17:51 +00:00
|
|
|
};
|
|
|
|
Coefs m_coefs = {};
|
|
|
|
Coefs m_oldCoefs = {};
|
|
|
|
size_t m_slewFrames = 0;
|
|
|
|
size_t m_curSlewFrame = ~size_t(0);
|
|
|
|
|
2016-03-24 00:01:57 +00:00
|
|
|
public:
|
2018-12-08 05:17:51 +00:00
|
|
|
AudioMatrixMono() { setDefaultMatrixCoefficients(AudioChannelSet::Stereo); }
|
2016-03-24 00:01:57 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
void setDefaultMatrixCoefficients(AudioChannelSet acSet);
|
|
|
|
void setMatrixCoefficients(const float coefs[8], size_t slewFrames = 0) {
|
|
|
|
m_slewFrames = slewFrames;
|
2016-05-22 08:37:16 +00:00
|
|
|
#if __SSE__
|
2018-12-08 05:17:51 +00:00
|
|
|
if (m_curSlewFrame != 0) {
|
|
|
|
m_oldCoefs.q[0] = m_coefs.q[0];
|
|
|
|
m_oldCoefs.q[1] = m_coefs.q[1];
|
|
|
|
}
|
|
|
|
m_coefs.q[0] = _mm_loadu_ps(coefs);
|
|
|
|
m_coefs.q[1] = _mm_loadu_ps(&coefs[4]);
|
2016-05-22 08:37:16 +00:00
|
|
|
#else
|
2018-12-08 05:17:51 +00:00
|
|
|
for (int i = 0; i < 8; ++i) {
|
|
|
|
if (m_curSlewFrame != 0)
|
|
|
|
m_oldCoefs.v[i] = m_coefs.v[i];
|
|
|
|
m_coefs.v[i] = coefs[i];
|
2016-03-24 00:01:57 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
#endif
|
|
|
|
m_curSlewFrame = 0;
|
|
|
|
}
|
2016-03-24 00:01:57 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
int16_t* mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const int16_t* dataIn, int16_t* dataOut,
|
|
|
|
size_t samples);
|
|
|
|
int32_t* mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const int32_t* dataIn, int32_t* dataOut,
|
|
|
|
size_t samples);
|
|
|
|
float* mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const float* dataIn, float* dataOut, size_t samples);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2016-03-24 00:01:57 +00:00
|
|
|
};
|
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
class AudioMatrixStereo {
|
|
|
|
union Coefs {
|
|
|
|
float v[8][2];
|
2016-05-22 08:37:16 +00:00
|
|
|
#if __SSE__
|
2018-12-08 05:17:51 +00:00
|
|
|
__m128 q[4];
|
|
|
|
__m64 d[8];
|
2016-05-22 08:37:16 +00:00
|
|
|
#endif
|
2018-12-08 05:17:51 +00:00
|
|
|
};
|
|
|
|
Coefs m_coefs = {};
|
|
|
|
Coefs m_oldCoefs = {};
|
|
|
|
size_t m_slewFrames = 0;
|
|
|
|
size_t m_curSlewFrame = ~size_t(0);
|
|
|
|
|
2016-03-24 00:01:57 +00:00
|
|
|
public:
|
2018-12-08 05:17:51 +00:00
|
|
|
AudioMatrixStereo() { setDefaultMatrixCoefficients(AudioChannelSet::Stereo); }
|
2016-03-24 00:01:57 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
void setDefaultMatrixCoefficients(AudioChannelSet acSet);
|
|
|
|
void setMatrixCoefficients(const float coefs[8][2], size_t slewFrames = 0) {
|
|
|
|
m_slewFrames = slewFrames;
|
2016-05-22 08:37:16 +00:00
|
|
|
#if __SSE__
|
2018-12-08 05:17:51 +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];
|
|
|
|
}
|
|
|
|
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]);
|
2016-05-22 08:37:16 +00:00
|
|
|
#else
|
2018-12-08 05:17:51 +00:00
|
|
|
for (int i = 0; i < 8; ++i) {
|
|
|
|
if (m_curSlewFrame != 0) {
|
|
|
|
m_oldCoefs.v[i][0] = m_coefs.v[i][0];
|
|
|
|
m_oldCoefs.v[i][1] = m_coefs.v[i][1];
|
|
|
|
}
|
|
|
|
m_coefs.v[i][0] = coefs[i][0];
|
|
|
|
m_coefs.v[i][1] = coefs[i][1];
|
2016-03-24 00:01:57 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
#endif
|
|
|
|
m_curSlewFrame = 0;
|
|
|
|
}
|
2016-03-24 00:01:57 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
int16_t* mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const int16_t* dataIn, int16_t* dataOut,
|
|
|
|
size_t frames);
|
|
|
|
int32_t* mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const int32_t* dataIn, int32_t* dataOut,
|
|
|
|
size_t frames);
|
|
|
|
float* mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const float* dataIn, float* dataOut, size_t frames);
|
2016-03-24 00:01:57 +00:00
|
|
|
|
2018-12-08 05:17:51 +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;
|
|
|
|
}
|
|
|
|
};
|
2016-03-24 00:01:57 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
} // namespace boo
|