#ifndef REVERB_H #define REVERB_H #include #include #include #include template class Delay { dsp::BufferMulti 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 class Diffusor { Delay 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::inPlace(temp, m_shuffle_spec); Hadamard::inPlace(temp); Householder::inPlace(temp); return temp[0]; } inline void process_multi(T in_out[numCh]) { m_dly.process(in_out); Shuffle::inPlace(in_out, m_shuffle_spec); Hadamard::inPlace(in_out); } }; template class Reverb { std::vector> m_diffusors; Delay m_feedbackDly; T fb_dly_out[numCh]; T fb_gain; public: Reverb(std::initializer_list> 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::split(in[i], temp); for (auto diffusor: m_diffusors) { diffusor.process_multi(temp); } // Sum Householder::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