Browse Source

Split Vex and Zyn FX vs Synth code; Modify zyn fx to not use synth

tags/1.9.4
falkTX 12 years ago
parent
commit
3db9377c11
38 changed files with 1860 additions and 1613 deletions
  1. +8
    -4
      source/backend/plugin/NativePlugin.cpp
  2. +6
    -7
      source/modules/carla_native/Makefile
  3. +2
    -621
      source/modules/carla_native/vex-fx.cpp
  4. +720
    -0
      source/modules/carla_native/vex-synth.cpp
  5. +120
    -837
      source/modules/carla_native/zynaddsubfx-fx.cpp
  6. +19
    -0
      source/modules/carla_native/zynaddsubfx-src.cpp
  7. +794
    -0
      source/modules/carla_native/zynaddsubfx-synth.cpp
  8. +20
    -15
      source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.cpp
  9. +6
    -1
      source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.h
  10. +9
    -4
      source/modules/carla_native/zynaddsubfx/DSP/Filter.cpp
  11. +1
    -1
      source/modules/carla_native/zynaddsubfx/DSP/Filter.h
  12. +9
    -8
      source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.cpp
  13. +3
    -1
      source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.h
  14. +11
    -9
      source/modules/carla_native/zynaddsubfx/DSP/SVFilter.cpp
  15. +4
    -1
      source/modules/carla_native/zynaddsubfx/DSP/SVFilter.h
  16. +5
    -4
      source/modules/carla_native/zynaddsubfx/Effects/Alienwah.cpp
  17. +2
    -1
      source/modules/carla_native/zynaddsubfx/Effects/Alienwah.h
  18. +10
    -9
      source/modules/carla_native/zynaddsubfx/Effects/Chorus.cpp
  19. +1
    -1
      source/modules/carla_native/zynaddsubfx/Effects/Chorus.h
  20. +12
    -12
      source/modules/carla_native/zynaddsubfx/Effects/Distorsion.cpp
  21. +1
    -1
      source/modules/carla_native/zynaddsubfx/Effects/Distorsion.h
  22. +7
    -6
      source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.cpp
  23. +1
    -1
      source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.h
  24. +5
    -5
      source/modules/carla_native/zynaddsubfx/Effects/EQ.cpp
  25. +1
    -1
      source/modules/carla_native/zynaddsubfx/Effects/EQ.h
  26. +13
    -13
      source/modules/carla_native/zynaddsubfx/Effects/Echo.cpp
  27. +1
    -1
      source/modules/carla_native/zynaddsubfx/Effects/Echo.h
  28. +5
    -2
      source/modules/carla_native/zynaddsubfx/Effects/Effect.cpp
  29. +6
    -2
      source/modules/carla_native/zynaddsubfx/Effects/Effect.h
  30. +5
    -3
      source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.cpp
  31. +4
    -1
      source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.h
  32. +8
    -8
      source/modules/carla_native/zynaddsubfx/Effects/EffectMgr.cpp
  33. +11
    -11
      source/modules/carla_native/zynaddsubfx/Effects/Phaser.cpp
  34. +1
    -1
      source/modules/carla_native/zynaddsubfx/Effects/Phaser.h
  35. +14
    -14
      source/modules/carla_native/zynaddsubfx/Effects/Reverb.cpp
  36. +1
    -1
      source/modules/carla_native/zynaddsubfx/Effects/Reverb.h
  37. +6
    -2
      source/plugin/Makefile
  38. +8
    -4
      source/plugin/carla-native-base.cpp

+ 8
- 4
source/backend/plugin/NativePlugin.cpp View File

@@ -32,7 +32,8 @@ void carla_register_native_plugin_midiThrough();
void carla_register_native_plugin_midiTranspose();
void carla_register_native_plugin_nekofilter();
void carla_register_native_plugin_sunvoxfile();
void carla_register_native_plugin_vex();
void carla_register_native_plugin_vex_fx();
void carla_register_native_plugin_vex_synth();

#ifndef BUILD_BRIDGE
// Carla
@@ -65,7 +66,8 @@ void carla_register_native_plugin_Notes();

#ifdef WANT_ZYNADDSUBFX
// ZynAddSubFX
void carla_register_native_plugin_zynaddsubfx();
void carla_register_native_plugin_zynaddsubfx_fx();
void carla_register_native_plugin_zynaddsubfx_synth();
#endif
}

@@ -80,7 +82,8 @@ void carla_register_all_plugins()
carla_register_native_plugin_midiTranspose();
carla_register_native_plugin_nekofilter();
//carla_register_native_plugin_sunvoxfile(); // unfinished
carla_register_native_plugin_vex();
carla_register_native_plugin_vex_fx();
carla_register_native_plugin_vex_synth();

#ifndef BUILD_BRIDGE
// Carla
@@ -113,7 +116,8 @@ void carla_register_all_plugins()

#ifdef WANT_ZYNADDSUBFX
// ZynAddSubFX
carla_register_native_plugin_zynaddsubfx();
carla_register_native_plugin_zynaddsubfx_fx();
carla_register_native_plugin_zynaddsubfx_synth();
#endif
}



+ 6
- 7
source/modules/carla_native/Makefile View File

@@ -55,7 +55,8 @@ OBJS = \

# Simple plugins (C++)
OBJS += \
vex.cpp.o \
vex-fx.cpp.o \
vex-synth.cpp.o \
vex-src.cpp.o

# AudioFile
@@ -92,7 +93,8 @@ OBJS += \
ifeq ($(HAVE_ZYN_DEPS),true)
# ZynAddSubFX
OBJS += \
zynaddsubfx.cpp.o \
zynaddsubfx-fx.cpp.o \
zynaddsubfx-synth.cpp.o \
zynaddsubfx-src.cpp.o

