Rework plugin audio processing, use simple builtin module for it
This commit is contained in:
parent
30134b4b22
commit
caf5ca5df6
14 changed files with 578 additions and 318 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* DISTRHO Cardinal Plugin
|
||||
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
|
||||
* Copyright (C) 2021-2022 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
|
||||
|
|
@ -182,9 +182,6 @@ struct Initializer
|
|||
"Make sure Cardinal was downloaded and installed correctly.", asset::systemDir.c_str());
|
||||
}
|
||||
|
||||
INFO("Initializing audio driver");
|
||||
audio::addDriver(0, new CardinalAudioDriver);
|
||||
|
||||
INFO("Initializing midi driver");
|
||||
midi::addDriver(0, new CardinalMidiDriver);
|
||||
|
||||
|
|
@ -336,14 +333,11 @@ class CardinalPlugin : public CardinalBasePlugin
|
|||
{
|
||||
SharedResourcePointer<Initializer> fInitializer;
|
||||
|
||||
float* fAudioBufferIn;
|
||||
float* fAudioBufferOut;
|
||||
float** fAudioBufferCopy;
|
||||
std::string fAutosavePath;
|
||||
String fWindowSize;
|
||||
|
||||
// for base/context handling
|
||||
bool fIsActive;
|
||||
CardinalAudioDevice* fCurrentAudioDevice;
|
||||
CardinalMidiInputDevice** fCurrentMidiInputs;
|
||||
CardinalMidiOutputDevice** fCurrentMidiOutputs;
|
||||
uint64_t fPreviousFrame;
|
||||
|
|
@ -358,10 +352,7 @@ public:
|
|||
CardinalPlugin()
|
||||
: CardinalBasePlugin(kModuleParameters + kWindowParameterCount, 0, kCardinalStateCount),
|
||||
fInitializer(this),
|
||||
fAudioBufferIn(nullptr),
|
||||
fAudioBufferOut(nullptr),
|
||||
fIsActive(false),
|
||||
fCurrentAudioDevice(nullptr),
|
||||
fAudioBufferCopy(nullptr),
|
||||
fCurrentMidiInputs(nullptr),
|
||||
fCurrentMidiOutputs(nullptr),
|
||||
fPreviousFrame(0)
|
||||
|
|
@ -443,7 +434,6 @@ public:
|
|||
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
fCurrentAudioDevice = nullptr;
|
||||
delete[] fCurrentMidiInputs;
|
||||
fCurrentMidiInputs = nullptr;
|
||||
delete[] fCurrentMidiOutputs;
|
||||
|
|
@ -463,36 +453,6 @@ protected:
|
|||
/* --------------------------------------------------------------------------------------------------------
|
||||
* Cardinal Base things */
|
||||
|
||||
bool isActive() const noexcept override
|
||||
{
|
||||
return fIsActive;
|
||||
}
|
||||
|
||||
bool canAssignAudioDevice() const noexcept override
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
return fCurrentAudioDevice == nullptr;
|
||||
}
|
||||
|
||||
void assignAudioDevice(CardinalAudioDevice* const dev) noexcept override
|
||||
{
|
||||
DISTRHO_SAFE_ASSERT_RETURN(fCurrentAudioDevice == nullptr,);
|
||||
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
fCurrentAudioDevice = dev;
|
||||
}
|
||||
|
||||
bool clearAudioDevice(CardinalAudioDevice* const dev) noexcept override
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
|
||||
if (fCurrentAudioDevice != dev)
|
||||
return false;
|
||||
|
||||
fCurrentAudioDevice = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void assignMidiInputDevice(CardinalMidiInputDevice* const dev) noexcept override
|
||||
{
|
||||
CardinalMidiInputDevice** const oldDevs = fCurrentMidiInputs;
|
||||
|
|
@ -625,13 +585,15 @@ protected:
|
|||
|
||||
int64_t getUniqueId() const override
|
||||
{
|
||||
#if CARDINAL_VARIANT_SYNTH
|
||||
return d_cconst('d', 'C', 'n', 'S');
|
||||
#elif CARDINAL_VARIANT_FX
|
||||
return d_cconst('d', 'C', 'n', 'F');
|
||||
#else
|
||||
#if CARDINAL_VARIANT_MAIN
|
||||
return d_cconst('d', 'C', 'd', 'n');
|
||||
#endif
|
||||
#elif CARDINAL_VARIANT_FX
|
||||
return d_cconst('d', 'C', 'n', 'F');
|
||||
#elif CARDINAL_VARIANT_SYNTH
|
||||
return d_cconst('d', 'C', 'n', 'S');
|
||||
#else
|
||||
#error cardinal variant not set
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -892,42 +854,25 @@ protected:
|
|||
|
||||
void activate() override
|
||||
{
|
||||
#if DISTRHO_PLUGIN_NUM_INPUTS != 0
|
||||
const uint32_t bufferSize = getBufferSize();
|
||||
fAudioBufferOut = new float[bufferSize * DISTRHO_PLUGIN_NUM_OUTPUTS];
|
||||
|
||||
const uint32_t numInputs = std::max(1, DISTRHO_PLUGIN_NUM_INPUTS);
|
||||
fAudioBufferIn = new float[bufferSize * numInputs];
|
||||
std::memset(fAudioBufferIn, 0, sizeof(float)*bufferSize * numInputs);
|
||||
fAudioBufferCopy = new float*[DISTRHO_PLUGIN_NUM_INPUTS];
|
||||
for (int i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
|
||||
fAudioBufferCopy[i] = new float[newBufferSize];
|
||||
#endif
|
||||
|
||||
fPreviousFrame = 0;
|
||||
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
|
||||
if (fCurrentAudioDevice != nullptr)
|
||||
{
|
||||
rack::contextSet(context);
|
||||
fCurrentAudioDevice->onStartStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deactivate() override
|
||||
{
|
||||
if (fAudioBufferCopy != nullptr)
|
||||
{
|
||||
const MutexLocker cml(fDeviceMutex);
|
||||
|
||||
if (fCurrentAudioDevice != nullptr)
|
||||
{
|
||||
rack::contextSet(context);
|
||||
fCurrentAudioDevice->onStopStream();
|
||||
}
|
||||
for (int i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
|
||||
delete[] fAudioBufferCopy[i];
|
||||
delete[] fAudioBufferCopy;
|
||||
fAudioBufferCopy = nullptr;
|
||||
}
|
||||
|
||||
delete[] fAudioBufferOut;
|
||||
fAudioBufferOut = nullptr;
|
||||
delete[] fAudioBufferIn;
|
||||
fAudioBufferIn = nullptr;
|
||||
}
|
||||
|
||||
inline void sendSingleSimpleMidiMessage(const MidiEvent& midiEvent)
|
||||
|
|
@ -1006,41 +951,26 @@ protected:
|
|||
(*inputs)->handleMessagesFromHost(midiEvents, midiEventCount);
|
||||
}
|
||||
|
||||
if (fCurrentAudioDevice != nullptr)
|
||||
// separate buffers, use them
|
||||
if (inputs != outputs && (inputs == nullptr || inputs[0] != outputs[0]))
|
||||
{
|
||||
#if CARDINAL_NUM_AUDIO_INPUTS != 0
|
||||
for (uint32_t i=0, j=0; i<frames; ++i)
|
||||
for (uint32_t k=0; k<CARDINAL_NUM_AUDIO_INPUTS; ++k)
|
||||
fAudioBufferIn[j++] = inputs[k][i];
|
||||
fCurrentAudioDevice->processInput(fAudioBufferIn, CARDINAL_NUM_AUDIO_INPUTS, frames);
|
||||
#else
|
||||
std::memset(fAudioBufferIn, 0, sizeof(float)*frames);
|
||||
fCurrentAudioDevice->processInput(fAudioBufferIn, 1, frames);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CARDINAL_VARIANT_MAIN
|
||||
context->dataFrame = 0;
|
||||
context->dataIns = inputs;
|
||||
context->dataOuts = outputs;
|
||||
#endif
|
||||
|
||||
context->engine->stepBlock(frames);
|
||||
|
||||
if (fCurrentAudioDevice != nullptr)
|
||||
{
|
||||
std::memset(fAudioBufferOut, 0, sizeof(float)*frames*CARDINAL_NUM_AUDIO_OUTPUTS);
|
||||
fCurrentAudioDevice->processOutput(fAudioBufferOut, CARDINAL_NUM_AUDIO_OUTPUTS, frames);
|
||||
|
||||
for (uint32_t i=0, j=0; i<frames; ++i)
|
||||
for (uint32_t k=0; k<CARDINAL_NUM_AUDIO_OUTPUTS; ++k)
|
||||
outputs[k][i] = fAudioBufferOut[j++];
|
||||
context->dataIns = inputs;
|
||||
context->dataOuts = outputs;
|
||||
}
|
||||
// inline processing, use a safe copy
|
||||
else
|
||||
{
|
||||
for (uint32_t k=0; k<CARDINAL_NUM_AUDIO_OUTPUTS; ++k)
|
||||
std::memset(outputs[k], 0, sizeof(float)*frames);
|
||||
for (int i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
|
||||
std::memcpy(fAudioBufferCopy[i], inputs[i], sizeof(float)*frames);
|
||||
|
||||
context->dataIns = fAudioBufferCopy;
|
||||
context->dataOuts = outputs;
|
||||
}
|
||||
|
||||
for (int i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
|
||||
std::memset(outputs[i], 0, sizeof(float)*frames);
|
||||
|
||||
context->engine->stepBlock(frames);
|
||||
}
|
||||
|
||||
void bufferSizeChanged(const uint32_t newBufferSize) override
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* DISTRHO Cardinal Plugin
|
||||
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
|
||||
* Copyright (C) 2021-2022 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
|
||||
|
|
@ -39,20 +39,26 @@ START_NAMESPACE_DISTRHO
|
|||
|
||||
static constexpr const uint kModuleParameters = 24;
|
||||
|
||||
enum CardinalVariant {
|
||||
kCardinalVariantMain,
|
||||
kCardinalVariantFX,
|
||||
kCardinalVariantSynth,
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct CardinalPluginContext : rack::Context {
|
||||
uint32_t bufferSize;
|
||||
double sampleRate;
|
||||
float parameters[kModuleParameters];
|
||||
bool playing, reset, bbtValid, loadedHostCV;
|
||||
CardinalVariant variant;
|
||||
bool playing, reset, bbtValid;
|
||||
int32_t bar, beat, beatsPerBar, beatType;
|
||||
uint64_t frame;
|
||||
double barStartTick, beatsPerMinute;
|
||||
double tick, tickClock, ticksPerBeat, ticksPerClock, ticksPerFrame;
|
||||
uintptr_t nativeWindowId;
|
||||
uint32_t dataFrame;
|
||||
const float** dataIns;
|
||||
const float* const* dataIns;
|
||||
float** dataOuts;
|
||||
Plugin* const plugin;
|
||||
#ifndef HEADLESS
|
||||
|
|
@ -62,10 +68,18 @@ struct CardinalPluginContext : rack::Context {
|
|||
CardinalPluginContext(Plugin* const p)
|
||||
: bufferSize(p->getBufferSize()),
|
||||
sampleRate(p->getSampleRate()),
|
||||
#if CARDINAL_VARIANT_MAIN
|
||||
variant(kCardinalVariantMain),
|
||||
#elif CARDINAL_VARIANT_FX
|
||||
variant(kCardinalVariantFX),
|
||||
#elif CARDINAL_VARIANT_SYNTH
|
||||
variant(kCardinalVariantSynth),
|
||||
#else
|
||||
#error cardinal variant not set
|
||||
#endif
|
||||
playing(false),
|
||||
reset(false),
|
||||
bbtValid(false),
|
||||
loadedHostCV(false),
|
||||
bar(1),
|
||||
beat(1),
|
||||
beatsPerBar(4),
|
||||
|
|
@ -79,7 +93,6 @@ struct CardinalPluginContext : rack::Context {
|
|||
ticksPerClock(0.0),
|
||||
ticksPerFrame(0.0),
|
||||
nativeWindowId(0),
|
||||
dataFrame(0),
|
||||
dataIns(nullptr),
|
||||
dataOuts(nullptr),
|
||||
plugin(p)
|
||||
|
|
@ -116,10 +129,6 @@ public:
|
|||
: Plugin(parameterCount, programCount, stateCount),
|
||||
context(new CardinalPluginContext(this)) {}
|
||||
~CardinalBasePlugin() override {}
|
||||
virtual bool isActive() const noexcept = 0;
|
||||
virtual bool canAssignAudioDevice() const noexcept = 0;
|
||||
virtual bool clearAudioDevice(CardinalAudioDevice* dev) noexcept = 0;
|
||||
virtual void assignAudioDevice(CardinalAudioDevice* dev) noexcept = 0;
|
||||
virtual void assignMidiInputDevice(CardinalMidiInputDevice* dev) noexcept = 0;
|
||||
virtual void assignMidiOutputDevice(CardinalMidiOutputDevice* dev) noexcept = 0;
|
||||
virtual void clearMidiInputDevice(CardinalMidiInputDevice* dev) noexcept = 0;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* DISTRHO Cardinal Plugin
|
||||
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
|
||||
* Copyright (C) 2021-2022 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
|
||||
|
|
@ -23,145 +23,6 @@ START_NAMESPACE_DISTRHO
|
|||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct CardinalAudioDevice : rack::audio::Device
|
||||
{
|
||||
CardinalBasePlugin* const fPlugin;
|
||||
|
||||
CardinalAudioDevice(CardinalBasePlugin* const plugin)
|
||||
: fPlugin(plugin) {}
|
||||
|
||||
std::string getName() override
|
||||
{
|
||||
return "Cardinal";
|
||||
}
|
||||
|
||||
int getNumInputs() override
|
||||
{
|
||||
return CARDINAL_NUM_AUDIO_INPUTS;
|
||||
}
|
||||
|
||||
int getNumOutputs() override
|
||||
{
|
||||
return CARDINAL_NUM_AUDIO_OUTPUTS;
|
||||
}
|
||||
|
||||
int getBlockSize() override
|
||||
{
|
||||
return fPlugin->getBufferSize();
|
||||
}
|
||||
|
||||
float getSampleRate() override
|
||||
{
|
||||
return fPlugin->getSampleRate();
|
||||
}
|
||||
|
||||
std::set<int> getBlockSizes() override
|
||||
{
|
||||
return std::set<int>({ getBlockSize() });
|
||||
}
|
||||
|
||||
std::set<float> getSampleRates() override
|
||||
{
|
||||
return std::set<float>({ getSampleRate() });
|
||||
}
|
||||
|
||||
void setBlockSize(int) override {}
|
||||
void setSampleRate(float) override {}
|
||||
|
||||
void processInput(const float* const input, const int inputStride, const int frames)
|
||||
{
|
||||
for (rack::audio::Port* port : subscribed)
|
||||
port->processInput(input + port->inputOffset, inputStride, frames);
|
||||
}
|
||||
|
||||
void processOutput(float* const output, const int outputStride, const int frames)
|
||||
{
|
||||
for (rack::audio::Port* port : subscribed)
|
||||
port->processOutput(output + port->outputOffset, outputStride, frames);
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct CardinalAudioDriver : rack::audio::Driver
|
||||
{
|
||||
CardinalAudioDriver() {}
|
||||
|
||||
std::string getName() override
|
||||
{
|
||||
return "Plugin Driver";
|
||||
}
|
||||
|
||||
std::vector<int> getDeviceIds() override
|
||||
{
|
||||
return std::vector<int>({ 0 });
|
||||
}
|
||||
|
||||
int getDefaultDeviceId() override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string getDeviceName(int) override
|
||||
{
|
||||
return "Plugin Device";
|
||||
}
|
||||
|
||||
int getDeviceNumInputs(int) override
|
||||
{
|
||||
return CARDINAL_NUM_AUDIO_INPUTS;
|
||||
}
|
||||
|
||||
int getDeviceNumOutputs(int) override
|
||||
{
|
||||
return CARDINAL_NUM_AUDIO_OUTPUTS;
|
||||
}
|
||||
|
||||
rack::audio::Device* subscribe(int, rack::audio::Port* const port) override
|
||||
{
|
||||
CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(port->context);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr, nullptr);
|
||||
|
||||
CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr);
|
||||
|
||||
if (! plugin->canAssignAudioDevice())
|
||||
throw rack::Exception("Plugin driver only allows one audio device to be used simultaneously");
|
||||
|
||||
CardinalAudioDevice* const device = new CardinalAudioDevice(plugin);
|
||||
device->subscribe(port);
|
||||
|
||||
if (plugin->isActive())
|
||||
device->onStartStream();
|
||||
|
||||
plugin->assignAudioDevice(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
void unsubscribe(int, rack::audio::Port* const port) override
|
||||
{
|
||||
CardinalAudioDevice* const device = reinterpret_cast<CardinalAudioDevice*>(port->device);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(device != nullptr,);
|
||||
|
||||
CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(port->context);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr,);
|
||||
|
||||
CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
|
||||
DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr,);
|
||||
|
||||
if (plugin->clearAudioDevice(device))
|
||||
{
|
||||
if (plugin->isActive())
|
||||
device->onStopStream();
|
||||
|
||||
device->unsubscribe(port);
|
||||
delete device;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct CardinalMidiInputDevice : rack::midi::InputDevice
|
||||
{
|
||||
CardinalBasePlugin* const fPlugin;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
"modules": [
|
||||
{
|
||||
"id": 1,
|
||||
"plugin": "Core",
|
||||
"model": "AudioInterface2",
|
||||
"plugin": "Cardinal",
|
||||
"model": "HostAudio2",
|
||||
"version": "2.0",
|
||||
"params": [
|
||||
{
|
||||
|
|
@ -15,14 +15,6 @@
|
|||
],
|
||||
"rightModuleId": 2,
|
||||
"data": {
|
||||
"audio": {
|
||||
"driver": 0,
|
||||
"deviceName": "Cardinal",
|
||||
"sampleRate": 48000.0,
|
||||
"blockSize": 512,
|
||||
"inputOffset": 0,
|
||||
"outputOffset": 0
|
||||
},
|
||||
"dcFilter": true
|
||||
},
|
||||
"pos": [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue