47 KiB
插件接口API参考
目录
概述
插件系统是音频端的核心组件之一,提供了一个安全且可扩展的插件架构。该系统采用多进程隔离设计,可以安全地加载和运行第三方插件,同时保护主系统免受插件崩溃或恶意行为的影响。
核心特性:
- 多进程沙盒隔离:通过独立进程运行插件,避免崩溃影响主系统
- 资源配额管理:限制插件的CPU、内存、磁盘和网络使用
- 安全通信机制:经过验证的跨进程消息传递
- 统一插件接口:标准化的API,支持音频处理、参数控制和GUI
- 跨平台沙盒实现:支持Windows、Linux和macOS的平台特定隔离机制
- 故障检测与恢复:自动检测和处理插件崩溃
- 性能监控:实监控插件资源使用情况
插件系统架构图:
┌─────────────────────────────────┐ ┌─────────────────────────────────┐
│ 音频引擎核心进程 │ │ 插件沙盒进程 1 │
│ │ │ │
│ ┌─────────────────────────┐ │ │ ┌─────────────────────────┐ │
│ │ 插件宿主管理器 │ │ │ │ 沙盒运行时 │ │
│ └───────────┬─────────────┘ │ │ └───────────┬─────────────┘ │
│ │ │ │ │ │
│ ┌───────────▼─────────────┐ │ │ ┌───────────▼─────────────┐ │
│ │ 安全通信代理 │◄───┼─────┼─►│ 安全通信代理 │ │
│ └───────────┬─────────────┘ │ │ └───────────┬─────────────┘ │
│ │ │ │ │ │
│ ┌───────────▼─────────────┐ │ │ ┌───────────▼─────────────┐ │
│ │ 音频处理管线 │ │ │ │ 插件实例 │ │
│ └─────────────────────────┘ │ │ └─────────────────────────┘ │
└─────────────────────────────────┘ └─────────────────────────────────┘
┌─────────────────────────────────┐
│ 插件沙盒进程 2 │
│ │
│ ┌─────────────────────────┐ │
│ │ 沙盒运行时 │ │
│ └───────────┬─────────────┘ │
│ │ │
│ ┌───────────▼─────────────┐ │
│ │ 安全通信代理 │ │
│ └───────────┬─────────────┘ │
│ │ │
│ ┌───────────▼─────────────┐ │
│ │ 插件实例 │ │
│ └─────────────────────────┘ │
└─────────────────────────────────┘
插件接口核心
IPlugin接口
IPlugin是所有插件必须实现的核心接口,定义了插件的基本功能和生命周期:
class IPlugin {
public:
virtual ~IPlugin() = default;
// 基本信息
virtual std::unique_ptr<PluginInfo> get_plugin_info() const = 0;
virtual PluginId get_plugin_id() const = 0;
virtual std::string get_name() const = 0;
virtual std::string get_vendor() const = 0;
virtual Version get_version() const = 0;
virtual PluginCategory get_category() const = 0;
virtual PluginType get_type() const = 0;
virtual PluginCapability get_capabilities() const = 0;
// 生命周期管理
virtual common::ErrorCode initialize(const engine::AudioConfig& config) = 0;
virtual common::ErrorCode shutdown() = 0;
virtual common::ErrorCode activate() = 0;
virtual common::ErrorCode deactivate() = 0;
virtual common::ErrorCode suspend() = 0;
virtual common::ErrorCode resume() = 0;
virtual common::ErrorCode reset() = 0;
virtual PluginState get_state() const = 0;
// 音频处理
virtual common::ErrorCode prepare_to_play(double sample_rate, uint32_t max_block_size) = 0;
virtual ProcessingResult process_audio(
const engine::AudioBuffer& input,
engine::AudioBuffer& output,
const std::vector<MidiEvent>& midi_in,
std::vector<MidiEvent>& midi_out,
const PluginProcessContext& context) = 0;
virtual ProcessingResult process_midi(
const std::vector<MidiEvent>& midi_in,
std::vector<MidiEvent>& midi_out,
const PluginProcessContext& context) = 0;
virtual uint32_t get_latency_samples() const = 0;
virtual uint32_t get_tail_length_samples() const = 0;
virtual common::ErrorCode set_bypass(bool bypass) = 0;
virtual bool is_bypassed() const = 0;
// 音频配置
virtual std::vector<uint16_t> get_supported_input_channels() const = 0;
virtual std::vector<uint16_t> get_supported_output_channels() const = 0;
virtual common::ErrorCode set_channel_configuration(uint16_t input_channels, uint16_t output_channels) = 0;
virtual std::pair<uint16_t, uint16_t> get_channel_configuration() const = 0;
// 参数管理
virtual size_t get_parameter_count() const = 0;
virtual std::unique_ptr<PluginParameter> get_parameter_info(size_t index) const = 0;
virtual std::unique_ptr<PluginParameter> get_parameter_by_id(const std::string& parameter_id) const = 0;
virtual common::ErrorCode set_parameter(const std::string& parameter_id, const std::any& value) = 0;
virtual std::any get_parameter(const std::string& parameter_id) const = 0;
virtual common::ErrorCode reset_parameter(const std::string& parameter_id) = 0;
virtual common::ErrorCode reset_all_parameters() = 0;
// 预设管理
virtual size_t get_preset_count() const = 0;
virtual std::unique_ptr<PluginPreset> get_preset_info(size_t index) const = 0;
virtual common::ErrorCode load_preset(const std::string& preset_id) = 0;
virtual common::ErrorCode save_preset(const std::string& preset_id, const std::string& name) = 0;
virtual std::string get_current_preset_id() const = 0;
// 状态保存和恢复
virtual std::vector<uint8_t> get_state_data() const = 0;
virtual common::ErrorCode set_state_data(const std::vector<uint8_t>& data) = 0;
virtual size_t get_state_data_size() const = 0;
// GUI支持
virtual bool has_gui() const = 0;
virtual void* create_gui(void* parent_window) = 0;
virtual common::ErrorCode destroy_gui() = 0;
virtual common::ErrorCode set_gui_visible(bool visible) = 0;
virtual bool is_gui_visible() const = 0;
virtual std::pair<uint32_t, uint32_t> get_gui_size() const = 0;
virtual common::ErrorCode set_gui_size(uint32_t width, uint32_t height) = 0;
// 事件处理
virtual void set_event_listener(std::shared_ptr<IPluginEventListener> listener) = 0;
virtual void remove_event_listener() = 0;
// 性能和诊断
virtual double get_cpu_usage() const = 0;
virtual size_t get_memory_usage() const = 0;
virtual std::chrono::nanoseconds get_average_processing_time() const = 0;
virtual std::chrono::nanoseconds get_max_processing_time() const = 0;
virtual void reset_performance_statistics() = 0;
// 扩展功能
template<typename T>
T* get_extension();
protected:
virtual void* get_extension_impl(const std::type_info& type);
};
生命周期管理
插件生命周期包括以下状态和转换:
-
初始化(Initialize):首次加载插件后,进行初始化配置
- 分配资源
- 加载配置
- 准备状态
-
激活(Activate):准备音频处理
- 申请实时处理资源
- 初始化处理状态
- 准备缓冲区
-
停用(Deactivate):暂停音频处理
- 释放实时处理资源
- 保持状态
-
挂起(Suspend):系统节能或不需要处理
- 释放部分资源
- 保持核心状态
-
恢复(Resume):从挂起状态恢复
- 重新申请资源
- 恢复到之前状态
-
关闭(Shutdown):完全卸载插件
- 释放所有资源
- 关闭所有连接
音频处理
音频处理是插件的核心功能,通过process_audio方法实现:
ProcessingResult process_audio(
const engine::AudioBuffer& input, // 输入音频缓冲区
engine::AudioBuffer& output, // 输出音频缓冲区
const std::vector<MidiEvent>& midi_in, // 输入MIDI事件
std::vector<MidiEvent>& midi_out, // 输出MIDI事件
const PluginProcessContext& context // 处理上下文
);
处理上下文提供了重要的信息,如播放位置、速度等:
struct PluginProcessContext {
// 时间信息
uint64_t sample_position = 0; // 当前样本位置
double sample_rate = 44100.0; // 采样率
uint32_t block_size = 512; // 块大小
// 传输状态
bool is_playing = false; // 是否播放中
bool is_recording = false; // 是否录制中
bool is_looping = false; // 是否循环中
double tempo = 120.0; // 速度(BPM)
// 小节信息
int32_t time_signature_numerator = 4; // 拍号分子
int32_t time_signature_denominator = 4; // 拍号分母
double ppq_position = 0.0; // PPQ位置
double bar_start_position = 0.0; // 小节开始位置
// 系统信息
uint64_t system_time = 0; // 系统时间
bool is_realtime = true; // 是否实时处理
};
MIDI事件由以下结构表示:
struct MidiEvent {
uint32_t timestamp; // 时间戳(样本偏移)
uint8_t data[4]; // MIDI数据
uint8_t size; // 数据大小
// MIDI消息类型检测
bool is_note_on() const;
bool is_note_off() const;
bool is_control_change() const;
bool is_program_change() const;
bool is_pitch_bend() const;
uint8_t get_channel() const;
uint8_t get_note() const;
uint8_t get_velocity() const;
uint8_t get_controller() const;
uint8_t get_value() const;
};
参数管理
插件参数提供了用户控制插件行为的机制:
// 获取参数数量
size_t get_parameter_count() const;
// 获取参数信息
std::unique_ptr<PluginParameter> get_parameter_info(size_t index) const;
// 根据ID获取参数信息
std::unique_ptr<PluginParameter> get_parameter_by_id(const std::string& parameter_id) const;
// 设置参数值
common::ErrorCode set_parameter(const std::string& parameter_id, const std::any& value);
// 获取参数值
std::any get_parameter(const std::string& parameter_id) const;
插件宿主管理器
PluginHostManager
PluginHostManager负责管理插件的完整生命周期,包括加载、初始化、音频处理和卸载:
class PluginHostManager {
public:
explicit PluginHostManager(const PluginHostConfig& config);
~PluginHostManager();
// 初始化和关闭
common::ErrorCode initialize();
common::ErrorCode shutdown();
// 插件加载和卸载
common::ErrorCode load_plugin(
const std::string& plugin_path,
const std::string& instance_id,
const SandboxConfig& sandbox_config = SandboxConfig(),
bool auto_activate = false);
common::ErrorCode unload_plugin(
const std::string& instance_id,
bool force = false);
// 插件控制
common::ErrorCode activate_plugin(const std::string& instance_id);
common::ErrorCode deactivate_plugin(const std::string& instance_id);
common::ErrorCode reset_plugin(const std::string& instance_id);
// 音频处理
ProcessingResult process_plugin_audio(
const std::string& instance_id,
const engine::AudioBuffer& input,
engine::AudioBuffer& output,
const std::vector<MidiEvent>& midi_in,
std::vector<MidiEvent>& midi_out,
const PluginProcessContext& context);
// 参数控制
common::ErrorCode set_plugin_parameter(
const std::string& instance_id,
const std::string& parameter_id,
const std::any& value);
std::any get_plugin_parameter(
const std::string& instance_id,
const std::string& parameter_id);
// 预设管理
common::ErrorCode load_plugin_preset(
const std::string& instance_id,
const std::string& preset_id);
// 插件状态管理
common::ErrorCode save_plugin_state(
const std::string& instance_id,
const std::string& file_path);
common::ErrorCode load_plugin_state(
const std::string& instance_id,
const std::string& file_path);
// 插件查询
bool has_plugin(const std::string& instance_id) const;
PluginState get_plugin_state(const std::string& instance_id) const;
std::vector<std::string> get_loaded_plugins() const;
std::unique_ptr<PluginInfo> get_plugin_info(const std::string& instance_id) const;
// 插件统计
PluginStatistics get_plugin_statistics(const std::string& instance_id) const;
// 沙盒控制
common::ErrorCode restart_plugin_sandbox(const std::string& instance_id);
common::ErrorCode update_sandbox_limits(
const std::string& instance_id,
const SandboxLimits& new_limits);
};
宿主配置
PluginHostConfig定义了插件宿主的配置选项:
struct PluginHostConfig {
// 沙盒设置
bool enable_sandbox_isolation = true; // 启用沙盒隔离
bool allow_non_sandboxed_plugins = false; // 允许不使用沙盒运行插件
// 默认沙盒配置
SandboxConfig default_sandbox_config; // 默认沙盒配置
// 性能设置
uint32_t max_plugins = 100; // 最大插件数量
uint32_t max_processing_time_ms = 500; // 最大处理时间限制
// 路径设置
std::string plugin_search_paths; // 插件搜索路径
std::string preset_storage_path; // 预设存储路径
// 日志设置
bool enable_detailed_logging = false; // 启用详细日志
};
工厂函数
系统提供了几个便捷的工厂函数来创建预配置的插件宿主:
// 创建默认配置的插件宿主管理器
std::shared_ptr<PluginHostManager> create_plugin_host_manager();
// 创建严格安全模式的插件宿主管理器
std::shared_ptr<PluginHostManager> create_strict_plugin_host_manager();
// 创建宽松模式的插件宿主管理器(用于调试)
std::shared_ptr<PluginHostManager> create_relaxed_plugin_host_manager();
// 创建自定义配置的插件宿主管理器
std::shared_ptr<PluginHostManager> create_custom_plugin_host_manager(
const PluginHostConfig& custom_config);
同样,还有用于创建不同类型插件沙盒配置的工厂函数:
// 创建用于音频效果器的沙盒配置
SandboxConfig create_audio_effect_sandbox_config();
// 创建用于乐器的沙盒配置
SandboxConfig create_instrument_sandbox_config();
// 创建用于分析器的沙盒配置
SandboxConfig create_analyzer_sandbox_config();
沙盒隔离机制
沙盒类型
系统支持多种沙盒类型,以适应不同的隔离需求:
enum class SandboxType {
None, // 无沙盒(不推荐用于生产环境)
Process, // 进程级隔离(标准)
Container, // 容器级隔离(Linux特定)
Thread, // 线程级隔离(有限保护,仅用于调试)
VM // 虚拟机隔离(最高安全性,但开销大)
};
资源限制
沙盒可以对插件使用的资源进行限制:
struct SandboxLimits {
// 内存限制
size_t max_memory_bytes = 256 * 1024 * 1024; // 256MB
// CPU限制
double max_cpu_percent = 25.0; // 最大CPU使用率(百分比)
size_t max_threads = 4; // 最大线程数
// 时间限制
uint32_t max_processing_time_ms = 10; // 最大处理时间(毫秒)
// 文件系统限制
size_t max_file_size_bytes = 10 * 1024 * 1024; // 最大文件大小
size_t max_file_descriptors = 32; // 最大文件描述符数
// 网络限制
bool allow_outbound_connections = false; // 允许出站连接
size_t max_network_bytes_per_second = 0; // 最大网络带宽(字节/秒)
};
安全策略
沙盒安全策略定义了插件的权限和访问控制:
struct SandboxSecurity {
// 访问控制
bool allow_network_access = false; // 允许网络访问
bool allow_file_system_access = false; // 允许文件系统访问
std::vector<std::string> allowed_paths; // 允许访问的路径列表
// 内存保护
bool enable_address_randomization = true; // 启用地址空间布局随机化
bool enable_data_execution_prevention = true; // 启用数据执行保护
// 进程隔离
bool enable_system_call_filtering = true; // 启用系统调用过滤
bool enable_privilege_dropping = true; // 启用权限下降
};
跨平台实现
沙盒系统针对不同操作系统采用不同的实现机制:
-
Windows
- Job Objects:资源限制进程监控
- Restricted Tokens:降低权限
- AppContainer:应用程序容器
- Integrity Levels:完整性级别
-
Linux
- Namespaces:进程隔离
- cgroups:资源限制
- seccomp:系统调用过滤
- capabilities:细粒度权限控制
-
macOS
- Sandbox:应用程序沙盒
- XPC:跨进程通信
- Entitlements:权限控制
插件元数据
PluginInfo
PluginInfo包含插件的基本描述信息:
class PluginInfo {
public:
// 基本信息
PluginId id; // 唯一标识符
std::string name; // 名称
std::string vendor; // 供应商
Version version; // 版本
PluginCategory category; // 分类
PluginType type; // 类型
PluginFormat format; // 格式
// 描述
std::string description; // 描述
std::string copyright; // 版权
std::string website; // 网站
std::string email; // 联系邮箱
// 技术信息
PluginCapability capabilities; // 能力标志
std::vector<uint16_t> supported_input_channels; // 支持的输入声道配置
std::vector<uint16_t> supported_output_channels; // 支持的输出声道配置
bool has_gui; // 是否有GUI
uint32_t latency_samples; // 延迟(样本数)
// 路径信息
std::string file_path; // 文件路径
// 兼容性信息
std::string sdk_version; // SDK版本
};
PluginParameter
PluginParameter定义了插件参数的特性:
class PluginParameter {
public:
// 基本信息
std::string id; // 唯一标识符
std::string name; // 显示名称
std::string unit; // 单位
std::string description; // 描述
// 值范围
double min_value; // 最小值
double max_value; // 最大值
double default_value; // 默认值
double step_size; // 步进大小
// 类型信息
ParameterType type; // 参数类型
ParameterCategory category; // 参数分类
ParameterFlags flags; // 参数标志
// 枚举参数选项(对于离散参数)
std::vector<std::string> enum_values; // 枚举值
};
PluginPreset
PluginPreset定义了件预设的属性:
class PluginPreset {
public:
// 基本信息
std::string id; // 唯一标识符
std::string name; // 名称
std::string category; // 分类
std::string description; // 描述
// 元数据
std::string author; // 作者
std::string tags; // 标签
std::string date_created; // 创建日期
// 路径
std::string file_path; // 文件路径(如果是文件预设)
// 状态
bool is_factory; // 是否为出厂预设
bool is_modified; // 是否已修改
};
安全通信代理
通信原理
插件沙盒与宿主进程之间的通信使用了安全通信代理,确保所有消息都经过验证和过滤:
┌──────────────────┐ ┌──────────────────┐
│ 宿主进程 │ │ 沙盒进程 │
│ │ │ │
│ ┌──────────────┐ │ 消息验证 │ ┌──────────────┐ │
│ │ │ │ 权限检查 │ │ │ │
│ │ 安全通信代理 ├─┼────────────────────┬─►│ 安全通信代理 │ │
│ │ │ │ 过滤和转发 │ │ │ │
│ └──────┬───────┘ │ │ └──────┬───────┘ │
│ │ │ │ │ │
│ │ │ 数据传输 │ │ │
│ │ │ ◄──────────────────┘ │ │
│ ┌──────▼───────┐ │ ┌──────▼───────┐ │
│ │ │ │ │ │ │
│ │ PluginHost │ │ │ Plugin实例 │ │
│ │ │ │ │ │ │
│ └──────────────┘ │ └──────────────┘ │
└──────────────────┘ └──────────────────┘
消息过滤
安全通信代理对所有消息执行以下过滤:
- 消息类型验证:确保消息类型合法且符合预期
- 消息大小检查:防止过大消息导致的内存问题
- 消息频率限制防止DOS攻击
- 消息内容验证:检查消息内容的合法性
权限检查
安全通信代理根据插件的沙盒安全策略检查权限:
- 资源访问权限检查插件是否有权访问特定资源
- 操作权限:检查插件是否有权执行特定操作
- 通信权限:检查插件是否有权进行特定通信
故障恢复机制
崩溃检测
系统通过以下机制检测插件崩溃:
- 心跳机制:插件定期发送心跳消息,如果连续多个心跳丢失则判定为崩溃
- 进程监控:直接监控沙盒进程的状态
- 超时检测:监控处理函数的执行时间,超时则判定为无响应
自动重启
当检测到插件崩溃时,系统可以自动重启插件:
- 创建新沙盒进程:启动新的沙盒进程
- 重新加载插件:在新进程中加载插件
- 恢复状态:尝试恢复插件的之前状态
- 重新连接:建立新的通信通道
降级模式
在多次崩溃后,系统可以进入降级模式:
- 功能限制:限插件的某些功能以提高稳定性
- 旁路处理:在插件失效时提供备用处理路径
- 资源限制:进一步限制插件的资源使用
实现示例
基础插件实现
以下是一个简单效果器插件的实现示例:
#include "audio_backend/plugin_host.h"
using namespace audio_backend::plugin_host;
class SimpleGainPlugin : public IPlugin {
public:
SimpleGainPlugin() : initialized_(false), activated_(false), bypass_(false), gain_(1.0f) {}
// 基本信息
std::unique_ptr<PluginInfo> get_plugin_info() const override {
auto info = std::make_unique<PluginInfo>();
info->id = "com.example.simplegain";
info->name = "Simple Gain";
info->vendor = "Example Audio";
info->version = {1, 0, 0};
info->category = PluginCategory::Effect;
info->type = PluginType::AudioEffect;
info->description = "A simple gain adjustment plugin";
info->capabilities = PluginCapability::AudioProcessing;
info->supported_input_channels = {1, 2}; // 支持单声道和立体声
info->supported_output_channels = {1, 2};
info->has_gui = false;
info->latency_samples = 0; // 无延迟
return info;
}
PluginId get_plugin_id() const override { return "com.example.simplegain"; }
std::string get_name() const override { return "Simple Gain"; }
std::string get_vendor() const override { return "Example Audio"; }
Version get_version() const override { return {1, 0, 0}; }
PluginCategory get_category() const override { return PluginCategory::Effect; }
PluginType get_type() const override { return PluginType::AudioEffect; }
PluginCapability get_capabilities() const override { return PluginCapability::AudioProcessing; }
// 生命周期管理
common::ErrorCode initialize(const engine::AudioConfig& config) override {
if (initialized_) {
return common::ErrorCode::ALREADY_INITIALIZED;
}
sample_rate_ = config.sample_rate;
max_block_size_ = config.frames_per_buffer;
num_channels_ = config.channels;
initialized_ = true;
return common::ErrorCode::SUCCESS;
}
common::ErrorCode shutdown() override {
if (!initialized_) {
return common::ErrorCode::NOT_INITIALIZED;
}
if (activated_) {
deactivate();
}
initialized_ = false;
return common::ErrorCode::SUCCESS;
}
common::ErrorCode activate() override {
if (!initialized_) {
return common::ErrorCode::NOT_INITIALIZED;
}
if (activated_) {
return common::ErrorCode::ALREADY_INITIALIZED;
}
activated_ = true;
return common::ErrorCode::SUCCESS;
}
common::ErrorCode deactivate() override {
if (!activated_) {
return common::ErrorCode::NOT_INITIALIZED;
}
activated_ = false;
return common::ErrorCode::SUCCESS;
}
common::ErrorCode suspend() override {
if (!activated_) {
return common::ErrorCode::NOT_INITIALIZED;
}
return common::ErrorCode::SUCCESS;
}
common::ErrorCode resume() override {
if (!initialized_) {
return common::ErrorCode::NOT_INITIALIZED;
}
return common::ErrorCode::SUCCESS;
}
common::ErrorCode reset() override {
gain_ = 1.0f;
return common::ErrorCode::SUCCESS;
}
PluginState get_state() const override {
if (!initialized_) return PluginState::Uninitialized;
if (!activated_) return PluginState::Initialized;
return PluginState::Active;
}
// 音频处理
common::ErrorCode prepare_to_play(double sample_rate, uint32_t max_block_size) override {
sample_rate_ = sample_rate;
max_block_size_ = max_block_size;
return common::ErrorCode::SUCCESS;
}
ProcessingResult process_audio(
const engine::AudioBuffer& input,
engine::AudioBuffer& output,
const std::vector<MidiEvent>& midi_in,
std::vector<MidiEvent>& midi_out,
const PluginProcessContext& context) override {
if (!activated_ || bypass_) {
// 旁路模式,直接复制输入到输出
input.copy_to(output);
return ProcessingResult::Success;
}
// 应用增益
input.copy_to(output);
output.apply_gain(gain_);
return ProcessingResult::Success;
}
ProcessingResult process_midi(
const std::vector<MidiEvent>& midi_in,
std::vector<MidiEvent>& midi_out,
const PluginProcessContext& context) override {
// 此简单插件不处理MIDI
return ProcessingResult::Success;
}
uint32_t get_latency_samples() const override {
return 0; // 无延迟
}
uint32_t get_tail_length_samples() const override {
return 0; // 无尾部
}
common::ErrorCode set_bypass(bool bypass) override {
bypass_ = bypass;
return common::ErrorCode::SUCCESS;
}
bool is_bypassed() const override {
return bypass_;
}
// 音频配置
std::vector<uint16_t> get_supported_input_channels() const override {
return {1, 2}; // 支持单声道和立体声
}
std::vector<uint16_t> get_supported_output_channels() const override {
return {1, 2}; // 支持单声道和立体声
}
common::ErrorCode set_channel_configuration(uint16_t input_channels, uint16_t output_channels) override {
// 检查是否支持请求的声道配置
if ((input_channels != 1 && input_channels != 2) ||
(output_channels != 1 && output_channels != 2)) {
return common::ErrorCode::INVALID_ARGUMENT;
}
num_channels_ = input_channels; // 简单起见,使用输入声道数
return common::ErrorCode::SUCCESS;
}
std::pair<uint16_t, uint16_t> get_channel_configuration() const override {
return {num_channels_, num_channels_};
}
// 参数管理
size_t get_parameter_count() const override {
return 1; // 只有一个增益参数
}
std::unique_ptr<PluginParameter> get_parameter_info(size_t index) const override {
if (index != 0) {
return nullptr;
}
auto param = std::make_unique<PluginParameter>();
param->id = "gain";
param->name = "Gain";
param->unit = "dB";
param->description = "Adjusts the output volume";
param->min_value = 0.0; // 0.0 = -inf dB
param->max_value = 2.0; // 2.0 = +6 dB
param->default_value = 1.0; // 1.0 = 0 dB
param->step_size = 0.01;
param->type = ParameterType::Float;
param->category = ParameterCategory::Level;
param->flags = ParameterFlags::Automatable;
return param;
}
std::unique_ptr<PluginParameter> get_parameter_by_id(const std::string& parameter_id) const override {
if (parameter_id != "gain") {
return nullptr;
}
return get_parameter_info(0);
}
common::ErrorCode set_parameter(const std::string& parameter_id, const std::any& value) override {
if (parameter_id != "gain") {
return common::ErrorCode::INVALID_ARGUMENT;
}
try {
gain_ = std::any_cast<float>(value);
// 限制在有效范围内
gain_ = std::max(0.0f, std::min(gain_, 2.0f));
return common::ErrorCode::SUCCESS;
} catch (const std::bad_any_cast&) {
return common::ErrorCode::INVALID_ARGUMENT;
}
}
std::any get_parameter(const std::string& parameter_id) const override {
if (parameter_id != "gain") {
return std::any();
}
return gain_;
}
common::ErrorCode reset_parameter(const std::string& parameter_id) override {
if (parameter_id != "gain") {
return common::ErrorCode::INVALID_ARGUMENT;
}
gain_ = 1.0f;
return common::ErrorCode::SUCCESS;
}
common::ErrorCode reset_all_parameters() override {
gain_ = 1.0f;
return common::ErrorCode::SUCCESS;
}
// 预设管理
size_t get_preset_count() const override {
return 0; // 没有预设
}
std::unique_ptr<PluginPreset> get_preset_info(size_t index) const override {
return nullptr; // 没有预设
}
common::ErrorCode load_preset(const std::string& preset_id) override {
return common::ErrorCode::NOT_SUPPORTED; // 没有预设
}
common::ErrorCode save_preset(const std::string& preset_id, const std::string& name) override {
return common::ErrorCode::NOT_SUPPORTED; // 没有预设
}
std::string get_current_preset_id() const override {
return ""; // 没有预设
}
// 状态保存和恢复
std::vector<uint8_t> get_state_data() const override {
// 简单地将增益值序列化
std::vector<uint8_t> data(sizeof(float));
std::memcpy(data.data(), &gain_, sizeof(float));
return data;
}
common::ErrorCode set_state_data(const std::vector<uint8_t>& data) override {
if (data.size() != sizeof(float)) {
return common::ErrorCode::INVALID_ARGUMENT;
}
std::memcpy(&gain_, data.data(), sizeof(float));
return common::ErrorCode::SUCCESS;
}
size_t get_state_data_size() const override {
return sizeof(float);
}
// GUI支持
bool has_gui() const override {
return false; // 没有GUI
}
void* create_gui(void* parent_window) override {
return nullptr; // 没有GUI
}
common::ErrorCode destroy_gui() override {
return common::ErrorCode::NOT_SUPPORTED; // 没有GUI
}
common::ErrorCode set_gui_visible(bool visible) override {
return common::ErrorCode::NOT_SUPPORTED; // 没有GUI
}
bool is_gui_visible() const override {
return false; // 没有GUI
}
std::pair<uint32_t, uint32_t> get_gui_size() const override {
return {0, 0}; // 没有GUI
}
common::ErrorCode set_gui_size(uint32_t width, uint32_t height) override {
return common::ErrorCode::NOT_SUPPORTED; // 没有GUI
}
// 事件处理
void set_event_listener(std::shared_ptr<IPluginEventListener> listener) override {
listener_ = listener;
}
void remove_event_listener() override {
listener_.reset();
}
// 性能和诊断
double get_cpu_usage() const override {
return 0.0; // 简单插件,不实现
}
size_t get_memory_usage() const override {
return 0; // 简单插件,不实现
}
std::chrono::nanoseconds get_average_processing_time() const override {
return std::chrono::nanoseconds(0); // 简单插件,不实现
}
std::chrono::nanoseconds get_max_processing_time() const override {
return std::chrono::nanoseconds(0); // 简单插件,不实现
}
void reset_performance_statistics() override {
// 简单插件,不实现
}
private:
bool initialized_;
bool activated_;
bool bypass_;
float gain_;
double sample_rate_;
uint32_t max_block_size_;
uint16_t num_channels_;
std::shared_ptr<IPluginEventListener> listener_;
};
// 导出插件工厂函数
extern "C" {
PLUGIN_EXPORT IPlugin* create_plugin() {
return new SimpleGainPlugin();
}
PLUGIN_EXPORT void destroy_plugin(IPlugin* plugin) {
delete plugin;
}
PLUGIN_EXPORT PluginVersion get_plugin_version() {
return {1, 0, 0};
}
}
沙盒插件集成
以下是使用沙盒运行插件的示例:
#include "audio_backend/plugin_host.h"
#include <iostream>
using namespace audio_backend::plugin;
int main() {
// 创建插件宿主管理器
auto host_manager = create_plugin_host_manager();
// 创建效果器沙盒配置
auto sandbox_config = create_audio_effect_sandbox_config();
// 自定义沙盒限制
sandbox_config.limits.max_memory_bytes = 128 * 1024 * 1024; // 128MB
sandbox_config.limits.max_cpu_percent = 10.0; // 10% CPU
// 加载插件
auto result = host_manager->load_plugin(
"plugins/SimpleGain.dll", // 插件路径
"gain_instance_1", // 实例ID
sandbox_config, // 沙盒配置
true // 自动激活
);
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "插件加载失败: " << common::get_error_description(result) << std::endl;
return 1;
}
// 设置参数
host_manager->set_plugin_parameter("gain_instance_1", "gain", 1.5f); // +3.5dB
// 创建音频缓冲区
engine::AudioConfig audio_config;
audio_config.sample_rate = 48000;
audio_config.channels = 2;
audio_config.format = engine::AudioFormat::FLOAT32;
audio_config.frames_per_buffer = 1024;
engine::AudioBuffer input_buffer(audio_config);
engine::AudioBuffer output_buffer(audio_config);
// 生成测试音频(1kHz正弦波)
float* input_data = input_buffer.interleaved_data<float>();
const float frequency = 1000.0f; // 1kHz
const float amplitude = 0.5f; // -6dB
for (uint32_t i = 0; i < audio_config.frames_per_buffer; ++i) {
float sample = amplitude * std::sin(2.0f * 3.14159f * frequency * i / audio_config.sample_rate);
input_data[i * 2] = sample; // 左声道
input_data[i * 2 + 1] = sample; // 右声道
}
// 创建处理上下文
PluginProcessContext context;
context.sample_rate = audio_config.sample_rate;
context.block_size = audio_config.frames_per_buffer;
context.is_playing = true;
// 处理音频
std::vector<MidiEvent> midi_in; // 空MIDI输入
std::vector<MidiEvent> midi_out; // 空MIDI输出
auto process_result = host_manager->process_plugin_audio(
"gain_instance_1",
input_buffer,
output_buffer,
midi_in,
midi_out,
context
);
if (process_result != ProcessingResult::Success) {
std::cerr << "音频处理失败" << std::endl;
return 1;
}
// 验证输出(应该比输入大约高3.5dB)
float* output_data = output_buffer.interleaved_data<float>();
float max_input = 0.0f;
float max_output = 0.0f;
for (uint32_t i = 0; i < audio_config.frames_per_buffer * audio_config.channels; ++i) {
max_input = std::max(max_input, std::abs(input_data[i]));
max_output = std::max(max_output, std::abs(output_data[i]));
}
std::cout << "最大输入振幅: " << max_input << std::endl;
std::cout << "最大输出振幅: " << max_output << std::endl;
std::cout << "增益比: " << max_output / max_input << std::endl;
// 卸载插件
host_manager->unload_plugin("gain_instance_1");
return 0;
}
自定义插件扩展
利用扩展机制为插件添加自定义功能:
// 定义自定义扩展接口
class ISpectrumAnalyzerExtension {
public:
virtual ~ISpectrumAnalyzerExtension() = default;
// 获取频谱数据
virtual void get_spectrum_data(float* output, size_t size, float scale = 1.0f) = 0;
// 获取最大频率
virtual float get_peak_frequency() const = 0;
// 设置FFT大小
virtual void set_fft_size(size_t fft_size) = 0;
};
// 在插件中实现扩展
class SpectrumAnalyzerPlugin : public IPlugin {
// ... 常规插件方法实现 ...
protected:
// 实现扩展接口
void* get_extension_impl(const std::type_info& type) override {
if (type == typeid(ISpectrumAnalyzerExtension)) {
return static_cast<ISpectrumAnalyzerExtension*>(this);
}
return nullptr;
}
public:
// 实现扩展方法
void get_spectrum_data(float* output, size_t size, float scale = 1.0f) override {
// 实现频谱数据获取
// ...
}
float get_peak_frequency() const override {
// 实现峰值频率获取
// ...
return peak_frequency_;
}
void set_fft_size(size_t fft_size) override {
// 设置FFT大小
// ...
fft_size_ = fft_size;
}
private:
float peak_frequency_ = 0.0f;
size_t fft_size_ = 2048;
// ...
};
// 使用扩展
void use_plugin_extension(PluginHostManager& host_manager, const std::string& instance_id) {
// 获取插件接口
IPlugin* plugin = host_manager.get_plugin_interface(instance_id);
if (!plugin) {
return;
}
// 尝试获取扩展
auto spectrum = plugin->get_extension<ISpectrumAnalyzerExtension>();
if (!spectrum) {
std::cout << "插件不支持频谱分析扩展" << std::endl;
return;
}
// 使用扩展功能
spectrum->set_fft_size(4096);
std::vector<float> spectrum_data(2048);
spectrum->get_spectrum_data(spectrum_data.data(), spectrum_data.size());
float peak_freq = spectrum->get_peak_frequency();
std::cout << "峰值频率: " << peak_freq << " Hz" << std::endl;
}
性能优化
资源管理
插件系统采用了多种技术优化资源使用:
- 按需激活:插件仅在需要时才激活,减少空闲资源占用
- 资源池:通过资源池复用常用资源,减少分配/释放开销
- 预分配缓冲区:预先分配关键缓冲区,避免实时处理中的内存分配
- 处理延迟控制:限制每个插件的处理时间,确保实时性
处理策略
多线程处理策略:
- 并行处理:独立插件可并行处理
- 任务分割:大型处理任务分割成小任务
- 优先级调度:根据实时性要求调整处理优先级
- 负载均衡:动态调整资源分配,优化性能
跨平台考虑
Windows特定实现
Windows平台上的沙盒实现使用:
- Job Objects:进程组管理,资源限制
- AppContainer:应用隔离
- Low Integrity Level:降低权限
- Token Restriction:限制进程权限
关键安全配置:
// Windows沙盒配置示例
void configure_windows_sandbox(HANDLE job_handle) {
JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_limits = {};
// 设置基本限制
job_limits.BasicLimitInformation.LimitFlags =
JOB_OBJECT_LIMIT_PROCESS_MEMORY |
JOB_OBJECT_LIMIT_PROCESS_TIME |
JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
job_limits.ProcessMemoryLimit = 256 * 1024 * 1024; // 256MB
job_limits.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart = 10000000; // 1秒
job_limits.BasicLimitInformation.ActiveProcessLimit = 1; // 单进程
SetInformationJobObject(
job_handle,
JobObjectExtendedLimitInformation,
&job_limits,
sizeof(job_limits)
);
}
Linux特定实现
Linux平台上的沙盒实现使用:
- Namespaces:进程离
- cgroups:资源限制
- seccomp:系统调用过滤
- chroot/pivot_root:文件系统隔离
关键安全配置:
// Linux沙盒配置示例
void configure_linux_sandbox() {
// 创建命名空间隔离
if (unshare(CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWNS) < 0) {
return; // 错误处理
}
// 配置seccomp过滤器
struct sock_filter filter[] = {
// 允许最小系统调用集合...
};
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
return; // 错误处理
}
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
return; // 错误处理
}
// 配置cgroups资源限制...
}
macOS特定实现
macOS平台上的沙盒实现使用:
- App Sandbox:应用级隔离
- XPC Services:安全进间通信
- Entitlements:权限控制
- Mach Exception Ports:异常处理
关键安全配置:
// macOS沙盒配置示例
void configure_macos_sandbox(const char* sandbox_profile) {
char* error = NULL;
int result = sandbox_init(sandbox_profile, SANDBOX_NAMED, &error);
if (result != 0) {
if (error != NULL) {
sandbox_free_error(error);
}
return; // 错误处理
}
// 配置XPC服务...
}