关于 matlab-write-audio-plugin
面向 MATLAB 音频插件开发的技能,涵盖插件结构、代码生成约束、验证与部署,适用于创建效果器、音源插件及排查生成问题。
主要功能
- 01音频插件类结构指导
- 02代码生成约束说明
- 03生命周期与状态管理
- 04验证及插件生成流程
- 05深度学习推理集成参考
适用场景
- 01创建音频效果器或音源插件
- 02排查插件验证与生成错误
- 03将 MATLAB 算法部署为 VST 或 AU
- 04在实时插件中集成深度学习推理
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill matlab-write-audio-plugin安装后在 Claude Code 中输入/matlab-write-audio-plugin确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
manifest.yamlreferences/advanced-patterns.mdavailable-functions.mddeep-learning.mdgrid-layout.mdparameters.md详细介绍
在 MATLAB 中编写音频插件
适用场景
- 创建音频效果或生成器插件(继承自
audioPlugin或audioPluginSource的 classdef) - 排查
validateAudioPlugin或generateAudioPlugin失败的问题 - 将 MATLAB 音频算法转换为可部署的 VST/AU 插件
- 将深度学习推理集成到实时音频插件中
不适用场景
- 与音频插件无关的一般 MATLAB 类编写
- 音频文件 I/O、特征提取或分析(不涉及插件)
- Simulink 音频处理模块
- 编写非插件的 Audio Toolbox 函数(例如
audioDatastore、audioFeatureExtractor)
结构
每个音频插件都是一个带有 %#codegen 的 classdef,包含公共可调参数、常量 PluginInterface,以及 process 和 reset 方法。
classdef MyPlugin < audioPlugin
%#codegen
properties
Gain = 0.5
Cutoff = 1000
end
properties (Access = private)
pSR = 44100
pB = [1 0 0]
pA = [1 0 0]
pState = zeros(2, 2) % (filterOrder, numChannels)
end
properties (Constant)
PluginInterface = audioPluginInterface( ...
audioPluginParameter('Gain', ...
DisplayName='Gain', Label='dB', Mapping={'lin', 0, 1}), ...
audioPluginParameter('Cutoff', ...
DisplayName='Cutoff', Label='Hz', Mapping={'log', 20, 20000}), ...
InputChannels=2, OutputChannels=2)
end
methods
function y = process(plugin, x)
[y, plugin.pState] = filter(plugin.pB, plugin.pA, x, plugin.pState);
y = y * plugin.Gain;
end
function reset(plugin)
plugin.pSR = getSampleRate(plugin);
plugin.pState = zeros(2, 2);
designFilter(plugin);
end
function set.Cutoff(plugin, val)
plugin.Cutoff = val;
designFilter(plugin); %#ok<MCSUP>
end
end
methods (Access = private)
function designFilter(plugin)
wn = plugin.Cutoff / (plugin.pSR / 2);
wn = max(eps, min(wn, 1 - eps));
[plugin.pB, plugin.pA] = butter(2, wn);
end
end
end
源插件继承自 audioPluginSource,省略 InputChannels,且 process 不接收音频输入——使用 getSamplesPerFrame(plugin) 获取输出帧大小。
System Object 混合类(matlab.System & audioPlugin)需要 (StrictDefaults)、返回 true 的 isInputSizeMutableImpl,并使用 stepImpl/resetImpl 取代 process/reset。仅在用户要求兼容 Simulink 时使用。
插件生命周期
- 构造函数——使用字面量参数构造所有子对象。此处
getSampleRate返回 44100;仅用于初始缓冲区大小设置。 reset——在采样率或帧大小变化时调用。将getSampleRate(plugin)缓存到pSR中。重新计算所有依赖采样率的值。设置子对象的采样率后,对每个子对象调用reset()。process——每个音频帧调用一次。返回大小为[N, numOutputChannels]的double输出。绝不向注册在audioPluginParameter中的属性赋值——对于输出计量表,保持属性公开但不注册。- Set 方法——参数变化时重新计算派生值(系数、缓冲区大小)。仅当 Set 方法确实通过
obj.PropertyName访问其他属性,或调用会执行此操作的方法时(例如,在set.Cutoff中调用designFilter(plugin)),才添加%#ok<MCSUP>。不要预先添加——仅抑制 checkcode 在该行实际报告的警告。 - 保存/加载(可选,仅限 MATLAB)——仅当插件具有无法通过参数和采样率由
reset重建的私有状态时才需要(例如,已加载的数据、带有内部缓冲区的句柄子对象)。不会编译到生成的 VST/独立程序中——DAW 主机会通过插件接口持久化参数,并在恢复时调用reset。有关此模式,请参阅references/advanced-patterns.md。
代码生成要求
所有代码都必须兼容代码生成。validateAudioPlugin 会遍历 5 个采样率(8000–192000)、帧大小 2.^(1:13)+1(最大 8193)以及所有参数极值。
始终优先使用内置函数,而非手动实现。 按以下顺序优先使用工具箱函数:Audio Toolbox → DSP System Toolbox → Signal Processing Toolbox → 基础 MATLAB。如果不确定是否存在兼容代码生成的内置函数来执行某项操作,请先查阅 references/available-functions.md,再进行手动实现。
缓冲区和状态
将所有状态预分配到所需的最大大小。Codegen 会根据构造函数中的最后一次赋值锁定属性大小——按参数可能达到的最大值分配,然后在运行时索引活动区域。
使用索引赋值进行移位:
buf(1:end-N) = buf(N+1:end); % shift left by N
buf(end-N+1:end) = newData; % fill tail
切勿通过拼接进行移位——[buf(N+1:end); zeros(N,ch)] 会生成可变大小的结果,codegen 拒绝将其赋值给固定大小属性。
将值赋给固定大小属性时,切勿在列维度上使用 :——codegen 会将 x(i,:) 视为可变大小。请显式索引列:[x(i,1), x(i,2)]。
用来存储复数值的数组,应使用 complex(zeros(...)) 初始化,而不是直接使用 zeros(...)。codegen 会根据第一次赋值锁定实数/复数属性。如果数组最初为实数,之后再将 FFT 输出赋给它,就会失败并报错“左侧受约束,不能为复数”。
dsp.AsyncBuffer 的容量必须大于插件将收到的最大单次 write 数据量。validateAudioPlugin 会传入最多 8193 个采样的帧;设置缓冲区大小时,请将其与任何重叠部分一并考虑。
当 filter() 的输入来自子对象(例如 crossoverFilter)时,codegen 无法传递列数信息,因此返回的状态会变为可变大小。请显式处理各通道:
[low(:,1), plugin.pState(:,1)] = filter(b, a, low(:,1), plugin.pState(:,1));
[low(:,2), plugin.pState(:,2)] = filter(b, a, low(:,2), plugin.pState(:,2));
枚举参数(值长度不同)
对于 3 个及以上的值,使用 Style='dropdown';恰好 2 个值时,使用 'vrocker'/'vtoggle'。
如果枚举值的字符长度不同('On'/'Off'、'Short'/'VeryLong'),建议使用单独的 int32 枚举类文件。框架可以在内部处理字符填充,但显式的枚举类能生成更简洁的代码,并使用带类型的分派,而不是字符串比较:
% MyMode.m
classdef MyMode < int32
enumeration
Normal (0)
Aggressive (1)
Subtle (2)
end
end
插件属性:Mode = MyMode.Normal,并设置 Mapping={'enum','Normal','Aggressive','Subtle'}。
根据参数派生的值
根据参数计算归一化频率或延迟索引时,应对结果进行限幅:
wn = plugin.Cutoff / (plugin.pSR / 2);
wn = max(eps, min(wn, 1 - eps)); % keep in valid (0,1) range for butter/cheby
将延迟线读取索引限制在 [1, bufferLength] 范围内。这可防止在极端采样率或参数设置下出现越界,而 validateAudioPlugin 会测试这些情况。
完整的 Switch 分支
凡是为变量赋值的 switch,都必须包含带安全默认值的 otherwise——codegen 要求所有分支定义相同的输出。
子对象
在构造函数中使用字面量参数进行构造。在 reset 中,先传递采样率,再重置:
function reset(plugin)
fs = getSampleRate(plugin);
setSampleRate(plugin.pEcho, fs);
reset(plugin.pEcho);
plugin.pCompressor.SampleRate = fs;
reset(plugin.pCompressor);
end
以 process(plugin.pSub, x) 的形式调用子插件。以 plugin.pObj(x) 的形式调用 System Objects。在 set 方法中转发参数更改。
外部数据和仅运行时调用
- 加载数据文件:在构造函数中使用
coder.load('data.mat')——数据会被嵌入二进制文件 - 保护非 codegen 调用:将
fprintf/disp/plot包装在if isempty(coder.target)中
验证
validateAudioPlugin -nomex ClassName % structural + testbench
validateAudioPlugin ClassName % full MEX codegen
generateAudioPlugin ClassName % produce VST/AU binary
验证通过后:
- 对所有生成的
.m文件运行checkcode——通过重命名或重构解决每条警告,不要添加%#ok抑制标记(set 方法中的%#ok<MCSUP>除外)。重新运行 checkcode,确认不再有任何警告。 - 验证功能行为:实例化、调用
setSampleRate和reset、处理测试信号,并确认输出符合预期。
生成
默认输出为 VST 2。使用标志选择其他格式:
| 标志 | 格式 | 平台 |
|---|---|---|
-vst | VST 2(默认) | Windows、macOS |
-vst3 | VST 3 | Windows、macOS |
-au | Audio Unit v2 | 仅 macOS |
-auv3 | Audio Unit v3 | 仅 macOS |
-exe | 独立可执行文件 | Windows、macOS |
-juceproject | JUCE 项目(源代码) | 所有平台(包括 Linux) |
如果用户请求的输出格式在当前平台上不可用(例如,在 Windows 上请求 AU,或在 Linux 上请求任何已编译的二进制文件),请说明限制,并建议最接近的替代方案(在 Linux 上使用 -juceproject;在 Windows 上使用 -vst/-vst3 代替 AU)。
参考资料
references/available-functions.md— 内置流式 DSP 对象(优先于手动实现)references/advanced-patterns.md— AsyncBuffer、调制延迟、保存/加载、代码生成边缘情况references/parameters.md— 映射定律、多总线 I/O、网格布局约束references/grid-layout.md— 网格布局语法,使用DisplayNameLocation分配行references/deep-learning.md— 使用coder.loadDeepLearningNetwork进行神经网络推理
Copyright 2026 The MathWorks, Inc.