-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAFCPlugin.m
More file actions
92 lines (79 loc) · 3.22 KB
/
Copy pathAFCPlugin.m
File metadata and controls
92 lines (79 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
classdef AFCPlugin < audioPlugin
% AFC Adaptive Feedback Cancellation plugin
properties
InputGain = 0;
FilterOrder = 64;
StepSize = 0.001;
FilterCoefficients = zeros(2^13, 1); % (Max order = 8192)
end
properties (Access = private)
FilterInput = zeros(2^13, 1); % Input buffer for adaptive filter
PreviousInput = zeros(2^15, 1); % Previous input samples (reference signal)
Epsilon = 1e-5; % Small constant to avoid division by zero
end
properties (Constant)
PluginInterface = audioPluginInterface( ...
'PluginName', 'Adaptive Feedback Canceller', ...
'VendorName', 'AudioGoodizer Inc', ...
'VendorVersion', '1.0.0', ...
'UniqueId', '2a0Y', ...
'InputChannels', 1, ...
'OutputChannels', 1, ...
audioPluginParameter('InputGain', ...
'DisplayName', 'Input gain', ...
'Label', 'dB', ...
'Mapping', {'pow', 1/3, -96, 12}, ...
'Style', 'rotary'), ...
audioPluginParameter('FilterOrder', ...
'DisplayName', 'Filter Order', ...
'Mapping', {'int', 64, 2^13}, ...
'Style', 'rotary'), ...
audioPluginParameter('StepSize', ...
'DisplayName', 'Step Size', ...
'Mapping', {'lin', 0.001, 1.0}, ...
'Style', 'rotary'));
end
methods
function set.FilterOrder(plugin, value)
plugin.FilterOrder = value;
plugin.FilterCoefficients = zeros(value, 1);
plugin.FilterInput = zeros(value, 1);
end
function set.StepSize(plugin, value)
plugin.StepSize = value;
end
function reset(plugin)
plugin.FilterCoefficients = zeros(plugin.FilterOrder, 1);
plugin.FilterInput = zeros(plugin.FilterOrder, 1);
plugin.PreviousInput = zeros(2^15, 1);
end
function out = process(plugin, in)
in = in * 10^(plugin.InputGain/20); % Apply gain to input signal
inBlockSize = length(in); % Get input block size
out = zeros(inBlockSize, 1); % Preallocate output block
prevBlock = plugin.PreviousInput(1:inBlockSize); % Get previous input block (reference signal)
plugin.PreviousInput(1:inBlockSize) = in; % Store current input block for next iteration
% Process each sample in the block
for n = 1:inBlockSize
% Get sample from previous block
x_n = prevBlock(n);
% Add sample to filter input
plugin.FilterInput = [x_n; plugin.FilterInput(1:end-1)];
% Estimate the feedback signal
y_hat = plugin.FilterCoefficients' * plugin.FilterInput;
% Calculate error signal
e_n = in(n) - y_hat;
% Update filter coefficients (NLMS rule)
normFactor = (plugin.FilterInput' * plugin.FilterInput) + plugin.Epsilon;
plugin.FilterCoefficients = plugin.FilterCoefficients + ...
(plugin.StepSize / normFactor) * plugin.FilterInput * e_n;
% Update output block
out(n) = e_n;
end
% Normalize output block if clipping occurs
if (max(abs(out)) > 1)
out = out / max(abs(out));
end
end
end
end