ifeq ($(HAVE_ZYN_UI_DEPS),true)
@@ -199,13 +201,10 @@ midi-sequencer.cpp.o: midi-sequencer.cpp midi-base.hpp $(CXXDEPS)
nekofilter.c.o: nekofilter.c nekofilter/*.c nekofilter/*.h $(CDEPS)
$(CC) $< $(BUILD_C_FLAGS) -c -o $@

zynaddsubfx.cpp.o: zynaddsubfx.cpp $(CXXDEPS) $(ZYN_UI_FILES_H)
$(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@

zynaddsubfx-src.cpp.o: zynaddsubfx-src.cpp $(ZYN_UI_FILES_H)
zynaddsubfx-ui.cpp.o: zynaddsubfx-ui.cpp $(ZYN_UI_FILES_H) $(ZYN_UI_FILES_CPP)
$(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@

zynaddsubfx-ui.cpp.o: zynaddsubfx-ui.cpp $(ZYN_UI_FILES_H) $(ZYN_UI_FILES_CPP)
zynaddsubfx-%.cpp.o: zynaddsubfx-%.cpp $(CXXDEPS) $(ZYN_UI_FILES_H)
$(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@

zynaddsubfx/UI/%.cpp: zynaddsubfx/UI/%.fl


source/modules/carla_native/vex.cpp → source/modules/carla_native/vex-fx.cpp View File

@@ -17,7 +17,7 @@

#include "CarlaNative.hpp"

#include "juce_core.h"
#include "juce_gui_basics.h"

using namespace juce;

@@ -25,13 +25,8 @@ using namespace juce;
#include "vex/VexChorus.h"
#include "vex/VexDelay.h"
#include "vex/VexReverb.h"
#include "vex/VexSyntModule.h"

#include "vex/PeggyViewComponent.h"
#include "vex/lookandfeel/MyLookAndFeel.h"
#include "vex/resources/Resources.h"

#include "vex/resources/Resources.cpp"

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

@@ -96,139 +91,6 @@ private:

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

class VexEditorComponent : public ComboBox::Listener,
public Slider::Listener,
public Button::Listener,
public ChangeListener,
public Component,
public PeggyViewComponent::Callback
{
public:
VexEditorComponent()
{
internalCachedImage1 = ImageCache::getFromMemory(Resources::vex3_png, Resources::vex3_pngSize);

// Comboboxes, wave selection
addAndMakeVisible(comboBox1 = new ComboBox (String::empty));
comboBox1->setEditableText(false);
comboBox1->setJustificationType(Justification::centredLeft);
comboBox1->setTextWhenNothingSelected(String("silent"));
comboBox1->setTextWhenNoChoicesAvailable(String("silent"));
comboBox1->addListener(this);
comboBox1->setColour(ComboBox::backgroundColourId, Colours::black);
comboBox1->setColour(ComboBox::textColourId, Colours::lightgrey);
comboBox1->setColour(ComboBox::outlineColourId, Colours::grey);
comboBox1->setColour(ComboBox::buttonColourId, Colours::grey);
comboBox1->setWantsKeyboardFocus(false);
comboBox1->setLookAndFeel(&mlaf);

addAndMakeVisible (comboBox2 = new ComboBox (String::empty));
comboBox2->setEditableText (false);
comboBox2->setJustificationType (Justification::centredLeft);
comboBox2->setTextWhenNothingSelected (String("silent"));
comboBox2->setTextWhenNoChoicesAvailable (String("silent"));
comboBox2->addListener (this);
comboBox2->setColour(ComboBox::backgroundColourId, Colours::black);
comboBox2->setColour(ComboBox::textColourId, Colours::lightgrey);
comboBox2->setColour(ComboBox::outlineColourId, Colours::grey);
comboBox2->setColour(ComboBox::buttonColourId, Colours::grey);
comboBox2->setWantsKeyboardFocus(false);
comboBox2->setLookAndFeel(&mlaf);

addAndMakeVisible (comboBox3 = new ComboBox (String::empty));
comboBox3->setEditableText (false);
comboBox3->setJustificationType (Justification::centredLeft);
comboBox3->setTextWhenNothingSelected (String("silent"));
comboBox3->setTextWhenNoChoicesAvailable (String("silent"));
comboBox3->addListener (this);
comboBox3->setColour(ComboBox::backgroundColourId, Colours::black);
comboBox3->setColour(ComboBox::textColourId, Colours::lightgrey);
comboBox3->setColour(ComboBox::outlineColourId, Colours::grey);
comboBox3->setColour(ComboBox::buttonColourId, Colours::grey);
comboBox3->setWantsKeyboardFocus(false);
comboBox3->setLookAndFeel(&mlaf);

for (int i = 0, tableSize = WaveRenderer::getWaveTableSize(); i < tableSize; ++i)
{
String tableName(WaveRenderer::getWaveTableName(i));

comboBox1->addItem(tableName, i + 1);
comboBox2->addItem(tableName, i + 1);
comboBox3->addItem(tableName, i + 1);
}

addChildComponent(p1 = new PeggyViewComponent(1, _d, this));
p1->setLookAndFeel(&mlaf);
addChildComponent(p2 = new PeggyViewComponent(2, _d, this));
p2->setLookAndFeel(&mlaf);
addChildComponent(p3 = new PeggyViewComponent(3, _d, this));
p3->setLookAndFeel(&mlaf);

//ownerFilter->addChangeListener (this);
setSize(800,500);
}

~VexEditorComponent()
{
removeAllChildren();
}

protected:
void paint(Graphics& g) override
{
g.drawImage(internalCachedImage1,
0, 0, 800, 500,
0, 0, internalCachedImage1.getWidth(), internalCachedImage1.getHeight());
}

void resized() override
{
comboBox1->setBounds(13, 38, 173, 23);
comboBox2->setBounds(213, 38, 173, 23);
comboBox3->setBounds(413, 38, 173, 23);

p1->setBounds(10, 20, 207, 280);
p2->setBounds(210, 20, 207, 280);
p3->setBounds(410, 20, 207, 280);
}

void changeListenerCallback(ChangeBroadcaster* source) override
{
}

void comboBoxChanged(ComboBox* comboBoxThatHasChanged) override
{
}

void sliderValueChanged(Slider* sliderThatWasMoved) override
{
}

void buttonClicked(Button* buttonThatWasClicked) override
{
}

void somethingChanged(const uint32_t id) override
{
}

private:
Image internalCachedImage1;
MyLookAndFeel mlaf;

ScopedPointer<ComboBox> comboBox1;
ScopedPointer<ComboBox> comboBox2;
ScopedPointer<ComboBox> comboBox3;

ScopedPointer<PeggyViewComponent> p1;
ScopedPointer<PeggyViewComponent> p2;
ScopedPointer<PeggyViewComponent> p3;

VexArpSettings _d;
};

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

class VexArpPlugin : public PluginClass,
public PeggyViewComponent::Callback
{
@@ -1009,469 +871,6 @@ private:

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

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

VexSynthPlugin(const HostDescriptor* const host)
: PluginClass(host),
obf(nullptr),
abf(nullptr),
dbf1(nullptr),
dbf2(nullptr),
dbf3(nullptr),
fChorus(fParameters),
fDelay(fParameters),
fReverb(fParameters),
fSynth(fParameters)
{
std::memset(fParameters, 0, sizeof(float)*92);

fParameters[0] = 1.0f; // main volume

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

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

// ^1 - 72

fParameters[73] = 0.5f; // Delay Time
fParameters[74] = 0.4f; // Delay Feedback
fParameters[75] = 0.0f; // Delay Volume

fParameters[76] = 0.3f; // Chorus Rate
fParameters[77] = 0.6f; // Chorus Depth
fParameters[78] = 0.5f; // Chorus Volume

fParameters[79] = 0.6f; // Reverb Size
fParameters[80] = 0.7f; // Reverb Width
fParameters[81] = 0.6f; // Reverb Damp
fParameters[82] = 0.0f; // Reverb Volume

fParameters[83] = 0.5f; // wave1 panning
fParameters[84] = 0.5f; // wave2 panning
fParameters[85] = 0.5f; // wave3 panning

fParameters[86] = 0.5f; // wave1 volume
fParameters[87] = 0.5f; // wave2 volume
fParameters[88] = 0.5f; // wave3 volume

fParameters[89] = 1.0f; // wave1 on/off
fParameters[90] = 1.0f; // wave2 on/off
fParameters[91] = 1.0f; // wave3 on/off

bufferSizeChanged(getBufferSize());
sampleRateChanged(getSampleRate());
}

~VexSynthPlugin()
{
delete obf;
delete abf;
delete dbf1;
delete dbf2;
delete dbf3;
}

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 = PARAMETER_RANGES_DEFAULT_STEP;
paramInfo.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL;
paramInfo.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE;
paramInfo.scalePointCount = 0;
paramInfo.scalePoints = nullptr;

if (index >= 1 && index <= 72)
{
uint32_t ri = index % 24;

switch (ri)
{
case 1:
paramInfo.name = "oct";
break;
case 2:
paramInfo.name = "cent";
break;
case 3:
paramInfo.name = "phaseOffset";
break;
case 4:
paramInfo.name = "phaseIncOffset";
break;
case 5:
paramInfo.name = "filter";
break;
case 6:
paramInfo.name = "filter";
break;
case 7:
paramInfo.name = "filter";
break;
case 8:
paramInfo.name = "filter";
break;
case 9:
paramInfo.name = "F ADSR";
break;
case 10:
paramInfo.name = "F ADSR";
break;
case 11:
paramInfo.name = "F ADSR";
break;
case 12:
paramInfo.name = "F ADSR";
break;
case 13:
paramInfo.name = "F velocity";
break;
case 14:
paramInfo.name = "A ADSR";
break;
case 15:
paramInfo.name = "A ADSR";
break;
case 16:
paramInfo.name = "A ADSR";
break;
case 17:
paramInfo.name = "A ADSR";
break;
case 18:
paramInfo.name = "A velocity";
break;
case 19:
paramInfo.name = "lfoC";
break;
case 20:
paramInfo.name = "lfoA";
break;
case 21:
paramInfo.name = "lfoF";
break;
case 22:
paramInfo.name = "fx vol D";
break;
case 23:
paramInfo.name = "fx vol C";
break;
case 24:
case 0:
paramInfo.name = "fx vol R";
break;
default:
paramInfo.name = "unknown2";
break;
}

paramInfo.hints = static_cast<ParameterHints>(hints);
return &paramInfo;
}

switch (index)
{
case 0:
paramInfo.name = "Main volume";
break;
case 73:
paramInfo.name = "Delay Time";
break;
case 74:
paramInfo.name = "Delay Feedback";
break;
case 75:
paramInfo.name = "Delay Volume";
break;
case 76:
paramInfo.name = "Chorus Rate";
break;
case 77:
paramInfo.name = "Chorus Depth";
break;
case 78:
paramInfo.name = "Chorus Volume";
break;
case 79:
paramInfo.name = "Reverb Size";
break;
case 80:
paramInfo.name = "Reverb Width";
break;
case 81:
paramInfo.name = "Reverb Damp";
break;
case 82:
paramInfo.name = "Reverb Volume";
break;
case 83:
paramInfo.name = "Wave1 Panning";
break;
case 84:
paramInfo.name = "Wave2 Panning";
break;
case 85:
paramInfo.name = "Wave3 Panning";
break;
case 86:
paramInfo.name = "Wave1 Volume";
break;
case 87:
paramInfo.name = "Wave2 Volume";
break;
case 88:
paramInfo.name = "Wave3 Volume";
break;
case 89:
paramInfo.name = "Wave1 on/off";
break;
case 90:
paramInfo.name = "Wave2 on/off";
break;
case 91:
paramInfo.name = "Wave3 on/off";
break;
default:
paramInfo.name = "unknown";
break;
}

paramInfo.hints = static_cast<ParameterHints>(hints);
return &paramInfo;
}

float getParameterValue(const uint32_t index) const override
{
return (index < kParamCount) ? fParameters[index] : 0.0f;
}

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

void setParameterValue(const uint32_t index, const float value) override
{
if (index < kParamCount)
{
fParameters[index] = value;
fSynth.update(index);
}
}

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

void process(float**, float** outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override
{
const TimeInfo* const timeInfo(getTimeInfo());
const double bpm((timeInfo != nullptr && timeInfo->bbt.valid) ? timeInfo->bbt.beatsPerMinute : 120.0);

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)
{
fSynth.playNote(midiEvent->data[1], midiEvent->data[2], 0, 1);
}
else if (status == MIDI_STATUS_NOTE_OFF)
{
fSynth.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)
fSynth.kill();
else if (control == MIDI_CONTROL_ALL_NOTES_OFF)
fSynth.releaseAll(1);
}
}

if (obf->getNumSamples() != (int)frames)
{
obf->setSize(2, frames, 0, 0, 1);
abf->setSize(2, frames, 0, 0, 1);
dbf1->setSize(2, frames, 0, 0, 1);
dbf2->setSize(2, frames, 0, 0, 1);
dbf3->setSize(2, frames, 0, 0, 1);
}

obf ->clear();
dbf1->clear();
dbf2->clear();
dbf3->clear();

fSynth.doProcess(*obf, *abf, *dbf1, *dbf2, *dbf3);

if (fParameters[75] > 0.001f) fDelay.processBlock(dbf1, bpm);
if (fParameters[78] > 0.001f) fChorus.processBlock(dbf2);
if (fParameters[82] > 0.001f) fReverb.processBlock(dbf3);

AudioSampleBuffer output(outBuffer, 2, 0, frames);
output.clear();

obf->addFrom(0, 0, *dbf1, 0, 0, frames, fParameters[75]);
obf->addFrom(1, 0, *dbf1, 1, 0, frames, fParameters[75]);
obf->addFrom(0, 0, *dbf2, 0, 0, frames, fParameters[78]);
obf->addFrom(1, 0, *dbf2, 1, 0, frames, fParameters[78]);
obf->addFrom(0, 0, *dbf3, 0, 0, frames, fParameters[82]);
obf->addFrom(1, 0, *dbf3, 1, 0, frames, fParameters[82]);

output.addFrom(0, 0, *obf, 0, 0, frames, fParameters[0]);
output.addFrom(1, 0, *obf, 1, 0, frames, fParameters[0]);
}

// -------------------------------------------------------------------
// Plugin UI calls

void uiShow(const bool show) override
{
if (show)
{
if (fWindow == nullptr)
{
fWindow = new HelperWindow();
fWindow->setName(getUiName());
}

if (fView == nullptr)
fView = new VexEditorComponent();

fWindow->show(fView);
}
else if (fWindow != nullptr)
{
fWindow->hide();

fView = nullptr;
fWindow = nullptr;
}
}

void uiIdle() override
{
if (fWindow == nullptr)
return;

if (fWindow->wasClosedByUser())
{
uiShow(false);
uiClosed();
}
}

void uiSetParameterValue(const uint32_t, const float) override
{
if (fView == nullptr)
return;

//fView->update();
}

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

void bufferSizeChanged(const uint32_t bufferSize) override
{
delete obf;
delete abf;
delete dbf1;
delete dbf2;
delete dbf3;

obf = new AudioSampleBuffer(2, bufferSize);
abf = new AudioSampleBuffer(2, bufferSize);
dbf1 = new AudioSampleBuffer(2, bufferSize);
dbf2 = new AudioSampleBuffer(2, bufferSize);
dbf3 = new AudioSampleBuffer(2, bufferSize);
}

void sampleRateChanged(const double sampleRate) override
{
fChorus.setSampleRate(sampleRate);
fDelay.setSampleRate(sampleRate);
fSynth.setSampleRate(sampleRate);
}

void uiNameChanged(const char* const uiName) override
{
if (fWindow == nullptr)
return;

fWindow->setName(uiName);
}

private:
float fParameters[92];

AudioSampleBuffer* obf;
AudioSampleBuffer* abf;
AudioSampleBuffer* dbf1; // delay
AudioSampleBuffer* dbf2; // chorus
AudioSampleBuffer* dbf3; // reverb

VexChorus fChorus;
VexDelay fDelay;
VexReverb fReverb;
VexSyntModule fSynth;

ScopedPointer<VexEditorComponent> fView;
ScopedPointer<HelperWindow> fWindow;

PluginClassEND(VexSynthPlugin)
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexSynthPlugin)
};

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

static const PluginDescriptor vexArpDesc = {
/* category */ PLUGIN_CATEGORY_UTILITY,
/* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME),
@@ -1540,33 +939,15 @@ static const PluginDescriptor vexReverbDesc = {
PluginDescriptorFILL(VexReverbPlugin)
};

static const PluginDescriptor vexSynthDesc = {
/* category */ PLUGIN_CATEGORY_SYNTH,
/* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME),
/* 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
void carla_register_native_plugin_vex()
void carla_register_native_plugin_vex_fx()
{
carla_register_native_plugin(&vexArpDesc);
carla_register_native_plugin(&vexChorusDesc);
carla_register_native_plugin(&vexDelayDesc);
carla_register_native_plugin(&vexReverbDesc);
carla_register_native_plugin(&vexSynthDesc);
}

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

+ 720
- 0
source/modules/carla_native/vex-synth.cpp View File

@@ -0,0 +1,720 @@
/*
* Carla Native Plugins
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it 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.
*
* For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/

#include "CarlaNative.hpp"

#include "juce_gui_basics.h"

using namespace juce;

#include "vex/VexArp.h"
#include "vex/VexChorus.h"
#include "vex/VexDelay.h"
#include "vex/VexReverb.h"
#include "vex/VexSyntModule.h"

#include "vex/PeggyViewComponent.h"
#include "vex/lookandfeel/MyLookAndFeel.h"
#include "vex/resources/Resources.h"

#include "vex/resources/Resources.cpp"

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

class HelperWindow2 : public DocumentWindow
{
public:
HelperWindow2()
: DocumentWindow("PlugWindow", Colour(50, 50, 200), DocumentWindow::closeButton, false),
fClosed(false)
{
setVisible(false);
setAlwaysOnTop(true);
setDropShadowEnabled(false);
setOpaque(true);
//setResizable(false, false);
//setUsingNativeTitleBar(false);
}

void show(Component* const comp)
{
fClosed = false;

const int width = comp->getWidth();
const int height = comp->getHeight()+getTitleBarHeight();

centreWithSize(width, height);
setContentNonOwned(comp, false);
setSize(width, height);

if (! isOnDesktop())
addToDesktop();

setVisible(true);
}

void hide()
{
setVisible(false);

if (isOnDesktop())
removeFromDesktop();

clearContentComponent();
}

bool wasClosedByUser() const
{
return fClosed;
}

protected:
void closeButtonPressed() override
{
fClosed = true;
}

private:
bool fClosed;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HelperWindow2)
};

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

class VexEditorComponent : public ComboBox::Listener,
public Slider::Listener,
public Button::Listener,
public ChangeListener,
public Component,
public PeggyViewComponent::Callback
{
public:
VexEditorComponent()
{
internalCachedImage1 = ImageCache::getFromMemory(Resources::vex3_png, Resources::vex3_pngSize);

// Comboboxes, wave selection
addAndMakeVisible(comboBox1 = new ComboBox (String::empty));
comboBox1->setEditableText(false);
comboBox1->setJustificationType(Justification::centredLeft);
comboBox1->setTextWhenNothingSelected(String("silent"));
comboBox1->setTextWhenNoChoicesAvailable(String("silent"));
comboBox1->addListener(this);
comboBox1->setColour(ComboBox::backgroundColourId, Colours::black);
comboBox1->setColour(ComboBox::textColourId, Colours::lightgrey);
comboBox1->setColour(ComboBox::outlineColourId, Colours::grey);
comboBox1->setColour(ComboBox::buttonColourId, Colours::grey);
comboBox1->setWantsKeyboardFocus(false);
comboBox1->setLookAndFeel(&mlaf);

addAndMakeVisible (comboBox2 = new ComboBox (String::empty));
comboBox2->setEditableText (false);
comboBox2->setJustificationType (Justification::centredLeft);
comboBox2->setTextWhenNothingSelected (String("silent"));
comboBox2->setTextWhenNoChoicesAvailable (String("silent"));
comboBox2->addListener (this);
comboBox2->setColour(ComboBox::backgroundColourId, Colours::black);
comboBox2->setColour(ComboBox::textColourId, Colours::lightgrey);
comboBox2->setColour(ComboBox::outlineColourId, Colours::grey);
comboBox2->setColour(ComboBox::buttonColourId, Colours::grey);
comboBox2->setWantsKeyboardFocus(false);
comboBox2->setLookAndFeel(&mlaf);

addAndMakeVisible (comboBox3 = new ComboBox (String::empty));
comboBox3->setEditableText (false);
comboBox3->setJustificationType (Justification::centredLeft);
comboBox3->setTextWhenNothingSelected (String("silent"));
comboBox3->setTextWhenNoChoicesAvailable (String("silent"));
comboBox3->addListener (this);
comboBox3->setColour(ComboBox::backgroundColourId, Colours::black);
comboBox3->setColour(ComboBox::textColourId, Colours::lightgrey);
comboBox3->setColour(ComboBox::outlineColourId, Colours::grey);
comboBox3->setColour(ComboBox::buttonColourId, Colours::grey);
comboBox3->setWantsKeyboardFocus(false);
comboBox3->setLookAndFeel(&mlaf);

for (int i = 0, tableSize = WaveRenderer::getWaveTableSize(); i < tableSize; ++i)
{
String tableName(WaveRenderer::getWaveTableName(i));

comboBox1->addItem(tableName, i + 1);
comboBox2->addItem(tableName, i + 1);
comboBox3->addItem(tableName, i + 1);
}

addChildComponent(p1 = new PeggyViewComponent(1, _d, this));
p1->setLookAndFeel(&mlaf);
addChildComponent(p2 = new PeggyViewComponent(2, _d, this));
p2->setLookAndFeel(&mlaf);
addChildComponent(p3 = new PeggyViewComponent(3, _d, this));
p3->setLookAndFeel(&mlaf);

//ownerFilter->addChangeListener (this);
setSize(800,500);
}

~VexEditorComponent()
{
removeAllChildren();
}

protected:
void paint(Graphics& g) override
{
g.drawImage(internalCachedImage1,
0, 0, 800, 500,
0, 0, internalCachedImage1.getWidth(), internalCachedImage1.getHeight());
}

void resized() override
{
comboBox1->setBounds(13, 38, 173, 23);
comboBox2->setBounds(213, 38, 173, 23);
comboBox3->setBounds(413, 38, 173, 23);

p1->setBounds(10, 20, 207, 280);
p2->setBounds(210, 20, 207, 280);
p3->setBounds(410, 20, 207, 280);
}

void changeListenerCallback(ChangeBroadcaster* source) override
{
}

void comboBoxChanged(ComboBox* comboBoxThatHasChanged) override
{
}

void sliderValueChanged(Slider* sliderThatWasMoved) override
{
}

void buttonClicked(Button* buttonThatWasClicked) override
{
}

void somethingChanged(const uint32_t id) override
{
}

private:
Image internalCachedImage1;
MyLookAndFeel mlaf;

ScopedPointer<ComboBox> comboBox1;
ScopedPointer<ComboBox> comboBox2;
ScopedPointer<ComboBox> comboBox3;

ScopedPointer<PeggyViewComponent> p1;
ScopedPointer<PeggyViewComponent> p2;
ScopedPointer<PeggyViewComponent> p3;

VexArpSettings _d;
};

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

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

VexSynthPlugin(const HostDescriptor* const host)
: PluginClass(host),
obf(nullptr),
abf(nullptr),
dbf1(nullptr),
dbf2(nullptr),
dbf3(nullptr),
fChorus(fParameters),
fDelay(fParameters),
fReverb(fParameters),
fSynth(fParameters)
{
std::memset(fParameters, 0, sizeof(float)*92);

fParameters[0] = 1.0f; // main volume

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

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

// ^1 - 72

fParameters[73] = 0.5f; // Delay Time
fParameters[74] = 0.4f; // Delay Feedback
fParameters[75] = 0.0f; // Delay Volume

fParameters[76] = 0.3f; // Chorus Rate
fParameters[77] = 0.6f; // Chorus Depth
fParameters[78] = 0.5f; // Chorus Volume

fParameters[79] = 0.6f; // Reverb Size
fParameters[80] = 0.7f; // Reverb Width
fParameters[81] = 0.6f; // Reverb Damp
fParameters[82] = 0.0f; // Reverb Volume

fParameters[83] = 0.5f; // wave1 panning
fParameters[84] = 0.5f; // wave2 panning
fParameters[85] = 0.5f; // wave3 panning

fParameters[86] = 0.5f; // wave1 volume
fParameters[87] = 0.5f; // wave2 volume
fParameters[88] = 0.5f; // wave3 volume

fParameters[89] = 1.0f; // wave1 on/off
fParameters[90] = 1.0f; // wave2 on/off
fParameters[91] = 1.0f; // wave3 on/off

bufferSizeChanged(getBufferSize());
sampleRateChanged(getSampleRate());
}

~VexSynthPlugin()
{
delete obf;
delete abf;
delete dbf1;
delete dbf2;
delete dbf3;
}

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 = PARAMETER_RANGES_DEFAULT_STEP;
paramInfo.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL;
paramInfo.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE;
paramInfo.scalePointCount = 0;
paramInfo.scalePoints = nullptr;

if (index >= 1 && index <= 72)
{
uint32_t ri = index % 24;

switch (ri)
{
case 1:
paramInfo.name = "oct";
break;
case 2:
paramInfo.name = "cent";
break;
case 3:
paramInfo.name = "phaseOffset";
break;
case 4:
paramInfo.name = "phaseIncOffset";
break;
case 5:
paramInfo.name = "filter";
break;
case 6:
paramInfo.name = "filter";
break;
case 7:
paramInfo.name = "filter";
break;
case 8:
paramInfo.name = "filter";
break;
case 9:
paramInfo.name = "F ADSR";
break;
case 10:
paramInfo.name = "F ADSR";
break;
case 11:
paramInfo.name = "F ADSR";
break;
case 12:
paramInfo.name = "F ADSR";
break;
case 13:
paramInfo.name = "F velocity";
break;
case 14:
paramInfo.name = "A ADSR";
break;
case 15:
paramInfo.name = "A ADSR";
break;
case 16:
paramInfo.name = "A ADSR";
break;
case 17:
paramInfo.name = "A ADSR";
break;
case 18:
paramInfo.name = "A velocity";
break;
case 19:
paramInfo.name = "lfoC";
break;
case 20:
paramInfo.name = "lfoA";
break;
case 21:
paramInfo.name = "lfoF";
break;
case 22:
paramInfo.name = "fx vol D";
break;
case 23:
paramInfo.name = "fx vol C";
break;
case 24:
case 0:
paramInfo.name = "fx vol R";
break;
default:
paramInfo.name = "unknown2";
break;
}

paramInfo.hints = static_cast<ParameterHints>(hints);
return &paramInfo;
}

switch (index)
{
case 0:
paramInfo.name = "Main volume";
break;
case 73:
paramInfo.name = "Delay Time";
break;
case 74:
paramInfo.name = "Delay Feedback";
break;
case 75:
paramInfo.name = "Delay Volume";
break;
case 76:
paramInfo.name = "Chorus Rate";
break;
case 77:
paramInfo.name = "Chorus Depth";
break;
case 78:
paramInfo.name = "Chorus Volume";
break;
case 79:
paramInfo.name = "Reverb Size";
break;
case 80:
paramInfo.name = "Reverb Width";
break;
case 81:
paramInfo.name = "Reverb Damp";
break;
case 82:
paramInfo.name = "Reverb Volume";
break;
case 83:
paramInfo.name = "Wave1 Panning";
break;
case 84:
paramInfo.name = "Wave2 Panning";
break;
case 85:
paramInfo.name = "Wave3 Panning";
break;
case 86:
paramInfo.name = "Wave1 Volume";
break;
case 87:
paramInfo.name = "Wave2 Volume";
break;
case 88:
paramInfo.name = "Wave3 Volume";
break;
case 89:
paramInfo.name = "Wave1 on/off";
break;
case 90:
paramInfo.name = "Wave2 on/off";
break;
case 91:
paramInfo.name = "Wave3 on/off";
break;
default:
paramInfo.name = "unknown";
break;
}

paramInfo.hints = static_cast<ParameterHints>(hints);
return &paramInfo;
}

float getParameterValue(const uint32_t index) const override
{
return (index < kParamCount) ? fParameters[index] : 0.0f;
}

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

void setParameterValue(const uint32_t index, const float value) override
{
if (index < kParamCount)
{
fParameters[index] = value;
fSynth.update(index);
}
}

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

void process(float**, float** outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override
{
const TimeInfo* const timeInfo(getTimeInfo());
const double bpm((timeInfo != nullptr && timeInfo->bbt.valid) ? timeInfo->bbt.beatsPerMinute : 120.0);

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)
{
fSynth.playNote(midiEvent->data[1], midiEvent->data[2], 0, 1);
}
else if (status == MIDI_STATUS_NOTE_OFF)
{
fSynth.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)
fSynth.kill();
else if (control == MIDI_CONTROL_ALL_NOTES_OFF)
fSynth.releaseAll(1);
}
}

if (obf->getNumSamples() != (int)frames)
{
obf->setSize(2, frames, 0, 0, 1);
abf->setSize(2, frames, 0, 0, 1);
dbf1->setSize(2, frames, 0, 0, 1);
dbf2->setSize(2, frames, 0, 0, 1);
dbf3->setSize(2, frames, 0, 0, 1);
}

obf ->clear();
dbf1->clear();
dbf2->clear();
dbf3->clear();

fSynth.doProcess(*obf, *abf, *dbf1, *dbf2, *dbf3);

if (fParameters[75] > 0.001f) fDelay.processBlock(dbf1, bpm);
if (fParameters[78] > 0.001f) fChorus.processBlock(dbf2);
if (fParameters[82] > 0.001f) fReverb.processBlock(dbf3);

AudioSampleBuffer output(outBuffer, 2, 0, frames);
output.clear();

obf->addFrom(0, 0, *dbf1, 0, 0, frames, fParameters[75]);
obf->addFrom(1, 0, *dbf1, 1, 0, frames, fParameters[75]);
obf->addFrom(0, 0, *dbf2, 0, 0, frames, fParameters[78]);
obf->addFrom(1, 0, *dbf2, 1, 0, frames, fParameters[78]);
obf->addFrom(0, 0, *dbf3, 0, 0, frames, fParameters[82]);
obf->addFrom(1, 0, *dbf3, 1, 0, frames, fParameters[82]);

output.addFrom(0, 0, *obf, 0, 0, frames, fParameters[0]);
output.addFrom(1, 0, *obf, 1, 0, frames, fParameters[0]);
}

// -------------------------------------------------------------------
// Plugin UI calls

void uiShow(const bool show) override
{
if (show)
{
if (fWindow == nullptr)
{
fWindow = new HelperWindow2();
fWindow->setName(getUiName());
}

if (fView == nullptr)
fView = new VexEditorComponent();

fWindow->show(fView);
}
else if (fWindow != nullptr)
{
fWindow->hide();

fView = nullptr;
fWindow = nullptr;
}
}

void uiIdle() override
{
if (fWindow == nullptr)
return;

if (fWindow->wasClosedByUser())
{
uiShow(false);
uiClosed();
}
}

void uiSetParameterValue(const uint32_t, const float) override
{
if (fView == nullptr)
return;

//fView->update();
}

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

void bufferSizeChanged(const uint32_t bufferSize) override
{
delete obf;
delete abf;
delete dbf1;
delete dbf2;
delete dbf3;

obf = new AudioSampleBuffer(2, bufferSize);
abf = new AudioSampleBuffer(2, bufferSize);
dbf1 = new AudioSampleBuffer(2, bufferSize);
dbf2 = new AudioSampleBuffer(2, bufferSize);
dbf3 = new AudioSampleBuffer(2, bufferSize);
}

void sampleRateChanged(const double sampleRate) override
{
fChorus.setSampleRate(sampleRate);
fDelay.setSampleRate(sampleRate);
fSynth.setSampleRate(sampleRate);
}

void uiNameChanged(const char* const uiName) override
{
if (fWindow == nullptr)
return;

fWindow->setName(uiName);
}

private:
float fParameters[92];

AudioSampleBuffer* obf;
AudioSampleBuffer* abf;
AudioSampleBuffer* dbf1; // delay
AudioSampleBuffer* dbf2; // chorus
AudioSampleBuffer* dbf3; // reverb

VexChorus fChorus;
VexDelay fDelay;
VexReverb fReverb;
VexSyntModule fSynth;

ScopedPointer<VexEditorComponent> fView;
ScopedPointer<HelperWindow2> fWindow;

PluginClassEND(VexSynthPlugin)
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexSynthPlugin)
};

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

static const PluginDescriptor vexSynthDesc = {
/* category */ PLUGIN_CATEGORY_SYNTH,
/* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME),
/* 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
void carla_register_native_plugin_vex_synth()
{
carla_register_native_plugin(&vexSynthDesc);
}

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

source/modules/carla_native/zynaddsubfx-fx.cpp
File diff suppressed because it is too large
View File


+ 19
- 0
source/modules/carla_native/zynaddsubfx-src.cpp View File

@@ -63,3 +63,22 @@
#include "zynaddsubfx/Synth/Resonance.cpp"
#include "zynaddsubfx/Synth/SUBnote.cpp"
#include "zynaddsubfx/Synth/SynthNote.cpp"

// Dummy variables and functions for linking purposes
const char* instance_name = nullptr;
SYNTH_T* synth = nullptr;
class WavFile;
namespace Nio {
bool start(void){return 1;}
void stop(void){}
bool setSource(std::string){return true;}
bool setSink(std::string){return true;}
std::set<std::string> getSources(void){return std::set<std::string>();}
std::set<std::string> getSinks(void){return std::set<std::string>();}
std::string getSource(void){return "";}
std::string getSink(void){return "";}
void waveNew(WavFile*){}
void waveStart(void){}
void waveStop(void){}
void waveEnd(void){}
}

+ 794
- 0
source/modules/carla_native/zynaddsubfx-synth.cpp View File

@@ -0,0 +1,794 @@
/*
* Carla Native Plugins
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it 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.
*
* For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/

// for UINT32_MAX
#define __STDC_LIMIT_MACROS
#include <cstdint>

#include "CarlaNative.hpp"
#include "CarlaMIDI.h"
#include "CarlaString.hpp"
#include "RtList.hpp"

#include "zynaddsubfx/Misc/Master.h"
#include "zynaddsubfx/Misc/Part.h"
#include "zynaddsubfx/Misc/Util.h"

#ifdef WANT_ZYNADDSUBFX_UI
# ifdef override
# define override_hack
# undef override
# endif

# include "zynaddsubfx/UI/common.H"
# include "zynaddsubfx/UI/MasterUI.h"
# include <FL/Fl_Shared_Image.H>
# include <FL/Fl_Tiled_Image.H>
# include <FL/Fl_Theme.H>

# ifdef override_hack
# define override
# undef override_hack
# endif
#endif

#include <ctime>
#include <set>
#include <string>

#include "juce_core.h"

#ifdef WANT_ZYNADDSUBFX_UI

static Fl_Tiled_Image* gModuleBackdrop = nullptr;
static CarlaString gPixmapPath;
extern CarlaString gUiPixmapPath;

void set_module_parameters(Fl_Widget* o)
{
CARLA_ASSERT(gModuleBackdrop != nullptr);

o->box(FL_DOWN_FRAME);
o->align(o->align() | FL_ALIGN_IMAGE_BACKDROP);
o->color(FL_BLACK);
o->labeltype(FL_SHADOW_LABEL);

if (gModuleBackdrop != nullptr)
o->image(gModuleBackdrop);
}
#endif

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

class ZynAddSubFxPrograms
{
public:
ZynAddSubFxPrograms()
: fInitiated(false)
{
}

~ZynAddSubFxPrograms()
{
if (! fInitiated)
return;

for (auto it = fPrograms.begin(); it.valid(); it.next())
{
const ProgramInfo*& pInfo(*it);
delete pInfo;
}

fPrograms.clear();
}

void init()
{
if (fInitiated)
return;
fInitiated = true;

fPrograms.append(new ProgramInfo(0, 0, "default"));

Master& master(Master::getInstance());

pthread_mutex_lock(&master.mutex);

// refresh banks
master.bank.rescanforbanks();

for (uint32_t i=0, size = master.bank.banks.size(); i < size; ++i)
{
if (master.bank.banks[i].dir.empty())
continue;

master.bank.loadbank(master.bank.banks[i].dir);

for (unsigned int instrument = 0; instrument < BANK_SIZE; ++instrument)
{
const std::string insName(master.bank.getname(instrument));

if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
continue;

fPrograms.append(new ProgramInfo(i+1, instrument, insName.c_str()));
}
}

pthread_mutex_unlock(&master.mutex);
}

void load(Master* const master, const uint8_t channel, const uint32_t bank, const uint32_t program)
{
if (bank == 0)
{
pthread_mutex_lock(&master->mutex);

master->partonoff(channel, 1);
master->part[channel]->defaults();
master->part[channel]->applyparameters(false);

pthread_mutex_unlock(&master->mutex);

return;
}

const std::string& bankdir(master->bank.banks[bank-1].dir);

if (! bankdir.empty())
{
pthread_mutex_lock(&master->mutex);

master->partonoff(channel, 1);

master->bank.loadbank(bankdir);
master->bank.loadfromslot(program, master->part[channel]);

master->part[channel]->applyparameters(false);

pthread_mutex_unlock(&master->mutex);
}
}

uint32_t count()
{
return fPrograms.count();
}

const MidiProgram* getInfo(const uint32_t index)
{
if (index >= fPrograms.count())
return nullptr;

const ProgramInfo*& pInfo(fPrograms.getAt(index));

fRetProgram.bank = pInfo->bank;
fRetProgram.program = pInfo->prog;
fRetProgram.name = pInfo->name;

return &fRetProgram;
}

private:
struct ProgramInfo {
uint32_t bank;
uint32_t prog;
const char* name;

ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_)
: bank(bank_),
prog(prog_),
name(carla_strdup(name_)) {}

~ProgramInfo()
{
if (name != nullptr)
{
delete[] name;
name = nullptr;
}
}

#ifdef CARLA_PROPER_CPP11_SUPPORT
ProgramInfo() = delete;
ProgramInfo(ProgramInfo&) = delete;
ProgramInfo(const ProgramInfo&) = delete;
ProgramInfo& operator=(ProgramInfo&);
ProgramInfo& operator=(const ProgramInfo&);
#endif
};

bool fInitiated;
MidiProgram fRetProgram;
NonRtList<const ProgramInfo*> fPrograms;

CARLA_DECLARE_NON_COPY_CLASS(ZynAddSubFxPrograms)
};

static ZynAddSubFxPrograms sPrograms;

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

class ZynAddSubFxInstanceCount
{
public:
ZynAddSubFxInstanceCount()
: fCount(0)
{
}

~ZynAddSubFxInstanceCount()
{
CARLA_ASSERT(fCount == 0);
}

void addOne(const HostDescriptor* const host)
{
if (fCount++ == 0)
{
CARLA_ASSERT(synth == nullptr);
CARLA_ASSERT(denormalkillbuf == nullptr);

reinit(host);

#ifdef WANT_ZYNADDSUBFX_UI
if (gPixmapPath.isEmpty())
{
gPixmapPath = host->resourceDir;
gPixmapPath += "/zynaddsubfx/";
gUiPixmapPath = gPixmapPath;
}
#endif
}
}

void removeOne()
{
if (--fCount == 0)
{
CARLA_ASSERT(synth != nullptr);
CARLA_ASSERT(denormalkillbuf != nullptr);

Master::deleteInstance();

delete[] denormalkillbuf;
denormalkillbuf = nullptr;

delete synth;
synth = nullptr;
}
}

void reinit(const HostDescriptor* const host)
{
Master::deleteInstance();

if (denormalkillbuf != nullptr)
{
delete[] denormalkillbuf;
denormalkillbuf = nullptr;
}

if (synth != nullptr)
{
delete synth;
synth = nullptr;
}

synth = new SYNTH_T();
synth->buffersize = host->get_buffer_size(host->handle);
synth->samplerate = host->get_sample_rate(host->handle);
synth->alias();

config.init();
config.cfg.SoundBufferSize = synth->buffersize;
config.cfg.SampleRate = synth->samplerate;
config.cfg.GzipCompression = 0;

sprng(std::time(nullptr));

denormalkillbuf = new float[synth->buffersize];
for (int i=0; i < synth->buffersize; ++i)
denormalkillbuf[i] = (RND - 0.5f) * 1e-16;

Master::getInstance();
}

void maybeReinit(const HostDescriptor* const host)
{
if (host->get_buffer_size(host->handle) == static_cast<uint32_t>(synth->buffersize) &&
host->get_sample_rate(host->handle) == static_cast<double>(synth->samplerate))
return;

reinit(host);
}

private:
int fCount;

CARLA_DECLARE_NON_COPY_CLASS(ZynAddSubFxInstanceCount)
};

static ZynAddSubFxInstanceCount sInstanceCount;

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

class ZynAddSubFxThread : public juce::Thread
{
public:
ZynAddSubFxThread(Master* const master, const HostDescriptor* const host)
: juce::Thread("ZynAddSubFxThread"),
fMaster(master),
kHost(host),
#ifdef WANT_ZYNADDSUBFX_UI
fUi(nullptr),
fUiClosed(0),
fNextUiAction(-1),
#endif
fChangeProgram(false),
fNextChannel(0),
fNextBank(0),
fNextProgram(0)
{
}

~ZynAddSubFxThread()
{
#ifdef WANT_ZYNADDSUBFX_UI
// must be closed by now
CARLA_ASSERT(fUi == nullptr);
#endif
}

void loadProgramLater(const uint8_t channel, const uint32_t bank, const uint32_t program)
{
fNextChannel = channel;
fNextBank = bank;
fNextProgram = program;
fChangeProgram = true;
}

void stopLoadProgramLater()
{
fChangeProgram = false;
fNextChannel = 0;
fNextBank = 0;
fNextProgram = 0;
}

void setMaster(Master* const master)
{
fMaster = master;
}

#ifdef WANT_ZYNADDSUBFX_UI
void uiHide()
{
fNextUiAction = 0;
}

void uiShow()
{
fNextUiAction = 1;
}

void uiRepaint()
{
if (fUi != nullptr)
fNextUiAction = 2;
}
#endif

protected:
void run() override
{
while (! threadShouldExit())
{
#ifdef WANT_ZYNADDSUBFX_UI
Fl::lock();

if (fNextUiAction == 2) // repaint
{
CARLA_ASSERT(fUi != nullptr);

if (fUi != nullptr)
fUi->refresh_master_ui();
}
else if (fNextUiAction == 1) // init/show
{
static bool initialized = false;

if (! initialized)
{
initialized = true;
fl_register_images();

Fl_Dial::default_style(Fl_Dial::PIXMAP_DIAL);

if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "knob.png"))
Fl_Dial::default_image(img);

if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "window_backdrop.png"))
Fl::scheme_bg(new Fl_Tiled_Image(img));

if(Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "module_backdrop.png"))
gModuleBackdrop = new Fl_Tiled_Image(img);

Fl::background(50, 50, 50);
Fl::background2(70, 70, 70);
Fl::foreground(255, 255, 255);

Fl_Theme::set("Cairo");
}

CARLA_ASSERT(fUi == nullptr);

if (fUi == nullptr)
{
fUiClosed = 0;
fUi = new MasterUI(fMaster, &fUiClosed);
fUi->masterwindow->label(kHost->uiName);
fUi->showUI();
}
}
else if (fNextUiAction == 0) // close
{
CARLA_ASSERT(fUi != nullptr);

if (fUi != nullptr)
{
delete fUi;
fUi = nullptr;
}
}

fNextUiAction = -1;

if (fUiClosed != 0)
{
fUiClosed = 0;
fNextUiAction = 0;
kHost->ui_closed(kHost->handle);
}

Fl::check();
Fl::unlock();
#endif

if (fChangeProgram)
{
fChangeProgram = false;
sPrograms.load(fMaster, fNextChannel, fNextBank, fNextProgram);
fNextChannel = 0;
fNextBank = 0;
fNextProgram = 0;

#ifdef WANT_ZYNADDSUBFX_UI
if (fUi != nullptr)
{
Fl::lock();
fUi->refresh_master_ui();
Fl::unlock();
}
#endif

carla_msleep(15);
}
else
{
carla_msleep(30);
}
}

#ifdef WANT_ZYNADDSUBFX_UI
if (threadShouldExit() && fUi != nullptr)
{
Fl::lock();
delete fUi;
fUi = nullptr;
Fl::check();
Fl::unlock();
}
#endif
}

private:
Master* fMaster;
const HostDescriptor* const kHost;

#ifdef WANT_ZYNADDSUBFX_UI
MasterUI* fUi;
int fUiClosed;
volatile int fNextUiAction;
#endif

volatile bool fChangeProgram;
volatile uint8_t fNextChannel;
volatile uint32_t fNextBank;
volatile uint32_t fNextProgram;
};

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

class ZynAddSubFxPlugin : public PluginClass
{
public:
ZynAddSubFxPlugin(const HostDescriptor* const host)
: PluginClass(host),
fMaster(new Master()),
fSampleRate(getSampleRate()),
fIsActive(false),
fThread(fMaster, host)
{
fThread.startThread(3);

for (int i = 0; i < NUM_MIDI_PARTS; ++i)
fMaster->partonoff(i, 1);

sPrograms.init();
}

~ZynAddSubFxPlugin() override
{
//ensure that everything has stopped
pthread_mutex_lock(&fMaster->mutex);
pthread_mutex_unlock(&fMaster->mutex);
fThread.stopThread(-1);

delete fMaster;
fMaster = nullptr;
}

protected:
// -------------------------------------------------------------------
// Plugin midi-program calls

uint32_t getMidiProgramCount() const override
{
return sPrograms.count();
}

const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
{
return sPrograms.getInfo(index);
}

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

void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override
{
if (bank >= fMaster->bank.banks.size())
return;
if (program >= BANK_SIZE)
return;

if (isOffline() || ! fIsActive)
{
sPrograms.load(fMaster, channel, bank, program);
#ifdef WANT_ZYNADDSUBFX_UI
fThread.uiRepaint();
#endif
}
else
fThread.loadProgramLater(channel, bank, program);
}

void setCustomData(const char* const key, const char* const value) override
{
CARLA_ASSERT(key != nullptr);
CARLA_ASSERT(value != nullptr);

if (std::strcmp(key, "CarlaAlternateFile1") == 0) // xmz
fMaster->loadXML(value);
else if (std::strcmp(key, "CarlaAlternateFile2") == 0) // xiz
fMaster->part[0]->loadXMLinstrument(value);
}

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

void activate() override
{
fIsActive = true;
}

void deactivate() override
{
fIsActive = false;
}

void process(float**, float** const outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override
{
if (pthread_mutex_trylock(&fMaster->mutex) != 0)
{
carla_zeroFloat(outBuffer[0], frames);
carla_zeroFloat(outBuffer[1], frames);
return;
}

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);
const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent->data);

if (MIDI_IS_STATUS_NOTE_OFF(status))
{
const uint8_t note = midiEvent->data[1];

fMaster->noteOff(channel, note);
}
else if (MIDI_IS_STATUS_NOTE_ON(status))
{
const uint8_t note = midiEvent->data[1];
const uint8_t velo = midiEvent->data[2];

fMaster->noteOn(channel, note, velo);
}
else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
{
const uint8_t note = midiEvent->data[1];
const uint8_t pressure = midiEvent->data[2];

fMaster->polyphonicAftertouch(channel, note, pressure);
}
else if (MIDI_IS_STATUS_CONTROL_CHANGE(status))
{
const uint8_t control = midiEvent->data[1];
const uint8_t value = midiEvent->data[2];

fMaster->setController(channel, control, value);
}
else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status))
{
const uint8_t lsb = midiEvent->data[1];
const uint8_t msb = midiEvent->data[2];
const int value = ((msb << 7) | lsb) - 8192;

fMaster->setController(channel, C_pitchwheel, value);
}
}

fMaster->GetAudioOutSamples(frames, fSampleRate, outBuffer[0], outBuffer[1]);

pthread_mutex_unlock(&fMaster->mutex);
}

#ifdef WANT_ZYNADDSUBFX_UI
// -------------------------------------------------------------------
// Plugin UI calls

void uiShow(const bool show) override
{
if (show)
fThread.uiShow();
else
fThread.uiHide();
}
#endif

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

char* getState() const override
{
config.save();

char* data = nullptr;
fMaster->getalldata(&data);
return data;
}

void setState(const char* const data) override
{
fThread.stopLoadProgramLater();
fMaster->putalldata((char*)data, 0);
fMaster->applyparameters(true);
}

#if 0
// -------------------------------------------------------------------
// Plugin dispatcher

intptr_t pluginDispatcher(const PluginDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float) override
{
switch (opcode)
{
case PLUGIN_OPCODE_NULL:
break;
case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
// TODO
break;
case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
// TODO
break;
case PLUGIN_OPCODE_OFFLINE_CHANGED:
break;
case PLUGIN_OPCODE_UI_NAME_CHANGED:
#ifdef WANT_ZYNADDSUBFX_UI
// TODO
#endif
break;
}

return 0;

// unused
(void)index;
(void)value;
(void)ptr;
}
#endif

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

private:
Master* fMaster;
unsigned fSampleRate;
bool fIsActive;

ZynAddSubFxThread fThread;

public:
static PluginHandle _instantiate(const HostDescriptor* host)
{
sInstanceCount.addOne(host);
return new ZynAddSubFxPlugin(host);
}
static void _cleanup(PluginHandle handle)
{
delete (ZynAddSubFxPlugin*)handle;
sInstanceCount.removeOne();
}

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin)
};

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

static const PluginDescriptor zynaddsubfxDesc = {
/* category */ PLUGIN_CATEGORY_SYNTH,
#ifdef WANT_ZYNADDSUBFX_UI
/* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_USES_STATE),
#else
/* hints */ static_cast<PluginHints>(PLUGIN_USES_STATE),
#endif
/* supports */ static_cast<PluginSupports>(PLUGIN_SUPPORTS_CONTROL_CHANGES|PLUGIN_SUPPORTS_NOTE_AFTERTOUCH|PLUGIN_SUPPORTS_PITCHBEND|PLUGIN_SUPPORTS_ALL_SOUND_OFF),
/* audioIns */ 0,
/* audioOuts */ 2,
/* midiIns */ 1,
/* midiOuts */ 0,
/* paramIns */ 0,
/* paramOuts */ 0,
/* name */ "ZynAddSubFX",
/* label */ "zynaddsubfx",
/* maker */ "falkTX",
/* copyright */ "GNU GPL v2+",
PluginDescriptorFILL(ZynAddSubFxPlugin)
};

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

