boo/lib/audiodev/AudioMatrix.hpp

149 lines
4.0 KiB
C++
Raw Normal View History

2018-10-07 03:36:44 +00:00
#pragma once
2017-12-29 07:54:26 +00:00
#include <cfloat>
#include <climits>
#include <cstddef>
#include <cstdint>
#include "boo/audiodev/IAudioVoice.hpp"
2016-05-22 08:37:16 +00:00
#if __SSE__
#include <immintrin.h>
2016-05-22 08:37:16 +00:00
#endif
2018-12-08 05:17:51 +00:00
namespace boo {
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 > static_cast<float>(INT_MAX))
2018-12-08 05:17:51 +00:00
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__
2020-04-15 02:12:35 +00:00
alignas(16) __m128 q[2];
alignas(16) __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);
public:
2018-12-08 05:17:51 +00:00
AudioMatrixMono() { setDefaultMatrixCoefficients(AudioChannelSet::Stereo); }
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];
}
2018-12-08 05:17:51 +00:00
#endif
m_curSlewFrame = 0;
}
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;
}
};
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__
2020-04-15 02:12:35 +00:00
alignas(16) __m128 q[4];
alignas(16) __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);
public:
2018-12-08 05:17:51 +00:00
AudioMatrixStereo() { setDefaultMatrixCoefficients(AudioChannelSet::Stereo); }
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];
}
2018-12-08 05:17:51 +00:00
#endif
m_curSlewFrame = 0;
}
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);
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;
}
};
2018-12-08 05:17:51 +00:00
} // namespace boo