|  | /*
 ==============================================================================
 This file is part of the JUCETICE project - Copyright 2008 by Lucio Asnaghi.
 JUCETICE is based around the JUCE library - "Jules' Utility Class Extensions"
 Copyright 2008 by Julian Storer.
 ------------------------------------------------------------------------------
 JUCE and JUCETICE can be redistributed and/or modified under the terms of
 the GNU Lesser General Public License, as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.
 JUCE and JUCETICE are distributed in the hope that they 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 Lesser General Public License
 along with JUCE and JUCETICE; if not, visit www.gnu.org/licenses or write to
 Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 Boston, MA 02111-1307 USA
 ==============================================================================
   @author  rockhardbuns
   @tweaker Lucio Asnaghi
   @tweaker falkTX
 ==============================================================================
*/
#ifndef DISTRHO_VEX_SYNTH_MODULE_HEADER_INCLUDED
#define DISTRHO_VEX_SYNTH_MODULE_HEADER_INCLUDED
#ifndef CARLA_EXPORT
 #define CARLA_EXPORT
#endif
#ifdef CARLA_EXPORT
 #include "juce_audio_basics.h"
#else
 #include "../StandardHeader.h"
#endif
#include "VexVoice.h"
class VexSyntModule
{
public:
    VexSyntModule(const float* const p)
        : parameters(p),
          sampleRate(44100),
          benchwarmer(0),
          playCount(1),
          part1(false),
          part2(false),
          part3(false)
    {
        for (int i = 0; i < kNumVoices; ++i)
        {
            vo1[i] = new VexVoice(p,  0, wr1);
            vo2[i] = new VexVoice(p, 24, wr2);
            vo3[i] = new VexVoice(p, 48, wr3);
        }
    }
    ~VexSyntModule()
    {
        for (int i = 0; i < kNumVoices; ++i)
        {
            delete vo1[i];
            delete vo2[i];
            delete vo3[i];
        }
    }
    void doProcess(AudioSampleBuffer& obf, AudioSampleBuffer& assbf, AudioSampleBuffer& ebf1, AudioSampleBuffer& ebf2, AudioSampleBuffer& ebf3)
    {
        const int numSamples = obf.getNumSamples();
        float* const outPtrL = assbf.getWritePointer(0);
        float* const outPtrR = assbf.getWritePointer(1);
        if (part1)
        {
            float right = parameters[86] * parameters[83];
            float left  = parameters[86] * (1.0f - parameters[83]);
            for (int i = 0; i < kNumVoices; ++i)
            {
                if (vo1[i]->getIsOn())
                {
                    vo1[i]->doProcess(outPtrL, outPtrR, numSamples);
                    obf.addFrom(0, 0,  assbf, 0, 0, numSamples, left);
                    obf.addFrom(1, 0,  assbf, 1, 0, numSamples, right);
                    ebf1.addFrom(0, 0, assbf, 0, 0, numSamples, parameters[22] * left);
                    ebf1.addFrom(1, 0, assbf, 1, 0, numSamples, parameters[22] * right);
                    ebf2.addFrom(0, 0, assbf, 0, 0, numSamples, parameters[23] * left);
                    ebf2.addFrom(1, 0, assbf, 1, 0, numSamples, parameters[23] * right);
                    ebf3.addFrom(0, 0, assbf, 0, 0, numSamples, parameters[24] * left);
                    ebf3.addFrom(1, 0, assbf, 1, 0, numSamples, parameters[24] * right);
                }
            }
        }
        if (part2)
        {
            float right = parameters[87] * parameters[84];
            float left  = parameters[87] * (1.0f - parameters[84]);
            for (int i = 0; i < kNumVoices; ++i)
            {
                if (vo2[i]->getIsOn())
                {
                    vo2[i]->doProcess(outPtrL, outPtrR, numSamples);
                    obf.addFrom(0, 0,  assbf, 0, 0, numSamples, left);
                    obf.addFrom(1, 0,  assbf, 1, 0, numSamples, right);
                    ebf1.addFrom(0, 0, assbf, 0, 0, numSamples, parameters[22 + 24] * left);
                    ebf1.addFrom(1, 0, assbf, 1, 0, numSamples, parameters[22 + 24] * right);
                    ebf2.addFrom(0, 0, assbf, 0, 0, numSamples, parameters[23 + 24] * left);
                    ebf2.addFrom(1, 0, assbf, 1, 0, numSamples, parameters[23 + 24] * right);
                    ebf3.addFrom(0, 0, assbf, 0, 0, numSamples, parameters[24 + 24] * left);
                    ebf3.addFrom(1, 0, assbf, 1, 0, numSamples, parameters[24 + 24] * right);
                }
            }
        }
        if (part3)
        {
            float right = parameters[88] * parameters[85];
            float left  = parameters[88] * (1.0f - parameters[85]);
            for (int i = 0; i < kNumVoices; ++i)
            {
                if (vo3[i]->getIsOn())
                {
                    vo3[i]->doProcess(outPtrL, outPtrR, numSamples);
                    obf.addFrom(0, 0,  assbf, 0, 0, numSamples, left);
                    obf.addFrom(1, 0,  assbf, 1, 0, numSamples, right);
                    ebf1.addFrom(0, 0, assbf, 0, 0, numSamples, parameters[22 + 48] * left);
                    ebf1.addFrom(1, 0, assbf, 1, 0, numSamples, parameters[22 + 48] * right);
                    ebf2.addFrom(0, 0, assbf, 0, 0, numSamples, parameters[23 + 48] * left);
                    ebf2.addFrom(1, 0, assbf, 1, 0, numSamples, parameters[23 + 48] * right);
                    ebf3.addFrom(0, 0, assbf, 0, 0, numSamples, parameters[24 + 48] * left);
                    ebf3.addFrom(1, 0, assbf, 1, 0, numSamples, parameters[24 + 48] * right);
                }
            }
        }
    }
    void setSampleRate(const double s)
    {
        if (sampleRate == s)
            return;
        sampleRate = s;
        for (int i = 0; i < kNumVoices; ++i)
        {
            delete vo1[i];
            delete vo2[i];
            delete vo3[i];
            vo1[i] = new VexVoice(parameters,  0, wr1);
            vo2[i] = new VexVoice(parameters, 24, wr2);
            vo3[i] = new VexVoice(parameters, 48, wr3);
        }
    }
    void updateParameterPtr(const float* const p)
    {
        parameters = p;
        for (int i = 0; i < kNumVoices; ++i)
        {
            vo1[i]->updateParameterPtr(parameters);
            vo2[i]->updateParameterPtr(parameters);
            vo3[i]->updateParameterPtr(parameters);
        }
    }
    void playNote(const int n, const int vel, const int preroll, const int part)
    {
        VexVoice** v   = nullptr;
        const int note = n + 12;
        switch (part)
        {
        case 1:
            if (!part1) return;
            v = vo1;
            break;
        case 2:
            if (!part2) return;
            v = vo2;
            break;
        case 3:
            if (!part3) return;
            v = vo3;
            break;
        }
        if (v == nullptr)
            return;
        int OldestOn = kNumVoices-1;
        int OldestOff = kNumVoices-1;
        int OldestReleased = kNumVoices-1;
        int tmpOn = 100000000;
        //int tmpOff = 100000000;
        int tmpReleased = 100000000;
        for (int i = 0; i < kNumVoices; ++i)
        {
            if (i == benchwarmer)
                continue;
            if (! v[i]->getIsOn())
            {
                OldestOff = i;
                break;
            }
            if (vo1[i]->getIsReleased())
            {
                OldestReleased = (v[i]->getOrdinal() < tmpReleased) ? i : OldestReleased;
                tmpReleased = v[OldestReleased]->getOrdinal();
                continue;
            }
            OldestOn = (v[i]->getOrdinal() < tmpOn) ? i : OldestOn;
            tmpOn = v[OldestOn]->getOrdinal();
        }
        float noteInHertz = (float)MidiMessage::getMidiNoteInHertz(note);
        playCount++;
        if (OldestOff < kNumVoices)
        {
            v[OldestOff]->start(noteInHertz, float(vel)/127.0f, note, preroll, sampleRate, playCount);
            return;
        }
        if (OldestReleased < kNumVoices)
        {
            v[benchwarmer]->start(noteInHertz, float(vel)/127.0f, note, preroll, sampleRate, playCount);
            benchwarmer = OldestReleased;
            v[OldestReleased]->quickRelease();
            return;
        }
        if (OldestOn < kNumVoices)
        {
            v[benchwarmer]->start(noteInHertz, float(vel)/127.0f, note, preroll, sampleRate, playCount);
            benchwarmer = OldestOn;
            v[OldestReleased]->quickRelease();
            return;
        }
    }
    void releaseNote(const int n, const int preroll, const int part)
    {
        VexVoice** v   = nullptr;
        const int note = n + 12;
        switch (part)
        {
        case 1:
            if (!part1) return;
            v = vo1;
            break;
        case 2:
            if (!part2) return;
            v = vo2;
            break;
        case 3:
            if (!part3) return;
            v = vo3;
            break;
        }
        if (v == nullptr)
            return;
        for (int i = 0; i < kNumVoices; ++i)
        {
            if (v[i]->getNote() == note)
                v[i]->release(preroll);
        }
    }
    void releaseAll(const int p)
    {
        for (int i = 0; i < kNumVoices; ++i)
        {
            vo1[i]->release(p);
            vo2[i]->release(p);
            vo3[i]->release(p);
        }
    }
    void kill(const int what = 0)
    {
        switch (what)
        {
        case 0:
            for (int i = 0; i < kNumVoices; ++i)
            {
                vo1[i]->kill();
                vo2[i]->kill();
                vo3[i]->kill();
            }
            break;
        case 1:
            for (int i = 0; i < kNumVoices; ++i)
                vo1[i]->kill();
            break;
        case 2:
            for (int i = 0; i < kNumVoices; ++i)
                vo2[i]->kill();
            break;
        case 3:
            for (int i = 0; i < kNumVoices; ++i)
                vo3[i]->kill();
            break;
        }
    }
    String getWaveName(const int part) const
    {
        switch (part)
        {
        case 1:
            return wr1.getCurrentWaveName();
        case 2:
            return wr2.getCurrentWaveName();
        case 3:
            return wr3.getCurrentWaveName();
        default:
            return "";
        }
    }
    void setWaveLater(const int part, const String& waveName)
    {
        switch (part)
        {
        case 1:
            wr1.setWaveLater(waveName);
            kill(1);
            break;
        case 2:
            wr2.setWaveLater(waveName);
            kill(2);
            break;
        case 3:
            wr3.setWaveLater(waveName);
            kill(3);
            break;
        }
    }
    void update(const int index)
    {
        if (index == 89)
        {
            part1 = (parameters[89] > 0.5f);
            return;
        }
        if (index == 90)
        {
            part2 = (parameters[90] > 0.5f);
            return;
        }
        if (index == 91)
        {
            part3 = (parameters[91] > 0.5f);
            return;
        }
        for (int i = 0; i < kNumVoices; ++i)
        {
            vo1[i]->update(index);
            vo2[i]->update(index);
            vo3[i]->update(index);
        }
    }
private:
    static const int kNumVoices = 8;
    const float* parameters;
    double sampleRate;
    int benchwarmer;
    VexVoice* vo1[kNumVoices];
    VexVoice* vo2[kNumVoices];
    VexVoice* vo3[kNumVoices];
    long playCount;
    bool part1, part2, part3;
    WaveRenderer wr1;
    WaveRenderer wr2;
    WaveRenderer wr3;
};
#endif // DISTRHO_VEX_SYNTH_MODULE_HEADER_INCLUDED
 |