CARLA_EXPORT
void carla_register_native_plugin_zynaddsubfx_synth()
{
carla_register_native_plugin(&zynaddsubfxDesc);
}

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

+ 20
- 15
source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.cpp View File

@@ -31,14 +31,19 @@
AnalogFilter::AnalogFilter(unsigned char Ftype,
float Ffreq,
float Fq,
unsigned char Fstages)
unsigned char Fstages,
float srate, int bufsize)
:type(Ftype),
stages(Fstages),
freq(Ffreq),
q(Fq),
gain(1.0),
abovenq(false),
oldabovenq(false)
oldabovenq(false),
samplerate_f(srate),
halfsamplerate_f(srate/2.0f),
buffersize(bufsize),
buffersize_f(bufsize)
{
for(int i = 0; i < 3; ++i)
coeff.c[i] = coeff.d[i] = oldCoeff.c[i] = oldCoeff.d[i] = 0.0f;
@@ -74,8 +79,8 @@ void AnalogFilter::computefiltercoefs(void)

//do not allow frequencies bigger than samplerate/2
float freq = this->freq;
if(freq > (synth->halfsamplerate_f - 500.0f)) {
freq = synth->halfsamplerate_f - 500.0f;
if(freq > (halfsamplerate_f - 500.0f)) {
freq = halfsamplerate_f - 500.0f;
zerocoefs = true;
}
if(freq < 0.1f)
@@ -98,7 +103,7 @@ void AnalogFilter::computefiltercoefs(void)
float *d = coeff.d;

//General Constants
const float omega = 2 * PI * freq / synth->samplerate_f;
const float omega = 2 * PI * freq / samplerate_f;
const float sn = sinf(omega), cs = cosf(omega);
float alpha, beta;

@@ -109,7 +114,7 @@ void AnalogFilter::computefiltercoefs(void)
switch(type) {
case 0: //LPF 1 pole
if(!zerocoefs)
tmp = expf(-2.0f * PI * freq / synth->samplerate_f);
tmp = expf(-2.0f * PI * freq / samplerate_f);
else
tmp = 0.0f;
c[0] = 1.0f - tmp;
@@ -121,7 +126,7 @@ void AnalogFilter::computefiltercoefs(void)
break;
case 1: //HPF 1 pole
if(!zerocoefs)
tmp = expf(-2.0f * PI * freq / synth->samplerate_f);
tmp = expf(-2.0f * PI * freq / samplerate_f);
else
tmp = 0.0f;
c[0] = (1.0f + tmp) / 2.0f;
@@ -276,7 +281,7 @@ void AnalogFilter::setfreq(float frequency)
rap = 1.0f / rap;

oldabovenq = abovenq;
abovenq = frequency > (synth->halfsamplerate_f - 500.0f);
abovenq = frequency > (halfsamplerate_f - 500.0f);

bool nyquistthresh = (abovenq ^ oldabovenq);

@@ -331,7 +336,7 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist,
const Coeff &coeff)
{
if(order == 1) //First order filter
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1]
+ hist.y1 * coeff.d[1];
hist.y1 = y0;
@@ -339,7 +344,7 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist,
smp[i] = y0;
}
if(order == 2) //Second order filter
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1]
+ hist.x2 * coeff.c[2] + hist.y1 * coeff.d[1]
+ hist.y2 * coeff.d[2];
@@ -359,26 +364,26 @@ void AnalogFilter::filterout(float *smp)
if(needsinterpolation) {
//Merge Filter at old coeff with new coeff
float *ismp = getTmpBuffer();
memcpy(ismp, smp, synth->bufferbytes);
memcpy(ismp, smp, buffersize*sizeof(float));

for(int i = 0; i < stages + 1; ++i)
singlefilterout(ismp, oldHistory[i], oldCoeff);

for(int i = 0; i < synth->buffersize; ++i) {
float x = (float)i / synth->buffersize_f;
for(int i = 0; i < buffersize; ++i) {
float x = (float)i / buffersize_f;
smp[i] = ismp[i] * (1.0f - x) + smp[i] * x;
}
returnTmpBuffer(ismp);
needsinterpolation = false;
}

for(int i = 0; i < synth->buffersize; ++i)
for(int i = 0; i < buffersize; ++i)
smp[i] *= outgain;
}

float AnalogFilter::H(float freq)
{
float fr = freq / synth->samplerate_f * PI * 2.0f;
float fr = freq / samplerate_f * PI * 2.0f;
float x = coeff.c[0], y = 0.0f;
for(int n = 1; n < 3; ++n) {
x += cosf(n * fr) * coeff.c[n];


+ 6
- 1
source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.h View File

@@ -35,7 +35,7 @@ class AnalogFilter:public Filter
{
public:
AnalogFilter(unsigned char Ftype, float Ffreq, float Fq,
unsigned char Fstages);
unsigned char Fstages, float srate, int bufsize);
~AnalogFilter();
void filterout(float *smp);
void setfreq(float frequency);
@@ -79,6 +79,11 @@ class AnalogFilter:public Filter
bool abovenq, //if the frequency is above the nyquist
oldabovenq; //if the last time was above nyquist
//(used to see if it needs interpolation)

float samplerate_f;
float halfsamplerate_f;
int buffersize;
float buffersize_f;
};




+ 9
- 4
source/modules/carla_native/zynaddsubfx/DSP/Filter.cpp View File

@@ -29,24 +29,29 @@
#include "SVFilter.h"
#include "../Params/FilterParams.h"

Filter *Filter::generate(FilterParams *pars)
Filter *Filter::generate(FilterParams *pars, float srate, int bufsize)
{
if (srate == 0.0f)
srate = synth->samplerate_f;
if (bufsize == 0)
bufsize = synth->buffersize;

unsigned char Ftype = pars->Ptype;
unsigned char Fstages = pars->Pstages;

Filter *filter;
switch(pars->Pcategory) {
case 1:
filter = new FormantFilter(pars);
filter = new FormantFilter(pars, srate, bufsize);
break;
case 2:
filter = new SVFilter(Ftype, 1000.0f, pars->getq(), Fstages);
filter = new SVFilter(Ftype, 1000.0f, pars->getq(), Fstages, srate, bufsize);
filter->outgain = dB2rap(pars->getgain());
if(filter->outgain > 1.0f)
filter->outgain = sqrt(filter->outgain);
break;
default:
filter = new AnalogFilter(Ftype, 1000.0f, pars->getq(), Fstages);
filter = new AnalogFilter(Ftype, 1000.0f, pars->getq(), Fstages, srate, bufsize);
if((Ftype >= 6) && (Ftype <= 8))
filter->setgain(pars->getgain());
else


+ 1
- 1
source/modules/carla_native/zynaddsubfx/DSP/Filter.h View File

@@ -29,7 +29,7 @@ class Filter
{
public:
static float getrealfreq(float freqpitch);
static Filter *generate(class FilterParams * pars);
static Filter *generate(class FilterParams * pars, float srate = 0, int bufsize = 0);

virtual ~Filter() {}
virtual void filterout(float *smp) = 0;


+ 9
- 8
source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.cpp View File

@@ -27,11 +27,12 @@
#include "AnalogFilter.h"
#include "../Params/FilterParams.h"

FormantFilter::FormantFilter(FilterParams *pars)
FormantFilter::FormantFilter(FilterParams *pars, float srate, int bufsize)
{
buffersize = bufsize;
numformants = pars->Pnumformants;
for(int i = 0; i < numformants; ++i)
formant[i] = new AnalogFilter(4 /*BPF*/, 1000.0f, 10.0f, pars->Pstages);
formant[i] = new AnalogFilter(4 /*BPF*/, 1000.0f, 10.0f, pars->Pstages, srate, bufsize);
cleanup();

for(int j = 0; j < FF_MAX_VOWELS; ++j)
@@ -205,24 +206,24 @@ void FormantFilter::filterout(float *smp)
{
float *inbuffer = getTmpBuffer();

memcpy(inbuffer, smp, synth->bufferbytes);
memset(smp, 0, synth->bufferbytes);
memcpy(inbuffer, smp, buffersize*sizeof(float));
memset(smp, 0, buffersize*sizeof(float));

for(int j = 0; j < numformants; ++j) {
float *tmpbuf = getTmpBuffer();
for(int i = 0; i < synth->buffersize; ++i)
for(int i = 0; i < buffersize; ++i)
tmpbuf[i] = inbuffer[i] * outgain;
formant[j]->filterout(tmpbuf);

if(ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j], currentformants[j].amp))
for(int i = 0; i < synth->buffersize; ++i)
for(int i = 0; i < buffersize; ++i)
smp[i] += tmpbuf[i]
* INTERPOLATE_AMPLITUDE(oldformantamp[j],
currentformants[j].amp,
i,
synth->buffersize);
buffersize);
else
for(int i = 0; i < synth->buffersize; ++i)
for(int i = 0; i < buffersize; ++i)
smp[i] += tmpbuf[i] * currentformants[j].amp;
returnTmpBuffer(tmpbuf);
oldformantamp[j] = currentformants[j].amp;


+ 3
- 1
source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.h View File

@@ -30,7 +30,7 @@
class FormantFilter:public Filter
{
public:
FormantFilter(class FilterParams *pars);
FormantFilter(class FilterParams *pars, float srate, int bufsize);
~FormantFilter();
void filterout(float *smp);
void setfreq(float frequency);
@@ -61,6 +61,8 @@ class FormantFilter:public Filter
float oldinput, slowinput;
float Qfactor, formantslowness, oldQfactor;
float vowelclearness, sequencestretch;

int buffersize;
};

#endif

+ 11
- 9
source/modules/carla_native/zynaddsubfx/DSP/SVFilter.cpp View File

@@ -29,14 +29,16 @@
#include "SVFilter.h"

SVFilter::SVFilter(unsigned char Ftype, float Ffreq, float Fq,
unsigned char Fstages)
unsigned char Fstages, float srate, int bufsize)
:type(Ftype),
stages(Fstages),
freq(Ffreq),
q(Fq),
gain(1.0f),
needsinterpolation(false),
firsttime(true)
firsttime(true),
samplerate_f(srate),
buffersize(bufsize)
{
if(stages >= MAX_FILTER_STAGES)
stages = MAX_FILTER_STAGES;
@@ -58,7 +60,7 @@ void SVFilter::cleanup()

void SVFilter::computefiltercoefs(void)
{
par.f = freq / synth->samplerate_f * 4.0f;
par.f = freq / samplerate_f * 4.0f;
if(par.f > 0.99999f)
par.f = 0.99999f;
par.q = 1.0f - atanf(sqrtf(q)) * 2.0f / PI;
@@ -76,7 +78,7 @@ void SVFilter::setfreq(float frequency)
rap = 1.0f / rap;

oldabovenq = abovenq;
abovenq = frequency > (synth->samplerate_f / 2 - 500.0f);
abovenq = frequency > (samplerate_f / 2 - 500.0f);

bool nyquistthresh = (abovenq ^ oldabovenq);

@@ -144,7 +146,7 @@ void SVFilter::singlefilterout(float *smp, fstage &x, parameters &par)
errx(1, "Impossible SVFilter type encountered [%d]", type);
}

for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
x.low = x.low + par.f * x.band;
x.high = par.q_sqrt * smp[i] - x.low - par.q * x.band;
x.band = par.f * x.high + x.band;
@@ -160,19 +162,19 @@ void SVFilter::filterout(float *smp)

if(needsinterpolation) {
float *ismp = getTmpBuffer();
memcpy(ismp, smp, synth->bufferbytes);
memcpy(ismp, smp, buffersize*sizeof(float));

for(int i = 0; i < stages + 1; ++i)
singlefilterout(ismp, st[i], ipar);

for(int i = 0; i < synth->buffersize; ++i) {
float x = i / synth->buffersize_f;
for(int i = 0; i < buffersize; ++i) {
float x = i / (float)buffersize;
smp[i] = ismp[i] * (1.0f - x) + smp[i] * x;
}
returnTmpBuffer(ismp);
needsinterpolation = false;
}

for(int i = 0; i < synth->buffersize; ++i)
for(int i = 0; i < buffersize; ++i)
smp[i] *= outgain;
}

+ 4
- 1
source/modules/carla_native/zynaddsubfx/DSP/SVFilter.h View File

@@ -32,7 +32,7 @@ class SVFilter:public Filter
SVFilter(unsigned char Ftype,
float Ffreq,
float Fq,
unsigned char Fstages);
unsigned char Fstages, float srate, int bufsize);
~SVFilter();
void filterout(float *smp);
void setfreq(float frequency);
@@ -64,6 +64,9 @@ class SVFilter:public Filter
bool abovenq, //if the frequency is above the nyquist
oldabovenq;
bool needsinterpolation, firsttime;

float samplerate_f;
int buffersize;
};

#endif

+ 5
- 4
source/modules/carla_native/zynaddsubfx/Effects/Alienwah.cpp View File

@@ -23,8 +23,9 @@
#include <cmath>
#include "Alienwah.h"

Alienwah::Alienwah(bool insertion_, float *efxoutl_, float *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
Alienwah::Alienwah(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize),
lfo(srate, bufsize),
oldl(NULL),
oldr(NULL)
{
@@ -58,8 +59,8 @@ void Alienwah::out(const Stereo<float *> &smp)
clfol = complex<float>(cosf(lfol + phase) * fb, sinf(lfol + phase) * fb); //rework
clfor = complex<float>(cosf(lfor + phase) * fb, sinf(lfor + phase) * fb); //rework

for(int i = 0; i < synth->buffersize; ++i) {
float x = ((float) i) / synth->buffersize_f;
for(int i = 0; i < buffersize; ++i) {
float x = float(i) / float(buffersize);
float x1 = 1.0f - x;
//left
complex<float> tmp = clfol * x + oldclfol * x1;


+ 2
- 1
source/modules/carla_native/zynaddsubfx/Effects/Alienwah.h View File

@@ -44,7 +44,8 @@ class Alienwah:public Effect
*/
Alienwah(bool insertion_,
float *const efxoutl_,
float *const efxoutr_);
float *const efxoutr_,
unsigned int srate, int bufsize);
~Alienwah();
void out(const Stereo<float *> &smp);



+ 10
- 9
source/modules/carla_native/zynaddsubfx/Effects/Chorus.cpp View File

@@ -26,9 +26,10 @@

using namespace std;

Chorus::Chorus(bool insertion_, float *const efxoutl_, float *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
maxdelay((int)(MAX_CHORUS_DELAY / 1000.0f * synth->samplerate_f)),
Chorus::Chorus(bool insertion_, float *const efxoutl_, float *efxoutr_, unsigned int srate, int bufsize)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize),
lfo(srate, bufsize),
maxdelay((int)(MAX_CHORUS_DELAY / 1000.0f * (float)srate)),
delaySample(new float[maxdelay], new float[maxdelay])
{
dlk = 0;
@@ -51,7 +52,7 @@ Chorus::~Chorus()
float Chorus::getdelay(float xlfo)
{
float result =
(Pflangemode) ? 0 : (delay + xlfo * depth) * synth->samplerate_f;
(Pflangemode) ? 0 : (delay + xlfo * depth) * (float)samplerate;

//check if delay is too big (caused by bad setdelay() and setdepth()
if((result + 0.5f) >= maxdelay) {
@@ -75,7 +76,7 @@ void Chorus::out(const Stereo<float *> &input)
dl2 = getdelay(lfol);
dr2 = getdelay(lfor);

for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
float inL = input.l[i];
float inR = input.r[i];
//LRcross
@@ -87,7 +88,7 @@ void Chorus::out(const Stereo<float *> &input)

//compute the delay in samples using linear interpolation between the lfo delays
float mdel =
(dl1 * (synth->buffersize - i) + dl2 * i) / synth->buffersize_f;
(dl1 * (buffersize - i) + dl2 * i) / (float)buffersize;
if(++dlk >= maxdelay)
dlk = 0;
float tmp = dlk - mdel + maxdelay * 2.0f; //where should I get the sample from
@@ -105,7 +106,7 @@ void Chorus::out(const Stereo<float *> &input)
//Right channel

//compute the delay in samples using linear interpolation between the lfo delays
mdel = (dr1 * (synth->buffersize - i) + dr2 * i) / synth->buffersize_f;
mdel = (dr1 * (buffersize - i) + dr2 * i) / (float)buffersize;
if(++drk >= maxdelay)
drk = 0;
tmp = drk * 1.0f - mdel + maxdelay * 2.0f; //where should I get the sample from
@@ -122,12 +123,12 @@ void Chorus::out(const Stereo<float *> &input)
}

if(Poutsub)
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
efxoutl[i] *= -1.0f;
efxoutr[i] *= -1.0f;
}

for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
efxoutl[i] *= pangainL;
efxoutr[i] *= pangainR;
}


+ 1
- 1
source/modules/carla_native/zynaddsubfx/Effects/Chorus.h View File

@@ -32,7 +32,7 @@
class Chorus:public Effect
{
public:
Chorus(bool insertion_, float *efxoutl_, float *efxoutr_);
Chorus(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize);
/**Destructor*/
~Chorus();
void out(const Stereo<float *> &input);


+ 12
- 12
source/modules/carla_native/zynaddsubfx/Effects/Distorsion.cpp View File

@@ -25,8 +25,8 @@
#include "../Misc/WaveShapeSmps.h"
#include <cmath>

Distorsion::Distorsion(bool insertion_, float *efxoutl_, float *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
Distorsion::Distorsion(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize),
Pvolume(50),
Pdrive(90),
Plevel(64),
@@ -37,10 +37,10 @@ Distorsion::Distorsion(bool insertion_, float *efxoutl_, float *efxoutr_)
Pstereo(0),
Pprefiltering(0)
{
lpfl = new AnalogFilter(2, 22000, 1, 0);
lpfr = new AnalogFilter(2, 22000, 1, 0);
hpfl = new AnalogFilter(3, 20, 1, 0);
hpfr = new AnalogFilter(3, 20, 1, 0);
lpfl = new AnalogFilter(2, 22000, 1, 0, srate, bufsize);
lpfr = new AnalogFilter(2, 22000, 1, 0, srate, bufsize);
hpfl = new AnalogFilter(3, 20, 1, 0, srate, bufsize);
hpfr = new AnalogFilter(3, 20, 1, 0, srate, bufsize);
setpreset(Ppreset);
cleanup();
}
@@ -83,29 +83,29 @@ void Distorsion::out(const Stereo<float *> &smp)
inputvol *= -1.0f;

if(Pstereo) //Stereo
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
efxoutl[i] = smp.l[i] * inputvol * pangainL;
efxoutr[i] = smp.r[i] * inputvol * pangainR;
}
else //Mono
for(int i = 0; i < synth->buffersize; ++i)
for(int i = 0; i < buffersize; ++i)
efxoutl[i] = (smp.l[i] * pangainL + smp.r[i] * pangainR) * inputvol;

if(Pprefiltering)
applyfilters(efxoutl, efxoutr);

waveShapeSmps(synth->buffersize, efxoutl, Ptype + 1, Pdrive);
waveShapeSmps(buffersize, efxoutl, Ptype + 1, Pdrive);
if(Pstereo)
waveShapeSmps(synth->buffersize, efxoutr, Ptype + 1, Pdrive);
waveShapeSmps(buffersize, efxoutr, Ptype + 1, Pdrive);

if(!Pprefiltering)
applyfilters(efxoutl, efxoutr);

if(!Pstereo)
memcpy(efxoutr, efxoutl, synth->bufferbytes);
memcpy(efxoutr, efxoutl, buffersize*sizeof(float));

float level = dB2rap(60.0f * Plevel / 127.0f - 40.0f);
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
float lout = efxoutl[i];
float rout = efxoutr[i];
float l = lout * (1.0f - lrcross) + rout * lrcross;


+ 1
- 1
source/modules/carla_native/zynaddsubfx/Effects/Distorsion.h View File

@@ -29,7 +29,7 @@
class Distorsion:public Effect
{
public:
Distorsion(bool insertion, float *efxoutl_, float *efxoutr_);
Distorsion(bool insertion, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize);
~Distorsion();
void out(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);


+ 7
- 6
source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.cpp View File

@@ -24,8 +24,9 @@
#include "DynamicFilter.h"
#include "../DSP/Filter.h"

DynamicFilter::DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, new FilterParams(0, 64, 64), 0),
DynamicFilter::DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize)
:Effect(insertion_, efxoutl_, efxoutr_, new FilterParams(0, 64, 64), 0, srate, bufsize),
lfo(srate, bufsize),
Pvolume(110),
Pdepth(0),
Pampsns(90),
@@ -61,7 +62,7 @@ void DynamicFilter::out(const Stereo<float *> &smp)
const float freq = filterpars->getfreq();
const float q = filterpars->getq();

for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
efxoutl[i] = smp.l[i];
efxoutr[i] = smp.r[i];

@@ -85,7 +86,7 @@ void DynamicFilter::out(const Stereo<float *> &smp)
filterr->filterout(efxoutr);

//panning
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
efxoutl[i] *= pangainL;
efxoutr[i] *= pangainR;
}
@@ -130,8 +131,8 @@ void DynamicFilter::reinitfilter(void)
{
delete filterl;
delete filterr;
filterl = Filter::generate(filterpars);
filterr = Filter::generate(filterpars);
filterl = Filter::generate(filterpars, samplerate, buffersize);
filterr = Filter::generate(filterpars, samplerate, buffersize);
}

void DynamicFilter::setpreset(unsigned char npreset)


+ 1
- 1
source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.h View File

@@ -30,7 +30,7 @@
class DynamicFilter:public Effect
{
public:
DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_);
DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize);
~DynamicFilter();
void out(const Stereo<float *> &smp);



+ 5
- 5
source/modules/carla_native/zynaddsubfx/Effects/EQ.cpp View File

@@ -24,8 +24,8 @@
#include "EQ.h"
#include "../DSP/AnalogFilter.h"

EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0)
EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize)
{
for(int i = 0; i < MAX_EQ_BANDS; ++i) {
filter[i].Ptype = 0;
@@ -33,8 +33,8 @@ EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_)
filter[i].Pgain = 64;
filter[i].Pq = 64;
filter[i].Pstages = 0;
filter[i].l = new AnalogFilter(6, 1000.0f, 1.0f, 0);
filter[i].r = new AnalogFilter(6, 1000.0f, 1.0f, 0);
filter[i].l = new AnalogFilter(6, 1000.0f, 1.0f, 0, srate, bufsize);
filter[i].r = new AnalogFilter(6, 1000.0f, 1.0f, 0, srate, bufsize);
}
//default values
Pvolume = 50;
@@ -56,7 +56,7 @@ void EQ::cleanup(void)
//Effect output
void EQ::out(const Stereo<float *> &smp)
{
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
efxoutl[i] = smp.l[i] * volume;
efxoutr[i] = smp.r[i] * volume;
}


+ 1
- 1
source/modules/carla_native/zynaddsubfx/Effects/EQ.h View File

@@ -29,7 +29,7 @@
class EQ:public Effect
{
public:
EQ(bool insertion_, float *efxoutl_, float *efxoutr_);
EQ(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize);
~EQ() {}
void out(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);


+ 13
- 13
source/modules/carla_native/zynaddsubfx/Effects/Echo.cpp View File

@@ -27,8 +27,8 @@

#define MAX_DELAY 2

Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize),
Pvolume(50),
Pdelay(60),
Plrdelay(100),
@@ -37,8 +37,8 @@ Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_)
delayTime(1),
lrdelay(0),
avgDelay(0),
delay(new float[(int)(MAX_DELAY * synth->samplerate)],
new float[(int)(MAX_DELAY * synth->samplerate)]),
delay(new float[(int)(MAX_DELAY * srate)],
new float[(int)(MAX_DELAY * srate)]),
old(0.0f),
pos(0),
delta(1),
@@ -57,8 +57,8 @@ Echo::~Echo()
//Cleanup the effect
void Echo::cleanup(void)
{
memset(delay.l, 0, MAX_DELAY * synth->samplerate * sizeof(float));
memset(delay.r, 0, MAX_DELAY * synth->samplerate * sizeof(float));
memset(delay.l, 0, MAX_DELAY * samplerate * sizeof(float));
memset(delay.r, 0, MAX_DELAY * samplerate * sizeof(float));
old = Stereo<float>(0.0f);
}

