Rework plugin audio processing, use simple builtin module for it

This commit is contained in:
falkTX 2022-01-19 17:40:57 +00:00
parent 30134b4b22
commit caf5ca5df6
14 changed files with 578 additions and 318 deletions

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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": [