#ifndef REVERB_H #define REVERB_H #include #include #include #include #include template class Delay { dsp::BufferMulti m_buf; int m_delay_spec[numCh]; uint m_delaySize; public: Delay(uint delayCapacity, int delayOffset) : m_buf(delayCapacity) { setDelay(delayCapacity, delayOffset); } void setDelay(uint delaySize, int delayOffset) { float delayRagePerWindow = (float)(delaySize-delayOffset)/(float)numCh; if (delayRagePerWindow < 0) { return; } // 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; } m_delaySize = delaySize; } uint getDelay() { return m_delaySize; } 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, 0) { // 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; } } } void setDelay(uint delay) { m_dly.setDelay(delay, 0); } uint getDelay() { return m_dly.getDelay(); } 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]; } // In-place inline void process_multi(T in_out[numCh]) { m_dly.process(in_out); Shuffle::inPlace(in_out, m_shuffle_spec); Hadamard::inPlace(in_out); } // Out-of-place inline void process_multi(T in[numCh], T out[numCh]) { m_dly.process(in); Shuffle::outOfPlace(in, out, m_shuffle_spec); Hadamard::inPlace(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_maxDelay, uint fb_minDelay) : m_diffusors(maxDelay) , m_feedbackDly(fb_maxDelay, fb_minDelay) , fb_gain(0) { for (int c=0; c < numCh; c++) { fb_dly_out[c] = 0; } } void setDelay(uint delay, uint index) { m_diffusors[index].setDelay(delay); } uint getDelay(uint index) { return m_diffusors[index].getDelay(); } void setFeedbackGain(T value) { fb_gain = value; } T getFeedbackGain() { return fb_gain; } void setFeedbackDelay(uint delay_min, uint delay_max) { m_feedbackDly.setDelay(delay_max, delay_min); } 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 for (int c=0; c < numCh; c++) { out[i] += fb_dly_out[c]; } } } 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