@@ -77,14 +77,14 @@ void Echo::initdelays(void)
//number of seconds to delay right chan
float dr = avgDelay + lrdelay;

ndelta.l = max(1, (int) (dl * synth->samplerate));
ndelta.r = max(1, (int) (dr * synth->samplerate));
ndelta.l = max(1, (int) (dl * samplerate));
ndelta.r = max(1, (int) (dr * samplerate));
}

//Effect output
void Echo::out(const Stereo<float *> &input)
{
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
float ldl = delay.l[pos.l];
float rdl = delay.r[pos.r];
ldl = ldl * (1.0f - lrcross) + rdl * lrcross;
@@ -97,9 +97,9 @@ void Echo::out(const Stereo<float *> &input)
rdl = input.r[i] * pangainR - rdl * fb;

//LowPass Filter
old.l = delay.l[(pos.l + delta.l) % (MAX_DELAY * synth->samplerate)] =
old.l = delay.l[(pos.l + delta.l) % (MAX_DELAY * samplerate)] =
ldl * hidamp + old.l * (1.0f - hidamp);
old.r = delay.r[(pos.r + delta.r) % (MAX_DELAY * synth->samplerate)] =
old.r = delay.r[(pos.r + delta.r) % (MAX_DELAY * samplerate)] =
rdl * hidamp + old.r * (1.0f - hidamp);

//increment
@@ -107,8 +107,8 @@ void Echo::out(const Stereo<float *> &input)
++pos.r; // += delta.r;

//ensure that pos is still in bounds
pos.l %= MAX_DELAY * synth->samplerate;
pos.r %= MAX_DELAY * synth->samplerate;
pos.l %= MAX_DELAY * samplerate;
pos.r %= MAX_DELAY * samplerate;

//adjust delay if needed
delta.l = (15 * delta.l + ndelta.l) / 16;


+ 1
- 1
source/modules/carla_native/zynaddsubfx/Effects/Echo.h View File

@@ -30,7 +30,7 @@
class Echo:public Effect
{
public:
Echo(bool insertion_, float *efxoutl_, float *efxoutr_);
Echo(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize);
~Echo();

void out(const Stereo<float *> &input);


+ 5
- 2
source/modules/carla_native/zynaddsubfx/Effects/Effect.cpp View File

@@ -26,12 +26,15 @@
#include <cmath>

Effect::Effect(bool insertion_, float *efxoutl_, float *efxoutr_,
FilterParams *filterpars_, unsigned char Ppreset_)
FilterParams *filterpars_, unsigned char Ppreset_,
unsigned int srate, int bufsize)
:Ppreset(Ppreset_),
efxoutl(efxoutl_),
efxoutr(efxoutr_),
filterpars(filterpars_),
insertion(insertion_)
insertion(insertion_),
samplerate(srate),
buffersize(bufsize)
{}

void Effect::out(float *const smpsl, float *const smpsr)


+ 6
- 2
source/modules/carla_native/zynaddsubfx/Effects/Effect.h View File

@@ -24,7 +24,6 @@
#define EFFECT_H

#include "../Misc/Util.h"
#include "../globals.h"
#include "../Params/FilterParams.h"
#include "../Misc/Stereo.h"

@@ -43,7 +42,8 @@ class Effect
* @param Ppreset_ chosen preset
* @return Initialized Effect object*/
Effect(bool insertion_, float *efxoutl_, float *efxoutr_,
FilterParams *filterpars_, unsigned char Ppreset_);
FilterParams *filterpars_, unsigned char Ppreset_,
unsigned int srate, int bufsize);
virtual ~Effect() {}
/**
* Choose a preset
@@ -100,6 +100,10 @@ class Effect
float pangainR;
char Plrcross; // L/R mix
float lrcross;

// current setup
unsigned int samplerate;
int buffersize;
};

#endif

+ 5
- 3
source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.cpp View File

@@ -25,7 +25,7 @@

#include <cmath>

EffectLFO::EffectLFO(void)
EffectLFO::EffectLFO(float srate, float bufsize)
:Pfreq(40),
Prandomness(0),
PLFOtype(0),
@@ -36,7 +36,9 @@ EffectLFO::EffectLFO(void)
ampl2(RND),
ampr1(RND),
ampr2(RND),
lfornd(0.0f)
lfornd(0.0f),
samplerate_f(srate),
buffersize_f(bufsize)
{
updateparams();
}
@@ -47,7 +49,7 @@ EffectLFO::~EffectLFO() {}
void EffectLFO::updateparams(void)
{
float lfofreq = (powf(2.0f, Pfreq / 127.0f * 10.0f) - 1.0f) * 0.03f;
incx = fabsf(lfofreq) * synth->buffersize_f / synth->samplerate_f;
incx = fabsf(lfofreq) * buffersize_f / samplerate_f;
if(incx > 0.49999999f)
incx = 0.499999999f; //Limit the Frequency



+ 4
- 1
source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.h View File

@@ -28,7 +28,7 @@
class EffectLFO
{
public:
EffectLFO();
EffectLFO(float srate, float bufsize);
~EffectLFO();
void effectlfoout(float *outl, float *outr);
void updateparams(void);
@@ -45,6 +45,9 @@ class EffectLFO
float lfointensity;
float lfornd;
char lfotype;

float samplerate_f;
float buffersize_f;
};

#endif

+ 8
- 8
source/modules/carla_native/zynaddsubfx/Effects/EffectMgr.cpp View File

@@ -76,28 +76,28 @@ void EffectMgr::changeeffect(int _nefx)
delete efx;
switch(nefx) {
case 1:
efx = new Reverb(insertion, efxoutl, efxoutr);
efx = new Reverb(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
break;
case 2:
efx = new Echo(insertion, efxoutl, efxoutr);
efx = new Echo(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
break;
case 3:
efx = new Chorus(insertion, efxoutl, efxoutr);
efx = new Chorus(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
break;
case 4:
efx = new Phaser(insertion, efxoutl, efxoutr);
efx = new Phaser(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
break;
case 5:
efx = new Alienwah(insertion, efxoutl, efxoutr);
efx = new Alienwah(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
break;
case 6:
efx = new Distorsion(insertion, efxoutl, efxoutr);
efx = new Distorsion(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
break;
case 7:
efx = new EQ(insertion, efxoutl, efxoutr);
efx = new EQ(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
break;
case 8:
efx = new DynamicFilter(insertion, efxoutl, efxoutr);
efx = new DynamicFilter(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
break;
//put more effect here
default:


+ 11
- 11
source/modules/carla_native/zynaddsubfx/Effects/Phaser.cpp View File

@@ -39,8 +39,8 @@ using namespace std;
#define ONE_ 0.99999f // To prevent LFO ever reaching 1.0f for filter stability purposes
#define ZERO_ 0.00001f // Same idea as above.

Phaser::Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), old(NULL), xn1(NULL),
Phaser::Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), lfo(srate, bufsize), old(NULL), xn1(NULL),
yn1(NULL), diff(0.0f), oldgain(0.0f), fb(0.0f)
{
analog_setup();
@@ -72,8 +72,8 @@ void Phaser::analog_setup()
Rmx = Rmin / Rmax;
Rconst = 1.0f + Rmx; // Handle parallel resistor relationship
C = 0.00000005f; // 50 nF
CFs = 2.0f * synth->samplerate_f * C;
invperiod = 1.0f / synth->buffersize_f;
CFs = 2.0f * float(samplerate) * C;
invperiod = 1.0f / float(buffersize);
}

Phaser::~Phaser()
@@ -129,7 +129,7 @@ void Phaser::AnalogPhase(const Stereo<float *> &input)
g = oldgain;
oldgain = mod;

for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
g.l += diff.l; // Linear interpolation between LFO samples
g.r += diff.r;

@@ -151,8 +151,8 @@ void Phaser::AnalogPhase(const Stereo<float *> &input)
}

if(Poutsub) {
invSignal(efxoutl, synth->buffersize);
invSignal(efxoutr, synth->buffersize);
invSignal(efxoutl, buffersize);
invSignal(efxoutr, buffersize);
}
}

@@ -202,8 +202,8 @@ void Phaser::normalPhase(const Stereo<float *> &input)
gain.l = limit(gain.l, ZERO_, ONE_);
gain.r = limit(gain.r, ZERO_, ONE_);

for(int i = 0; i < synth->buffersize; ++i) {
float x = (float) i / synth->buffersize_f;
for(int i = 0; i < buffersize; ++i) {
float x = float(i) / float(buffersize);
float x1 = 1.0f - x;
//TODO think about making panning an external feature
Stereo<float> xn(input.l[i] * pangainL + fb.l,
@@ -227,8 +227,8 @@ void Phaser::normalPhase(const Stereo<float *> &input)
oldgain = gain;

if(Poutsub) {
invSignal(efxoutl, synth->buffersize);
invSignal(efxoutr, synth->buffersize);
invSignal(efxoutl, buffersize);
invSignal(efxoutr, buffersize);
}
}



+ 1
- 1
source/modules/carla_native/zynaddsubfx/Effects/Phaser.h View File

@@ -35,7 +35,7 @@
class Phaser:public Effect
{
public:
Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_);
Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize);
~Phaser();
void out(const Stereo<float *> &input);
void setpreset(unsigned char npreset);


+ 14
- 14
source/modules/carla_native/zynaddsubfx/Effects/Reverb.cpp View File

@@ -28,8 +28,8 @@

//todo: EarlyReflections, Prdelay, Perbalance

Reverb::Reverb(bool insertion_, float *efxoutl_, float *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
Reverb::Reverb(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize),
// defaults
Pvolume(48),
Ptime(64),
@@ -116,7 +116,7 @@ void Reverb::processmono(int ch, float *output, float *inputbuf)
const int comblength = comblen[j];
float &lpcombj = lpcomb[j];

for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
float fbout = comb[j][ck] * combfb[j];
fbout = fbout * (1.0f - lohifb) + lpcombj * lohifb;
lpcombj = fbout;
@@ -132,7 +132,7 @@ void Reverb::processmono(int ch, float *output, float *inputbuf)
for(int j = REV_APS * ch; j < REV_APS * (1 + ch); ++j) {
int &ak = apk[j];
const int aplength = aplen[j];
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
float tmp = ap[j][ak];
ap[j][ak] = 0.7f * tmp + output[i];
output[i] = tmp - 0.7f * ap[j][ak];
@@ -149,11 +149,11 @@ void Reverb::out(const Stereo<float *> &smp)
return;

float *inputbuf = getTmpBuffer();
for(int i = 0; i < synth->buffersize; ++i)
for(int i = 0; i < buffersize; ++i)
inputbuf[i] = (smp.l[i] + smp.r[i]) / 2.0f;

if(idelay)
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
//Initial delay r
float tmp = inputbuf[i] + idelay[idelayk] * idelayfb;
inputbuf[i] = idelay[idelayk];
@@ -164,7 +164,7 @@ void Reverb::out(const Stereo<float *> &smp)
}

if(bandwidth)
bandwidth->process(synth->buffersize, inputbuf);
bandwidth->process(buffersize, inputbuf);

if(lpf)
lpf->filterout(inputbuf);
@@ -181,7 +181,7 @@ void Reverb::out(const Stereo<float *> &smp)
lvol *= 2.0f;
rvol *= 2.0f;
}
for(int i = 0; i < synth->buffersize; ++i) {
for(int i = 0; i < buffersize; ++i) {
efxoutl[i] *= lvol;
efxoutr[i] *= rvol;
}
@@ -210,7 +210,7 @@ void Reverb::settime(unsigned char _Ptime)

for(int i = 0; i < REV_COMBS * 2; ++i)
combfb[i] =
-expf((float)comblen[i] / synth->samplerate_f * logf(0.001f) / t);
-expf((float)comblen[i] / (float)samplerate * logf(0.001f) / t);
//the feedback is negative because it removes the DC
}

@@ -241,7 +241,7 @@ void Reverb::setidelay(unsigned char _Pidelay)
delete [] idelay;
idelay = NULL;

idelaylen = (int) (synth->samplerate_f * delay / 1000);
idelaylen = (int) ((float)samplerate * delay / 1000.0f);
if(idelaylen > 1) {
idelayk = 0;
idelay = new float[idelaylen];
@@ -266,7 +266,7 @@ void Reverb::sethpf(unsigned char _Phpf)
else {
float fr = expf(powf(Phpf / 127.0f, 0.5f) * logf(10000.0f)) + 20.0f;
if(hpf == NULL)
hpf = new AnalogFilter(3, fr, 1, 0);
hpf = new AnalogFilter(3, fr, 1, 0, samplerate, buffersize);
else
hpf->setfreq(fr);
}
@@ -283,7 +283,7 @@ void Reverb::setlpf(unsigned char _Plpf)
else {
float fr = expf(powf(Plpf / 127.0f, 0.5f) * logf(25000.0f)) + 40.0f;
if(!lpf)
lpf = new AnalogFilter(2, fr, 1, 0);
lpf = new AnalogFilter(2, fr, 1, 0, samplerate, buffersize);
else
lpf->setfreq(fr);
}
@@ -315,7 +315,7 @@ void Reverb::settype(unsigned char _Ptype)
Ptype = NUM_TYPES - 1;

// adjust the combs according to the samplerate
float samplerate_adjust = synth->samplerate_f / 44100.0f;
float samplerate_adjust = (float)samplerate / 44100.0f;
float tmp;
for(int i = 0; i < REV_COMBS * 2; ++i) {
if(Ptype == 0)
@@ -360,7 +360,7 @@ void Reverb::settype(unsigned char _Ptype)
//not been verified yet.
//As this cannot be resized in a RT context, a good upper bound should
//be found
bandwidth = new Unison(synth->buffersize / 4 + 1, 2.0f);
bandwidth = new Unison(buffersize / 4 + 1, 2.0f);
bandwidth->setSize(50);
bandwidth->setBaseFrequency(1.0f);
}


+ 1
- 1
source/modules/carla_native/zynaddsubfx/Effects/Reverb.h View File

@@ -32,7 +32,7 @@
class Reverb:public Effect
{
public:
Reverb(bool insertion_, float *efxoutl_, float *efxoutr_);
Reverb(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize);
~Reverb();
void out(const Stereo<float *> &smp);
void cleanup(void);


+ 6
- 2
source/plugin/Makefile View File

@@ -45,7 +45,7 @@ endif
# --------------------------------------------------------------
# Native

DGL_LIBS = -lX11
DGL_LIBS = -lX11 -lXext

ifeq ($(HAVE_OPENGL),true)
LINK_FLAGS += $(shell pkg-config --libs gl) $(DGL_LIBS)
@@ -76,6 +76,10 @@ LINK_FLAGS += $(EXTRA_LIBS)
LIBS = ../modules/carla_native.a
LIBS += ../modules/juce_audio_basics.a
LIBS += ../modules/juce_core.a
LIBS += ../modules/juce_data_structures.a
LIBS += ../modules/juce_events.a
LIBS += ../modules/juce_graphics.a
LIBS += ../modules/juce_gui_basics.a
LIBS += ../modules/rtmempool.a

# ifeq ($(CARLA_PLUGIN_SUPPORT),true)
@@ -143,7 +147,7 @@ carla-native-lv2-export.exe: carla-native-lv2-export.cpp.o $(LIBS)
# --------------------------------------------------------------

.FORCE:
.PHONY: .FORCE
.PHONY: .FORCE carla-native-lv2-export carla-native-lv2-export.exe

../modules/%.a: .FORCE
$(MAKE) -C ../modules $*

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

@@ -35,7 +35,8 @@ void carla_register_native_plugin_midiTranspose();
void carla_register_native_plugin_nekofilter();

// Simple plugins (C++)
void carla_register_native_plugin_vex();
void carla_register_native_plugin_vex_fx();
void carla_register_native_plugin_vex_synth();

#ifdef WANT_AUDIOFILE
// AudioFile
@@ -63,7 +64,8 @@ void carla_register_native_plugin_Notes();

#ifdef WANT_ZYNADDSUBFX
// ZynAddSubFX
void carla_register_native_plugin_zynaddsubfx();
void carla_register_native_plugin_zynaddsubfx_fx();
void carla_register_native_plugin_zynaddsubfx_synth();
#endif
}

@@ -83,7 +85,8 @@ struct PluginListManager {
carla_register_native_plugin_nekofilter();

// Simple plugins (C++)
carla_register_native_plugin_vex();
carla_register_native_plugin_vex_fx();
carla_register_native_plugin_vex_synth();

#ifdef WANT_AUDIOFILE
// AudioFile
@@ -111,7 +114,8 @@ struct PluginListManager {

#ifdef WANT_ZYNADDSUBFX
// ZynAddSubFX
carla_register_native_plugin_zynaddsubfx();
carla_register_native_plugin_zynaddsubfx_fx();
carla_register_native_plugin_zynaddsubfx_synth();
#endif
}



Loading…
Cancel
Save