@@ -39,21 +39,6 @@ extern "C" { | |||
typedef void* HostHandle; | |||
typedef void* PluginHandle; | |||
const uint32_t PLUGIN_IS_RTSAFE = 1 << 0; | |||
const uint32_t PLUGIN_IS_SYNTH = 1 << 1; | |||
const uint32_t PLUGIN_HAS_GUI = 1 << 2; | |||
const uint32_t PLUGIN_USES_SINGLE_THREAD = 1 << 3; | |||
const uint32_t PARAMETER_IS_OUTPUT = 1 << 0; | |||
const uint32_t PARAMETER_IS_ENABLED = 1 << 1; | |||
const uint32_t PARAMETER_IS_AUTOMABLE = 1 << 2; | |||
const uint32_t PARAMETER_IS_BOOLEAN = 1 << 3; | |||
const uint32_t PARAMETER_IS_INTEGER = 1 << 4; | |||
const uint32_t PARAMETER_IS_LOGARITHMIC = 1 << 5; | |||
const uint32_t PARAMETER_USES_SAMPLE_RATE = 1 << 6; | |||
const uint32_t PARAMETER_USES_SCALEPOINTS = 1 << 7; | |||
const uint32_t PARAMETER_USES_CUSTOM_TEXT = 1 << 8; | |||
typedef enum _PluginCategory { | |||
PLUGIN_CATEGORY_NONE = 0, //!< Null plugin category. | |||
PLUGIN_CATEGORY_SYNTH = 1, //!< A synthesizer or generator. | |||
@@ -66,6 +51,25 @@ typedef enum _PluginCategory { | |||
PLUGIN_CATEGORY_OTHER = 8 //!< Misc plugin (used to check if the plugin has a category). | |||
} PluginCategory; | |||
typedef enum _PluginHints { | |||
PLUGIN_IS_RTSAFE = 1 << 0, | |||
PLUGIN_IS_SYNTH = 1 << 1, | |||
PLUGIN_HAS_GUI = 1 << 2, | |||
PLUGIN_USES_SINGLE_THREAD = 1 << 3 | |||
} PluginHints; | |||
typedef enum _ParameterHints { | |||
PARAMETER_IS_OUTPUT = 1 << 0, | |||
PARAMETER_IS_ENABLED = 1 << 1, | |||
PARAMETER_IS_AUTOMABLE = 1 << 2, | |||
PARAMETER_IS_BOOLEAN = 1 << 3, | |||
PARAMETER_IS_INTEGER = 1 << 4, | |||
PARAMETER_IS_LOGARITHMIC = 1 << 5, | |||
PARAMETER_USES_SAMPLE_RATE = 1 << 6, | |||
PARAMETER_USES_SCALEPOINTS = 1 << 7, | |||
PARAMETER_USES_CUSTOM_TEXT = 1 << 8 | |||
} ParameterHints; | |||
typedef struct _ParameterScalePoint { | |||
const char* label; | |||
float value; | |||
@@ -85,7 +89,7 @@ typedef struct _ParameterRanges { | |||
#define PARAMETER_RANGES_DEFAULT_STEP_LARGE 0.1f | |||
typedef struct _Parameter { | |||
uint32_t hints; | |||
ParameterHints hints; | |||
const char* name; | |||
const char* unit; | |||
ParameterRanges ranges; | |||
@@ -145,7 +149,7 @@ typedef struct _HostDescriptor { | |||
typedef struct _PluginDescriptor { | |||
const PluginCategory category; | |||
const uint32_t hints; | |||
const PluginHints hints; | |||
const uint32_t audioIns; | |||
const uint32_t audioOuts; | |||
const uint32_t midiIns; | |||
@@ -17,8 +17,6 @@ | |||
#include "carla_native.h" | |||
#include <string.h> // for memcpy | |||
static PluginHandle bypass_instantiate(const PluginDescriptor* _this_, HostDescriptor* host) | |||
{ | |||
// dummy, return non-NULL | |||
@@ -37,8 +35,6 @@ static void bypass_process(PluginHandle handle, float** inBuffer, float** outBuf | |||
for (uint32_t i=0; i < frames; i++) | |||
*in++ = *out++; | |||
//memcpy(out, in, sizeof(float)*frames); | |||
return; | |||
// unused | |||
@@ -51,19 +47,20 @@ static void bypass_process(PluginHandle handle, float** inBuffer, float** outBuf | |||
static const PluginDescriptor bypassDesc = { | |||
.category = PLUGIN_CATEGORY_NONE, | |||
.hints = /*PLUGIN_IS_RTSAFE*/0, | |||
.hints = PLUGIN_IS_RTSAFE, | |||
.audioIns = 1, | |||
.audioOuts = 1, | |||
.midiIns = 0, | |||
.midiOuts = 0, | |||
.parameterIns = 0, | |||
.parameterOuts = 0, | |||
.name = "ByPass", | |||
.label = "bypass", | |||
.maker = "falkTX", | |||
.copyright = "GNU GPL v2+", | |||
.name = "ByPass", | |||
.label = "bypass", | |||
.maker = "falkTX", | |||
.copyright = "GNU GPL v2+", | |||
.instantiate = bypass_instantiate, | |||
.cleanup = NULL, | |||
.get_parameter_count = NULL, | |||
.get_parameter_info = NULL, | |||
@@ -86,7 +83,6 @@ static const PluginDescriptor bypassDesc = { | |||
.activate = NULL, | |||
.deactivate = NULL, | |||
.cleanup = NULL, | |||
.process = bypass_process | |||
}; | |||
@@ -0,0 +1,130 @@ | |||
/* | |||
* 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 COPYING file | |||
*/ | |||
#include "carla_midi.h" | |||
#include "carla_native.h" | |||
#include <stdlib.h> | |||
typedef struct _MidiSplitHandle { | |||
HostDescriptor* host; | |||
} MidiSplitHandle; | |||
static PluginHandle midiSplit_instantiate(const PluginDescriptor* _this_, HostDescriptor* host) | |||
{ | |||
MidiSplitHandle* const handle = (MidiSplitHandle*)malloc(sizeof(MidiSplitHandle)); | |||
if (handle) | |||
{ | |||
handle->host = host; | |||
return handle; | |||
} | |||
return NULL; | |||
// unused | |||
(void)_this_; | |||
} | |||
static void midiSplit_cleanup(PluginHandle handle) | |||
{ | |||
free((MidiSplitHandle*)handle); | |||
} | |||
static void midiSplit_process(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents) | |||
{ | |||
HostDescriptor* const host = ((MidiSplitHandle*)handle)->host; | |||
MidiEvent tmpEvent; | |||
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 (channel >= MAX_MIDI_CHANNELS) | |||
continue; | |||
tmpEvent.port = channel; | |||
tmpEvent.time = midiEvent->time; | |||
tmpEvent.data[0] = status; | |||
tmpEvent.data[1] = midiEvent->data[1]; | |||
tmpEvent.data[2] = midiEvent->data[2]; | |||
host->write_midi_event(host, &tmpEvent); | |||
} | |||
return; | |||
// unused | |||
(void)inBuffer; | |||
(void)outBuffer; | |||
(void)frames; | |||
} | |||
// ----------------------------------------------------------------------- | |||
static const PluginDescriptor midiSplitDesc = { | |||
.category = PLUGIN_CATEGORY_UTILITY, | |||
.hints = PLUGIN_IS_RTSAFE, | |||
.audioIns = 0, | |||
.audioOuts = 0, | |||
.midiIns = 1, | |||
.midiOuts = 16, | |||
.parameterIns = 0, | |||
.parameterOuts = 0, | |||
.name = "MIDI Split", | |||
.label = "midiSplit", | |||
.maker = "falkTX", | |||
.copyright = "GNU GPL v2+", | |||
.instantiate = midiSplit_instantiate, | |||
.cleanup = midiSplit_cleanup, | |||
.get_parameter_count = NULL, | |||
.get_parameter_info = NULL, | |||
.get_parameter_value = NULL, | |||
.get_parameter_text = NULL, | |||
.get_midi_program_count = NULL, | |||
.get_midi_program_info = NULL, | |||
.set_parameter_value = NULL, | |||
.set_midi_program = NULL, | |||
.set_custom_data = NULL, | |||
.ui_show = NULL, | |||
.ui_idle = NULL, | |||
.ui_set_parameter_value = NULL, | |||
.ui_set_midi_program = NULL, | |||
.ui_set_custom_data = NULL, | |||
.activate = NULL, | |||
.deactivate = NULL, | |||
.process = midiSplit_process | |||
}; | |||
// ----------------------------------------------------------------------- | |||
void carla_register_native_plugin_midiSplit() | |||
{ | |||
carla_register_native_plugin(&midiSplitDesc); | |||
} | |||
// ----------------------------------------------------------------------- |
@@ -1,94 +0,0 @@ | |||
/* | |||
* Carla Native Plugins | |||
* Copyright (C) 2012 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 COPYING file | |||
*/ | |||
#include "carla_native.hpp" | |||
#include <cstring> | |||
class MidiSplitPlugin : public PluginDescriptorClass | |||
{ | |||
public: | |||
MidiSplitPlugin(const HostDescriptor* const host) | |||
: PluginDescriptorClass(host) | |||
{ | |||
} | |||
~MidiSplitPlugin() | |||
{ | |||
} | |||
protected: | |||
// ------------------------------------------------------------------- | |||
// Plugin process calls | |||
void process(float**, float**, const uint32_t, const uint32_t midiEventCount, const MidiEvent* const midiEvents) | |||
{ | |||
for (uint32_t i=0; i < midiEventCount; i++) | |||
{ | |||
memcpy(&m_midiEvent, &midiEvents[i], sizeof(MidiEvent)); | |||
const uint8_t status = m_midiEvent.data[0] & 0xF0; | |||
const uint8_t channel = status & 0x0F; | |||
CARLA_ASSERT(channel < 16); | |||
if (channel >= 16) | |||
continue; | |||
m_midiEvent.port = channel; | |||
m_midiEvent.data[0] = status; | |||
writeMidiEvent(&m_midiEvent); | |||
} | |||
} | |||
// ------------------------------------------------------------------- | |||
private: | |||
MidiEvent m_midiEvent; | |||
PluginDescriptorClassEND(MidiSplitPlugin) | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiSplitPlugin) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
static const PluginDescriptor midiSplitDesc = { | |||
/* category */ PLUGIN_CATEGORY_UTILITY, | |||
/* hints */ PLUGIN_IS_RTSAFE, | |||
/* audioIns */ 0, | |||
/* audioOuts */ 0, | |||
/* midiIns */ 1, | |||
/* midiOuts */ 16, | |||
/* paramIns */ 0, | |||
/* paramOuts */ 0, | |||
/* name */ "MIDI Split", | |||
/* label */ "midiSplit", | |||
/* maker */ "falkTX", | |||
/* copyright */ "GNU GPL v2+", | |||
PluginDescriptorFILL(MidiSplitPlugin) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
void carla_register_native_plugin_midiSplit() | |||
{ | |||
carla_register_native_plugin(&midiSplitDesc); | |||
} | |||
// ----------------------------------------------------------------------- |
@@ -0,0 +1,113 @@ | |||
/* | |||
* 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 COPYING file | |||
*/ | |||
#include "carla_midi.h" | |||
#include "carla_native.h" | |||
#include <stdlib.h> | |||
typedef struct _MidiThroughHandle { | |||
HostDescriptor* host; | |||
} MidiThroughHandle; | |||
static PluginHandle midiThrough_instantiate(const PluginDescriptor* _this_, HostDescriptor* host) | |||
{ | |||
MidiThroughHandle* const handle = (MidiThroughHandle*)malloc(sizeof(MidiThroughHandle)); | |||
if (handle) | |||
{ | |||
handle->host = host; | |||
return handle; | |||
} | |||
return NULL; | |||
// unused | |||
(void)_this_; | |||
} | |||
static void midiThrough_cleanup(PluginHandle handle) | |||
{ | |||
free((MidiThroughHandle*)handle); | |||
} | |||
static void midiThrough_process(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents) | |||
{ | |||
HostDescriptor* const host = ((MidiThroughHandle*)handle)->host; | |||
for (uint32_t i=0; i < midiEventCount; i++) | |||
host->write_midi_event(host, &midiEvents[i]); | |||
return; | |||
// unused | |||
(void)inBuffer; | |||
(void)outBuffer; | |||
(void)frames; | |||
} | |||
// ----------------------------------------------------------------------- | |||
static const PluginDescriptor midiThroughDesc = { | |||
.category = PLUGIN_CATEGORY_NONE, | |||
.hints = PLUGIN_IS_RTSAFE, | |||
.audioIns = 0, | |||
.audioOuts = 0, | |||
.midiIns = 1, | |||
.midiOuts = 1, | |||
.parameterIns = 0, | |||
.parameterOuts = 0, | |||
.name = "MIDI Through", | |||
.label = "midiThrough", | |||
.maker = "falkTX", | |||
.copyright = "GNU GPL v2+", | |||
.instantiate = midiThrough_instantiate, | |||
.cleanup = midiThrough_cleanup, | |||
.get_parameter_count = NULL, | |||
.get_parameter_info = NULL, | |||
.get_parameter_value = NULL, | |||
.get_parameter_text = NULL, | |||
.get_midi_program_count = NULL, | |||
.get_midi_program_info = NULL, | |||
.set_parameter_value = NULL, | |||
.set_midi_program = NULL, | |||
.set_custom_data = NULL, | |||
.ui_show = NULL, | |||
.ui_idle = NULL, | |||
.ui_set_parameter_value = NULL, | |||
.ui_set_midi_program = NULL, | |||
.ui_set_custom_data = NULL, | |||
.activate = NULL, | |||
.deactivate = NULL, | |||
.process = midiThrough_process | |||
}; | |||
// ----------------------------------------------------------------------- | |||
void carla_register_native_plugin_midiThrough() | |||
{ | |||
carla_register_native_plugin(&midiThroughDesc); | |||
} | |||
// ----------------------------------------------------------------------- |
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla Native Plugins | |||
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | |||
* 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 | |||
@@ -9,7 +9,7 @@ | |||
* | |||
* 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 | |||
* 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 COPYING file | |||
@@ -25,7 +25,9 @@ | |||
#include "zynaddsubfx/Misc/Master.h" | |||
#include "zynaddsubfx/Misc/Util.h" | |||
//Dummy variables and functions for linking purposes | |||
#include <ctime> | |||
// Dummy variables and functions for linking purposes | |||
class WavFile; | |||
namespace Nio { | |||
bool start(void){return 1;} | |||
@@ -46,10 +48,9 @@ public: | |||
}; | |||
ZynAddSubFxPlugin(const HostDescriptor* const host) | |||
: PluginDescriptorClass(host) | |||
: PluginDescriptorClass(host), | |||
m_master(new Master) | |||
{ | |||
m_master = new Master; | |||
// refresh banks | |||
m_master->bank.rescanforbanks(); | |||
@@ -67,7 +68,7 @@ public: | |||
if (insName.empty() || insName[0] == '\0' || insName[0] == ' ') | |||
continue; | |||
ProgramInfo pInfo = { i, instrument, CarlaString(insName.c_str()) }; | |||
ProgramInfo pInfo(i, instrument, insName.c_str()); | |||
m_programs.push_back(pInfo); | |||
} | |||
} | |||
@@ -127,6 +128,8 @@ protected: | |||
float getParameterValue(const uint32_t index) | |||
{ | |||
CARLA_ASSERT(index < getParameterCount()); | |||
switch (index) | |||
{ | |||
#if 0 | |||
@@ -168,9 +171,15 @@ protected: | |||
void setParameterValue(const uint32_t index, const float value) | |||
{ | |||
CARLA_ASSERT(index < getParameterCount()); | |||
switch (index) | |||
{ | |||
} | |||
return; | |||
// unused, TODO | |||
Q_UNUSED(value); | |||
} | |||
@@ -181,7 +190,7 @@ protected: | |||
if (program >= BANK_SIZE) | |||
return; | |||
const std::string bankdir = m_master->bank.banks[bank].dir; | |||
const std::string bankdir(m_master->bank.banks[bank].dir); | |||
if (! bankdir.empty()) | |||
{ | |||
@@ -204,11 +213,17 @@ protected: | |||
void process(float**, float** const outBuffer, const uint32_t frames, const uint32_t midiEventCount, const MidiEvent* const midiEvents) | |||
{ | |||
if (pthread_mutex_trylock(&m_master->mutex) != 0) | |||
{ | |||
carla_zeroFloat(outBuffer[0], frames); | |||
carla_zeroFloat(outBuffer[1], frames); | |||
return; | |||
} | |||
uint32_t fromFrame = 0; | |||
uint32_t eventIndex = 0; | |||
uint32_t nextEventFrame = 0; | |||
uint32_t toFrame = 0; | |||
pthread_mutex_lock(&m_master->mutex); | |||
do { | |||
// Find the time of the next event, if any | |||
@@ -237,26 +252,26 @@ protected: | |||
// Now process any event(s) at the current timing point | |||
while (eventIndex < midiEventCount && midiEvents[eventIndex].time == toFrame) | |||
{ | |||
uint8_t status = midiEvents[eventIndex].data[0]; | |||
uint8_t channel = status & 0x0F; | |||
const uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvents[eventIndex].data); | |||
const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvents[eventIndex].data); | |||
if (MIDI_IS_STATUS_NOTE_OFF(status)) | |||
{ | |||
uint8_t note = midiEvents[eventIndex].data[1]; | |||
const uint8_t note = midiEvents[eventIndex].data[1]; | |||
m_master->noteOff(channel, note); | |||
} | |||
else if (MIDI_IS_STATUS_NOTE_ON(status)) | |||
{ | |||
uint8_t note = midiEvents[eventIndex].data[1]; | |||
uint8_t velo = midiEvents[eventIndex].data[2]; | |||
const uint8_t note = midiEvents[eventIndex].data[1]; | |||
const uint8_t velo = midiEvents[eventIndex].data[2]; | |||
m_master->noteOn(channel, note, velo); | |||
} | |||
else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status)) | |||
{ | |||
uint8_t note = midiEvents[eventIndex].data[1]; | |||
uint8_t pressure = midiEvents[eventIndex].data[2]; | |||
const uint8_t note = midiEvents[eventIndex].data[1]; | |||
const uint8_t pressure = midiEvents[eventIndex].data[2]; | |||
m_master->polyphonicAftertouch(channel, note, pressure); | |||
} | |||
@@ -277,10 +292,18 @@ private: | |||
uint32_t bank; | |||
uint32_t prog; | |||
CarlaString name; | |||
ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_) | |||
: bank(bank_), | |||
prog(prog_), | |||
name(name_) {} | |||
ProgramInfo() = delete; | |||
}; | |||
std::vector<ProgramInfo> m_programs; | |||
Master* m_master; | |||
Master* const m_master; | |||
public: | |||
static int s_instanceCount; | |||
@@ -299,8 +322,8 @@ public: | |||
config.cfg.SampleRate = synth->samplerate; | |||
config.cfg.GzipCompression = 0; | |||
sprng(time(NULL)); | |||
denormalkillbuf = new float [synth->buffersize]; | |||
sprng(std::time(nullptr)); | |||
denormalkillbuf = new float[synth->buffersize]; | |||
for (int i=0; i < synth->buffersize; i++) | |||
denormalkillbuf[i] = (RND - 0.5f) * 1e-16; | |||
} | |||
@@ -321,6 +344,8 @@ public: | |||
synth = nullptr; | |||
} | |||
} | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin) | |||
}; | |||
int ZynAddSubFxPlugin::s_instanceCount = 0; | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla common MIDI code | |||
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | |||
* 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 | |||
@@ -37,6 +37,10 @@ | |||
#define MIDI_IS_STATUS_AFTERTOUCH(status) (((status) & 0xF0) == MIDI_STATUS_AFTERTOUCH) | |||
#define MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) (((status) & 0xF0) == MIDI_STATUS_PITCH_WHEEL_CONTROL) | |||
// MIDI Utils | |||
#define MIDI_GET_STATUS_FROM_DATA(data) ((data[0]) & 0xF0) | |||
#define MIDI_GET_CHANNEL_FROM_DATA(data) ((data[0]) & 0x0F) | |||
// Control Change Messages List | |||
#define MIDI_CONTROL_BANK_SELECT 0x00 // 0-127, MSB | |||
#define MIDI_CONTROL_MODULATION_WHEEL 0x01 // 0-127, MSB | |||