124 lines
3.6 KiB
C++
124 lines
3.6 KiB
C++
|
|
#include <XCEngine/Audio/Reverbation.h>
|
||
|
|
#include <algorithm>
|
||
|
|
#include <cstring>
|
||
|
|
|
||
|
|
namespace XCEngine {
|
||
|
|
namespace Audio {
|
||
|
|
|
||
|
|
static const uint32 CombTuning[] = { 1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 };
|
||
|
|
static const uint32 AllPassTuning[] = { 556, 441, 341, 225 };
|
||
|
|
|
||
|
|
Reverbation::Reverbation()
|
||
|
|
: m_sampleRate(48000)
|
||
|
|
{
|
||
|
|
for (uint32 i = 0; i < CombCount; ++i) {
|
||
|
|
m_combFilters[i].bufferSize = CombTuning[i];
|
||
|
|
m_combFilters[i].buffer.resize(m_combFilters[i].bufferSize, 0.0f);
|
||
|
|
m_combFilters[i].writeIndex = 0;
|
||
|
|
m_combFilters[i].feedback = 0.0f;
|
||
|
|
m_combFilters[i].damp1 = 0.0f;
|
||
|
|
m_combFilters[i].damp2 = 0.0f;
|
||
|
|
m_combFilters[i].filterStore = 0.0f;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (uint32 i = 0; i < AllPassCount; ++i) {
|
||
|
|
m_allPassFilters[i].bufferSize = AllPassTuning[i];
|
||
|
|
m_allPassFilters[i].buffer.resize(m_allPassFilters[i].bufferSize, 0.0f);
|
||
|
|
m_allPassFilters[i].writeIndex = 0;
|
||
|
|
m_allPassFilters[i].feedback = 0.5f;
|
||
|
|
}
|
||
|
|
|
||
|
|
SetRoomSize(0.5f);
|
||
|
|
SetDamping(0.5f);
|
||
|
|
}
|
||
|
|
|
||
|
|
Reverbation::~Reverbation() {
|
||
|
|
}
|
||
|
|
|
||
|
|
void Reverbation::ProcessAudio(float* buffer, uint32 sampleCount, uint32 channels) {
|
||
|
|
if (!m_enabled || buffer == nullptr || sampleCount == 0) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (channels == 0) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (uint32 i = 0; i < sampleCount; ++i) {
|
||
|
|
float input = buffer[i * channels];
|
||
|
|
|
||
|
|
float wet = 0.0f;
|
||
|
|
|
||
|
|
for (uint32 c = 0; c < CombCount; ++c) {
|
||
|
|
float output = m_combFilters[c].buffer[m_combFilters[c].writeIndex];
|
||
|
|
|
||
|
|
m_combFilters[c].filterStore = output * m_combFilters[c].damp2 + m_combFilters[c].filterStore * m_combFilters[c].damp1;
|
||
|
|
|
||
|
|
m_combFilters[c].buffer[m_combFilters[c].writeIndex] = input + m_combFilters[c].filterStore * m_combFilters[c].feedback;
|
||
|
|
|
||
|
|
m_combFilters[c].writeIndex++;
|
||
|
|
if (m_combFilters[c].writeIndex >= m_combFilters[c].bufferSize) {
|
||
|
|
m_combFilters[c].writeIndex = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
wet += output;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (uint32 a = 0; a < AllPassCount; ++a) {
|
||
|
|
float output = m_allPassFilters[a].buffer[m_allPassFilters[a].writeIndex];
|
||
|
|
float temp = output;
|
||
|
|
|
||
|
|
m_allPassFilters[a].buffer[m_allPassFilters[a].writeIndex] = wet + output * m_allPassFilters[a].feedback;
|
||
|
|
|
||
|
|
wet = -wet + output;
|
||
|
|
wet += temp;
|
||
|
|
|
||
|
|
m_allPassFilters[a].writeIndex++;
|
||
|
|
if (m_allPassFilters[a].writeIndex >= m_allPassFilters[a].bufferSize) {
|
||
|
|
m_allPassFilters[a].writeIndex = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
float outSample = input * m_dryMix + wet * m_wetMix;
|
||
|
|
|
||
|
|
for (uint32 ch = 0; ch < channels; ++ch) {
|
||
|
|
buffer[i * channels + ch] = outSample;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Reverbation::SetRoomSize(float size) {
|
||
|
|
m_roomSize = std::max(0.0f, std::min(1.0f, size));
|
||
|
|
float roomScale = 0.28f + 0.7f * m_roomSize;
|
||
|
|
for (uint32 i = 0; i < CombCount; ++i) {
|
||
|
|
m_combFilters[i].feedback = roomScale;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Reverbation::SetDamping(float damping) {
|
||
|
|
m_damping = std::max(0.0f, std::min(1.0f, damping));
|
||
|
|
for (uint32 i = 0; i < CombCount; ++i) {
|
||
|
|
m_combFilters[i].damp1 = m_damping * 0.4f;
|
||
|
|
m_combFilters[i].damp2 = 1.0f - m_damping * 0.4f;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Reverbation::SetWetMix(float wetMix) {
|
||
|
|
m_wetMix = std::max(0.0f, std::min(1.0f, wetMix));
|
||
|
|
}
|
||
|
|
|
||
|
|
void Reverbation::SetDryMix(float dryMix) {
|
||
|
|
m_dryMix = std::max(0.0f, std::min(1.0f, dryMix));
|
||
|
|
}
|
||
|
|
|
||
|
|
void Reverbation::SetWidth(float width) {
|
||
|
|
m_width = std::max(0.0f, std::min(1.0f, width));
|
||
|
|
}
|
||
|
|
|
||
|
|
void Reverbation::SetFreeze(bool freeze) {
|
||
|
|
m_freeze = freeze;
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace Audio
|
||
|
|
} // namespace XCEngine
|