vst2 host
This commit is contained in:
parent
dc28bf6e0f
commit
2f1fc152ff
@ -6,7 +6,7 @@
|
||||
|
||||
void audio_device_manager::init(singleton_initliazer& initliazer) {
|
||||
singleton_t<audio_device_manager>::init(initliazer);
|
||||
initliazer.require<mixer>();
|
||||
|
||||
dummy_audio_device_ = new dummy_audio_device();
|
||||
main_audio_device_ = new port_audio_device();
|
||||
|
||||
@ -19,3 +19,29 @@ void audio_device_manager::release() {
|
||||
delete dummy_audio_device_;
|
||||
delete main_audio_device_;
|
||||
}
|
||||
|
||||
double audio_device_manager::get_sample_rate() const {
|
||||
return main_audio_device_->sample_rate();
|
||||
}
|
||||
|
||||
void audio_device_manager::set_sample_rate(double sample_rate) {
|
||||
main_audio_device_->set_sample_rate(sample_rate);
|
||||
dummy_audio_device_->set_sample_rate(sample_rate);
|
||||
}
|
||||
|
||||
uint32_t audio_device_manager::get_buffer_size() const {
|
||||
return main_audio_device_->buffer_size();
|
||||
}
|
||||
|
||||
void audio_device_manager::set_buffer_size(int buffer_size) {
|
||||
main_audio_device_->set_buffer_size(buffer_size);
|
||||
dummy_audio_device_->set_buffer_size(buffer_size);
|
||||
}
|
||||
|
||||
uint32_t audio_device_manager::get_input_channel_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t audio_device_manager::get_output_channel_count() const {
|
||||
return 2; // 现在是固定值, 以后可能会改
|
||||
}
|
||||
|
@ -9,10 +9,17 @@ public:
|
||||
void init(singleton_initliazer& initliazer) override;
|
||||
void release() override;
|
||||
|
||||
const char* get_name() override { return "audio_device_manager"; }
|
||||
[[nodiscard]] const char* get_name() override { return "audio_device_manager"; }
|
||||
|
||||
[[nodiscard]] double get_sample_rate() const;
|
||||
void set_sample_rate(double sample_rate);
|
||||
[[nodiscard]] uint32_t get_buffer_size() const;
|
||||
void set_buffer_size(int buffer_size);
|
||||
[[nodiscard]] uint32_t get_input_channel_count() const;
|
||||
[[nodiscard]] uint32_t get_output_channel_count() const;
|
||||
private:
|
||||
port_audio_device* main_audio_device_ = nullptr;
|
||||
dummy_audio_device* dummy_audio_device_ = nullptr;
|
||||
};
|
||||
|
||||
CORE_API inline audio_device_manager g_audio_device_manager;
|
||||
DEFINE_SINGLETON_INSTANCE(audio_device_manager)
|
||||
|
@ -16,6 +16,6 @@ public:
|
||||
|
||||
private:
|
||||
std::vector<std::vector<float>> buffer_;
|
||||
std::vector<float*> headers_;
|
||||
std::mutex lock_;
|
||||
std::vector<float*> headers_{};
|
||||
std::mutex lock_{};
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "channel_interface.h"
|
||||
|
||||
#include "channel_node.h"
|
||||
#include "mixer.h"
|
||||
|
||||
channel_interface::channel_interface(uint32_t input_channels, uint32_t output_channels) {
|
||||
const uint32_t input_node_num = input_channels / 2;
|
||||
@ -32,7 +33,8 @@ void channel_interface::set_input_channel(uint32_t node_index, channel_node* nod
|
||||
|
||||
input_headers_[node_index * 2] = node_headers[0];
|
||||
input_headers_[node_index * 2 + 1] = node_headers[1];
|
||||
// TODO rebuild process node
|
||||
|
||||
g_mixer.request_build_process_node();
|
||||
}
|
||||
|
||||
void channel_interface::set_input_channel(const std::vector<channel_node*>& nodes, uint32_t start_index) {
|
||||
@ -52,7 +54,8 @@ void channel_interface::set_output_channel(uint32_t node_index, channel_node* no
|
||||
|
||||
output_headers_[node_index * 2] = node_headers[0];
|
||||
output_headers_[node_index * 2 + 1] = node_headers[1];
|
||||
// TODO rebuild process node
|
||||
|
||||
g_mixer.request_build_process_node();
|
||||
}
|
||||
|
||||
void channel_interface::set_output_channel(const std::vector<channel_node*>& nodes, uint32_t start_index) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "channel_interface.h"
|
||||
#include "channel_node.h"
|
||||
#include "mixer_track.h"
|
||||
#include "audio/device/audio_device_manager.h"
|
||||
#include "audio/plugin_host/plugin_host.h"
|
||||
#include "audio/plugin_host/plugin_host_manager.h"
|
||||
#include "thread_message/thread_message_hubs.h"
|
||||
@ -46,7 +47,7 @@ int32_t build_process_node_internal(mixer_track* track, std::map<mixer_track*, i
|
||||
build_process_node_internal(ChildTrack, processed_tracks, layer + 1);
|
||||
for (const plugin_host* effect: ChildTrack->effects)
|
||||
{
|
||||
build_effect_channel_interface(ChildTrack, effect->interface.get(), processed_tracks);
|
||||
build_effect_channel_interface(ChildTrack, effect->channel, processed_tracks);
|
||||
}
|
||||
}
|
||||
return ++layer;
|
||||
@ -55,12 +56,13 @@ int32_t build_process_node_internal(mixer_track* track, std::map<mixer_track*, i
|
||||
void build_instrument_process_node(const plugin_host* host, std::map<mixer_track*, int32_t>& processed_tracks) {
|
||||
for (mixer_track* Track : host->owner_tracks)
|
||||
{
|
||||
build_effect_channel_interface(Track, host->interface.get(), processed_tracks);
|
||||
build_effect_channel_interface(Track, host->channel, processed_tracks);
|
||||
}
|
||||
}
|
||||
|
||||
void mixer::init(singleton_initliazer& initliazer) {
|
||||
singleton_t<mixer>::init(initliazer);
|
||||
initliazer.require<audio_device_manager>();
|
||||
zero_track = new dummy_track();
|
||||
zero_track->rename("zero");
|
||||
zero_track->init();
|
||||
|
@ -42,4 +42,4 @@ private:
|
||||
std::vector<int32_t> layer_order_;
|
||||
};
|
||||
|
||||
CORE_API inline mixer g_mixer;
|
||||
DEFINE_SINGLETON_INSTANCE(mixer)
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "mixer_track.h"
|
||||
|
||||
#include "channel_interface.h"
|
||||
#include "audio/device/audio_device_manager.h"
|
||||
#include "audio/plugin_host/plugin_host.h"
|
||||
|
||||
mixer_track::~mixer_track() {
|
||||
@ -7,7 +9,10 @@ mixer_track::~mixer_track() {
|
||||
}
|
||||
|
||||
void mixer_track::init() {
|
||||
const uint32_t channel_count = g_audio_device_manager.get_output_channel_count();
|
||||
buffer.resize(channel_count, g_audio_device_manager.get_buffer_size());
|
||||
|
||||
channel_interface_ = new mixer_channel_interface(this);
|
||||
}
|
||||
|
||||
void mixer_track::add_effect(plugin_host* in_effect) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "audio/misc/audio_buffer.h"
|
||||
|
||||
class channel_interface;
|
||||
class mixer_track;
|
||||
class plugin_host;
|
||||
|
||||
@ -35,6 +36,8 @@ public:
|
||||
|
||||
[[nodiscard]] mixer_track_type get_type() const { return type_; }
|
||||
|
||||
[[nodiscard]] channel_interface* get_channel_interface() const { return channel_interface_; }
|
||||
|
||||
audio_buffer buffer;
|
||||
std::atomic<float> volume = 1.0f;
|
||||
std::vector<plugin_host*> effects{};
|
||||
@ -42,6 +45,7 @@ public:
|
||||
private:
|
||||
void add_effect_internal(plugin_host* in_effect);
|
||||
const mixer_track_type type_;
|
||||
channel_interface* channel_interface_ = nullptr;
|
||||
};
|
||||
|
||||
class instrument_track : public mixer_track {
|
||||
|
@ -1,4 +1,13 @@
|
||||
#include "midi_sequencer.h"
|
||||
|
||||
#include "vst2/vst2_plugin_host.h"
|
||||
|
||||
void midi_sequencer::init(singleton_initliazer& initliazer) {
|
||||
singleton_t<midi_sequencer>::init(initliazer);
|
||||
|
||||
vst2_plugin_host::vst_time_info.tempo = 128.0;
|
||||
|
||||
}
|
||||
|
||||
void midi_sequencer::process(double sample_rate, uint32_t in_frames) {
|
||||
}
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
class midi_sequencer : public singleton_t<midi_sequencer> {
|
||||
public:
|
||||
void init(singleton_initliazer& initliazer) override;
|
||||
void process(double sample_rate, uint32_t in_frames);
|
||||
|
||||
const char* get_name() override { return "midi_sequencer"; }
|
||||
};
|
||||
|
||||
CORE_API inline midi_sequencer g_midi_sequencer;
|
||||
DEFINE_SINGLETON_INSTANCE(midi_sequencer)
|
||||
|
@ -1 +1,17 @@
|
||||
#include "plugin_host.h"
|
||||
|
||||
#include "audio/mixer/channel_interface.h"
|
||||
|
||||
plugin_host::~plugin_host() {
|
||||
delete channel;
|
||||
}
|
||||
|
||||
void plugin_host::try_open_editor() {
|
||||
auto editor_size = get_editor_size();
|
||||
editor_window = glfwCreateWindow(editor_size.x, editor_size.y, name.c_str(), nullptr, nullptr);
|
||||
open_editor(editor_window);
|
||||
}
|
||||
|
||||
void plugin_host::init_channel_interface() {
|
||||
channel = new channel_interface(get_input_channels(), get_output_channels());
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ class channel_interface;
|
||||
|
||||
class plugin_host {
|
||||
public:
|
||||
virtual ~plugin_host();
|
||||
|
||||
virtual bool load_plugin(const char* path) = 0;
|
||||
|
||||
virtual void set_enabled(bool enabled) = 0;
|
||||
@ -14,20 +16,28 @@ public:
|
||||
|
||||
virtual void on_update_sample_rate(double sample_rate) = 0;
|
||||
virtual void on_update_buffer_size(int buffer_size) = 0;
|
||||
virtual uint32_t get_input_channels() const = 0;
|
||||
virtual uint32_t get_output_channels() const = 0;
|
||||
[[nodiscard]] virtual uint32_t get_input_channels() const = 0;
|
||||
[[nodiscard]] virtual uint32_t get_output_channels() const = 0;
|
||||
virtual void update_channel_node_name() {}
|
||||
|
||||
virtual void process(uint32_t frame_num) {}
|
||||
virtual void process(uint32_t frame_num) = 0;
|
||||
|
||||
virtual void open_editor(GLFWwindow* window) {}
|
||||
virtual void close_editor() {}
|
||||
void try_open_editor();
|
||||
virtual void open_editor(GLFWwindow* window) = 0;
|
||||
virtual void close_editor() = 0;
|
||||
virtual void idle_editor() {}
|
||||
virtual bool has_editor() const { return false; }
|
||||
virtual ImVec2 get_editor_size() const { return ImVec2(0, 0); }
|
||||
|
||||
[[nodiscard]] virtual bool has_editor() const { return false; }
|
||||
[[nodiscard]] virtual ImVec2 get_editor_size() const { return ImVec2(0, 0); }
|
||||
|
||||
[[nodiscard]] virtual std::string load_name() const { return ""; }
|
||||
[[nodiscard]] virtual std::string load_vendor() const { return ""; }
|
||||
|
||||
void init_channel_interface();
|
||||
|
||||
std::string name;
|
||||
std::string vendor;
|
||||
std::shared_ptr<channel_interface> interface;
|
||||
channel_interface* channel = nullptr;
|
||||
std::vector<mixer_track*> owner_tracks;
|
||||
GLFWwindow* editor_window = nullptr;
|
||||
};
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "audio/mixer/channel_interface.h"
|
||||
#include "audio/mixer/mixer.h"
|
||||
#include "misc/singleton/singleton_manager.h"
|
||||
#include "vst2/vst2_plugin_host.h"
|
||||
|
||||
void plugin_host_manager::init(singleton_initliazer& initliazer) {
|
||||
singleton_t<plugin_host_manager>::init(initliazer);
|
||||
@ -13,6 +14,15 @@ void plugin_host_manager::init(singleton_initliazer& initliazer) {
|
||||
mixer_ptr->on_remove_track.add_raw(this, &plugin_host_manager::on_mixer_track_removed);
|
||||
}
|
||||
|
||||
plugin_host* plugin_host_manager::load_plugin(const char* path) {
|
||||
auto host = new vst2_plugin_host();
|
||||
host->load_plugin(path);
|
||||
host->init_channel_interface();
|
||||
plugin_hosts_.push_back(host);
|
||||
host->try_open_editor();
|
||||
return host;
|
||||
}
|
||||
|
||||
void plugin_host_manager::process(uint32_t in_frames) const {
|
||||
tf::Executor executor;
|
||||
tf::Taskflow taskflow;
|
||||
@ -26,6 +36,6 @@ void plugin_host_manager::process(uint32_t in_frames) const {
|
||||
|
||||
void plugin_host_manager::on_mixer_track_removed(mixer_track* track) {
|
||||
for (auto host : plugin_hosts_) {
|
||||
host->interface->remove_track(track);
|
||||
host->channel->remove_track(track);
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,12 @@
|
||||
class plugin_host;
|
||||
class mixer_track;
|
||||
|
||||
class plugin_host_manager : public singleton_t<plugin_host_manager> {
|
||||
class CORE_API plugin_host_manager : public singleton_t<plugin_host_manager> {
|
||||
public:
|
||||
void init(singleton_initliazer& initliazer) override;
|
||||
|
||||
plugin_host* load_plugin(const char* path);
|
||||
|
||||
const std::vector<plugin_host*>& get_plugin_hosts() { return plugin_hosts_; }
|
||||
void process(uint32_t in_frames) const;
|
||||
|
||||
@ -19,4 +21,4 @@ private:
|
||||
std::vector<plugin_host*> plugin_hosts_{};
|
||||
};
|
||||
|
||||
CORE_API inline plugin_host_manager g_plugin_host_manager;
|
||||
DEFINE_SINGLETON_INSTANCE(plugin_host_manager)
|
||||
|
396
core/audio/plugin_host/vst2/pluginterfaces/vst2.x/aeffect.h
Normal file
396
core/audio/plugin_host/vst2/pluginterfaces/vst2.x/aeffect.h
Normal file
@ -0,0 +1,396 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Project : VST SDK
|
||||
// Version : 2.4
|
||||
//
|
||||
// Category : VST 2.x Interfaces
|
||||
// Filename : pluginterfaces/vst2.x/aeffect.h
|
||||
// Created by : Steinberg, 01/2004
|
||||
// Description : Definition of AEffect structure (VST 1.0)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// LICENSE
|
||||
// (c) 2016, Steinberg Media Technologies GmbH, All Rights Reserved
|
||||
//-----------------------------------------------------------------------------
|
||||
// This Software Development Kit may not be distributed in parts or its entirety
|
||||
// without prior written agreement by Steinberg Media Technologies GmbH.
|
||||
// This SDK must not be used to re-engineer or manipulate any technology used
|
||||
// in any Steinberg or Third-party application or software module,
|
||||
// unless permitted by law.
|
||||
// Neither the name of the Steinberg Media Technologies nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SDK IS PROVIDED BY STEINBERG MEDIA TECHNOLOGIES GMBH "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL STEINBERG MEDIA TECHNOLOGIES GMBH BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __aeffect__
|
||||
#define __aeffect__
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// gcc based compiler, or CodeWarrior on Mac OS X
|
||||
#if ((defined(__GNUC__) && (defined(__APPLE_CPP__) || defined(__APPLE_CC__))) || (defined (__MWERKS__) && defined (__MACH__)))
|
||||
#ifndef TARGET_API_MAC_CARBON
|
||||
#define TARGET_API_MAC_CARBON 1
|
||||
#endif
|
||||
#if __ppc__
|
||||
#ifndef VST_FORCE_DEPRECATED
|
||||
#define VST_FORCE_DEPRECATED 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32
|
||||
#define WIN32 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_API_MAC_CARBON
|
||||
#ifdef __LP64__
|
||||
#pragma options align=power
|
||||
#else
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
#define VSTCALLBACK
|
||||
#elif defined __BORLANDC__
|
||||
#pragma -a8
|
||||
#pragma options push -a8
|
||||
#elif defined(__GNUC__)
|
||||
#pragma pack(push,8)
|
||||
#define VSTCALLBACK //__cdecl
|
||||
#elif defined(WIN32) || defined(__FLAT__) || defined CBUILDER
|
||||
#pragma pack(push)
|
||||
#pragma pack(8)
|
||||
#define VSTCALLBACK __cdecl
|
||||
#else
|
||||
#define VSTCALLBACK
|
||||
#endif
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
#include <string.h> // for strncpy
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// VST Version
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Define SDK Version (you can generate different versions (from 2.0 to 2.4) of this SDK by setting the unwanted extensions to 0). */
|
||||
#define VST_2_1_EXTENSIONS 1 ///< Version 2.1 extensions (08-06-2000)
|
||||
#define VST_2_2_EXTENSIONS 1 ///< Version 2.2 extensions (08-06-2001)
|
||||
#define VST_2_3_EXTENSIONS 1 ///< Version 2.3 extensions (20-05-2003)
|
||||
#ifndef VST_2_4_EXTENSIONS
|
||||
#define VST_2_4_EXTENSIONS 1 ///< Version 2.4 extensions (01-01-2006)
|
||||
#endif
|
||||
|
||||
/** Current VST Version */
|
||||
#if VST_2_4_EXTENSIONS
|
||||
#define kVstVersion 2400
|
||||
#elif VST_2_3_EXTENSIONS
|
||||
#define kVstVersion 2300
|
||||
#elif VST_2_2_EXTENSIONS
|
||||
#define kVstVersion 2200
|
||||
#elif VST_2_1_EXTENSIONS
|
||||
#define kVstVersion 2100
|
||||
#else
|
||||
#define kVstVersion 2
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/** Disable for Hosts to serve Plug-ins below VST 2.4 */
|
||||
#ifndef VST_FORCE_DEPRECATED
|
||||
#define VST_FORCE_DEPRECATED VST_2_4_EXTENSIONS
|
||||
#endif
|
||||
|
||||
#undef VST_FORCE_DEPRECATED
|
||||
|
||||
/** Declares identifier as deprecated. */
|
||||
#ifdef VST_FORCE_DEPRECATED
|
||||
#define DECLARE_VST_DEPRECATED(identifier) __##identifier##Deprecated
|
||||
#else
|
||||
#define DECLARE_VST_DEPRECATED(identifier) identifier
|
||||
#endif
|
||||
|
||||
/** Define for 64 Bit Platform. */
|
||||
#ifndef VST_64BIT_PLATFORM
|
||||
#define VST_64BIT_PLATFORM _WIN64 || __LP64__
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// Integral Types
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
typedef char VstInt8; ///< 8 bit integer type
|
||||
|
||||
#ifdef WIN32
|
||||
typedef short VstInt16; ///< 16 bit integer type
|
||||
typedef int VstInt32; ///< 32 bit integer type
|
||||
typedef __int64 VstInt64; ///< 64 bit integer type
|
||||
#else
|
||||
#include <stdint.h>
|
||||
typedef int16_t VstInt16; ///< 16 bit integer type
|
||||
typedef int32_t VstInt32; ///< 32 bit integer type
|
||||
typedef int64_t VstInt64; ///< 64 bit integer type
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// Generic Types
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if VST_64BIT_PLATFORM
|
||||
typedef VstInt64 VstIntPtr; ///< platform-dependent integer type, same size as pointer
|
||||
#else
|
||||
typedef VstInt32 VstIntPtr; ///< platform-dependent integer type, same size as pointer
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// Misc. Definition
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
#undef CCONST
|
||||
typedef struct AEffect AEffect;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/// @cond ignore
|
||||
typedef VstIntPtr (VSTCALLBACK *audioMasterCallback) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);
|
||||
typedef VstIntPtr (VSTCALLBACK *AEffectDispatcherProc) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);
|
||||
typedef void (VSTCALLBACK *AEffectProcessProc) (AEffect* effect, float** inputs, float** outputs, VstInt32 sampleFrames);
|
||||
typedef void (VSTCALLBACK *AEffectProcessDoubleProc) (AEffect* effect, double** inputs, double** outputs, VstInt32 sampleFrames);
|
||||
typedef void (VSTCALLBACK *AEffectSetParameterProc) (AEffect* effect, VstInt32 index, float parameter);
|
||||
typedef float (VSTCALLBACK *AEffectGetParameterProc) (AEffect* effect, VstInt32 index);
|
||||
/// @endcond
|
||||
|
||||
/** Four Character Constant (for AEffect->uniqueID) */
|
||||
#define CCONST(a, b, c, d) \
|
||||
((((VstInt32)a) << 24) | (((VstInt32)b) << 16) | (((VstInt32)c) << 8) | (((VstInt32)d) << 0))
|
||||
|
||||
/** AEffect magic number */
|
||||
#define kEffectMagic CCONST ('V', 's', 't', 'P')
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Basic VST Effect "C" Interface. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
struct AEffect
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VstInt32 magic; ///< must be #kEffectMagic ('VstP')
|
||||
|
||||
/** Host to Plug-in dispatcher @see AudioEffect::dispatcher */
|
||||
AEffectDispatcherProc dispatcher;
|
||||
|
||||
/** \deprecated Accumulating process mode is deprecated in VST 2.4! Use AEffect::processReplacing instead! */
|
||||
AEffectProcessProc DECLARE_VST_DEPRECATED (process);
|
||||
|
||||
/** Set new value of automatable parameter @see AudioEffect::setParameter */
|
||||
AEffectSetParameterProc setParameter;
|
||||
|
||||
/** Returns current value of automatable parameter @see AudioEffect::getParameter*/
|
||||
AEffectGetParameterProc getParameter;
|
||||
|
||||
VstInt32 numPrograms; ///< number of programs
|
||||
VstInt32 numParams; ///< all programs are assumed to have numParams parameters
|
||||
VstInt32 numInputs; ///< number of audio inputs
|
||||
VstInt32 numOutputs; ///< number of audio outputs
|
||||
|
||||
VstInt32 flags; ///< @see VstAEffectFlags
|
||||
|
||||
VstIntPtr resvd1; ///< reserved for Host, must be 0
|
||||
VstIntPtr resvd2; ///< reserved for Host, must be 0
|
||||
|
||||
VstInt32 initialDelay; ///< for algorithms which need input in the first place (Group delay or latency in Samples). This value should be initialized in a resume state.
|
||||
|
||||
VstInt32 DECLARE_VST_DEPRECATED (realQualities); ///< \deprecated unused member
|
||||
VstInt32 DECLARE_VST_DEPRECATED (offQualities); ///< \deprecated unused member
|
||||
float DECLARE_VST_DEPRECATED (ioRatio); ///< \deprecated unused member
|
||||
|
||||
void* object; ///< #AudioEffect class pointer
|
||||
void* user; ///< user-defined pointer
|
||||
|
||||
VstInt32 uniqueID; ///< registered unique identifier (register it at Steinberg 3rd party support Web). This is used to identify a plug-in during save+load of preset and project.
|
||||
VstInt32 version; ///< plug-in version (example 1100 for version 1.1.0.0)
|
||||
|
||||
/** Process audio samples in replacing mode @see AudioEffect::processReplacing */
|
||||
AEffectProcessProc processReplacing;
|
||||
|
||||
#if VST_2_4_EXTENSIONS
|
||||
/** Process double-precision audio samples in replacing mode @see AudioEffect::processDoubleReplacing */
|
||||
AEffectProcessDoubleProc processDoubleReplacing;
|
||||
|
||||
char future[56]; ///< reserved for future use (please zero)
|
||||
#else
|
||||
char future[60]; ///< reserved for future use (please zero)
|
||||
#endif // VST_2_4_EXTENSIONS
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** AEffect flags */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
enum VstAEffectFlags
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
effFlagsHasEditor = 1 << 0, ///< set if the plug-in provides a custom editor
|
||||
effFlagsCanReplacing = 1 << 4, ///< supports replacing process mode (which should the default mode in VST 2.4)
|
||||
effFlagsProgramChunks = 1 << 5, ///< program data is handled in formatless chunks
|
||||
effFlagsIsSynth = 1 << 8, ///< plug-in is a synth (VSTi), Host may assign mixer channels for its outputs
|
||||
effFlagsNoSoundInStop = 1 << 9, ///< plug-in does not produce sound when input is all silence
|
||||
|
||||
#if VST_2_4_EXTENSIONS
|
||||
effFlagsCanDoubleReplacing = 1 << 12, ///< plug-in supports double precision processing
|
||||
#endif
|
||||
|
||||
DECLARE_VST_DEPRECATED (effFlagsHasClip) = 1 << 1, ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effFlagsHasVu) = 1 << 2, ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effFlagsCanMono) = 1 << 3, ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effFlagsExtIsAsync) = 1 << 10, ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effFlagsExtHasBuffer) = 1 << 11 ///< \deprecated deprecated in VST 2.4
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Basic dispatcher Opcodes (Host to Plug-in) */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
enum AEffectOpcodes
|
||||
{
|
||||
effOpen = 0, ///< no arguments @see AudioEffect::open
|
||||
effClose, ///< no arguments @see AudioEffect::close
|
||||
|
||||
effSetProgram, ///< [value]: new program number @see AudioEffect::setProgram
|
||||
effGetProgram, ///< [return value]: current program number @see AudioEffect::getProgram
|
||||
effSetProgramName, ///< [ptr]: char* with new program name, limited to #kVstMaxProgNameLen @see AudioEffect::setProgramName
|
||||
effGetProgramName, ///< [ptr]: char buffer for current program name, limited to #kVstMaxProgNameLen @see AudioEffect::getProgramName
|
||||
|
||||
effGetParamLabel, ///< [ptr]: char buffer for parameter label, limited to #kVstMaxParamStrLen @see AudioEffect::getParameterLabel
|
||||
effGetParamDisplay, ///< [ptr]: char buffer for parameter display, limited to #kVstMaxParamStrLen @see AudioEffect::getParameterDisplay
|
||||
effGetParamName, ///< [ptr]: char buffer for parameter name, limited to #kVstMaxParamStrLen @see AudioEffect::getParameterName
|
||||
|
||||
DECLARE_VST_DEPRECATED (effGetVu), ///< \deprecated deprecated in VST 2.4
|
||||
|
||||
effSetSampleRate, ///< [opt]: new sample rate for audio processing @see AudioEffect::setSampleRate
|
||||
effSetBlockSize, ///< [value]: new maximum block size for audio processing @see AudioEffect::setBlockSize
|
||||
effMainsChanged, ///< [value]: 0 means "turn off", 1 means "turn on" @see AudioEffect::suspend @see AudioEffect::resume
|
||||
|
||||
effEditGetRect, ///< [ptr]: #ERect** receiving pointer to editor size @see ERect @see AEffEditor::getRect
|
||||
effEditOpen, ///< [ptr]: system dependent Window pointer, e.g. HWND on Windows @see AEffEditor::open
|
||||
effEditClose, ///< no arguments @see AEffEditor::close
|
||||
|
||||
DECLARE_VST_DEPRECATED (effEditDraw), ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effEditMouse), ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effEditKey), ///< \deprecated deprecated in VST 2.4
|
||||
|
||||
effEditIdle, ///< no arguments @see AEffEditor::idle
|
||||
|
||||
DECLARE_VST_DEPRECATED (effEditTop), ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effEditSleep), ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effIdentify), ///< \deprecated deprecated in VST 2.4
|
||||
|
||||
effGetChunk, ///< [ptr]: void** for chunk data address [index]: 0 for bank, 1 for program @see AudioEffect::getChunk
|
||||
effSetChunk, ///< [ptr]: chunk data [value]: byte size [index]: 0 for bank, 1 for program @see AudioEffect::setChunk
|
||||
|
||||
effNumOpcodes
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Basic dispatcher Opcodes (Plug-in to Host) */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
enum AudioMasterOpcodes
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
audioMasterAutomate = 0, ///< [index]: parameter index [opt]: parameter value @see AudioEffect::setParameterAutomated
|
||||
audioMasterVersion, ///< [return value]: Host VST version (for example 2400 for VST 2.4) @see AudioEffect::getMasterVersion
|
||||
audioMasterCurrentId, ///< [return value]: current unique identifier on shell plug-in @see AudioEffect::getCurrentUniqueId
|
||||
audioMasterIdle, ///< no arguments @see AudioEffect::masterIdle
|
||||
DECLARE_VST_DEPRECATED (audioMasterPinConnected) ///< \deprecated deprecated in VST 2.4 r2
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** String length limits (in characters excl. 0 byte) */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
enum VstStringConstants
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
kVstMaxProgNameLen = 24, ///< used for #effGetProgramName, #effSetProgramName, #effGetProgramNameIndexed
|
||||
kVstMaxParamStrLen = 8, ///< used for #effGetParamLabel, #effGetParamDisplay, #effGetParamName
|
||||
kVstMaxVendorStrLen = 64, ///< used for #effGetVendorString, #audioMasterGetVendorString
|
||||
kVstMaxProductStrLen = 64, ///< used for #effGetProductString, #audioMasterGetProductString
|
||||
kVstMaxEffectNameLen = 32 ///< used for #effGetEffectName
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define VST_INLINE inline
|
||||
#else
|
||||
#define VST_INLINE
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** String copy taking care of null terminator. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VST_INLINE char* vst_strncpy (char* dst, const char* src, size_t maxLen)
|
||||
{
|
||||
char* result = strncpy (dst, src, maxLen);
|
||||
dst[maxLen] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** String concatenation taking care of null terminator. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VST_INLINE char* vst_strncat (char* dst, const char* src, size_t maxLen)
|
||||
{
|
||||
char* result = strncat (dst, src, maxLen);
|
||||
dst[maxLen] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Cast #VstIntPtr to pointer. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
template <class T> inline T* FromVstPtr (VstIntPtr& arg)
|
||||
{
|
||||
T** address = (T**)&arg;
|
||||
return *address;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Cast pointer to #VstIntPtr. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
template <class T> inline VstIntPtr ToVstPtr (T* ptr)
|
||||
{
|
||||
VstIntPtr* address = (VstIntPtr*)&ptr;
|
||||
return *address;
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Structure used for #effEditGetRect. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
struct ERect
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VstInt16 top; ///< top coordinate
|
||||
VstInt16 left; ///< left coordinate
|
||||
VstInt16 bottom; ///< bottom coordinate
|
||||
VstInt16 right; ///< right coordinate
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
#if TARGET_API_MAC_CARBON
|
||||
#pragma options align=reset
|
||||
#elif defined(WIN32) || defined(__FLAT__) || defined(__GNUC__)
|
||||
#pragma pack(pop)
|
||||
#elif defined __BORLANDC__
|
||||
#pragma -a-
|
||||
#endif
|
||||
|
||||
#endif // __aeffect__
|
1170
core/audio/plugin_host/vst2/pluginterfaces/vst2.x/aeffectx.h
Normal file
1170
core/audio/plugin_host/vst2/pluginterfaces/vst2.x/aeffectx.h
Normal file
File diff suppressed because it is too large
Load Diff
128
core/audio/plugin_host/vst2/pluginterfaces/vst2.x/vstfxstore.h
Normal file
128
core/audio/plugin_host/vst2/pluginterfaces/vst2.x/vstfxstore.h
Normal file
@ -0,0 +1,128 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Project : VST SDK
|
||||
// Version : 2.4
|
||||
//
|
||||
// Category : VST 2.x Interfaces
|
||||
// Filename : pluginterfaces/vst2.x/vstfxstore.h
|
||||
// Created by : Steinberg, 01/2004
|
||||
// Description : Definition of Program (fxp) and Bank (fxb) structures
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// LICENSE
|
||||
// (c) 2016, Steinberg Media Technologies GmbH, All Rights Reserved
|
||||
//-----------------------------------------------------------------------------
|
||||
// This Software Development Kit may not be distributed in parts or its entirety
|
||||
// without prior written agreement by Steinberg Media Technologies GmbH.
|
||||
// This SDK must not be used to re-engineer or manipulate any technology used
|
||||
// in any Steinberg or Third-party application or software module,
|
||||
// unless permitted by law.
|
||||
// Neither the name of the Steinberg Media Technologies nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SDK IS PROVIDED BY STEINBERG MEDIA TECHNOLOGIES GMBH "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL STEINBERG MEDIA TECHNOLOGIES GMBH BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __vstfxstore__
|
||||
#define __vstfxstore__
|
||||
|
||||
#ifndef __aeffect__
|
||||
#include "aeffect.h"
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Root chunk identifier for Programs (fxp) and Banks (fxb). */
|
||||
#define cMagic 'CcnK'
|
||||
|
||||
/** Regular Program (fxp) identifier. */
|
||||
#define fMagic 'FxCk'
|
||||
|
||||
/** Regular Bank (fxb) identifier. */
|
||||
#define bankMagic 'FxBk'
|
||||
|
||||
/** Program (fxp) identifier for opaque chunk data. */
|
||||
#define chunkPresetMagic 'FPCh'
|
||||
|
||||
/** Bank (fxb) identifier for opaque chunk data. */
|
||||
#define chunkBankMagic 'FBCh'
|
||||
|
||||
/*
|
||||
Note: The C data structures below are for illustration only. You can not read/write them directly.
|
||||
The byte order on disk of fxp and fxb files is Big Endian. You have to swap integer
|
||||
and floating-point values on Little Endian platforms (Windows, MacIntel)!
|
||||
*/
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Program (fxp) structure. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
typedef struct fxProgram
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VstInt32 chunkMagic; ///< 'CcnK'
|
||||
VstInt32 byteSize; ///< size of this chunk, excl. magic + byteSize
|
||||
|
||||
VstInt32 fxMagic; ///< 'FxCk' (regular) or 'FPCh' (opaque chunk)
|
||||
VstInt32 version; ///< format version (currently 1)
|
||||
VstInt32 fxID; ///< fx unique ID
|
||||
VstInt32 fxVersion; ///< fx version
|
||||
|
||||
VstInt32 numParams; ///< number of parameters
|
||||
char prgName[28]; ///< program name (null-terminated ASCII string)
|
||||
|
||||
union
|
||||
{
|
||||
float params[1]; ///< variable sized array with parameter values
|
||||
struct
|
||||
{
|
||||
VstInt32 size; ///< size of program data
|
||||
char chunk[1]; ///< variable sized array with opaque program data
|
||||
} data; ///< program chunk data
|
||||
} content; ///< program content depending on fxMagic
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
} fxProgram;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Bank (fxb) structure. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
struct fxBank
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VstInt32 chunkMagic; ///< 'CcnK'
|
||||
VstInt32 byteSize; ///< size of this chunk, excl. magic + byteSize
|
||||
|
||||
VstInt32 fxMagic; ///< 'FxBk' (regular) or 'FBCh' (opaque chunk)
|
||||
VstInt32 version; ///< format version (1 or 2)
|
||||
VstInt32 fxID; ///< fx unique ID
|
||||
VstInt32 fxVersion; ///< fx version
|
||||
|
||||
VstInt32 numPrograms; ///< number of programs
|
||||
|
||||
#if VST_2_4_EXTENSIONS
|
||||
VstInt32 currentProgram; ///< version 2: current program number
|
||||
char future[124]; ///< reserved, should be zero
|
||||
#else
|
||||
char future[128]; ///< reserved, should be zero
|
||||
#endif
|
||||
|
||||
union
|
||||
{
|
||||
fxProgram programs[1]; ///< variable number of programs
|
||||
struct
|
||||
{
|
||||
VstInt32 size; ///< size of bank data
|
||||
char chunk[1]; ///< variable sized array with opaque bank data
|
||||
} data; ///< bank chunk data
|
||||
} content; ///< bank content depending on fxMagic
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
#endif // __vstfxstore__
|
266
core/audio/plugin_host/vst2/vst2_plugin_host.cpp
Normal file
266
core/audio/plugin_host/vst2/vst2_plugin_host.cpp
Normal file
@ -0,0 +1,266 @@
|
||||
#include "vst2_plugin_host.h"
|
||||
|
||||
#include "audio/device/audio_device_manager.h"
|
||||
#include "audio/mixer/channel_interface.h"
|
||||
#include "misc/glfw_misc.h"
|
||||
|
||||
std::map<std::string, std::weak_ptr<dynamic_library>> vst2_library_map;
|
||||
VstTimeInfo vst2_plugin_host::vst_time_info{};
|
||||
|
||||
std::map<std::string, bool> can_do_map =
|
||||
{
|
||||
{"sendVstEvents", true},
|
||||
{"sendVstMidiEvent", true},
|
||||
{"sendVstTimeInfo", true},
|
||||
{"receiveVstEvents", false},
|
||||
{"receiveVstMidiEvent", false},
|
||||
{"receiveVstTimeInfo", false},
|
||||
{"offline", false},
|
||||
{"reportConnectionChanges", false},
|
||||
{"acceptIOChanges", true},
|
||||
{"sizeWindow", true},
|
||||
{"asyncProcessing", true},
|
||||
{"supplyIdle", true},
|
||||
{"supportShell", false},
|
||||
{"openFileSelector", false},
|
||||
{"editFile", false},
|
||||
{"closeFileSelector", false},
|
||||
{"NIMKPIVendorSpecificCallbacks", false},
|
||||
};
|
||||
|
||||
std::shared_ptr<dynamic_library> get_vst2_library(const std::string& path) {
|
||||
if (vst2_library_map.contains(path) && !vst2_library_map[path].expired()) {
|
||||
return vst2_library_map[path].lock();
|
||||
}
|
||||
auto library = std::make_shared<dynamic_library>(path);
|
||||
vst2_library_map[path] = library;
|
||||
return library;
|
||||
}
|
||||
|
||||
bool vst_host_can_do(const char* can_do)
|
||||
{
|
||||
if (can_do_map.contains(can_do))
|
||||
return can_do_map[can_do];
|
||||
spdlog::warn("Unknown can do: {}", can_do);
|
||||
return false;
|
||||
}
|
||||
|
||||
VstIntPtr vst_master_callback(AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case audioMasterAutomate:
|
||||
return 1;
|
||||
case audioMasterVersion:
|
||||
return kVstVersion; // 返回插件版本号
|
||||
case audioMasterWantMidi:
|
||||
return 1;
|
||||
case audioMasterGetSampleRate:
|
||||
return g_audio_device_manager.get_sample_rate(); // 返回采样率
|
||||
case audioMasterGetCurrentProcessLevel:
|
||||
return kVstProcessLevelRealtime; // 返回当前处理级别
|
||||
case audioMasterGetBlockSize:
|
||||
return g_audio_device_manager.get_buffer_size(); // 返回块大小
|
||||
case audioMasterSizeWindow:
|
||||
{
|
||||
// 设置插件窗口大小
|
||||
// FVST2PluginHost* Host = static_cast<FVST2PluginHost*>(Effect->user);
|
||||
// if (const TSharedPtr<SWindow> Window = FWindowManager::Get().FindPluginEditor(Host))
|
||||
// Window->Resize(FVector2D(Index, Value));
|
||||
return 1;
|
||||
}
|
||||
case audioMasterGetTime:
|
||||
return (VstIntPtr)&vst2_plugin_host::vst_time_info;
|
||||
case audioMasterIdle:
|
||||
// UE_LOG(LogTemp, Log, TEXT("Plugin Idle"));
|
||||
return 1;
|
||||
case audioMasterNeedIdle:
|
||||
// UE_LOG(LogTemp, Log, TEXT("Plugin Need Idle"));
|
||||
return 1;
|
||||
case audioMasterGetVendorString:
|
||||
{
|
||||
const char* Ptr1 = (const char*)ptr;
|
||||
Ptr1 = "Arona";
|
||||
return 1;
|
||||
}
|
||||
case audioMasterGetProductString:
|
||||
{
|
||||
const char* Ptr1 = (const char*)ptr;
|
||||
Ptr1 = "Arona";
|
||||
return 1;
|
||||
}
|
||||
case audioMasterGetVendorVersion:
|
||||
return 1000;
|
||||
case audioMasterCanDo:
|
||||
{
|
||||
const char* Ptr1 = (const char*)ptr;
|
||||
return vst_host_can_do(Ptr1) ? 1 : 0;
|
||||
}
|
||||
case audioMasterUpdateDisplay:
|
||||
return 1;
|
||||
case audioMasterBeginEdit:
|
||||
{
|
||||
// UE_LOG(LogTemp, Log, TEXT("Want Begin Edit"));
|
||||
return 1;
|
||||
}
|
||||
case audioMasterEndEdit:
|
||||
{
|
||||
// UE_LOG(LogTemp, Log, TEXT("Want End Edit"));
|
||||
return 1;
|
||||
}
|
||||
case audioMasterVendorSpecific:
|
||||
return 0;
|
||||
case audioMasterProcessEvents:
|
||||
// TODO
|
||||
{
|
||||
VstEvents* Events = (VstEvents*)ptr;
|
||||
Events->events[0]->type;
|
||||
// FVST2PluginHost* Host = static_cast<FVST2PluginHost*>(Effect->user);
|
||||
|
||||
}
|
||||
return 1;
|
||||
default: break;
|
||||
// ensureMsgf(0, TEXT("No Implement OpCode: %d"), OpCode);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef AEffect*(*vst_plugin_entry_proc)(audioMasterCallback AudioMaster);
|
||||
|
||||
vst2_plugin_host::vst2_plugin_host() {
|
||||
effect_ = nullptr;
|
||||
library_ = nullptr;
|
||||
}
|
||||
|
||||
vst2_plugin_host::~vst2_plugin_host() {
|
||||
spdlog::info("vst2 plugin {} destroyed", name);
|
||||
if (effect_) {
|
||||
dispatch(effClose);
|
||||
}
|
||||
}
|
||||
|
||||
bool vst2_plugin_host::load_plugin(const char* path) {
|
||||
// load vst
|
||||
library_ = get_vst2_library(path);
|
||||
// get main function
|
||||
const auto entry_proc = static_cast<vst_plugin_entry_proc>(library_->get_function("VSTPluginMain"));
|
||||
if (!entry_proc) {
|
||||
spdlog::error("Failed to get entry point from {}", path);
|
||||
return false;
|
||||
}
|
||||
// create effect
|
||||
effect_ = entry_proc(&vst_master_callback);
|
||||
if (!effect_) {
|
||||
return false;
|
||||
}
|
||||
if (effect_->magic != kEffectMagic)
|
||||
throw std::runtime_error("Not a VST2 plugin");
|
||||
effect_->user = this;
|
||||
|
||||
name = load_name();
|
||||
vendor = load_vendor();
|
||||
|
||||
dispatch(effOpen);
|
||||
return true;
|
||||
}
|
||||
|
||||
void vst2_plugin_host::set_enabled(bool enabled) {
|
||||
enabled_ = enabled;
|
||||
dispatch(effMainsChanged, 0, enabled);
|
||||
}
|
||||
|
||||
bool vst2_plugin_host::is_enabled() const {
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
void vst2_plugin_host::on_update_sample_rate(double sample_rate) {
|
||||
dispatch(effSetSampleRate, 0, 0, nullptr, sample_rate);
|
||||
}
|
||||
|
||||
void vst2_plugin_host::on_update_buffer_size(int buffer_size) {
|
||||
dispatch(effSetBlockSize, 0, buffer_size);
|
||||
}
|
||||
|
||||
uint32_t vst2_plugin_host::get_input_channels() const {
|
||||
return effect_->numInputs;
|
||||
}
|
||||
|
||||
uint32_t vst2_plugin_host::get_output_channels() const {
|
||||
return effect_->numOutputs;
|
||||
}
|
||||
|
||||
void vst2_plugin_host::update_channel_node_name() {
|
||||
for (int i = 0; i < effect_->numInputs; ++i)
|
||||
{
|
||||
VstPinProperties pin_properties{};
|
||||
if (dispatch(effGetInputProperties, i, 0, &pin_properties) == 1)
|
||||
{
|
||||
channel->set_input_channel_node_name(i / 2, i, pin_properties.label);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < effect_->numOutputs; ++i)
|
||||
{
|
||||
VstPinProperties pin_properties{};
|
||||
if (dispatch(effGetOutputProperties, i, 0, &pin_properties) == 1)
|
||||
{
|
||||
channel->set_output_channel_node_name(i / 2, i, pin_properties.label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vst2_plugin_host::process(uint32_t frame_num) {
|
||||
// TODO send midi
|
||||
|
||||
|
||||
effect_->processReplacing(effect_, channel->get_input_headers(), channel->get_output_headers(), frame_num);
|
||||
}
|
||||
|
||||
void vst2_plugin_host::open_editor(GLFWwindow* window) {
|
||||
if (!has_editor())
|
||||
return;
|
||||
void* window_handle = glfwGetWindowHandle(window);
|
||||
|
||||
dispatch(effEditOpen, 0, 0, window_handle);
|
||||
}
|
||||
|
||||
void vst2_plugin_host::close_editor() {
|
||||
if (!has_editor())
|
||||
return;
|
||||
dispatch(effEditClose);
|
||||
}
|
||||
|
||||
void vst2_plugin_host::idle_editor() {
|
||||
plugin_host::idle_editor();
|
||||
dispatch(effEditIdle);
|
||||
}
|
||||
|
||||
bool vst2_plugin_host::has_editor() const {
|
||||
return effect_->flags & effFlagsHasEditor;
|
||||
}
|
||||
|
||||
ImVec2 vst2_plugin_host::get_editor_size() const {
|
||||
ERect* EditorRect = nullptr;
|
||||
dispatch(effEditGetRect, 0, 0, &EditorRect);
|
||||
if (EditorRect)
|
||||
return ImVec2(EditorRect->right - EditorRect->left, EditorRect->bottom - EditorRect->top);
|
||||
return ImVec2(0, 0);
|
||||
}
|
||||
|
||||
std::string vst2_plugin_host::load_name() const {
|
||||
char buffer[256];
|
||||
dispatch(effGetEffectName, 0, 0, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::string vst2_plugin_host::load_vendor() const {
|
||||
char buffer[256];
|
||||
dispatch(effGetVendorString, 0, 0, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
VstIntPtr vst2_plugin_host::dispatch(VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt) const {
|
||||
return effect_->dispatcher(effect_, opcode, index, value, ptr, opt);
|
||||
}
|
38
core/audio/plugin_host/vst2/vst2_plugin_host.h
Normal file
38
core/audio/plugin_host/vst2/vst2_plugin_host.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include "audio/plugin_host/plugin_host.h"
|
||||
#include "misc/lib_load.h"
|
||||
#include "pluginterfaces/vst2.x/aeffect.h"
|
||||
#include "pluginterfaces/vst2.x/aeffectx.h"
|
||||
|
||||
class vst2_plugin_host : public plugin_host {
|
||||
public:
|
||||
static VstTimeInfo vst_time_info;
|
||||
vst2_plugin_host();
|
||||
~vst2_plugin_host() override;
|
||||
bool load_plugin(const char* path) override;
|
||||
|
||||
void set_enabled(bool enabled) override;
|
||||
bool is_enabled() const override;
|
||||
|
||||
void on_update_sample_rate(double sample_rate) override;
|
||||
void on_update_buffer_size(int buffer_size) override;
|
||||
[[nodiscard]] uint32_t get_input_channels() const override;
|
||||
[[nodiscard]] uint32_t get_output_channels() const override;
|
||||
void update_channel_node_name() override;
|
||||
|
||||
void process(uint32_t frame_num) override;
|
||||
|
||||
void open_editor(GLFWwindow* window) override;
|
||||
void close_editor() override;
|
||||
void idle_editor() override;
|
||||
[[nodiscard]] bool has_editor() const override;
|
||||
[[nodiscard]] ImVec2 get_editor_size() const override;
|
||||
|
||||
[[nodiscard]] std::string load_name() const override;
|
||||
[[nodiscard]] std::string load_vendor() const override;
|
||||
private:
|
||||
VstIntPtr dispatch(VstInt32 opcode, VstInt32 index = 0, VstIntPtr value = 0, void* ptr = nullptr, float opt = 0) const;
|
||||
AEffect* effect_;
|
||||
std::shared_ptr<dynamic_library> library_;
|
||||
bool enabled_ = false;
|
||||
};
|
20
core/misc/glfw_misc.cpp
Normal file
20
core/misc/glfw_misc.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include "glfw_misc.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#elif defined(__APPLE__)
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#else
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#endif
|
||||
#include <GLFW/glfw3native.h>
|
||||
|
||||
void* glfwGetWindowHandle(GLFWwindow* window) {
|
||||
#ifdef WIN32
|
||||
return glfwGetWin32Window(window);
|
||||
#elif defined(__APPLE__)
|
||||
return glfwGetCocoaWindow(window);
|
||||
#else
|
||||
return glfwGetX11Window(window);
|
||||
#endif
|
||||
}
|
7
core/misc/glfw_misc.h
Normal file
7
core/misc/glfw_misc.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
CORE_API void* glfwGetWindowHandle(GLFWwindow* window);
|
||||
}
|
62
core/misc/lib_load.h
Normal file
62
core/misc/lib_load.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
class CORE_API dynamic_library {
|
||||
public:
|
||||
dynamic_library() {
|
||||
|
||||
}
|
||||
|
||||
explicit dynamic_library(const std::string& libraryPath) {
|
||||
#ifdef _WIN32
|
||||
hModule = LoadLibraryA(libraryPath.c_str());
|
||||
#else
|
||||
handle = dlopen(libraryPath.c_str(), RTLD_LAZY);
|
||||
#endif
|
||||
if (!get_handle()) {
|
||||
spdlog::error("Failed to load library: {}", libraryPath);
|
||||
throw std::runtime_error("Failed to load library");
|
||||
}
|
||||
spdlog::info("Load library: {}", libraryPath);
|
||||
}
|
||||
|
||||
~dynamic_library() {
|
||||
#ifdef _WIN32
|
||||
if (hModule) FreeLibrary(hModule);
|
||||
#else
|
||||
if (handle) dlclose(handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] void* get_function(const char* functionName) const {
|
||||
#ifdef _WIN32
|
||||
return GetProcAddress(hModule, functionName);
|
||||
#else
|
||||
dlerror(); // 清除之前的错误
|
||||
void* function = dlsym(handle, functionName);
|
||||
// 添加错误检查
|
||||
return function;
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] void* get_handle() const {
|
||||
#ifdef _WIN32
|
||||
return hModule;
|
||||
#else
|
||||
return handle;
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
HMODULE hModule = nullptr;
|
||||
#else
|
||||
void* handle = nullptr;
|
||||
#endif
|
||||
};
|
@ -41,3 +41,12 @@ public:
|
||||
singleton_manager::get()->add(this);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(core_EXPORTS)
|
||||
#define DEFINE_SINGLETON_INSTANCE(T) \
|
||||
inline T g_##T; \
|
||||
extern "C" CORE_API inline T& get_##T() { return g_##T; }
|
||||
#else
|
||||
#define DEFINE_SINGLETON_INSTANCE(T) \
|
||||
extern "C" CORE_API inline T& get_##T();
|
||||
#endif
|
||||
|
@ -7,9 +7,9 @@
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define APP_USE_VULKAN_DEBUG_REPORT
|
||||
#endif
|
||||
// #ifdef _DEBUG
|
||||
// #define APP_USE_VULKAN_DEBUG_REPORT
|
||||
// #endif
|
||||
|
||||
#define APP_USE_UNLIMITED_FRAME_RATE
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user