diff options
-rw-r--r-- | muse/synti/organ/reverb.cpp | 165 | ||||
-rw-r--r-- | muse/synti/organ/reverb.h | 208 |
2 files changed, 373 insertions, 0 deletions
diff --git a/muse/synti/organ/reverb.cpp b/muse/synti/organ/reverb.cpp new file mode 100644 index 00000000..975c8289 --- /dev/null +++ b/muse/synti/organ/reverb.cpp @@ -0,0 +1,165 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// based on "freeverb" written by Jezar at Dreampoint, +// June 2000 +// +// (C) Copyright 2007 Werner Schweer (ws@seh.de) +//========================================================= + +#include "reverb.h" + +//--------------------------------------------------------- +// Reverb +//--------------------------------------------------------- + +Reverb::Reverb() + { + // Tie the components to their buffers + combL[0].setbuffer(bufcombL1,combtuningL1); + combR[0].setbuffer(bufcombR1,combtuningR1); + combL[1].setbuffer(bufcombL2,combtuningL2); + combR[1].setbuffer(bufcombR2,combtuningR2); + combL[2].setbuffer(bufcombL3,combtuningL3); + combR[2].setbuffer(bufcombR3,combtuningR3); + combL[3].setbuffer(bufcombL4,combtuningL4); + combR[3].setbuffer(bufcombR4,combtuningR4); + combL[4].setbuffer(bufcombL5,combtuningL5); + combR[4].setbuffer(bufcombR5,combtuningR5); + combL[5].setbuffer(bufcombL6,combtuningL6); + combR[5].setbuffer(bufcombR6,combtuningR6); + combL[6].setbuffer(bufcombL7,combtuningL7); + combR[6].setbuffer(bufcombR7,combtuningR7); + combL[7].setbuffer(bufcombL8,combtuningL8); + combR[7].setbuffer(bufcombR8,combtuningR8); + allpassL[0].setbuffer(bufallpassL1,allpasstuningL1); + allpassR[0].setbuffer(bufallpassR1,allpasstuningR1); + allpassL[1].setbuffer(bufallpassL2,allpasstuningL2); + allpassR[1].setbuffer(bufallpassR2,allpasstuningR2); + allpassL[2].setbuffer(bufallpassL3,allpasstuningL3); + allpassR[2].setbuffer(bufallpassR3,allpasstuningR3); + allpassL[3].setbuffer(bufallpassL4,allpasstuningL4); + allpassR[3].setbuffer(bufallpassR4,allpasstuningR4); + + // Set default values + allpassL[0].setfeedback(0.5f); + allpassR[0].setfeedback(0.5f); + allpassL[1].setfeedback(0.5f); + allpassR[1].setfeedback(0.5f); + allpassL[2].setfeedback(0.5f); + allpassR[2].setfeedback(0.5f); + allpassL[3].setfeedback(0.5f); + allpassR[3].setfeedback(0.5f); + + setRoomSize(.5); + setMix(.5); + setdamp(.5); + setwidth(initialwidth); + + // Buffer will be full of rubbish - so we MUST mute them + + for (int i = 0; i < numcombs; i++) { + combL[i].mute(); + combR[i].mute(); + } + for (int i=0;i<numallpasses;i++) { + allpassL[i].mute(); + allpassR[i].mute(); + } + } + +//--------------------------------------------------------- +// update +// Recalculate internal values after parameter change +//--------------------------------------------------------- + +void Reverb::update() + { + roomsize1 = roomsize; + damp1 = damp; + gain = fixedgain; + + for (int i = 0; i < numcombs; i++) { + combL[i].setfeedback(roomsize1); + combR[i].setfeedback(roomsize1); + } + + for (int i = 0; i < numcombs; i++) { + combL[i].setdamp(damp1); + combR[i].setdamp(damp1); + } + } + +//--------------------------------------------------------- +// setroomsize +//--------------------------------------------------------- + +void Reverb::setRoomSize(float value) + { + roomsize = (value*scaleroom) + offsetroom; + update(); + } + +//--------------------------------------------------------- +// setdamp +//--------------------------------------------------------- + +void Reverb::setdamp(float value) + { + damp = value*scaledamp; + update(); + } + +//--------------------------------------------------------- +// setwidth +//--------------------------------------------------------- + +void Reverb::setwidth(float value) + { + width = value; + update(); + } + +//--------------------------------------------------------- +// setMix +//--------------------------------------------------------- + +void Reverb::setMix(float value) + { + wetLevel = value; + } + +//--------------------------------------------------------- +// process +//--------------------------------------------------------- + +void Reverb::process(float* l, float* r, int n) + { + float wet = (1.0f - wetLevel) * scalewet; + float dry = wetLevel * scaledry; + float wet1 = wet * (width/2 + 0.5f); + float wet2 = wet * ((1-width)/2); + + for (int i = 0; i < n; ++i) { + float outL = 0; + float outR = 0; + float input = l[i] * gain; + + // Accumulate comb filters in parallel + for (int k = 0; k < numcombs; k++) { + outL += combL[k].process(input); + outR += combR[k].process(input); + } + + // Feed through allpasses in series + for (int k = 0; k < numallpasses; k++) { + outL = allpassL[k].process(outL); + outR = allpassR[k].process(outR); + } + l[i] = outL * wet1 + outR * wet2 + l[i] * dry; + r[i] = outR * wet1 + outL * wet2 + l[i] * dry; + } + } + diff --git a/muse/synti/organ/reverb.h b/muse/synti/organ/reverb.h new file mode 100644 index 00000000..10ba239e --- /dev/null +++ b/muse/synti/organ/reverb.h @@ -0,0 +1,208 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// based on "freeverb" written by Jezar at Dreampoint, +// June 2000 +// +// (C) Copyright 2007 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __REVERB_H__ +#define __REVERB_H__ + +#define undenormalise(sample) \ + do { \ + volatile float __forced_float = 1e-29 + sample; \ + sample = __forced_float - 1e-29; \ + } while (0) + +const int numcombs = 8; +const int numallpasses = 4; +const float muted = 0; +const float fixedgain = 0.015f; +const float scalewet = 3; +const float scaledry = 2; +const float scaledamp = 0.4f; +const float scaleroom = 0.28f; +const float offsetroom = 0.7f; +const float initialwet = 1/scalewet; +const float initialdry = 0.0; +const float initialwidth = 1.0; +const int stereospread = 23; + +// These values assume 44.1KHz sample rate +// they will probably be OK for 48KHz sample rate +// but would need scaling for 96KHz (or other) sample rates. +// The values were obtained by listening tests. +const int combtuningL1 = 1116; +const int combtuningR1 = 1116+stereospread; +const int combtuningL2 = 1188; +const int combtuningR2 = 1188+stereospread; +const int combtuningL3 = 1277; +const int combtuningR3 = 1277+stereospread; +const int combtuningL4 = 1356; +const int combtuningR4 = 1356+stereospread; +const int combtuningL5 = 1422; +const int combtuningR5 = 1422+stereospread; +const int combtuningL6 = 1491; +const int combtuningR6 = 1491+stereospread; +const int combtuningL7 = 1557; +const int combtuningR7 = 1557+stereospread; +const int combtuningL8 = 1617; +const int combtuningR8 = 1617+stereospread; +const int allpasstuningL1 = 556; +const int allpasstuningR1 = 556+stereospread; +const int allpasstuningL2 = 441; +const int allpasstuningR2 = 441+stereospread; +const int allpasstuningL3 = 341; +const int allpasstuningR3 = 341+stereospread; +const int allpasstuningL4 = 225; +const int allpasstuningR4 = 225+stereospread; + +//--------------------------------------------------------- +// allpass +//--------------------------------------------------------- + +class allpass + { + float feedback; + float *buffer; + int bufsize; + int bufidx; + + public: + allpass() { bufidx = 0; } + void setbuffer(float *buf, int size) { + buffer = buf; + bufsize = size; + } + float process(float input) { + float bufout = buffer[bufidx]; + undenormalise(bufout); + float output = -input + bufout; + buffer[bufidx] = input + (bufout*feedback); + if (++bufidx >= bufsize) + bufidx = 0; + return output; + } + void mute() { + memset(buffer, 0, sizeof(float) * bufsize); + } + void setfeedback(float val) { feedback = val; } + float getfeedback() { return feedback; } + }; + +//--------------------------------------------------------- +// comb +//--------------------------------------------------------- + +class comb + { + float feedback; + float filterstore; + float damp1; + float damp2; + float *buffer; + int bufsize; + int bufidx; + + public: + comb() { + filterstore = 0; + bufidx = 0; + } + void setbuffer(float *buf, int size) { + buffer = buf; + bufsize = size; + } + float process(float input) { + float output = buffer[bufidx]; + undenormalise(output); + filterstore = (output*damp2) + (filterstore*damp1); + undenormalise(filterstore); + buffer[bufidx] = input + (filterstore*feedback); + if (++bufidx >= bufsize) + bufidx = 0; + return output; + } + void mute() { + for (int i=0; i<bufsize; i++) + buffer[i]=0; + } + void setdamp(float val) { + damp1 = val; + damp2 = 1-val; + } + float getdamp() { return damp1; } + void setfeedback(float val) { feedback = val; } + float getfeedback() { return feedback; } + }; + + +//--------------------------------------------------------- +// Reverb +//--------------------------------------------------------- + +class Reverb { + float gain; + float roomsize,roomsize1; + float damp,damp1; + float width; + float mode; + + // Comb filters + comb combL[numcombs]; + comb combR[numcombs]; + + // Allpass filters + allpass allpassL[numallpasses]; + allpass allpassR[numallpasses]; + + // Buffers for the combs + float bufcombL1[combtuningL1]; + float bufcombR1[combtuningR1]; + float bufcombL2[combtuningL2]; + float bufcombR2[combtuningR2]; + float bufcombL3[combtuningL3]; + float bufcombR3[combtuningR3]; + float bufcombL4[combtuningL4]; + float bufcombR4[combtuningR4]; + float bufcombL5[combtuningL5]; + float bufcombR5[combtuningR5]; + float bufcombL6[combtuningL6]; + float bufcombR6[combtuningR6]; + float bufcombL7[combtuningL7]; + float bufcombR7[combtuningR7]; + float bufcombL8[combtuningL8]; + float bufcombR8[combtuningR8]; + + // Buffers for the allpasses + float bufallpassL1[allpasstuningL1]; + float bufallpassR1[allpasstuningR1]; + float bufallpassL2[allpasstuningL2]; + float bufallpassR2[allpasstuningR2]; + float bufallpassL3[allpasstuningL3]; + float bufallpassR3[allpasstuningR3]; + float bufallpassL4[allpasstuningL4]; + float bufallpassR4[allpasstuningR4]; + + float roomSize; + float damping; + float wetLevel; + + void update(); + + public: + Reverb(); + void process(float* l, float* r, int numsamples); + void setdamp(float value); + void setwidth(float value); + + void setRoomSize(float value); + void setMix(float value); + }; + +#endif + |