Browse Source

More work on Vex

tags/1.9.4
falkTX 12 years ago
parent
commit
4cec48b989
15 changed files with 71308 additions and 17 deletions
  1. +7
    -7
      source/includes/CarlaMIDI.h
  2. +195
    -8
      source/modules/carla_native/vex.cpp
  3. +69541
    -0
      source/modules/carla_native/vex/ResourceFile.cpp
  4. +174
    -0
      source/modules/carla_native/vex/ResourceFile.h
  5. +196
    -0
      source/modules/carla_native/vex/cADSR.h
  6. +4
    -2
      source/modules/carla_native/vex/cArp.h
  7. +2
    -0
      source/modules/carla_native/vex/cChorus.h
  8. +2
    -0
      source/modules/carla_native/vex/cDelay.h
  9. +2
    -0
      source/modules/carla_native/vex/cReverb.h
  10. +400
    -0
      source/modules/carla_native/vex/cSyntModule.h
  11. +265
    -0
      source/modules/carla_native/vex/cVoice.cpp
  12. +91
    -0
      source/modules/carla_native/vex/cVoice.h
  13. +91
    -0
      source/modules/carla_native/vex/cWaveRenderer.cpp
  14. +330
    -0
      source/modules/carla_native/vex/cWaveRenderer.h
  15. +8
    -0
      source/plugin/carla-native-plugin.cpp

+ 7
- 7
source/includes/CarlaMIDI.h View File

@@ -34,13 +34,13 @@
#define MIDI_STATUS_CHANNEL_PRESSURE 0xD0 // pressure (0-127), none
#define MIDI_STATUS_PITCH_WHEEL_CONTROL 0xE0 // LSB (0-127), MSB (0-127)

#define MIDI_IS_STATUS_NOTE_OFF(status) (((status) & MIDI_STATUS_BIT) == MIDI_STATUS_NOTE_OFF)
#define MIDI_IS_STATUS_NOTE_ON(status) (((status) & MIDI_STATUS_BIT) == MIDI_STATUS_NOTE_ON)
#define MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) (((status) & MIDI_STATUS_BIT) == MIDI_STATUS_POLYPHONIC_AFTERTOUCH)
#define MIDI_IS_STATUS_CONTROL_CHANGE(status) (((status) & MIDI_STATUS_BIT) == MIDI_STATUS_CONTROL_CHANGE)
#define MIDI_IS_STATUS_PROGRAM_CHANGE(status) (((status) & MIDI_STATUS_BIT) == MIDI_STATUS_PROGRAM_CHANGE)
#define MIDI_IS_STATUS_CHANNEL_PRESSURE(status) (((status) & MIDI_STATUS_BIT) == MIDI_STATUS_CHANNEL_PRESSURE)
#define MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) (((status) & MIDI_STATUS_BIT) == MIDI_STATUS_PITCH_WHEEL_CONTROL)
#define MIDI_IS_STATUS_NOTE_OFF(status) (((status) < 0xF0) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_NOTE_OFF)
#define MIDI_IS_STATUS_NOTE_ON(status) (((status) < 0xF0) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_NOTE_ON)
#define MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) (((status) < 0xF0) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_POLYPHONIC_AFTERTOUCH)
#define MIDI_IS_STATUS_CONTROL_CHANGE(status) (((status) < 0xF0) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_CONTROL_CHANGE)
#define MIDI_IS_STATUS_PROGRAM_CHANGE(status) (((status) < 0xF0) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_PROGRAM_CHANGE)
#define MIDI_IS_STATUS_CHANNEL_PRESSURE(status) (((status) < 0xF0) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_CHANNEL_PRESSURE)
#define MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) (((status) < 0xF0) && ((status) & MIDI_STATUS_BIT) == MIDI_STATUS_PITCH_WHEEL_CONTROL)

// MIDI Utils
#define MIDI_GET_STATUS_FROM_DATA(data) ((data[0] < 0xF0) ? data[0] & MIDI_STATUS_BIT : data[0])


+ 195
- 8
source/modules/carla_native/vex.cpp View File

@@ -23,6 +23,7 @@ using namespace juce;
#include "vex/cChorus.h"
#include "vex/cDelay.h"
#include "vex/cReverb.h"
#include "vex/cSyntModule.h"

// -----------------------------------------------------------------------

@@ -192,7 +193,7 @@ protected:
// -------------------------------------------------------------------
// Plugin state calls

