VST Plugin Creation from Matlab Script
23 ビュー (過去 30 日間)
古いコメントを表示
Hello Gabriele!
I wanna create a VST Plugin for real time audio processing that simulates a shoebox and it auralizes the sound you give it as an input mono or stereo, and with the use of HRTF data and HelperImageSource method , filters/auralizes the output sound. I have my matlab script ready and working , but I am dealing with issues In my conversion of the Matlab script to VST Coding in order to audiotestbench / prototype and generate my audio plugin.
roomDimensions = [25, 20, 17];
receiverCoord = [5, 6, 8];
sourceCoord = [5, 8, 9];
A = [ ...
0.10 0.20 0.40 0.60 0.50 0.60; ...
0.10 0.20 0.40 0.60 0.50 0.60; ...
0.10 0.20 0.40 0.60 0.50 0.60; ...
0.10 0.20 0.40 0.60 0.50 0.60; ...
0.02 0.03 0.03 0.03 0.04 0.07; ...
0.02 0.03 0.03 0.03 0.04 0.07].';
FVect = [125 250 500 1000 2000 4000];
fs = 48000;
useHRTF = true;
ARIDataset = load("ReferenceHRTF.mat");
hrtfData = permute(ARIDataset.hrtfData, [2, 3, 1]);
sourcePosition = ARIDataset.sourcePosition(:, [1, 2]);
h = HelperImageSource(roomDimensions, receiverCoord, sourceCoord, A, FVect, fs, useHRTF, hrtfData, sourcePosition);
disp(size(h)); % Επιβεβαίωσε τις διαστάσεις του h
% --- Initialize audio input ---
% Load an audio file (replace 'your_audio_file.wav' with your file name)
[audioIn, fs] = audioread('FunkyDrums-44p1-stereo-25secs.mp3');
% Define playback duration in seconds
T = 5; % Set to 5 seconds (or any desired duration)
% Ensure audio duration is sufficient for playback
if length(audioIn) < fix(fs*T)
error('Audio file is shorter than the requested playback duration T.');
end
% --- Test original audio ---
sound(audioIn(1:fix(fs*T)), fs); % Fix ensures integer sample length
pause(T);
% --- Visualize original audio signal ---
% Create time axis for plotting
time = (0:length(audioIn)-1) / fs;
% Plot original signal
figure;
subplot(2, 1, 1);
plot(time, audioIn);
title('Original Audio Signal');
xlabel('Time (s)');
ylabel('Amplitude');
grid on;
% --- Apply audio filter ---
y1 = filter(h(:, 1), 1, audioIn);
y2 = filter(h(:, 2), 1, audioIn);
y = [y1 y2];
y = y / max(abs(y(:))); % Normalize
% --- Save filtered audio signal ---
outputFileName = 'filtered_audio2.wav'; % Specify the output file name
audiowrite(outputFileName, y, fs); % Save the filtered audio
disp(['Filtered audio saved to ', outputFileName]);
% --- Test filtered audio ---
sound(y(1:round(fs*T)), fs); % Round ensures integer sample length
% --- Visualize filtered audio signal ---
subplot(2, 1, 2);
plot(time, y);
title('Filtered Audio Signal');
xlabel('Time (s)');
ylabel('Amplitude');
grid on;
This is the Matlab initial script code and the code I wrote to convert it to a VST is this below:
classdef RoomAudioSimulator2 < audioPlugin
% RoomAudioSimulator: A VST plugin simulating room acoustics.
properties
roomLength = 25; % Room length
roomWidth = 20; % Room width
roomHeight = 17; % Room height
receiverX = 5; % Receiver X-coordinate
receiverY = 6; % Receiver Y-coordinate
receiverZ = 8; % Receiver Z-coordinate
sourceX = 5; % Source X-coordinate
sourceY = 8; % Source Y-coordinate
sourceZ = 9; % Source Z-coordinate
end
properties (Constant)
PluginInterface = audioPluginInterface( ...
audioPluginParameter('roomLength', ...
'DisplayName', 'Room Length', ...
'Mapping', {'lin', 5, 35}), ...
audioPluginParameter('roomWidth', ...
'DisplayName', 'Room Width', ...
'Mapping', {'lin', 5, 35}), ...
audioPluginParameter('roomHeight', ...
'DisplayName', 'Room Height', ...
'Mapping', {'lin', 5, 35}), ...
audioPluginParameter('receiverX', ...
'DisplayName', 'Receiver X', ...
'Mapping', {'lin', 0, 35}), ...
audioPluginParameter('receiverY', ...
'DisplayName', 'Receiver Y', ...
'Mapping', {'lin', 0, 35}), ...
audioPluginParameter('receiverZ', ...
'DisplayName', 'Receiver Z', ...
'Mapping', {'lin', 0, 35}), ...
audioPluginParameter('sourceX', ...
'DisplayName', 'Source X', ...
'Mapping', {'lin', 0, 35}), ...
audioPluginParameter('sourceY', ...
'DisplayName', 'Source Y', ...
'Mapping', {'lin', 0, 35}), ...
audioPluginParameter('sourceZ', ...
'DisplayName', 'Source Z', ...
'Mapping', {'lin', 0, 35}));
end
properties (Access = private)
hrtfData; % HRTF data loaded from ARI dataset
sourcePosition; % Source positions for HRTF
h; % Filter coefficients
fs = 48000; % Sampling rate
filterState; % Filter state for processing
end
methods
function obj = RoomAudioSimulator2()
% Load HRTF dataset
ARIDataset = load("ReferenceHRTF.mat");
obj.hrtfData = permute(ARIDataset.hrtfData, [2, 3, 1]);
obj.sourcePosition = ARIDataset.sourcePosition(:, [1, 2]);
% Initialize filters
obj.updateFilters();
obj.reset();
end
function audioOut = process(obj, audioIn)
% Ensure h is initialized
if isempty(obj.h)
obj.updateFilters();
end
% Handle mono input
if size(audioIn, 2) == 1
audioIn = repmat(audioIn, 1, 2);
elseif size(audioIn, 2) ~= 2
error('Input audio must have 1 or 2 channels.');
end
% Apply filtering with state preservation
[y1, obj.filterState(:, 1)] = filter(obj.h(:, 1), 1, audioIn(:, 1), obj.filterState(:, 1));
[y2, obj.filterState(:, 2)] = filter(obj.h(:, 2), 1, audioIn(:, 2), obj.filterState(:, 2));
audioOut = [y1, y2];
end
function reset(obj)
% Reset filter states
if isempty(obj.h)
obj.filterState = zeros(100, 2); % Default size if h is uninitialized
else
obj.filterState = zeros(size(obj.h, 1) - 1, 2);
end
end
function update(obj)
% Called during real-time parameter tuning
obj.adaptPositions();
obj.updateFilters();
end
function updateFilters(obj)
% Efficiently update filter coefficients
roomDimensions = [obj.roomLength, obj.roomWidth, obj.roomHeight];
receiverCoord = [obj.receiverX, obj.receiverY, obj.receiverZ];
sourceCoord = [obj.sourceX, obj.sourceY, obj.sourceZ];
A = [ ...
0.10 0.20 0.40 0.60 0.50 0.60; ...
0.10 0.20 0.40 0.60 0.50 0.60; ...
0.10 0.20 0.40 0.60 0.50 0.60; ...
0.10 0.20 0.40 0.60 0.50 0.60; ...
0.02 0.03 0.03 0.03 0.04 0.07; ...
0.02 0.03 0.03 0.03 0.04 0.07].';
FVect = [125, 250, 500, 1000, 2000, 4000];
obj.h = HelperImageSource(roomDimensions, receiverCoord, ...
sourceCoord, A, FVect, obj.fs, ...
true, obj.hrtfData, obj.sourcePosition);
obj.reset(); % Ensure state is reinitialized
end
function adaptPositions(obj)
% Ensure receiver and source positions stay inside room dimensions
obj.receiverX = min(max(round(obj.receiverX), 0), obj.roomLength);
obj.receiverY = min(max(round(obj.receiverY), 0), obj.roomWidth);
obj.receiverZ = min(max(round(obj.receiverZ), 0), obj.roomHeight);
obj.sourceX = min(max(round(obj.sourceX), 0), obj.roomLength);
obj.sourceY = min(max(round(obj.sourceY), 0), obj.roomWidth);
obj.sourceZ = min(max(round(obj.sourceZ), 0), obj.roomHeight);
end
end
end
It's working with no errors on AudioTestBench , but it's for sure wrong because whenever I change the tuneable parameters ( RoomDimensions , source-receiver positioning ) the output sound remains the same , so something is wrong. Another issue is that , I cant seem to make it work like a real-time VST Plugin. It would be so helpful to give me some feedback and help me build this!
Thanks in Advance!
Noulis Dimitrios , Electrical & Electronics Engineer in UniWA, Athens, Greece.
0 件のコメント
回答 (1 件)
jibrahim
2025 年 1 月 31 日 19:11
Hi DIMITRIOS,
I have a few high-level remarks:
1) On the issue of not hearing any changes when you tune source position and other properties: In an audio plugin, you typically react to a change in the property value in a set method (for example, set.receiverX). In that set method, you should update the room impulse response based on the new parameters. Alternatively, you can manage a logical property (for example, needUpdate), which you set to true in set.receiverX and other such set method. Then, in process, you can re-design the filter if need be:
function audioOut = process(obj, audioIn)
if obj.needUpdate
obj.updateFilters();
end
...
end
2) There are other considerations when authoring a plugin. If your goal is to eventually generate a plugin (.VST, .AU, etc), then the MATLAB code in your plugin must pass validateAudioPlugin, which your plugin does not pass yet, partly because your MATLAB code does not support code generation.
Moreover, for the plugin to run efficiently in run time, the computation of the impulse response must be fast and efficient enough, otherwise you will epxerience drops whenever you tune parameters. I suspect you are suing HelperImageSource from a shipping example in Audio Toolbox. That helper function is not necessarly suitable for such real-time scenarios.
0 件のコメント
参考
カテゴリ
Help Center および File Exchange で Audio Plugin Creation and Hosting についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!