Files
dsp/reverb/reverb.hpp
T
jens 1d55f63a5e [Reverb]
- removed numSteps. NumSteps is determied by length of initializer_list
2025-11-10 10:48:21 +01:00

177 lines
3.1 KiB
C++

#ifndef REVERB_H
#define REVERB_H
#include <cstdlib>
#include <delay/buffer_multi.hpp>
#include <common/mix.hpp>
#include <initializer_list>
template<typename T, size_t numCh>
class Delay
{
dsp::BufferMulti<T, numCh> m_buf;
int m_delay_spec[numCh];
public:
Delay(uint maxDelaySize, int delayOffset=0)
: m_buf(maxDelaySize)
{
float delayRagePerWindow = (float)(maxDelaySize-delayOffset)/(float)numCh;
// Delay spec
for (int i=0; i < numCh; i++)
{
float base_delay = i*delayRagePerWindow + delayOffset;
float z = (float)rand()/(float)RAND_MAX;
int delay = (int)(base_delay + z*delayRagePerWindow);
m_delay_spec[i] = -delay;
}
}
void process(T in, T out[numCh])
{
m_buf = in;
m_buf.quer(out, m_delay_spec);
++m_buf;
}
void process(T data[numCh])
{
m_buf = data;
m_buf.quer(data, m_delay_spec);
++m_buf;
}
void process(T in[numCh], T out[numCh])
{
m_buf = in;
m_buf.quer(out, m_delay_spec);
++m_buf;
}
};
template<typename T, size_t numCh>
class Diffusor
{
Delay<T, numCh> m_dly;
int m_shuffle_spec[numCh];
public:
Diffusor(uint maxDelaySize)
: m_dly(maxDelaySize)
{
// Shuffle spec
for (int i=0; i < numCh; i++)
{
m_shuffle_spec[i] = i;
}
// Shuffle values
for (int i=0; i < 2*numCh; i++)
{
int i1 = rand() & (numCh-1);
int i2 = rand() & (numCh-1);
int temp = m_shuffle_spec[i1];
m_shuffle_spec[i1] = m_shuffle_spec[i2];
m_shuffle_spec[i2] = temp;
}
// Shuffle signs
float p = 0.3;
for (int i=0; i < numCh; i++)
{
float z = (float)rand()/(float)RAND_MAX;
if (z <= p)
{
m_shuffle_spec[i] *= (T)-1;
}
}
}
inline T process(T in)
{
T temp[numCh];
m_dly.process(in, temp);
Shuffle<T, numCh>::inPlace(temp, m_shuffle_spec);
Hadamard<T, numCh>::inPlace(temp);
Householder<T, numCh>::inPlace(temp);
return temp[0];
}
inline void process_multi(T in_out[numCh])
{
m_dly.process(in_out);
Shuffle<T, numCh>::inPlace(in_out, m_shuffle_spec);
Hadamard<T, numCh>::inPlace(in_out);
}
};
template<typename T, uint numCh>
class Reverb
{
std::vector<Diffusor<T, numCh>> m_diffusors;
Delay<T, numCh> m_feedbackDly;
T fb_dly_out[numCh];
T fb_gain;
public:
Reverb(std::initializer_list<Diffusor<T, numCh>> maxDelay, uint fb_dly_min, uint fb_dly_max)
: m_diffusors(maxDelay)
, m_feedbackDly(fb_dly_max, fb_dly_min)
, fb_gain(0)
{
for (int c=0; c < numCh; c++)
{
fb_dly_out[c] = 0;
}
}
void setFeedbackGain(T value)
{
fb_gain = value;
}
void process_multi(float *in, float *out, unsigned numPoints)
{
for (int i=0; i < numPoints; i++)
{
T temp[numCh];
Mix<T, numCh>::split(in[i], temp);
for (auto diffusor: m_diffusors)
{
diffusor.process_multi(temp);
}
// Sum
Householder<T, numCh>::inPlace(fb_dly_out);
for (int c=0; c < numCh; c++)
{
temp[c] += fb_gain*fb_dly_out[c];
}
m_feedbackDly.process(temp, fb_dly_out);
// Mix
out[i] = fb_dly_out[0];
}
}
void process(float *in, float *out, unsigned numPoints)
{
for (int i=0; i < numPoints; i++)
{
T temp = in[i];
for (auto diffusor: m_diffusors)
{
temp = diffusor.process(temp);
}
out[i] = temp;
}
}
};
#endif