void setParameterValue(const uint32_t index, const float value)
void setParameterValue(const uint32_t index, const float value) override
{
switch (index)
{
@@ -375,7 +376,7 @@ protected:
// -------------------------------------------------------------------
// Plugin state calls

void setParameterValue(const uint32_t index, const float value)
void setParameterValue(const uint32_t index, const float value) override
{
if (index < kParamCount)
parameters[index] = value;
@@ -490,7 +491,7 @@ protected:
// -------------------------------------------------------------------
// Plugin state calls

void setParameterValue(const uint32_t index, const float value)
void setParameterValue(const uint32_t index, const float value) override
{
if (index < kParamCount)
parameters[index] = value;
@@ -612,7 +613,7 @@ protected:
// -------------------------------------------------------------------
// Plugin state calls

void setParameterValue(const uint32_t index, const float value)
void setParameterValue(const uint32_t index, const float value) override
{
if (index < kParamCount)
parameters[index] = value;
@@ -641,6 +642,170 @@ private:

// -----------------------------------------------------------------------

class VexSynthPlugin : public PluginClass
{
public:
static const unsigned int kParamCount = 1;

VexSynthPlugin(const HostDescriptor* const host)
: PluginClass(host),
synth(parameters)
{
std::memset(parameters, 0, sizeof(float)*92);

for (int i = 0; i < 3; ++i)
{
const int offset = i * 24;

parameters[offset + 1] = 0.5f;
parameters[offset + 2] = 0.5f;
parameters[offset + 3] = 0.5f;
parameters[offset + 4] = 0.5f;
parameters[offset + 5] = 0.9f;
parameters[offset + 6] = 0.0f;
parameters[offset + 7] = 1.0f;
parameters[offset + 8] = 0.5f;
parameters[offset + 9] = 0.0f;
parameters[offset + 10] = 0.2f;
parameters[offset + 11] = 0.0f;
parameters[offset + 12] = 0.5f;
parameters[offset + 13] = 0.5f;
parameters[offset + 14] = 0.0f;
parameters[offset + 15] = 0.3f;
parameters[offset + 16] = 0.7f;
parameters[offset + 17] = 0.1f;
parameters[offset + 18] = 0.5f;
parameters[offset + 19] = 0.5f;
parameters[offset + 20] = 0.0f;
parameters[offset + 21] = 0.0f;
parameters[offset + 22] = 0.5f;
parameters[offset + 23] = 0.5f;
parameters[offset + 24] = 0.5f;
}

parameters[89] = 1.0f;

synth.setSampleRate(getSampleRate());
synth.update(89);
}

protected:
// -------------------------------------------------------------------
// Plugin parameter calls

uint32_t getParameterCount() const override
{
return kParamCount;
}

const Parameter* getParameterInfo(const uint32_t index) const override
{
static Parameter paramInfo;

int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_AUTOMABLE;

paramInfo.name = nullptr;
paramInfo.unit = nullptr;
paramInfo.ranges.def = 0.0f;
paramInfo.ranges.min = 0.0f;
paramInfo.ranges.max = 1.0f;
paramInfo.ranges.step = 1.0f;
paramInfo.ranges.stepSmall = 1.0f;
paramInfo.ranges.stepLarge = 1.0f;
paramInfo.scalePointCount = 0;
paramInfo.scalePoints = nullptr;

switch (index)
{
case 0:
hints |= PARAMETER_IS_INTEGER;
paramInfo.name = "Wave";
paramInfo.ranges.def = 0.0f;
paramInfo.ranges.min = 0.0f;
paramInfo.ranges.max = WaveRenderer::getWaveTableSize();
break;
}

paramInfo.hints = static_cast<ParameterHints>(hints);

return &paramInfo;
}

float getParameterValue(const uint32_t index) const override
{
if (index < kParamCount)
return parameters[index];
return 0.0f;
}

// -------------------------------------------------------------------
// Plugin state calls

void setParameterValue(const uint32_t index, const float value) override
{
if (index < kParamCount)
{
parameters[index] = value;
synth.setWaveLater(1, WaveRenderer::getWaveTableName(value));

//synth.update(index);
}
}

// -------------------------------------------------------------------
// Plugin process calls

void process(float**, float** outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override
{
for (uint32_t i=0; i < midiEventCount; ++i)
{
const MidiEvent* const midiEvent(&midiEvents[i]);

const uint8_t status(MIDI_GET_STATUS_FROM_DATA(midiEvent->data));

if (status == MIDI_STATUS_NOTE_ON)
{
synth.playNote(midiEvent->data[1], midiEvent->data[2], 0, 1);
}
else if (status == MIDI_STATUS_NOTE_OFF)
{
synth.releaseNote(midiEvent->data[1], 0, 1);
}
else if (status == MIDI_STATUS_CONTROL_CHANGE)
{
const uint8_t control(midiEvent->data[1]);

if (control == MIDI_CONTROL_ALL_SOUND_OFF)
synth.kill();
else if (control == MIDI_CONTROL_ALL_NOTES_OFF)
synth.releaseAll(1);
}
}

carla_zeroFloat(outBuffer[0], frames);
carla_zeroFloat(outBuffer[1], frames);

synth.doProcess(outBuffer[0], outBuffer[1], frames);
}

// -------------------------------------------------------------------
// Plugin dispatcher calls

void sampleRateChanged(const double sampleRate) override
{
synth.setSampleRate(sampleRate);
}

private:
VexSyntModule synth;
float parameters[92];

PluginClassEND(VexSynthPlugin)
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexSynthPlugin)
};

// -----------------------------------------------------------------------

static const PluginDescriptor vexArpDesc = {
/* category */ PLUGIN_CATEGORY_UTILITY,
/* hints */ static_cast<PluginHints>(0x0),
@@ -651,7 +816,7 @@ static const PluginDescriptor vexArpDesc = {
/* midiOuts */ 1,
/* paramIns */ VexArpPlugin::kParamCount,
/* paramOuts */ 0,
/* name */ "Vex Arp",
/* name */ "VexArp",
/* label */ "vexArp",
/* maker */ "falkTX",
/* copyright */ "GNU GPL v2+",
@@ -668,7 +833,7 @@ static const PluginDescriptor vexChorusDesc = {
/* midiOuts */ 0,
/* paramIns */ VexChorusPlugin::kParamCount,
/* paramOuts */ 0,
/* name */ "Vex Chorus",
/* name */ "VexChorus",
/* label */ "vexChorus",
/* maker */ "falkTX",
/* copyright */ "GNU GPL v2+",
@@ -685,7 +850,7 @@ static const PluginDescriptor vexDelayDesc = {
/* midiOuts */ 0,
/* paramIns */ VexDelayPlugin::kParamCount,
/* paramOuts */ 0,
/* name */ "Vex Delay",
/* name */ "VexDelay",
/* label */ "vexDelay",
/* maker */ "falkTX",
/* copyright */ "GNU GPL v2+",
@@ -702,13 +867,30 @@ static const PluginDescriptor vexReverbDesc = {
/* midiOuts */ 0,
/* paramIns */ VexReverbPlugin::kParamCount,
/* paramOuts */ 0,
/* name */ "Vex Reverb",
/* name */ "VexReverb",
/* label */ "vexReverb",
/* maker */ "falkTX",
/* copyright */ "GNU GPL v2+",
PluginDescriptorFILL(VexReverbPlugin)
};

static const PluginDescriptor vexSynthDesc = {
/* category */ PLUGIN_CATEGORY_SYNTH,
/* hints */ static_cast<PluginHints>(0x0),
/* supports */ static_cast<PluginSupports>(0x0),
/* audioIns */ 0,
/* audioOuts */ 2,
/* midiIns */ 1,
/* midiOuts */ 0,
/* paramIns */ VexSynthPlugin::kParamCount,
/* paramOuts */ 0,
/* name */ "VexSynth",
/* label */ "vexSynth",
/* maker */ "falkTX",
/* copyright */ "GNU GPL v2+",
PluginDescriptorFILL(VexSynthPlugin)
};

// -----------------------------------------------------------------------

CARLA_EXPORT
@@ -718,6 +900,7 @@ void carla_register_native_plugin_vex()
carla_register_native_plugin(&vexChorusDesc);
carla_register_native_plugin(&vexDelayDesc);
carla_register_native_plugin(&vexReverbDesc);
carla_register_native_plugin(&vexSynthDesc);
}

// -----------------------------------------------------------------------
@@ -726,4 +909,8 @@ void carla_register_native_plugin_vex()
#include "vex/freeverb/comb.cpp"
#include "vex/freeverb/revmodel.cpp"

#include "vex/cVoice.cpp"
#include "vex/cWaveRenderer.cpp"
#include "vex/ResourceFile.cpp"

// -----------------------------------------------------------------------

+ 69541
- 0
source/modules/carla_native/vex/ResourceFile.cpp
File diff suppressed because it is too large
View File


+ 174
- 0
source/modules/carla_native/vex/ResourceFile.h View File

@@ -0,0 +1,174 @@
/* (Auto-generated binary data file). */
#ifndef BINARY_RESOURCEFILE_H
#define BINARY_RESOURCEFILE_H
namespace Wavetables
{
extern const char* asym_saw;
extern const char* asym_saw_ext;
const int asym_saw_size = 1024;
extern const char* bass_tone;
extern const char* bass_tone_ext;
const int bass_tone_size = 1024;
extern const char* buzz_1;
extern const char* buzz_1_ext;
const int buzz_1_size = 1024;
extern const char* buzz_2;
extern const char* buzz_2_ext;
const int buzz_2_size = 1024;
extern const char* dark_strings;
extern const char* dark_strings_ext;
const int dark_strings_size = 131072;
extern const char* deep_ring_1;
extern const char* deep_ring_1_ext;
const int deep_ring_1_size = 1024;
extern const char* deep_ring_2;
extern const char* deep_ring_2_ext;
const int deep_ring_2_size = 1024;
extern const char* epiano_tone;
extern const char* epiano_tone_ext;
const int epiano_tone_size = 4096;
extern const char* ghost_1;
extern const char* ghost_1_ext;
const int ghost_1_size = 131072;
extern const char* ghost_2;
extern const char* ghost_2_ext;
const int ghost_2_size = 131072;
extern const char* ghost_3;
extern const char* ghost_3_ext;
const int ghost_3_size = 131072;
extern const char* ghost_4;
extern const char* ghost_4_ext;
const int ghost_4_size = 131072;
extern const char* grind_1;
extern const char* grind_1_ext;
const int grind_1_size = 131072;
extern const char* grind_2;
extern const char* grind_2_ext;
const int grind_2_size = 131072;
extern const char* more_strings;
extern const char* more_strings_ext;
const int more_strings_size = 131072;
extern const char* multi_pulse;
extern const char* multi_pulse_ext;
const int multi_pulse_size = 1024;
extern const char* one_string;
extern const char* one_string_ext;
const int one_string_size = 131072;
extern const char* organ_1;
extern const char* organ_1_ext;
const int organ_1_size = 131072;
extern const char* organ_2;
extern const char* organ_2_ext;
const int organ_2_size = 131072;
extern const char* phasing_sqr;
extern const char* phasing_sqr_ext;
const int phasing_sqr_size = 131072;
extern const char* pulse;
extern const char* pulse_ext;
const int pulse_size = 1024;
extern const char* saw;
extern const char* saw_ext;
const int saw_size = 1024;
extern const char* sharp_1;
extern const char* sharp_1_ext;
const int sharp_1_size = 1024;
extern const char* sharp_2;
extern const char* sharp_2_ext;
const int sharp_2_size = 1024;
extern const char* sine;
extern const char* sine_ext;
const int sine_size = 1024;
extern const char* soft_1;
extern const char* soft_1_ext;
const int soft_1_size = 1024;
extern const char* soft_2;
extern const char* soft_2_ext;
const int soft_2_size = 1024;
extern const char* soft_3;
extern const char* soft_3_ext;
const int soft_3_size = 1024;
extern const char* soft_4;
extern const char* soft_4_ext;
const int soft_4_size = 1024;
extern const char* square;
extern const char* square_ext;
const int square_size = 1024;
extern const char* strings_1;
extern const char* strings_1_ext;
const int strings_1_size = 131072;
extern const char* strings_2;
extern const char* strings_2_ext;
const int strings_2_size = 131072;
extern const char* string_fuzz;
extern const char* string_fuzz_ext;
const int string_fuzz_size = 131072;
extern const char* syn_choir_1;
extern const char* syn_choir_1_ext;
const int syn_choir_1_size = 131072;
extern const char* syn_choir_2;
extern const char* syn_choir_2_ext;
const int syn_choir_2_size = 131072;
extern const char* syn_choir_3;
extern const char* syn_choir_3_ext;
const int syn_choir_3_size = 131072;
extern const char* thin_1;
extern const char* thin_1_ext;
const int thin_1_size = 1024;
extern const char* thin_2;
extern const char* thin_2_ext;
const int thin_2_size = 1024;
extern const char* two_strings;
extern const char* two_strings_ext;
const int two_strings_size = 131072;
extern const char* voice_1;
extern const char* voice_1_ext;
const int voice_1_size = 131072;
extern const char* voice_2;
extern const char* voice_2_ext;
const int voice_2_size = 131072;
};
#endif

+ 196
- 0
source/modules/carla_native/vex/cADSR.h View File

@@ -0,0 +1,196 @@
/*
==============================================================================
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
==============================================================================
*/
#ifndef __JUCETICE_VEXCADSR_HEADER__
#define __JUCETICE_VEXCADSR_HEADER__
#ifdef CARLA_EXPORT
#include "JuceHeader.h"
#else
#include "../StandardHeader.h"
#endif
//Process every sample in a buffer
class VexADSR
{
public:
enum State {
kStateDone = 0,
kStateAttack,
kStateDecay,
kStateSustain,
kStateRelease,
kStateQRelease,
kStateCount
};
typedef void (VexADSR::*StateFunc)();
VexADSR()
: state(kStateAttack),
attackRate(0.1f),
decayRate(0.3f),
sustainLevel(0.5f),
releaseRate(0.1f),
preCount(0),
postCount(0),
value(0.0f)
{
stateFn[kStateDone] = &VexADSR::fn_done;
stateFn[kStateAttack] = &VexADSR::fn_attack;
stateFn[kStateDecay] = &VexADSR::fn_decay;
stateFn[kStateSustain] = &VexADSR::fn_sustain;
stateFn[kStateRelease] = &VexADSR::fn_release;
stateFn[kStateQRelease] = &VexADSR::fn_qrelease;
}
// Process a buffer
void doProcess(float* BufferL, float* BufferR, int bSize)
{
for(int i = 0; i < bSize; i++)
{
(this->*stateFn[state])();
BufferL[i] *= value * value;
BufferR[i] *= value * value;
}
}
// Process a Sample
float getSample()
{
(this->*stateFn[state])();
return value * value;
}
void reset(int p)
{
preCount = p;
state = kStateAttack;
value = 0.0f;
}
void release(int p)
{
postCount = p;
state = kStateRelease;
}
void quickRelease()
{
state = kStateQRelease;
}
bool getState()
{
return (state != kStateDone);
}
void kill()
{
state = kStateDone;
}
void setADSR(double a, double d, double s, double r, double sr)
{
double rate = sr * 5.0;
attackRate = float(1.0f / (rate * jmax(a * a, 0.001)));
decayRate = float(1.0f / (rate * jmax(d * d, 0.005)));
releaseRate = float(1.0f / (rate * jmax(r * r, 0.0002)));
sustainLevel = (float)s;
}
private:
void fn_done()
{
}
void fn_attack()
{
--preCount;
value += attackRate * float(preCount < 1);
if (value >= 1.0f)
{
state = kStateDecay;
value = 1.0f;
}
}
void fn_decay()
{
value -= decayRate;
if (value <= sustainLevel)
state = kStateSustain;
}
void fn_sustain()
{
}
void fn_release()
{
--postCount;
value -= releaseRate * bool(postCount < 1);
postCount -= int(postCount > 0);
if (value <= 0.0f)
{
state = kStateDone;
value = 0.0f;
}
}
void fn_qrelease()
{
value -= 0.006f;
if (value <= 0.0f)
{
state = kStateDone;
value = 0.0f;
}
}
State state;
StateFunc stateFn[kStateCount]; //Function pointer array for the state functions
float attackRate, decayRate, sustainLevel, releaseRate;
int preCount, postCount; //counter to delay release to sync with the sampleframe
float value; //this is the current value of the envelope
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexADSR)
};
#endif

+ 4
- 2
source/modules/carla_native/vex/cArp.h View File

@@ -158,7 +158,7 @@ public:
}
// BarSync
const int samplesPerStep = int((60.0 / bpm) * sampleRate * 4) / timeSig;
const unsigned int samplesPerStep = int((60.0 / bpm) * sampleRate * 4) / timeSig;
if (isPlaying && arpSet->syncMode == 2)
{
@@ -300,12 +300,14 @@ private:
const VexArpSettings* arpSet;
MidiBuffer outMidiBuffer;
bool dead, notesPlaying, doSync;
char nextStep;
unsigned int nextStep;
unsigned int sampleCount, sampleRate;
int meter[4];
char cKeysDown[kMaxNotes];
char cKeysVelocity[kMaxNotes];
char cNotesToKill[kMaxNotes];
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexArp)
};
#endif

+ 2
- 0
source/modules/carla_native/vex/cChorus.h View File

@@ -151,6 +151,8 @@ private:
int iRead, iWrite;
AudioSampleBuffer buffer;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexChorus)
};
#endif

+ 2
- 0
source/modules/carla_native/vex/cDelay.h View File

@@ -123,6 +123,8 @@ private:
float sampleRate;
int bufferSize, iRead, iWrite;
AudioSampleBuffer buffer;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexDelay)
};
#endif

+ 2
- 0
source/modules/carla_native/vex/cReverb.h View File

@@ -79,6 +79,8 @@ public:
private:
revmodel model;
const float* parameters;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexReverb)
};
#endif

