/* ============================================================================== 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_WAVE_RENDERER_HEADER_INCLUDED #define DISTRHO_VEX_WAVE_RENDERER_HEADER_INCLUDED #ifndef CARLA_EXPORT #define CARLA_EXPORT #endif #ifdef CARLA_EXPORT #include "juce_audio_basics.h" #include "resources/Resources.h" #else #include "../StandardHeader.h" #include "resources/Resources.h" #endif struct OscSet { float phase; float phaseOffset; float phaseInc; float phaseIncOffset; float cut; float buf[4]; }; struct WaveTableNames { const char* name; const char* data; }; class WaveRenderer { public: WaveRenderer() : cycle(256), //base pitch 86 Hz tableSize(0), daTable(nullptr), sWave("sine"), loadWave(true) { } ~WaveRenderer() { //M.setSize(0); daTable = nullptr; } const String& getCurrentWaveName() const { return sWave; } void setWaveLater(const String& waveName) { sWave = waveName; loadWave = true; } void actuallySetWave() { if (sWave == "asym_saw") { daTable = (uint16*) Wavetables::asym_saw; tableSize = Wavetables::asym_saw_size / 2; } else if (sWave == "bass_tone") { daTable = (uint16*) Wavetables::bass_tone; tableSize = Wavetables::bass_tone_size / 2; } else if (sWave == "buzz_1") { daTable = (uint16*) Wavetables::buzz_1; tableSize = Wavetables::buzz_1_size / 2; } else if (sWave == "buzz_2") { daTable = (uint16*) Wavetables::buzz_2; tableSize = Wavetables::buzz_2_size / 2; } else if (sWave == "dark_strings") { daTable = (uint16*) Wavetables::dark_strings; tableSize = Wavetables::dark_strings_size / 2; } else if (sWave == "deep_ring_1") { daTable = (uint16*) Wavetables::deep_ring_1; tableSize = Wavetables::deep_ring_1_size / 2; } else if (sWave == "deep_ring_2") { daTable = (uint16*) Wavetables::deep_ring_2; tableSize = Wavetables::deep_ring_2_size / 2; } else if (sWave == "epiano_tone") { daTable = (uint16*) Wavetables::epiano_tone; tableSize = Wavetables::epiano_tone_size / 2; } else if (sWave == "ghost_1") { daTable = (uint16*) Wavetables::ghost_1; tableSize = Wavetables::ghost_1_size / 2; } else if (sWave == "ghost_2") { daTable = (uint16*) Wavetables::ghost_2; tableSize = Wavetables::ghost_2_size / 2; } else if (sWave == "ghost_3") { daTable = (uint16*) Wavetables::ghost_3; tableSize = Wavetables::ghost_3_size / 2; } else if (sWave == "ghost_4") { daTable = (uint16*) Wavetables::ghost_4; tableSize = Wavetables::ghost_4_size / 2; } else if (sWave == "grind_1") { daTable = (uint16*) Wavetables::grind_1; tableSize = Wavetables::grind_1_size / 2; } else if (sWave == "grind_2") { daTable = (uint16*) Wavetables::grind_2; tableSize = Wavetables::grind_2_size / 2; } else if (sWave == "more_strings") { daTable = (uint16*) Wavetables::more_strings; tableSize = Wavetables::more_strings_size / 2; } else if (sWave == "multi_pulse") { daTable = (uint16*) Wavetables::multi_pulse; tableSize = Wavetables::multi_pulse_size / 2; } else if (sWave == "one_string") { daTable = (uint16*) Wavetables::one_string; tableSize = Wavetables::one_string_size / 2; } else if (sWave == "organ_1") { daTable = (uint16*) Wavetables::organ_1; tableSize = Wavetables::organ_1_size / 2; } else if (sWave == "organ_2") { daTable = (uint16*) Wavetables::organ_2; tableSize = Wavetables::organ_2_size / 2; } else if (sWave == "phasing_sqr") { daTable = (uint16*) Wavetables::phasing_sqr; tableSize = Wavetables::phasing_sqr_size / 2; } else if (sWave == "pulse") { daTable = (uint16*) Wavetables::pulse; tableSize = Wavetables::pulse_size / 2; } else if (sWave == "saw") { daTable = (uint16*) Wavetables::saw; tableSize = Wavetables::saw_size / 2; } else if (sWave == "sharp_1") { daTable = (uint16*) Wavetables::sharp_1; tableSize = Wavetables::sharp_1_size / 2; } else if (sWave == "sharp_2") { daTable = (uint16*) Wavetables::sharp_2; tableSize = Wavetables::sharp_2_size / 2; } else if (sWave == "sine") { daTable = (uint16*) Wavetables::sine; tableSize = Wavetables::sine_size / 2; } else if (sWave == "soft_1") { daTable = (uint16*) Wavetables::soft_1; tableSize = Wavetables::soft_1_size / 2; } else if (sWave == "soft_2") { daTable = (uint16*) Wavetables::soft_2; tableSize = Wavetables::soft_2_size / 2; } else if (sWave == "soft_3") { daTable = (uint16*) Wavetables::soft_3; tableSize = Wavetables::soft_3_size / 2; } else if (sWave == "soft_4") { daTable = (uint16*) Wavetables::soft_4; tableSize = Wavetables::soft_4_size / 2; } else if (sWave == "square") { daTable = (uint16*) Wavetables::square; tableSize = Wavetables::square_size / 2; } else if (sWave == "strings_1") { daTable = (uint16*) Wavetables::strings_1; tableSize = Wavetables::strings_1_size / 2; } else if (sWave == "strings_2") { daTable = (uint16*) Wavetables::strings_2; tableSize = Wavetables::strings_2_size / 2; } else if (sWave == "string_fuzz") { daTable = (uint16*) Wavetables::string_fuzz; tableSize = Wavetables::string_fuzz_size / 2; } else if (sWave == "syn_choir_1") { daTable = (uint16*) Wavetables::syn_choir_1; tableSize = Wavetables::syn_choir_1_size / 2; } else if (sWave == "syn_choir_2") { daTable = (uint16*) Wavetables::syn_choir_2; tableSize = Wavetables::syn_choir_2_size / 2; } else if (sWave == "syn_choir_3") { daTable = (uint16*) Wavetables::syn_choir_3; tableSize = Wavetables::syn_choir_3_size / 2; } else if (sWave == "thin_1") { daTable = (uint16*) Wavetables::thin_1; tableSize = Wavetables::thin_1_size / 2; } else if (sWave == "thin_2") { daTable = (uint16*) Wavetables::thin_2; tableSize = Wavetables::thin_2_size / 2; } else if (sWave == "two_strings") { daTable = (uint16*) Wavetables::two_strings; tableSize = Wavetables::two_strings_size / 2; } else if (sWave == "voice_1") { daTable = (uint16*) Wavetables::voice_1; tableSize = Wavetables::voice_1_size / 2; } else if (sWave == "voice_2") { daTable = (uint16*) Wavetables::voice_2; tableSize = Wavetables::voice_2_size / 2; } loadWave = false; #if 0 // TODO - this fails on linux (host directory not plugin one) // String waveName = (File::getSpecialLocation(File::currentExecutableFile)).getParentDirectory().getFullPathName(); File location = (File::getSpecialLocation(File::userHomeDirectory)).getChildFile(".vex"); if (! location.exists ()) location.createDirectory (); String waveName; waveName << location.getFullPathName() << "/" << sWave << ".raw"; DBG( waveName ); File f(waveName); if (f.existsAsFile ()) { tableSize = int(f.getSize() / 2); if (tableSize > 0) { M.setSize(0); f.loadFileAsData(M); daTable = (uint16*) M.getData(); } } else { tableSize = int(Wavetables::sine_size / 2); if (tableSize > 0) { M.setSize (0); M.append (Wavetables::sine, Wavetables::sine_size); daTable = (uint16*) M.getData(); } } loadWave = false; #endif } void reset(float f, double s, OscSet& o) { if (loadWave) actuallySetWave(); s = s * 2.0; f = f * 2.0f * (1.0f + o.phaseIncOffset * 0.01f); o.cut = float(2.0 * double_Pi * 9000.0 / s); o.phase = o.phaseOffset * tableSize * 0.5f; o.phaseInc = float(cycle / (s/f)); o.buf[0] = 0.0f; o.buf[1] = 0.0f; o.buf[2] = 0.0f; o.buf[3] = 0.0f; } void setFrequency(float f, double s, OscSet& o) { s = s * 2.0; f = f * 2.0f; o.phaseInc = float((float)cycle / (s/f)); } void fillBuffer(float* buffer, int bufferSize, OscSet& o) { if (buffer == nullptr || bufferSize == 0) return; float tmp; for (int i = 0; i < bufferSize; ++i) { buffer[i] = 0.0f; int index = roundFloatToInt(o.phase - 0.5f); float alpha = o.phase - (float)index; const float conv = 1.0f / 65535.0f; float sIndex = daTable[index] * conv - 0.5f; float sIndexp1 = daTable[(index + 1) % tableSize] * conv - 0.5f; tmp = sIndex + alpha * (sIndexp1 - sIndex); o.buf[1] = ((tmp - o.buf[1]) * o.cut) + o.buf[1]; o.buf[2] = ((o.buf[1] - o.buf[2]) * o.cut) + o.buf[2]; o.buf[3] = ((o.buf[2] - o.buf[3]) * o.cut) + o.buf[3]; o.buf[0] = ((o.buf[3] - o.buf[0]) * o.cut) + o.buf[0]; tmp = o.buf[0]; buffer[i] += tmp; o.phase += o.phaseInc; if (o.phase > (float)tableSize) o.phase -= (float)tableSize; index = roundFloatToInt(o.phase - 0.5f); alpha = o.phase - (float)index; sIndex = daTable[index] * conv - 0.5f; sIndexp1 = daTable[(index + 1) % tableSize] * conv - 0.5f; tmp = sIndex + alpha * (sIndexp1 - sIndex); o.buf[1] = ((tmp - o.buf[1]) * o.cut) + o.buf[1]; o.buf[2] = ((o.buf[1] - o.buf[2]) * o.cut) + o.buf[2]; o.buf[3] = ((o.buf[2] - o.buf[3]) * o.cut) + o.buf[3]; o.buf[0] = ((o.buf[3] - o.buf[0]) * o.cut) + o.buf[0]; tmp = o.buf[0]; buffer[i] += tmp; o.phase += o.phaseInc; if (o.phase > (float)tableSize) o.phase -= (float)tableSize; } } static int getWaveTableSize(); static String getWaveTableName(const int index); private: static const int kWaveTableSize = 41; static WaveTableNames waveTableNames[kWaveTableSize]; int cycle, tableSize; uint16* daTable; //MemoryBlock M; String sWave; bool loadWave; }; #endif // DISTRHO_VEX_WAVE_RENDERER_HEADER_INCLUDED