revmodel.cpp 6.32 KB
Newer Older
1
// Reverb model implementation
2 3
//
//
4
// Google Summer of Code 2007
5 6 7
//
// Authors: Biodun Osunkunle <biodun@videolan.org>
//
8 9 10 11 12 13 14
// Mentor : Jean-Baptiste Kempf <jb@videolan.org>
//
// Original written by Jezar at Dreampoint, June 2000

// This code is public domain

#include "revmodel.hpp"
15
#include "tuning.h"
16 17
#include <stdlib.h>

18 19
revmodel::revmodel() : roomsize(initialroom), damp(initialdamp),
                       wet(initialwet), dry(initialdry), width(1.), mode(0.)
20
{
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
    // 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);
    setwet(initialwet);
    setroomsize(initialroom);
    setdry(initialdry);
    setdamp(initialdamp);
    setwidth(initialwidth);
    setmode(initialmode);

    // Buffer will be full of rubbish - so we MUST mute them
    mute();
65 66 67 68
}

void revmodel::mute()
{
69
    int i;
JP Dinger's avatar
JP Dinger committed
70
    if (mode >= freezemode)
71 72 73 74 75 76 77 78 79 80 81 82
        return;

    for (i = 0 ; i < numcombs ; i++)
    {
        combL[i].mute();
        combR[i].mute();
    }
    for (i=0;i<numallpasses;i++)
    {
        allpassL[i].mute();
        allpassR[i].mute();
    }
83 84
}

85 86 87 88 89 90 91
/*****************************************************************************
 *  Transforms the audio stream
 * /param float *inputL     input buffer
 * /param float *outputL   output buffer
 * /param long numsamples  number of samples to be processed
 * /param int skip             number of channels in the audio stream
 *****************************************************************************/
92
void revmodel::processreplace(float *inputL, float *outputL, long /* numsamples */, int skip)
93
{
94 95 96
    float outL,outR,input;
    float inputR;
    int i;
97

98
    outL = outR = 0;
99
        /* TODO this module supports only 2 audio channels, let's improve this */
100
        if (skip > 1)
101
           inputR = inputL[1];
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
        else
           inputR = inputL[0];
        input = (inputL[0] + 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[0] = (outL*wet1 + outR*wet2 + inputR*dry);
122
           if (skip > 1)
123
        outputL[1] = (outR*wet1 + outL*wet2 + inputR*dry);
124 125
}

126
void revmodel::processmix(float *inputL, float *outputL, long /* numsamples */, int skip)
127
{
128 129
    float outL,outR,input;
    float inputR;
130

131 132
    outL = outR = 0;
        if (skip > 1)
133
           inputR = inputL[1];
134 135 136 137 138
        else
           inputR = inputL[0];
        input = (inputL[0] + inputR) * gain;

        // Accumulate comb filters in parallel
139
        for(int i=0; i<numcombs; i++)
140 141 142 143 144 145
        {
            outL += combL[i].process(input);
            outR += combR[i].process(input);
        }

        // Feed through allpasses in series
146
        for(int i=0; i<numallpasses; i++)
147 148 149 150 151 152 153
        {
            outL = allpassL[i].process(outL);
            outR = allpassR[i].process(outR);
        }

        // Calculate output REPLACING anything already there
        outputL[0] += (outL*wet1 + outR*wet2 + inputR*dry);
154
           if (skip > 1)
155
        outputL[1] += (outR*wet1 + outL*wet2 + inputR*dry);
156 157 158 159 160 161
}

void revmodel::update()
{
// Recalculate internal values after parameter change

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
    wet1 = wet*(width/2 + 0.5f);
    wet2 = wet*((1-width)/2);

    if (mode >= freezemode)
    {
        roomsize1 = 1;
        damp1 = 0;
        gain = muted;
    }
    else
    {
        roomsize1 = roomsize;
        damp1 = damp;
        gain = fixedgain;
    }

178
    for(int i=0; i<numcombs; i++)
179 180 181 182 183
    {
        combL[i].setfeedback(roomsize1);
        combR[i].setfeedback(roomsize1);
    }

184
    for(int i=0; i<numcombs; i++)
185 186 187 188
    {
        combL[i].setdamp(damp1);
        combR[i].setdamp(damp1);
    }
189 190 191 192 193 194 195 196 197
}

// The following get/set functions are not inlined, because
// speed is never an issue when calling them, and also
// because as you develop the reverb model, you may
// wish to take dynamic action when they are called.

void revmodel::setroomsize(float value)
{
198 199
    roomsize = (value*scaleroom) + offsetroom;
    update();
200 201 202 203
}

float revmodel::getroomsize()
{
204
    return (roomsize-offsetroom)/scaleroom;
205 206 207 208
}

void revmodel::setdamp(float value)
{
209 210
    damp = value*scaledamp;
    update();
211 212 213 214
}

float revmodel::getdamp()
{
215
    return damp/scaledamp;
216 217 218 219
}

void revmodel::setwet(float value)
{
220 221
    wet = value*scalewet;
    update();
222 223 224 225
}

float revmodel::getwet()
{
226
    return wet/scalewet;
227 228 229 230
}

void revmodel::setdry(float value)
{
231
    dry = value*scaledry;
232 233 234 235
}

float revmodel::getdry()
{
236
    return dry/scaledry;
237 238 239 240
}

void revmodel::setwidth(float value)
{
241 242
    width = value;
    update();
243 244 245 246
}

float revmodel::getwidth()
{
247
    return width;
248 249 250 251
}

void revmodel::setmode(float value)
{
252 253
    mode = value;
    update();
254 255 256
}

//ends