1409 lines
47 KiB
Markdown
1409 lines
47 KiB
Markdown
# 插件接口API参考
|
||
|
||
## 目录
|
||
|
||
- [概述](#概述)
|
||
- [插件接口核心](#插件接口核心)
|
||
- [IPlugin接口](#iplugin接口)
|
||
- [生命周期管理](#生命周期管理)
|
||
- [音频处理](#音频处理)
|
||
- [参数管理](#参数管理)
|
||
- [插件宿主管理器](#插件宿主管理器)
|
||
- [PluginHostManager](#pluginhostmanager)
|
||
- [宿主配置](#宿主配置)
|
||
- [工厂函数](#工厂函数)
|
||
- [沙盒隔离机制](#沙盒隔离机制)
|
||
- [沙盒类型](#沙盒类型)
|
||
- [资源限制](#资源限制)
|
||
- [安全策略](#安全策略)
|
||
- [跨平台实现](#跨平台实现)
|
||
- [插件元数据](#插件元数据)
|
||
- [PluginInfo](#plugininfo)
|
||
- [PluginParameter](#pluginparameter)
|
||
- [PluginPreset](#pluginpreset)
|
||
- [安全通信代理](#安全通信代理)
|
||
- [通信原理](#通信原理)
|
||
- [消息过滤](#消息过滤)
|
||
- [权限检查](#权限检查)
|
||
- [故障恢复机制](#障恢复机制)
|
||
- [崩溃检测](#崩溃检测)
|
||
- [自动重启](#自动重启)
|
||
- [降级模式](#降级模式)
|
||
- [实现示例](#实现示例)
|
||
- [基础插件实现](#基础插件实现)
|
||
- [沙盒插件集成](#沙盒插件集成)
|
||
- [自定义插件扩展](#自定义插件扩展)
|
||
- [性能优化](#性能优化)
|
||
- [资源管理](#资源理)
|
||
- [处理策略](#处理策略)
|
||
- [跨平台考虑](#跨台考虑)
|
||
- [Windows特定实现](#windows特定实现)
|
||
- [Linux特定实现](#linux特定实现)
|
||
- [macOS特定实现](#macos特定实现)
|
||
|
||
## 概述
|
||
|
||
插件系统是音频端的核心组件之一,提供了一个安全且可扩展的插件架构。该系统采用多进程隔离设计,可以安全地加载和运行第三方插件,同时保护主系统免受插件崩溃或恶意行为的影响。
|
||
|
||
核心特性:
|
||
|
||
- **多进程沙盒隔离**:通过独立进程运行插件,避免崩溃影响主系统
|
||
- **资源配额管理**:限制插件的CPU、内存、磁盘和网络使用
|
||
- **安全通信机制**:经过验证的跨进程消息传递
|
||
- **统一插件接口**:标准化的API,支持音频处理、参数控制和GUI
|
||
- **跨平台沙盒实现**:支持Windows、Linux和macOS的平台特定隔离机制
|
||
- **故障检测与恢复**:自动检测和处理插件崩溃
|
||
- **性能监控**:实监控插件资源使用情况
|
||
|
||
插件系统架构图:
|
||
|
||
```
|
||
┌─────────────────────────────────┐ ┌─────────────────────────────────┐
|
||
│ 音频引擎核心进程 │ │ 插件沙盒进程 1 │
|
||
│ │ │ │
|
||
│ ┌─────────────────────────┐ │ │ ┌─────────────────────────┐ │
|
||
│ │ 插件宿主管理器 │ │ │ │ 沙盒运行时 │ │
|
||
│ └───────────┬─────────────┘ │ │ └───────────┬─────────────┘ │
|
||
│ │ │ │ │ │
|
||
│ ┌───────────▼─────────────┐ │ │ ┌───────────▼─────────────┐ │
|
||
│ │ 安全通信代理 │◄───┼─────┼─►│ 安全通信代理 │ │
|
||
│ └───────────┬─────────────┘ │ │ └───────────┬─────────────┘ │
|
||
│ │ │ │ │ │
|
||
│ ┌───────────▼─────────────┐ │ │ ┌───────────▼─────────────┐ │
|
||
│ │ 音频处理管线 │ │ │ │ 插件实例 │ │
|
||
│ └─────────────────────────┘ │ │ └─────────────────────────┘ │
|
||
└─────────────────────────────────┘ └─────────────────────────────────┘
|
||
|
||
┌─────────────────────────────────┐
|
||
│ 插件沙盒进程 2 │
|
||
│ │
|
||
│ ┌─────────────────────────┐ │
|
||
│ │ 沙盒运行时 │ │
|
||
│ └───────────┬─────────────┘ │
|
||
│ │ │
|
||
│ ┌───────────▼─────────────┐ │
|
||
│ │ 安全通信代理 │ │
|
||
│ └───────────┬─────────────┘ │
|
||
│ │ │
|
||
│ ┌───────────▼─────────────┐ │
|
||
│ │ 插件实例 │ │
|
||
│ └─────────────────────────┘ │
|
||
└─────────────────────────────────┘
|
||
```
|
||
|
||
## 插件接口核心
|
||
|
||
### IPlugin接口
|
||
|
||
`IPlugin`是所有插件必须实现的核心接口,定义了插件的基本功能和生命周期:
|
||
|
||
```cpp
|
||
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);
|
||
};
|
||
```
|
||
|
||
### 生命周期管理
|
||
|
||
插件生命周期包括以下状态和转换:
|
||
|
||
1. **初始化(Initialize)**:首次加载插件后,进行初始化配置
|
||
- 分配资源
|
||
- 加载配置
|
||
- 准备状态
|
||
|
||
2. **激活(Activate)**:准备音频处理
|
||
- 申请实时处理资源
|
||
- 初始化处理状态
|
||
- 准备缓冲区
|
||
|
||
3. **停用(Deactivate)**:暂停音频处理
|
||
- 释放实时处理资源
|
||
- 保持状态
|
||
|
||
4. **挂起(Suspend)**:系统节能或不需要处理
|
||
- 释放部分资源
|
||
- 保持核心状态
|
||
|
||
5. **恢复(Resume)**:从挂起状态恢复
|
||
- 重新申请资源
|
||
- 恢复到之前状态
|
||
|
||
6. **关闭(Shutdown)**:完全卸载插件
|
||
- 释放所有资源
|
||
- 关闭所有连接
|
||
|
||
![插件状态转换图]()
|
||
|
||
### 音频处理
|
||
|
||
音频处理是插件的核心功能,通过`process_audio`方法实现:
|
||
|
||
```cpp
|
||
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 // 处理上下文
|
||
);
|
||
```
|
||
|
||
处理上下文提供了重要的信息,如播放位置、速度等:
|
||
|
||
```cpp
|
||
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事件由以下结构表示:
|
||
|
||
```cpp
|
||
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;
|
||
};
|
||
```
|
||
|
||
### 参数管理
|
||
|
||
插件参数提供了用户控制插件行为的机制:
|
||
|
||
```cpp
|
||
// 获取参数数量
|
||
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`负责管理插件的完整生命周期,包括加载、初始化、音频处理和卸载:
|
||
|
||
```cpp
|
||
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`定义了插件宿主的配置选项:
|
||
|
||
```cpp
|
||
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; // 启用详细日志
|
||
};
|
||
```
|
||
|
||
### 工厂函数
|
||
|
||
系统提供了几个便捷的工厂函数来创建预配置的插件宿主:
|
||
|
||
```cpp
|
||
// 创建默认配置的插件宿主管理器
|
||
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);
|
||
```
|
||
|
||
同样,还有用于创建不同类型插件沙盒配置的工厂函数:
|
||
|
||
```cpp
|
||
// 创建用于音频效果器的沙盒配置
|
||
SandboxConfig create_audio_effect_sandbox_config();
|
||
|
||
// 创建用于乐器的沙盒配置
|
||
SandboxConfig create_instrument_sandbox_config();
|
||
|
||
// 创建用于分析器的沙盒配置
|
||
SandboxConfig create_analyzer_sandbox_config();
|
||
```
|
||
|
||
## 沙盒隔离机制
|
||
|
||
### 沙盒类型
|
||
|
||
系统支持多种沙盒类型,以适应不同的隔离需求:
|
||
|
||
```cpp
|
||
enum class SandboxType {
|
||
None, // 无沙盒(不推荐用于生产环境)
|
||
Process, // 进程级隔离(标准)
|
||
Container, // 容器级隔离(Linux特定)
|
||
Thread, // 线程级隔离(有限保护,仅用于调试)
|
||
VM // 虚拟机隔离(最高安全性,但开销大)
|
||
};
|
||
```
|
||
|
||
### 资源限制
|
||
|
||
沙盒可以对插件使用的资源进行限制:
|
||
|
||
```cpp
|
||
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; // 最大网络带宽(字节/秒)
|
||
};
|
||
```
|
||
|
||
### 安全策略
|
||
|
||
沙盒安全策略定义了插件的权限和访问控制:
|
||
|
||
```cpp
|
||
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; // 启用权限下降
|
||
};
|
||
```
|
||
|
||
### 跨平台实现
|
||
|
||
沙盒系统针对不同操作系统采用不同的实现机制:
|
||
|
||
1. **Windows**
|
||
- Job Objects:资源限制进程监控
|
||
- Restricted Tokens:降低权限
|
||
- AppContainer:应用程序容器
|
||
- Integrity Levels:完整性级别
|
||
|
||
2. **Linux**
|
||
- Namespaces:进程隔离
|
||
- cgroups:资源限制
|
||
- seccomp:系统调用过滤
|
||
- capabilities:细粒度权限控制
|
||
|
||
3. **macOS**
|
||
- Sandbox:应用程序沙盒
|
||
- XPC:跨进程通信
|
||
- Entitlements:权限控制
|
||
|
||
## 插件元数据
|
||
|
||
### PluginInfo
|
||
|
||
`PluginInfo`包含插件的基本描述信息:
|
||
|
||
```cpp
|
||
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`定义了插件参数的特性:
|
||
|
||
```cpp
|
||
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`定义了件预设的属性:
|
||
|
||
```cpp
|
||
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实例 │ │
|
||
│ │ │ │ │ │ │
|
||
│ └──────────────┘ │ └──────────────┘ │
|
||
└──────────────────┘ └──────────────────┘
|
||
```
|
||
|
||
### 消息过滤
|
||
|
||
安全通信代理对所有消息执行以下过滤:
|
||
|
||
1. **消息类型验证**:确保消息类型合法且符合预期
|
||
2. **消息大小检查**:防止过大消息导致的内存问题
|
||
3. **消息频率限制**防止DOS攻击
|
||
4. **消息内容验证**:检查消息内容的合法性
|
||
|
||
### 权限检查
|
||
|
||
安全通信代理根据插件的沙盒安全策略检查权限:
|
||
|
||
- **资源访问权限**检查插件是否有权访问特定资源
|
||
- **操作权限**:检查插件是否有权执行特定操作
|
||
- **通信权限**:检查插件是否有权进行特定通信
|
||
|
||
## 故障恢复机制
|
||
|
||
### 崩溃检测
|
||
|
||
系统通过以下机制检测插件崩溃:
|
||
|
||
1. **心跳机制**:插件定期发送心跳消息,如果连续多个心跳丢失则判定为崩溃
|
||
2. **进程监控**:直接监控沙盒进程的状态
|
||
3. **超时检测**:监控处理函数的执行时间,超时则判定为无响应
|
||
|
||
### 自动重启
|
||
|
||
当检测到插件崩溃时,系统可以自动重启插件:
|
||
|
||
1. **创建新沙盒进程**:启动新的沙盒进程
|
||
2. **重新加载插件**:在新进程中加载插件
|
||
3. **恢复状态**:尝试恢复插件的之前状态
|
||
4. **重新连接**:建立新的通信通道
|
||
|
||
### 降级模式
|
||
|
||
在多次崩溃后,系统可以进入降级模式:
|
||
|
||
1. **功能限制**:限插件的某些功能以提高稳定性
|
||
2. **旁路处理**:在插件失效时提供备用处理路径
|
||
3. **资源限制**:进一步限制插件的资源使用
|
||
|
||
## 实现示例
|
||
|
||
### 基础插件实现
|
||
|
||
以下是一个简单效果器插件的实现示例:
|
||
|
||
```cpp
|
||
#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};
|
||
}
|
||
}
|
||
```
|
||
|
||
### 沙盒插件集成
|
||
|
||
以下是使用沙盒运行插件的示例:
|
||
|
||
```cpp
|
||
#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;
|
||
}
|
||
```
|
||
|
||
### 自定义插件扩展
|
||
|
||
利用扩展机制为插件添加自定义功能:
|
||
|
||
```cpp
|
||
// 定义自定义扩展接口
|
||
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;
|
||
}
|
||
```
|
||
|
||
## 性能优化
|
||
|
||
### 资源管理
|
||
|
||
插件系统采用了多种技术优化资源使用:
|
||
|
||
1. **按需激活**:插件仅在需要时才激活,减少空闲资源占用
|
||
2. **资源池**:通过资源池复用常用资源,减少分配/释放开销
|
||
3. **预分配缓冲区**:预先分配关键缓冲区,避免实时处理中的内存分配
|
||
4. **处理延迟控制**:限制每个插件的处理时间,确保实时性
|
||
|
||
### 处理策略
|
||
|
||
多线程处理策略:
|
||
|
||
1. **并行处理**:独立插件可并行处理
|
||
2. **任务分割**:大型处理任务分割成小任务
|
||
3. **优先级调度**:根据实时性要求调整处理优先级
|
||
4. **负载均衡**:动态调整资源分配,优化性能
|
||
|
||
## 跨平台考虑
|
||
|
||
### Windows特定实现
|
||
|
||
Windows平台上的沙盒实现使用:
|
||
|
||
- **Job Objects**:进程组管理,资源限制
|
||
- **AppContainer**:应用隔离
|
||
- **Low Integrity Level**:降低权限
|
||
- **Token Restriction**:限制进程权限
|
||
|
||
关键安全配置:
|
||
|
||
```cpp
|
||
// 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**:文件系统隔离
|
||
|
||
关键安全配置:
|
||
|
||
```cpp
|
||
// 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**:异常处理
|
||
|
||
关键安全配置:
|
||
|
||
```cpp
|
||
// 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服务...
|
||
} |