enter image description here
My problem is that I dont know how start with this structure. I know myself very well that I will do it wrong and therefore wanted some advice in how to implement this structure in Matlab
I already tried a FDN reverb in Matlab. There I did it in real time with ring buffer and so on. Can I apply this Idea to this structure too? What do you think?
Here the code of what I already tried and want to apply to the given structure in the pic
classdef FDNreverbDGL < audioPlugin
properties
preDelayT = 0; % pre delay [ms]
reverbTime = 3; % reverb time [s]
roomSize = 5;
mix = 50; % mix of wet and dry signal [Percent], 100 % -> only wet
order = enumFDNorder.order8; % order of FDN, should be power of 2
in_coeff = 1/2; % coeff for in and output lines --- just for now one value for all
out_coeff = 0.65;
m_AP = 1;
D_g; %sqrt(1-g^(2))
end
properties (Access = private)
N = 8; % order of FDN
a = 1.1; % multiplying factor for delays
cSound = 343.2; % speed of sound
primeDelays = [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 ...
67 71 73 79 83 89 97 101 103 107 109 113 127 131];
% following values have to be set manually for Interface
maxPreDelay = 0.2; % max pre delay [s] (200ms)
maxRoomSize = 20.0; % max room size [m]
% following variables initialized in reset method
fs; % sample rate
A; % feedback matrix
b; % input gain coefficients
c; % output gain coefficients
f; % feedback lines after matrix
v; % signal before delay - v_i(n) = b_i * x(n) + f_i(n)
s; % output lines
d; % signal to be sent to matrix A
buffDelayLines; % buffer delay lines, initialized in reset method
m; % delay in samples of each delay line
ms; % m'
m2; % delay in samples of each delay line
g; % gain coefficients of delay lines
maxDelay; % maximum delay in delay lines
buffInput; % input buffer for pre delay
pBuffDelayLines; % pointer for delay lines buffer
pBuffInput; % pointer for input buffer
preDelayS; % preDelay in samples
end
properties(Constant)
PluginInterface = audioPluginInterface( ...
audioPluginParameter('preDelayT', ...
'DisplayName', 'Pre Delay [ms]', ...
'Mapping', {'int', 0, 200}, ...
'Style', 'rotary', ...
'Layout', [1,1]), ...
audioPluginParameter('roomSize', ...
'DisplayName', 'Room Size [m]', ...
'Mapping', {'lin', 1.0, 20.0}, ...
'Style', 'rotary', ...
'Layout', [1,2]), ...
audioPluginParameter('reverbTime', ...
'DisplayName', 'Reverb Time [s]', ...
'Mapping', {'lin', 0.1, 10.0}, ...
'Style', 'rotary', ...
'Layout', [1,3]), ...
audioPluginParameter('order', ...
'DisplayName', 'Order of FDN', ...
'Mapping', {'enum','2', '8', '16', '32'}, ...
'Layout', [3,2]), ...
audioPluginParameter('in_coeff', ...
'DisplayName', 'Input Gain', ...
'Mapping', {'lin', 0.0, 1.0}, ...
'Style', 'rotary', ...
'Layout', [3,3]), ...
audioPluginParameter('out_coeff', ...
'DisplayName', 'Output Gain', ...
'Mapping', {'lin', 0.0, 1.0}, ...
'Style', 'rotary', ...
'Layout', [3,4]), ...
audioPluginParameter('mix', ...
'DisplayName', 'Mix', ...
'Mapping', {'int', 0, 100}, ...
'Style', 'rotary', ...
'Layout', [3,1]), ...
audioPluginGridLayout( ...
'RowHeight', [100 100 100 100 100 100], ...
'ColumnWidth',[100, 100 100 100 100 100], ...
'RowSpacing', 10, ...
'ColumnSpacing', 10, ...
'Padding', [10 10 10 10]) ...
);
end
methods
function plugin = FDNreverb
init(plugin)
end
function out = process(plugin, in)
out = zeros(size(in));
for i = 1:size(in,1)
% Summieren der L/R - Kan�le
inL = in(i,1);
inR = in(i,2);
inSum = (inL + inR)/2;
plugin.buffInput(plugin.pBuffInput + 1) = inSum;
% loop over delay lines
for n=1:plugin.N
% d_n = gain * delayed v_n
for k=1:plugin.N
plugin.d(k) = plugin.g(k) * plugin.buffDelayLines(k, mod(plugin.pBuffDelayLines + plugin.m(k)+1, plugin.maxDelay +1) +1);
%xa = plugin.buffDelayLines(k, mod(plugin.pBuffDelayLines + plugin.m(k)+1, plugin.maxDelay +1) +1);
%xb = plugin.buffDelayLines(k, mod(plugin.pBuffDelayLines + plugin.m(k)+plugin.ms(k)+1, plugin.maxDelay +1) +1);
%ya =
%plugin.d(k)= plugin.g(k) *
%xa+(sqrt(1-plugin.g(k)^2)/sqrt(1-plugin.g(k)^2))*
%(xb-plugin.g(k)*
end
% f_n = A(n,:) * d'
plugin.f(n) = plugin.A(n,:) * plugin.d(:);
% v_n with pre delay
plugin.v(n) = plugin.b(n) * plugin.buffInput(mod(plugin.pBuffInput + plugin.preDelayS, (plugin.maxPreDelay * plugin.fs + 1)) + 1) ...
+ plugin.f(n); %An pe delay noch arbeiten
plugin.buffDelayLines(n, plugin.pBuffDelayLines + 1) = plugin.v(n);
% output lines
plugin.s(n) = plugin.c(n) * plugin.d(n);
out(i,:) = out(i,:) + real(plugin.s(n));
end
% Assign to output
out(i,1) = plugin.mix/100 * out(i,1) + (1.0 - plugin.mix/100) * in(i,1);
out(i,2) = plugin.mix/100 * out(i,2) + (1.0 - plugin.mix/100) * in(i,2);
calculatePointer(plugin);
end
end
function calculatePointer(plugin)
if (plugin.pBuffDelayLines==0)
plugin.pBuffDelayLines = plugin.maxDelay;
else
plugin.pBuffDelayLines = plugin.pBuffDelayLines - 1;
end
if (plugin.pBuffInput==0)
plugin.pBuffInput = plugin.maxPreDelay * plugin.fs;
else
plugin.pBuffInput = plugin.pBuffInput - 1;
end
end
function set.in_coeff(plugin, val)
plugin.in_coeff = val;
plugin.b = ones(plugin.N,1) * val;
end
function set.out_coeff(plugin, val)
plugin.out_coeff = val;
plugin.c = ones(plugin.N,1) * val;
end
function set.order(plugin, val)
plugin.order = val;
switch (plugin.order)
case enumFDNorder.order8
plugin.N = 8;
case enumFDNorder.order16
plugin.N = 16;
case enumFDNorder.order32
plugin.N = 32;
end
reset(plugin)
end
function set.reverbTime(plugin, val)
plugin.reverbTime = val;
calculateGainCoeffs(plugin, plugin.reverbTime) %, plugin.reverbTime
calculateD elays(plugin)
%sprintf('Set Reverb Time: %f', plugin.reverbTime)
%disp(['Set Reverb Time: ', num2str(plugin.reverbTime), ' s.']);
end
function set.preDelayT(plugin, val)
plugin.preDelayT = val;
calculatePreDelayS(plugin, plugin.preDelayT)
%disp(['Set Predelay: ', int2str(plugin.preDelayT), ' ms.']);
end
function set.mix(plugin, val)
plugin.mix = val;
%disp(['Set Mix value: ', int2str(plugin.mix), ' %.']);
end
function calculateMatrix(plugin)
plugin.A = generateFDNmatrix(plugin.N);
end
function calculateDelays(plugin)
% calculate sample delays dependent on room size (val) and
% sample rate (fs)
% m_1 = trace of sound / cSound * fs
M = ceil(0.15 * plugin.reverbTime * plugin.fs);
%disp(['M = ', int2str(M)]);
plugin.m = zeros(plugin.N,1);
interval = M/(plugin.N*4);
%test = 0;
for i=1:plugin.N
tmp = interval/2 + (i-1) * interval;
e = floor(0.5 + log(tmp)/log(plugin.primeDelays(i)));
plugin.m(i) = plugin.primeDelays(i)^(e); %plugin.primeDelays(i)^(e)
end
plugin.ms = [1429 1523 1619 1741 1871 1993 2089 2221 2339 2437 2579 2689 2791 2909 3041 3187];
%plugin.m = [223 569 941 1451 1871 2297 2729 3209 3643 4111 4597 5077 5563 6053 6551 7013]; %JedeVierte
end
function calculateGainCoeffs(plugin,val) %,val
for i=1:plugin.N
% if mod(i,2) == 0
plugin.g(i) = 0.8;%10^((-3) * (plugin.m(i)/plugin.fs) / val);
% plugin.g(i) = -0.9;
% else
% plugin.g(i) = 0.2;
%end
end
end
%%
function calculatePreDelayS(plugin, val)
plugin.preDelayS = val * plugin.fs/100 ;
end
function init(plugin)
plugin.fs = getSampleRate(plugin);
% initialize buffDelayLines & pointer
%plugin.maxDelay = floor(plugin.maxRoomSize/plugin.cSound * plugin.fs * plugin.a^(plugin.N)); %probably higher than actual max delay as actual delays get rounded down
%plugin.maxDelay = ceil(0.15 * 5 * plugin.fs); % maximum possible delay for max reverb time = 5s
plugin.maxDelay = 131^2;
plugin.buffDelayLines = zeros(plugin.N, plugin.maxDelay + 1);
plugin.pBuffDelayLines = plugin.maxDelay;
% initialize
plugin.A = zeros(plugin.N);
plugin.b = ones(plugin.N,1) * plugin.in_coeff; % input gain coefficients
plugin.c = ones(plugin.N,1) * plugin.out_coeff; % output gain coefficients
plugin.f = zeros(plugin.N,1); % feedback lines after matrix
plugin.v = zeros(plugin.N,1); % signal before delay - v_i(n) = b_i * x(n) + f_i(n)
plugin.s = zeros(plugin.N,1); % output lines
plugin.d = zeros(plugin.N,1); % signal to be sent fsto matrix A
plugin.m = zeros(plugin.N,1); % delay in samples of each delay line
plugin.ms = zeros(plugin.N,1); % delay in samples of each delay line m'
plugin.g = zeros(plugin.N,1); % gain coefficients of delay lines
plugin.buffInput = zeros((plugin.maxPreDelay * plugin.fs) + 1, 1); % input buffer for pre delay, 0.2 = max pre delay of 200ms
plugin.preDelayS = 0; % pre delay in samples
plugin.pBuffInput = plugin.maxPreDelay * plugin.fs; % pointer for input buffer
% calculate sample delays of delay lines
calculateDelays(plugin)
% calculate gain coeffs of delay lines
calculateGainCoeffs(plugin, plugin.reverbTime) %, plugin.reverbTime
% calculate FDN matrix based on set order
calculateMatrix(plugin)
end
function reset(plugin)
init(plugin)
end
function generateFDNmatrix(order)
% generates FDN matrix with evenly distributed eigenvalues at
% the unit circle
eig_nr = order/2;
FDNmatrix = zeros(order, order);
M = orth((rand(order,order)));
BC_n = zeros(order, order, eig_nr);
DtD_n = zeros(order, order, eig_nr);
k1 = 1;
for k=2:2:eig_nr*2
x = M(:,k-1);
y = M(:,k);
x = x / sqrt(2);
y = y / sqrt(2);
B = x * x.';
C = y * y.';
D = x * y.';
BC_n(1:order,1:order,k1) = B + C;
DtD_n(1:order,1:order,k1) = D.' - D;
w = pi * k / (eig_nr * 2 + 2);
temp = 2 * BC_n(:,:,k1) * cos(w) + 2 * DtD_n(:,:,k1) * sin(w);
FDNmatrix = FDNmatrix + temp;
k1 = k1 + 1;
end
end
end
end