diff options
Diffstat (limited to 'audio/softsynth/mt32/freeverb.cpp')
-rw-r--r-- | audio/softsynth/mt32/freeverb.cpp | 357 |
1 files changed, 187 insertions, 170 deletions
diff --git a/audio/softsynth/mt32/freeverb.cpp b/audio/softsynth/mt32/freeverb.cpp index 67f065c20e..de8f2632cb 100644 --- a/audio/softsynth/mt32/freeverb.cpp +++ b/audio/softsynth/mt32/freeverb.cpp @@ -1,245 +1,245 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -// Comb filter implementation +// Allpass filter implementation // -// Written by +// Written by Jezar at Dreampoint, June 2000 // http://www.dreampoint.co.uk // This code is public domain -#include "audio/softsynth/mt32/freeverb.h" +#include "freeverb.h" -comb::comb() { - filterstore = 0; +allpass::allpass() +{ bufidx = 0; } -void comb::setbuffer(float *buf, int size) { +void allpass::setbuffer(float *buf, int size) +{ buffer = buf; bufsize = size; } -void comb::mute() { - for (int i = 0; i < bufsize; i++) - buffer[i] = 0; -} - -void comb::setdamp(float val) { - damp1 = val; - damp2 = 1 - val; -} - -float comb::getdamp() { - return damp1; +void allpass::mute() +{ + for (int i=0; i<bufsize; i++) + buffer[i]=0; } -void comb::setfeedback(float val) { +void allpass::setfeedback(float val) +{ feedback = val; } -float comb::getfeedback() { +float allpass::getfeedback() +{ return feedback; } -// Allpass filter implementation +void allpass::deletebuffer() +{ + delete[] buffer; + buffer = 0; +} +// Comb filter implementation +// +// Written by Jezar at Dreampoint, June 2000 +// http://www.dreampoint.co.uk +// This code is public domain -allpass::allpass() { +comb::comb() +{ + filterstore = 0; bufidx = 0; } -void allpass::setbuffer(float *buf, int size) { +void comb::setbuffer(float *buf, int size) +{ buffer = buf; bufsize = size; } -void allpass::mute() { - for (int i = 0; i < bufsize; i++) - buffer[i] = 0; +void comb::mute() +{ + for (int i=0; i<bufsize; i++) + buffer[i]=0; +} + +void comb::setdamp(float val) +{ + damp1 = val; + damp2 = 1-val; +} + +float comb::getdamp() +{ + return damp1; } -void allpass::setfeedback(float val) { +void comb::setfeedback(float val) +{ feedback = val; } -float allpass::getfeedback() { +float comb::getfeedback() +{ return feedback; } +void comb::deletebuffer() +{ + delete[] buffer; + buffer = 0; +} // Reverb model implementation +// +// Written by Jezar at Dreampoint, June 2000 +// Modifications by Jerome Fisher, 2009, 2011 +// http://www.dreampoint.co.uk +// This code is public domain -revmodel::revmodel() { - // 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); +revmodel::revmodel(float scaletuning) +{ + int i; + int bufsize; + + // Allocate buffers for the components + for (i = 0; i < numcombs; i++) { + bufsize = int(scaletuning * combtuning[i]); + combL[i].setbuffer(new float[bufsize], bufsize); + bufsize += int(scaletuning * stereospread); + combR[i].setbuffer(new float[bufsize], bufsize); + } + for (i = 0; i < numallpasses; i++) { + bufsize = int(scaletuning * allpasstuning[i]); + allpassL[i].setbuffer(new float[bufsize], bufsize); + allpassL[i].setfeedback(0.5f); + bufsize += int(scaletuning * stereospread); + allpassR[i].setbuffer(new float[bufsize], bufsize); + allpassR[i].setfeedback(0.5f); + } // 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); - setmode(initialmode); - setwet(initialwet); - setroomsize(initialroom); - setdry(initialdry); - setdamp(initialdamp); - setwidth(initialwidth); + dry = initialdry; + wet = initialwet*scalewet; + damp = initialdamp*scaledamp; + roomsize = (initialroom*scaleroom) + offsetroom; + width = initialwidth; + mode = initialmode; + update(); // Buffer will be full of rubbish - so we MUST mute them mute(); } -void revmodel::mute() { +revmodel::~revmodel() +{ + int i; + + for (i = 0; i < numcombs; i++) { + combL[i].deletebuffer(); + combR[i].deletebuffer(); + } + for (i = 0; i < numallpasses; i++) { + allpassL[i].deletebuffer(); + allpassR[i].deletebuffer(); + } +} + +void revmodel::mute() +{ int i; if (getmode() >= freezemode) return; - for (i = 0; i < numcombs; i++) { + for (i=0;i<numcombs;i++) + { combL[i].mute(); combR[i].mute(); } - - for (i = 0; i < numallpasses; i++) { + for (i=0;i<numallpasses;i++) + { allpassL[i].mute(); allpassR[i].mute(); } -} - -void revmodel::processreplace(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip) { - float outL, outR, input; - - while (numsamples-- > 0) { - int i; - - outL = outR = 0; - input = (*inputL + *inputR) * gain; - - // Accumulate comb filters in parallel - for (i = 0; i < numcombs; i++) { - outL += combL[i].process(input); - outR += combR[i].process(input); - } - // Feed through allpasses in series - for (i = 0; i < numallpasses; i++) { - outL = allpassL[i].process(outL); - outR = allpassR[i].process(outR); - } - - // Calculate output REPLACING anything already there - *outputL = outL * wet1 + outR * wet2 + *inputL * dry; - *outputR = outR * wet1 + outL * wet2 + *inputR * dry; - - // Increment sample pointers, allowing for interleave (if any) - inputL += skip; - inputR += skip; - outputL += skip; - outputR += skip; - } + // Init LPF history + filtprev1 = 0; + filtprev2 = 0; } -void revmodel::processmix(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip) { - float outL, outR, input; +void revmodel::process(const float *inputL, const float *inputR, float *outputL, float *outputR, long numsamples) +{ + float outL,outR,input; - while (numsamples-- > 0) { + while (numsamples-- > 0) + { int i; outL = outR = 0; input = (*inputL + *inputR) * gain; + // Implementation of 2-stage IIR single-pole low-pass filter + // found at the entrance of reverb processing on real devices + filtprev1 += (input - filtprev1) * filtval; + filtprev2 += (filtprev1 - filtprev2) * filtval; + input = filtprev2; + + int s = -1; // Accumulate comb filters in parallel - for (i = 0; i < numcombs; i++) { - outL += combL[i].process(input); - outR += combR[i].process(input); + for (i=0; i<numcombs; i++) + { + outL += s * combL[i].process(input); + outR += s * combR[i].process(input); + s = -s; } // Feed through allpasses in series - for (i = 0; i < numallpasses; i++) { + for (i=0; i<numallpasses; i++) + { outL = allpassL[i].process(outL); outR = allpassR[i].process(outR); } - // Calculate output MIXING with anything already there - *outputL += outL * wet1 + outR * wet2 + *inputL * dry; - *outputR += outR * wet1 + outL * wet2 + *inputR * dry; - - // Increment sample pointers, allowing for interleave (if any) - inputL += skip; - inputR += skip; - outputL += skip; - outputR += skip; + // Calculate output REPLACING anything already there + *outputL = outL*wet1 + outR*wet2; + *outputR = outR*wet1 + outL*wet2; + + inputL++; + inputR++; + outputL++; + outputR++; } } -void revmodel::update() { - // Recalculate internal values after parameter change +void revmodel::update() +{ +// Recalculate internal values after parameter change int i; - wet1 = wet * (width / 2 + 0.5f); - wet2 = wet * ((1 - width) / 2); + wet1 = wet*(width/2 + 0.5f); + wet2 = wet*((1-width)/2); - if (mode >= freezemode) { + if (mode >= freezemode) + { roomsize1 = 1; damp1 = 0; gain = muted; - } else { + } + else + { roomsize1 = roomsize; damp1 = damp; gain = fixedgain; } - for (i = 0; i < numcombs; i++) { + for (i=0; i<numcombs; i++) + { combL[i].setfeedback(roomsize1); combR[i].setfeedback(roomsize1); } - for (i = 0; i < numcombs; i++) { + for (i=0; i<numcombs; i++) + { combL[i].setdamp(damp1); combR[i].setdamp(damp1); } @@ -250,58 +250,75 @@ void revmodel::update() { // because as you develop the reverb model, you may // wish to take dynamic action when they are called. -void revmodel::setroomsize(float value) { - roomsize = (value * scaleroom) + offsetroom; +void revmodel::setroomsize(float value) +{ + roomsize = (value*scaleroom) + offsetroom; update(); } -float revmodel::getroomsize() { - return (roomsize - offsetroom) / scaleroom; +float revmodel::getroomsize() +{ + return (roomsize-offsetroom)/scaleroom; } -void revmodel::setdamp(float value) { - damp = value * scaledamp; +void revmodel::setdamp(float value) +{ + damp = value*scaledamp; update(); } -float revmodel::getdamp() { - return damp / scaledamp; +float revmodel::getdamp() +{ + return damp/scaledamp; } -void revmodel::setwet(float value) { - wet = value * scalewet; +void revmodel::setwet(float value) +{ + wet = value*scalewet; update(); } -float revmodel::getwet() { - return wet / scalewet; +float revmodel::getwet() +{ + return wet/scalewet; } -void revmodel::setdry(float value) { - dry = value * scaledry; +void revmodel::setdry(float value) +{ + dry = value*scaledry; } -float revmodel::getdry() { - return dry / scaledry; +float revmodel::getdry() +{ + return dry/scaledry; } -void revmodel::setwidth(float value) { +void revmodel::setwidth(float value) +{ width = value; update(); } -float revmodel::getwidth() { +float revmodel::getwidth() +{ return width; } -void revmodel::setmode(float value) { +void revmodel::setmode(float value) +{ mode = value; update(); } -float revmodel::getmode() { +float revmodel::getmode() +{ if (mode >= freezemode) return 1; else return 0; } + +void revmodel::setfiltval(float value) +{ + filtval = value; +} |