#include #include #include 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