Commit b86405d9 authored by Lyberta's avatar Lyberta

Updated OpenCL plugins.

parent 0c2d62d6
/// \file
/// \brief Header file that describes the OpenCLPluginTemplate class template.
/// \author Lyberta
/// \copyright GNU GPLv3 or any later version.
#pragma once
#include <ftz/Audio/ParallelPolyphonicSynth.h>
#include "PluginBaseTemplate.h"
namespace DISTRHO
{
/// \brief A plugin template for an OpenCL synth without special settings.
/// \details This template is used by all OpenCL synths except pulse wave.
/// \tparam Generator Generator of the synth.
/// \tparam PluginSettings Settings of the plugin. See Config.h.
template <typename Generator, typename PluginSettings>
class OpenCLPluginTemplate : public PluginBaseTemplate<PluginSettings>
{
public:
/// \brief Constructor.
OpenCLPluginTemplate();
protected:
/// \brief Initializes plugin parameter.
/// \param[in] index Index of the parameter.
/// \param[out] parameter Parameter info.
void initParameter(std::uint32_t index, Parameter& parameter) override;
/// \brief Returns the value of the plugin parameter.
/// \param[in] index Index of the parameter.
/// \return Parameter value.
float getParameterValue(std::uint32_t index) const override;
/// \brief Sets the value of the plugin parameter.
/// \param[in] index Index of the parameter.
/// \param[in] value Value to set.
void setParameterValue(std::uint32_t index, float value) override;
/// \brief Called when sample rate has changed.
/// \param[in] new_sample_rate Sample rate to set.
void sampleRateChanged(double new_sample_rate) override;
protected:
cl::Device device;
/// \brief Type of the synth.
using Synth = ftz::Audio::ParallelPolyphonicSynth<Generator,
typename PluginSettings::SampleFormat>;
std::optional<Synth> synth; ///< Holds the synth.
};
}
#include "OpenCLPluginTemplate.hpp"
/// \file
/// \brief Internal header file that contains implementation of the
/// OpenCLPluginTemplate class template.
/// \author Lyberta
/// \copyright GNU GPLv3 or any later version.
#pragma once
namespace DISTRHO
{
const std::uint32_t NumParameters = 7;
template <typename Generator, typename PluginSettings>
OpenCLPluginTemplate<Generator, PluginSettings>::OpenCLPluginTemplate()
: PluginBaseTemplate<PluginSettings>{NumParameters}
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
std::vector<cl::Device> devices;
platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
device = devices[0];
}
template <typename Generator, typename PluginSettings>
void OpenCLPluginTemplate<Generator, PluginSettings>::initParameter(
std::uint32_t index, Parameter& parameter)
{
this->template InitParameter<Synth>(static_cast<BaseParameterIndex>(index),
parameter);
}
template <typename Generator, typename PluginSettings>
float OpenCLPluginTemplate<Generator, PluginSettings>::getParameterValue(
std::uint32_t index) const
{
return this->GetParameterValue(*synth,
static_cast<BaseParameterIndex>(index));
}
template <typename Generator, typename PluginSettings>
void OpenCLPluginTemplate<Generator, PluginSettings>::setParameterValue(
std::uint32_t index, float value)
{
this->SetParameterValue(*synth, static_cast<BaseParameterIndex>(index),
value);
}
template <typename Generator, typename PluginSettings>
void OpenCLPluginTemplate<Generator, PluginSettings>::sampleRateChanged(
double new_sample_rate)
{
this->settings.SetSampleRate(new_sample_rate);
auto generator_settings = synth->GetGeneratorSettings();
generator_settings.SetSampleRate(new_sample_rate);
synth->SetGeneratorSettings(std::move(generator_settings));
auto envelope = synth->GetEnvelopeSettings();
envelope.SetSampleRate(new_sample_rate);
synth->SetEnvelopeSettings(std::move(envelope));
}
}
......@@ -15,7 +15,7 @@ template <typename Generator, typename PluginSettings>
SimplePluginTemplate<Generator, PluginSettings>::SimplePluginTemplate(
typename Generator::Settings generator_settings)
: PluginBaseTemplate<PluginSettings>{NumParameters},
synth{this->settings, this->channel, generator_settings, {}}
synth{this->settings, this->channel, generator_settings}
{
this->effects.insert(std::begin(this->effects), synth);
}
......
......@@ -6,41 +6,15 @@
#include "Plugin.h"
#include "../DPF/Utils.h"
namespace DISTRHO
{
const std::uint32_t NumParameters = 7;
enum class ParameterIndex
{
MasterVolume,
Pan,
PitchBendRange,
AttackTime,
DecayTime,
SustainLevel,
ReleaseTime
};
OpenCLSawtoothPlugin::OpenCLSawtoothPlugin()
: Plugin{NumParameters, 0, 0},
amp{OpenCLSettings::DefaultGain}
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
std::vector<cl::Device> devices;
platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
synth.emplace(settings, channel,
this->synth.emplace(this->settings, this->channel,
ftz::Audio::OpenCL::BandlimitedSawtoothWave<OpenCLSettings::CalcType>::
Settings{this->getSampleRate(), devices[0]},
ftz::Audio::Envelope<OpenCLSettings::CalcType>::Settings{
this->getSampleRate()});
effects.PushBack(*synth);
effects.PushBack(pan);
effects.PushBack(amp);
effects.PushBack(clamp);
Settings{{}, this->device});
this->effects.insert(std::begin(this->effects), *this->synth);
}
const char* OpenCLSawtoothPlugin::getName() const
......@@ -58,237 +32,11 @@ const char* OpenCLSawtoothPlugin::getDescription() const
return "Sawtooth wave synth.";
}
const char* OpenCLSawtoothPlugin::getMaker() const
{
return "Lyberta";
}
const char* OpenCLSawtoothPlugin::getHomePage() const
{
return "https://ftz.lyberta.net/projects/chiptune";
}
const char* OpenCLSawtoothPlugin::getLicense() const
{
return "GNU GPLv3+";
}
std::uint32_t OpenCLSawtoothPlugin::getVersion() const
{
return PluginVersion;
}
std::int64_t OpenCLSawtoothPlugin::getUniqueId() const
{
return d_cconst('F', 'C', 'T', '9');
}
void OpenCLSawtoothPlugin::initParameter(std::uint32_t index,
Parameter& parameter)
{
switch (static_cast<ParameterIndex>(index))
{
case ParameterIndex::MasterVolume:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Master volume";
parameter.symbol = "master_volume";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = OpenCLSettings::DefaultGain.GetValue();
return;
}
case ParameterIndex::Pan:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Pan";
parameter.symbol = "pan";
parameter.ranges.min = -1.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 0.0f;
return;
}
case ParameterIndex::PitchBendRange:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Pitch bend range";
parameter.symbol = "pitch_bend_range";
parameter.ranges.min = 0.0f;
parameter.ranges.max = OpenCLSettings::MaxPitchBend;
parameter.ranges.def = Synth::DefaultPitchBendRange;
return;
}
case ParameterIndex::AttackTime:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Attack time";
parameter.symbol = "decay_time";
parameter.unit = "seconds";
parameter.ranges.min = 0.0f;
parameter.ranges.max = OpenCLSettings::MaxAttackTime.count();
parameter.ranges.def = 0.0f;
return;
}
case ParameterIndex::DecayTime:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Decay time";
parameter.symbol = "decay_time";
parameter.unit = "seconds";
parameter.ranges.min = 0.0f;
parameter.ranges.max = OpenCLSettings::MaxDecayTime.count();
parameter.ranges.def = 0.0f;
return;
}
case ParameterIndex::SustainLevel:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Sustain level";
parameter.symbol = "sustain_level";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
return;
}
case ParameterIndex::ReleaseTime:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Release time";
parameter.symbol = "release_time";
parameter.unit = "seconds";
parameter.ranges.min = 0.0f;
parameter.ranges.max = OpenCLSettings::MaxReleaseTime.count();
parameter.ranges.def = 0.0f;
return;
}
}
}
float OpenCLSawtoothPlugin::getParameterValue(std::uint32_t index) const
{
switch (static_cast<ParameterIndex>(index))
{
case ParameterIndex::MasterVolume:
{
return amp.GetGain().GetValue();
}
case ParameterIndex::Pan:
{
return pan.GetPosition();
}
case ParameterIndex::PitchBendRange:
{
return synth->GetPitchBendRange();
}
case ParameterIndex::AttackTime:
{
return synth->GetEnvelopeSettings().GetAttackTime().count();
}
case ParameterIndex::DecayTime:
{
return synth->GetEnvelopeSettings().GetDecayTime().count();
}
case ParameterIndex::SustainLevel:
{
return synth->GetEnvelopeSettings().GetSustainLevel();
}
case ParameterIndex::ReleaseTime:
{
return synth->GetEnvelopeSettings().GetDecayTime().count();
}
}
return 0.0f;
}
void OpenCLSawtoothPlugin::setParameterValue(std::uint32_t index, float value)
{
switch (static_cast<ParameterIndex>(index))
{
case ParameterIndex::MasterVolume:
{
amp.SetGain(ftz::Audio::Gain<OpenCLSettings::CalcType>{value});
return;
}
case ParameterIndex::Pan:
{
pan.SetPosition(value);
return;
}
case ParameterIndex::PitchBendRange:
{
synth->SetPitchBendRange(value);
return;
}
case ParameterIndex::AttackTime:
{
auto envelope = synth->GetEnvelopeSettings();
envelope.SetAttackTime(
ftz::Audio::TimeDuration<OpenCLSettings::CalcType>{value});
synth->SetEnvelopeSettings(std::move(envelope));
return;
}
case ParameterIndex::DecayTime:
{
auto envelope = synth->GetEnvelopeSettings();
envelope.SetDecayTime(
ftz::Audio::TimeDuration<OpenCLSettings::CalcType>{value});
synth->SetEnvelopeSettings(std::move(envelope));
return;
}
case ParameterIndex::SustainLevel:
{
auto envelope = synth->GetEnvelopeSettings();
envelope.SetSustainLevel(value);
synth->SetEnvelopeSettings(std::move(envelope));
return;
}
case ParameterIndex::ReleaseTime:
{
auto envelope = synth->GetEnvelopeSettings();
envelope.SetReleaseTime(
ftz::Audio::TimeDuration<OpenCLSettings::CalcType>{value});
synth->SetEnvelopeSettings(std::move(envelope));
return;
}
}
}
void OpenCLSawtoothPlugin::activate()
{
auto sample_rate = this->getSampleRate();
this->sampleRateChanged(sample_rate);
}
void OpenCLSawtoothPlugin::run(const float**, float** outputs,
std::uint32_t frames, const MidiEvent* midi_events,
std::uint32_t midi_event_count)
{
ftz::Audio::MultichannelAudioBufferReference<
OpenCLSettings::SampleFormat> buffer{outputs, 2, frames};
auto first = std::begin(buffer);
decltype(first) last;
for (std::uint32_t i = 0; i < midi_event_count; ++i)
{
last = std::begin(buffer) + midi_events[i].frame;
effects.Render(first, last);
auto event = Utils::ConvertEvent(midi_events[i]);
channel.HandleEvent(*event);
first = last;
}
effects.Render(first, std::end(buffer));
}
void OpenCLSawtoothPlugin::sampleRateChanged(double new_sample_rate)
{
settings.SetSampleRate(new_sample_rate);
auto generator_settings = synth->GetGeneratorSettings();
generator_settings.SetSampleRate(new_sample_rate);
synth->SetGeneratorSettings(std::move(generator_settings));
auto envelope = synth->GetEnvelopeSettings();
envelope.SetSampleRate(new_sample_rate);
synth->SetEnvelopeSettings(std::move(envelope));
}
Plugin* createPlugin()
{
return new OpenCLSawtoothPlugin{};
......
......@@ -5,16 +5,9 @@
#pragma once
#include <ftz/Audio/SynthSettings.h>
#include <ftz/Audio/OpenCL/BandlimitedSawtoothWave.h>
#include <ftz/Audio/EnvelopeSettings.h>
#include <ftz/Audio/ParallelPolyphonicSynth.h>
#include <ftz/Audio/Pan.h>
#include <ftz/Audio/Amplifier.h>
#include <ftz/Audio/Clamper.h>
#include <ftz/Audio/EffectChain.h>
#include "../DPF/Config.h"
#include "../DPF/OpenCLPluginTemplate.h"
namespace DISTRHO
{
......@@ -23,7 +16,9 @@ namespace DISTRHO
/// \details This is a DPF wrapper of the bandlimited sawtooth synth implemented
/// using OpenCL.
class OpenCLSawtoothPlugin final : public Plugin
class OpenCLSawtoothPlugin final : public OpenCLPluginTemplate<
ftz::Audio::OpenCL::BandlimitedSawtoothWave<OpenCLSettings::CalcType>,
OpenCLSettings>
{
public:
/// \brief Constructor.
......@@ -41,72 +36,9 @@ protected:
/// \return Plugin description.
const char* getDescription() const override;
/// \brief Returns plugin author.
/// \return Plugin author.
const char* getMaker() const override;
/// \brief Returns plugin home page.
/// \return Plugin home page.
const char* getHomePage() const override;
/// \brief Returns plugin license.
/// \return Plugin license.
const char* getLicense() const override;
/// \brief Returns plugin version.
/// \return Plugin version.
std::uint32_t getVersion() const override;
/// \brief Returns plugin unique id.
/// \return Plugin unique id.
std::int64_t getUniqueId() const override;
/// \brief Initializes plugin parameter.
/// \param[in] index Index of the parameter.
/// \param[out] parameter Parameter info.
void initParameter(std::uint32_t index, Parameter& parameter) override;
/// \brief Returns the value of the plugin parameter.
/// \param[in] index Index of the parameter.
/// \return Parameter value.
float getParameterValue(std::uint32_t index) const override;
/// \brief Sets the value of the plugin parameter.
/// \param[in] index Index of the parameter.
/// \param[in] value Value to set.
void setParameterValue(std::uint32_t index, float value) override;
/// \brief Activates the plugin.
void activate() override;
/// \brief Processes MIDI input and renders audio.
/// \param[out] outputs Array of output channels.
/// \param[in] frames Number of frames to process.
/// \param[in] midi_events MIDI events to process.
/// \param[in] midi_event_count Number of MIDI events to process.
void run(const float**, float** outputs, std::uint32_t frames,
const MidiEvent* midi_events, std::uint32_t midi_event_count)
override;
/// \brief Called when sample rate has changed.
/// \param[in] new_sample_rate Sample rate to set.
void sampleRateChanged(double new_sample_rate) override;
private:
/// \brief Type of the synth.
using Synth = ftz::Audio::ParallelPolyphonicSynth<
ftz::Audio::OpenCL::BandlimitedSawtoothWave<OpenCLSettings::CalcType>,
OpenCLSettings::SampleFormat>;
ftz::MIDI::InputChannel channel; ///< Holds the MIDI channel.
/// \brief Holds synth settings.
ftz::Audio::SynthSettings<OpenCLSettings::CalcType> settings;
std::optional<Synth> synth; ///< Holds the synth.
ftz::Audio::Pan<OpenCLSettings::SampleFormat> pan; ///< Holds the pan.
/// \brief Holds the amplifier.
ftz::Audio::Amplifier<OpenCLSettings::SampleFormat> amp;
/// \brief Holds the clamper.
ftz::Audio::Clamper<OpenCLSettings::SampleFormat> clamp;
/// \brief Holds the effect chain.
ftz::Audio::EffectChain<OpenCLSettings::SampleFormat> effects;
};
}
......@@ -6,41 +6,15 @@
#include "Plugin.h"
#include "../DPF/Utils.h"
namespace DISTRHO
{
const std::uint32_t NumParameters = 7;
enum class ParameterIndex
{
MasterVolume,
Pan,
PitchBendRange,
AttackTime,
DecayTime,
SustainLevel,
ReleaseTime
};
OpenCLTrianglePlugin::OpenCLTrianglePlugin()
: Plugin{NumParameters, 0, 0},
amp{OpenCLSettings::DefaultGain}
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
std::vector<cl::Device> devices;
platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
synth.emplace(settings, channel,
this->synth.emplace(this->settings, this->channel,
ftz::Audio::OpenCL::BandlimitedTriangleWave<OpenCLSettings::CalcType>::
Settings{this->getSampleRate(), devices[0]},
ftz::Audio::Envelope<OpenCLSettings::CalcType>::Settings{
this->getSampleRate()});
effects.PushBack(*synth);
effects.PushBack(pan);
effects.PushBack(amp);
effects.PushBack(clamp);
Settings{{}, this->device});
this->effects.insert(std::begin(this->effects), *this->synth);
}
const char* OpenCLTrianglePlugin::getName() const
......@@ -58,237 +32,11 @@ const char* OpenCLTrianglePlugin::getDescription() const
return "Triangle wave synth.";
}
const char* OpenCLTrianglePlugin::getMaker() const
{
return "Lyberta";
}
const char* OpenCLTrianglePlugin::getHomePage() const
{
return "https://ftz.lyberta.net/projects/chiptune";
}
const char* OpenCLTrianglePlugin::getLicense() const
{
return "GNU GPLv3+";
}
std::uint32_t OpenCLTrianglePlugin::getVersion() const
{
return PluginVersion;
}
std::int64_t OpenCLTrianglePlugin::getUniqueId() const
{
return d_cconst('F', 'C', 'T', '8');
}
void OpenCLTrianglePlugin::initParameter(std::uint32_t index,
Parameter& parameter)
{
switch (static_cast<ParameterIndex>(index))
{
case ParameterIndex::MasterVolume:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Master volume";
parameter.symbol = "master_volume";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = OpenCLSettings::DefaultGain.GetValue();
return;
}
case ParameterIndex::Pan:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Pan";
parameter.symbol = "pan";
parameter.ranges.min = -1.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 0.0f;
return;
}
case ParameterIndex::PitchBendRange:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Pitch bend range";
parameter.symbol = "pitch_bend_range";
parameter.ranges.min = 0.0f;
parameter.ranges.max = OpenCLSettings::MaxPitchBend;
parameter.ranges.def = Synth::DefaultPitchBendRange;
return;
}
case ParameterIndex::AttackTime:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Attack time";
parameter.symbol = "decay_time";
parameter.unit = "seconds";
parameter.ranges.min = 0.0f;
parameter.ranges.max = OpenCLSettings::MaxAttackTime.count();
parameter.ranges.def = 0.0f;
return;
}
case ParameterIndex::DecayTime:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Decay time";
parameter.symbol = "decay_time";
parameter.unit = "seconds";
parameter.ranges.min = 0.0f;
parameter.ranges.max = OpenCLSettings::MaxDecayTime.count();
parameter.ranges.def = 0.0f;
return;
}
case ParameterIndex::SustainLevel:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Sustain level";
parameter.symbol = "sustain_level";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
return;
}
case ParameterIndex::ReleaseTime:
{
parameter.hints = kParameterIsAutomable;
parameter.name = "Release time";
parameter.symbol = "release_time";
parameter.unit = "seconds";
parameter.ranges.min = 0.0f;
parameter.ranges.max = OpenCLSettings::MaxReleaseTime.count();
parameter.ranges.def = 0.0f;
return;
}
}
}
float OpenCLTrianglePlugin::getParameterValue(std::uint32_t index) const
{
switch (static_cast<ParameterIndex>(index))
{
case ParameterIndex::MasterVolume:
{
return amp.GetGain().GetValue();
}
case ParameterIndex::Pan:
{
return pan.GetPosition();
}
case ParameterIndex::PitchBendRange:
{
return synth->GetPitchBendRange();
}
case ParameterIndex::AttackTime:
{
return synth->GetEnvelopeSettings().GetAttackTime().count();
}
case ParameterIndex::DecayTime:
{
return synth->GetEnvelopeSettings().GetDecayTime().count();
}
case ParameterIndex::SustainLevel:
{
return synth->GetEnvelopeSettings().GetSustainLevel();
}
case ParameterIndex::ReleaseTime:
{
return synth->GetEnvelopeSettings().GetDecayTime().count();
}
}
return 0.0f;
}
void OpenCLTrianglePlugin::setParameterValue(std::uint32_t index, float value)
{
switch (static_cast<ParameterIndex>(index))
{
case ParameterIndex::MasterVolume:
{
amp.SetGain(ftz::Audio::Gain<OpenCLSettings::CalcType>{value});
return;
}
case ParameterIndex::Pan:
{
pan.SetPosition(value);
return;
}
case ParameterIndex::PitchBendRange:
{
synth->SetPitchBendRange(value);
return;
}
case ParameterIndex::AttackTime:
{
auto envelope = synth->GetEnvelopeSettings();
envelope.SetAttackTime(