82 lines
3.0 KiB
C++
82 lines
3.0 KiB
C++
#include"Reberation.h"
|
|
#include<assert.h>
|
|
|
|
Reberation::Reberation(int p_block_size, int p_sampling_rate, float p_reberation_time)
|
|
: m_block_size(p_block_size),
|
|
m_reberation_output_read_pos(0) {
|
|
RenderImpulseResponse(p_block_size, p_sampling_rate, p_reberation_time);
|
|
|
|
m_left_reberation_filter = new FFTFilter(m_block_size);
|
|
m_left_reberation_filter->SetTimeDomainKernel(GetImpulseResponseLeft());
|
|
m_right_reberation_filter = new FFTFilter(m_block_size);
|
|
m_right_reberation_filter->SetTimeDomainKernel(GetImpulseResponseRight());
|
|
|
|
m_reberation_input.reserve(m_block_size);
|
|
m_reberation_output_left.resize(m_block_size, 0.0f);
|
|
m_reberation_output_right.resize(m_block_size, 0.0f);
|
|
}
|
|
|
|
Reberation::~Reberation()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
void Reberation::RenderImpulseResponse(int p_block_size, int p_sampling_rate, float p_reberation_time)
|
|
{
|
|
m_impulse_response_left.resize(p_block_size, 0.0f);
|
|
m_impulse_response_right.resize(p_block_size, 0.0f);
|
|
|
|
int quiet_period = p_block_size; // filter_delay = block_size
|
|
m_quiet_period_sec = static_cast<float>(quiet_period) / static_cast<float>(p_sampling_rate);
|
|
const float exp_decay = -13.8155;
|
|
|
|
srand(0);
|
|
for (int i = 0; i < p_block_size; ++i) {
|
|
float envelope = exp(exp_decay * (i + quiet_period) / p_sampling_rate / p_reberation_time);
|
|
assert(envelope >= 0 && envelope <= 1.0);
|
|
m_impulse_response_left[i] = FloatRand() * envelope;
|
|
m_impulse_response_right[i] = FloatRand() * envelope;
|
|
}
|
|
}
|
|
|
|
float Reberation::GetQuietPeriod() const {
|
|
return m_quiet_period_sec;
|
|
}
|
|
|
|
|
|
void Reberation::AddReberation(const std::vector<float>& p_input, std::vector<float>* p_output_left, std::vector<float>* p_output_right)
|
|
{
|
|
assert(p_output_left && p_output_right);
|
|
assert(p_output_left->size() == p_output_right->size());
|
|
assert(p_input.size() == p_output_right->size());
|
|
|
|
for (int i = 0; i < p_input.size(); ++i) {
|
|
(*p_output_left)[i] += m_reberation_output_left[m_reberation_output_read_pos];
|
|
(*p_output_right)[i] += m_reberation_output_right[m_reberation_output_read_pos];
|
|
++m_reberation_output_read_pos;
|
|
}
|
|
m_reberation_input.insert(m_reberation_input.end(), p_input.begin(), p_input.end());
|
|
|
|
if (m_reberation_output_read_pos == m_block_size) {
|
|
m_left_reberation_filter->AddSignalBlock(m_reberation_input);
|
|
m_right_reberation_filter->AddSignalBlock(m_reberation_input);
|
|
m_reberation_input.clear();
|
|
m_left_reberation_filter->GetResult(&m_reberation_output_left);
|
|
m_right_reberation_filter->GetResult(&m_reberation_output_right);
|
|
m_reberation_output_read_pos = 0;
|
|
}
|
|
assert(m_reberation_output_read_pos < m_block_size);
|
|
}
|
|
|
|
float Reberation::FloatRand() {
|
|
return static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
|
|
}
|
|
|
|
const std::vector<float>& Reberation::GetImpulseResponseLeft() const {
|
|
return m_impulse_response_left;
|
|
}
|
|
|
|
const std::vector<float>& Reberation::GetImpulseResponseRight() const {
|
|
return m_impulse_response_right;
|
|
} |