+ 400
- 0
source/modules/carla_native/vex/cSyntModule.h View File

@@ -0,0 +1,400 @@
/*
==============================================================================
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
==============================================================================
*/
#ifndef __JUCETICE_VEXCSYNTMODULE_HEADER__
#define __JUCETICE_VEXCSYNTMODULE_HEADER__
#ifdef CARLA_EXPORT
#include "JuceHeader.h"
#else
#include "../StandardHeader.h"
#endif
#include "cVoice.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];
}
}
#ifdef CARLA_EXPORT
void doProcess(float* const outPtrL, float* const outPtrR, const int numSamples)
{
#else
void doProcess(AudioSampleBuffer& assbf, AudioSampleBuffer& obf, AudioSampleBuffer& ebf1, AudioSampleBuffer& ebf2, AudioSampleBuffer& ebf3)
{
const int numSamples = obf.getNumSamples();
float* const outPtrL = assbf.getSampleData(0,0);
float* const outPtrR = assbf.getSampleData(1,0);
#endif
if (part1)
{
#ifndef CARLA_EXPORT
float right = parameters[86] * parameters[83];
float left = parameters[86] * (1.0f - parameters[83]);
#endif
for (int i = 0; i < kNumVoices; ++i)
{
if (vo1[i]->getIsOn())
{
vo1[i]->doProcess(outPtrL, outPtrR, numSamples);
#ifndef CARLA_EXPORT
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);
#endif
}
}
}
if (part2)
{
#ifndef CARLA_EXPORT
float right = parameters[87] * parameters[84];
float left = parameters[87] * (1.0f - parameters[84]);
#endif
for (int i = 0; i < kNumVoices; ++i)
{
if (vo2[i]->getIsOn())
{
vo2[i]->doProcess(outPtrL, outPtrR, numSamples);
#ifndef CARLA_EXPORT
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);
#endif
}
}
}
if (part3)
{
#ifndef CARLA_EXPORT
float right = parameters[88] * parameters[85];
float left = parameters[88] * (1.0f - parameters[85]);
#endif
for (int i = 0; i < kNumVoices; ++i)
{
if (vo3[i]->getIsOn())
{
vo3[i]->doProcess(outPtrL, outPtrR, numSamples);
#ifndef CARLA_EXPORT
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);
#endif
}
}
}
}
void setSampleRate(const double s)
{
sampleRate = s;
}
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;
}
}
void setWaveLater(const int part, const String& waveName)
{
switch (part)
{
case 1:
wr1.setWaveLater(waveName);
kill(1);
// REMOVE THIS
wr1.actuallySetWave();
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.9f);
return;
}
if (index == 90)
{
part2 = (parameters[90] > 0.9f);
return;
}
if (index == 91)
{
part3 = (parameters[91] > 0.9f);
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

+ 265
- 0
source/modules/carla_native/vex/cVoice.cpp View File

@@ -0,0 +1,265 @@
/*
==============================================================================
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
==============================================================================
*/
#include "cVoice.h"
float convertPitch(float pitch)
{
long convert;
float *p = (float*)&convert;
float fl, fr, warp, out;
fl = std::floor(pitch);
fr = pitch - fl;
warp = fr*0.696f + fr*fr*0.225f + fr*fr*fr*0.079f; // chebychev approx
out = fl+warp;
out *= 8388608.0; //2^23;
out += 127.0 * 8388608.0; //2^23;
convert = (long)out; //magic
return *p;
}
float bipolar(const float in)
{
return in * 2.0f - 1.0f;
}
VexVoice::VexVoice(const float* const p, int po, WaveRenderer& w, float sr)
: wr(w),
parameters(p),
poff(po)
{
Ordinal = 1;
SampleRate = sr;
isOn = false;
note = 0;
lfoC = 2.f * (float)std::sin(float_Pi * 5.0f / SampleRate);
lfoS[0] = 0.3f;
lfoS[1] = 0.0f;
lowL = 0.0f;
bandL = 0.0f;
highL = 0.0f;
lowR = 0.0f;
bandR = 0.0f;
highR = 0.0f;
q = 0.0f;
cut = 0.0f;
}
void VexVoice::updateParameterPtr(const float* const p)
{
parameters = p;
}
void VexVoice::doProcess(float* outBufferL, float* outBufferR, int bufferSize)
{
//float resAmt = 0.0;
float A, B;
float amod;
wr.fillBuffer(outBufferL, bufferSize, oL);
wr.fillBuffer(outBufferR, bufferSize, oR);
for (int i = 0; i < bufferSize; i++)
{
//LFO
lfoS[0] = lfoS[0] - lfoC * lfoS[1];
lfoS[1] = lfoS[1] + lfoC * lfoS[0];
LFOA = lfoS[0] * parameters[20 + poff];
LFOF = lfoS[0] * parameters[21 + poff];
//Filter Mod
q = 1.1f - parameters[6 + poff];
cut = jlimit(0.001f, 0.999f, parameters[5 + poff]
+ (fadsr.getSample() * bipolar(parameters[8 + poff]))
+ Fvelocity
+ LFOF);
amod = LFOA + Avelocity;
//Filter
//Left
lowL = lowL + cut * bandL;
highL = outBufferL[i] - lowL - (q * bandL);
bandL = cut * highL + bandL;
B = (lowL * ((q * 0.5f) + 0.5f));
A = (highL * ((q * 0.5f) + 0.5f));
outBufferL[i] = A + parameters[7 + poff] * ( B - A );
outBufferL[i] += outBufferL[i] * amod;
//Right
lowR = lowR + cut * bandR;
highR = outBufferR[i] - lowR - (q * bandR);
bandR = cut * highR + bandR;
B = (lowR * ((q * 0.5f) + 0.5f));
A = (highR * ((q * 0.5f) + 0.5f));
outBufferR[i] = A + parameters[7 + poff] * ( B - A );
outBufferR[i] += outBufferR[i] * amod;
}
aadsr.doProcess(outBufferL, outBufferR, bufferSize);
isOn = aadsr.getState();
}
void VexVoice::start(float f, float v, int n, int preroll, double s, long o)
{
Ordinal = o;
SampleRate = s;
float oct = (parameters[1 + poff] - 0.5f) * 4.0f;
float cent = (parameters[2 + poff] - 0.5f) * 0.1f;
BaseFrequency = f * convertPitch(cent + oct);
wr.reset(BaseFrequency, SampleRate, oL);
wr.reset(BaseFrequency, SampleRate, oR);
note = n;
lfoS[0] = 0.5f;
lfoS[1] = 0.0f;
isOn = true;
isReleased = false;
v = (v * v) - 1.0f;
Avelocity = (v * bipolar(parameters[18 + poff]));
Fvelocity = (1.0f + v) * bipolar(parameters[13 + poff]);
aadsr.reset(preroll);
fadsr.reset(preroll);
}
void VexVoice::release(const int p)
{
isReleased = true;
aadsr.release(p);
fadsr.release(p);
}
void VexVoice::quickRelease()
{
isReleased = true;
aadsr.quickRelease();
}
void VexVoice::kill()
{
isOn = false;
}
/*
* params:
1 = oct
2 = cent
3 = phaseOffset
4 = phaseIncOffset
5,6,7,8 = filter
9,10,11,12 = F ADSR
13 = F velocity
14,15,16,17 = A ADSR
18 = A velocity
19 = lfoC
20 = lfoA
21 = lfoF
22,23,24 = fx volumes
*3
83,84,85 = panning synths
86,87,88 = volume synths
89,90,91 = on/off synths
*/
void VexVoice::update(const int index)
{
float p;
switch (index-poff)
{
case 14:
case 15:
case 16:
case 17:
aadsr.setADSR(parameters[14+poff], parameters[15+poff], parameters[16+poff], parameters[17+poff], SampleRate);
break;
case 9:
case 10:
case 11:
case 12:
fadsr.setADSR(parameters[9+poff], parameters[10+poff], parameters[11+poff], parameters[12+poff], SampleRate);
break;
case 19:
lfoC = 2.f * (float)sin(float_Pi*(parameters[19 + poff] * 10.0f) / SampleRate);
break;
case 3:
p = bipolar(parameters[3 + poff]);
oL.phaseOffset = p > 0.0f ? p : 0.0f;
oR.phaseOffset = p < 0.0f ? fabs(p) : 0.0f;
break;
case 4:
p = bipolar(parameters[4 + poff]);
oL.phaseIncOffset = p > 0.0f ? p : 0.0f;
oR.phaseIncOffset = p < 0.0f ? fabs(p) : 0.0f;
break;
}
}
long VexVoice::getOrdinal() const
{
return Ordinal;
}
int VexVoice::getNote() const
{
return note;
}
bool VexVoice::getIsOn() const
{
return isOn;
}
bool VexVoice::getIsReleased() const
{
return isReleased;
}

+ 91
- 0
source/modules/carla_native/vex/cVoice.h View File

@@ -0,0 +1,91 @@
/*
==============================================================================
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
==============================================================================
*/
#ifndef __JUCETICE_VEXCVOICE_HEADER__
#define __JUCETICE_VEXCVOICE_HEADER__
#ifdef CARLA_EXPORT
#include "JuceHeader.h"
#else
#include "../StandardHeader.h"
#endif
#include "cADSR.h"
#include "cWaveRenderer.h"
class VexVoice
{
public:
VexVoice(const float* const p, int poff, WaveRenderer& w, float sr = 44100);
void updateParameterPtr(const float* const p);
void doProcess(float* outBufferL, float* outBufferR, int bufferSize);
void start(float f, float v, int n, int preroll, double s, long o);
void release(int p);
void quickRelease();
void kill();
void update(const int index);
long getOrdinal() const;
int getNote() const;
bool getIsOn() const;
bool getIsReleased() const;
private:
OscSet oL;
OscSet oR;
WaveRenderer& wr;
VexADSR aadsr;
VexADSR fadsr;
const float* parameters;
const int poff;
bool isOn, isReleased;
int note;
long Ordinal;
float Avelocity;
float Fvelocity;
double SampleRate;
float BaseFrequency;
float lfoC, LFOA, LFOP, LFOF;
float lfoS[2];
float lowL, bandL, highL, lowR, bandR, highR, q, cut;
};
#endif

+ 91
- 0
source/modules/carla_native/vex/cWaveRenderer.cpp View File

@@ -0,0 +1,91 @@
/*
==============================================================================
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
==============================================================================
*/
#include "cWaveRenderer.h"
WaveTableNames WaveRenderer::waveTableNames[kWaveTableSize] = {
{ "asym_saw", Wavetables::asym_saw },
{ "bass_tone", Wavetables::bass_tone },
{ "buzz_1", Wavetables::buzz_1 },
{ "buzz_2", Wavetables::buzz_2 },
{ "dark_strings", Wavetables::dark_strings },
{ "deep_ring_1", Wavetables::deep_ring_1 },
{ "deep_ring_2", Wavetables::deep_ring_2 },
{ "epiano_tone", Wavetables::epiano_tone },
{ "ghost_1", Wavetables::ghost_1 },
{ "ghost_2", Wavetables::ghost_2 },
{ "ghost_3", Wavetables::ghost_3 },
{ "ghost_4", Wavetables::ghost_4 },
{ "grind_1", Wavetables::grind_1 },
{ "grind_2", Wavetables::grind_2 },
{ "more_strings", Wavetables::more_strings },
{ "multi_pulse", Wavetables::multi_pulse },
{ "organ_1", Wavetables::organ_1 },
{ "organ_2", Wavetables::organ_2 },
{ "one_string", Wavetables::one_string },
{ "phasing_sqr", Wavetables::phasing_sqr },
{ "pulse", Wavetables::pulse },
{ "saw", Wavetables::saw },
{ "sharp_1", Wavetables::sharp_1 },
{ "sharp_2", Wavetables::sharp_2 },
{ "sine", Wavetables::sine },
{ "soft_1", Wavetables::soft_1 },
{ "soft_2", Wavetables::soft_2 },
{ "soft_3", Wavetables::soft_3 },
{ "soft_4", Wavetables::soft_4 },
{ "square", Wavetables::square },
{ "string_fuzz", Wavetables::string_fuzz },
{ "strings_1", Wavetables::strings_1 },
{ "strings_2", Wavetables::strings_2 },
{ "syn_choir_1", Wavetables::syn_choir_1 },
{ "syn_choir_2", Wavetables::syn_choir_2 },
{ "syn_choir_3", Wavetables::syn_choir_3 },
{ "thin_1", Wavetables::thin_1 },
{ "thin_2", Wavetables::thin_2 },
{ "two_strings", Wavetables::two_strings },
{ "voice_1", Wavetables::voice_1 },
{ "voice_2", Wavetables::voice_2 }
};
int WaveRenderer::getWaveTableSize()
{
return kWaveTableSize;
}
String WaveRenderer::getWaveTableName(const int index)
{
jassert (index >= 0)
jassert (index < kWaveTableSize)
return String(WaveRenderer::waveTableNames[index].name);
}

+ 330
- 0
source/modules/carla_native/vex/cWaveRenderer.h View File

@@ -0,0 +1,330 @@
/*
==============================================================================
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
==============================================================================
*/
#ifndef __JUCETICE_VEXCWAVERENDERER_HEADER__
#define __JUCETICE_VEXCWAVERENDERER_HEADER__
#ifdef CARLA_EXPORT
#include "JuceHeader.h"
#include "ResourceFile.h"
#else
#include "../StandardHeader.h"
#include "../waverom/ResourceFile.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;
}
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)
{
for (int i = 0; i < bufferSize; ++i)
{
buffer[i] = 0.0f;
float tmp = 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;
tmp = 0.0f;
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

+ 8
- 0
source/plugin/carla-native-plugin.cpp View File

@@ -392,6 +392,8 @@ public:

const LV2_Program_Descriptor* lv2_get_program(const uint32_t index) const
{
if (fDescriptor->hints & PLUGIN_IS_SYNTH)
return nullptr;
if (fDescriptor->get_midi_program_count == nullptr)
return nullptr;
if (fDescriptor->get_midi_program_info == nullptr)
@@ -415,6 +417,8 @@ public:

void lv2_select_program(uint32_t bank, uint32_t program)
{
if (fDescriptor->hints & PLUGIN_IS_SYNTH)
return;
if (fDescriptor->set_midi_program == nullptr)
return;

@@ -523,6 +527,8 @@ public:

void lv2ui_select_program(uint32_t bank, uint32_t program) const
{
if (fDescriptor->hints & PLUGIN_IS_SYNTH)
return;
if (fDescriptor->ui_set_midi_program == nullptr)
return;

@@ -1189,6 +1195,8 @@ static const void* lv2_extension_data(const char* uri)
static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char*, const char*, LV2UI_Write_Function writeFunction,
LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features)
{
carla_debug("lv2ui_instantiate(..., %p, %p, %p)", writeFunction, controller, widget, features);

NativePlugin* plugin = nullptr;

for (int i=0; features[i] != nullptr; ++i)


Loading…
Cancel
Save