/* ============================================================================== 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