function demo_blockproc_paramequalizer(source,varargin)
%DEMO_BLOCKPROC_PARAMEQUALIZER Real-time equalizer demonstration
% Usage: demo_blockproc_paramequalizer('gspi.wav')
%
% For additional help call DEMO_BLOCKPROC_PARAMEQUALIZER without arguments.
%
% This demonstration shows an example of a octave parametric
% equalizer. See chapter 5.2 in the book by Zolzer.
%
% References:
% U. Zolzer. Digital Audio Signal Processing. John Wiley and Sons Ltd, 2
% edition, 2008.
%
%
% Url: http://ltfat.github.io/doc/demos/demo_blockproc_paramequalizer.html
% Copyright (C) 2005-2023 Peter L. Soendergaard <peter@sonderport.dk> and others.
% This file is part of LTFAT version 2.6.0
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
if demo_blockproc_header(mfilename,nargin)
return;
end
% Buffer length
% Larger the number the higher the processing delay. 1024 with fs=44100Hz
% makes ~23ms.
% The value can be any positive integer.
% Note that the processing itself can introduce additional delay.
% Quality parameter of the peaking filters
Q = sqrt(2);
% Filters
filts = [
struct('Hb',[1;0],'Ha',[1;0],'G',0,'Z',[0;0],'type','lsf'),...
struct('Hb',[1;0;0],'Ha',[1;0;0],'G',0,'Z',[0;0],'type','peak'),...
struct('Hb',[1;0;0],'Ha',[1;0;0],'G',0,'Z',[0;0],'type','peak'),...
struct('Hb',[1;0;0],'Ha',[1;0;0],'G',0,'Z',[0;0],'type','peak'),...
struct('Hb',[1;0;0],'Ha',[1;0;0],'G',0,'Z',[0;0],'type','peak'),...
struct('Hb',[1;0;0],'Ha',[1;0;0],'G',0,'Z',[0;0],'type','hsf')...
];
% Control pannel (Java object)
% Each entry determines one parameter to be changed during the main loop
% execution.
pcell = cell(1,numel(filts));
for ii=1:numel(filts)
pcell{ii} = {sprintf('band%i',ii),'Gain',-10,10,filts(ii).G,41};
end
p = blockpanel(pcell);
% Setup blocktream
try
fs = block(source,varargin{:},'loadind',p);
catch
% Close the windows if initialization fails
blockdone(p);
err = lasterror;
error(err.message);
end
% Buffer length (30 ms)
bufLen = floor(30e-3*fs);
% Cutoff/center frequency
feq = [0.0060, 0.0156, 0.0313, 0.0625, 0.1250, 0.2600]*fs;
% Build the filters
[filts(1).Ha, filts(1).Hb] = parlsf(feq(1),blockpanelget(p,'band1'),fs);
[filts(2).Ha, filts(2).Hb] = parpeak(feq(2),Q,blockpanelget(p,'band2'),fs);
[filts(3).Ha, filts(3).Hb] = parpeak(feq(3),Q,blockpanelget(p,'band3'),fs);
[filts(4).Ha, filts(4).Hb] = parpeak(feq(4),Q,blockpanelget(p,'band4'),fs);
[filts(5).Ha, filts(5).Hb] = parpeak(feq(5),Q,blockpanelget(p,'band5'),fs);
[filts(6).Ha, filts(6).Hb] = parhsf(feq(6),blockpanelget(p,'band6'),fs);
flag = 1;
%Loop until end of the stream (flag) and until panel is opened
while flag && p.flag
% Obtain gains of the respective filters
G = blockpanelget(p,'band1','band2','band3','band4','band5','band6');
% Check if any of the user-defined gains is different from the actual ones
% and do recomputation.
for ii=1:numel(filts)
if G(ii)~=filts(ii).G
filts(ii).G = G(ii);
if strcmpi('lsf',filts(ii).type)
[filts(ii).Ha, filts(ii).Hb] = parlsf(feq(ii),filts(ii).G,fs);
elseif strcmpi('hsf',filts(ii).type)
[filts(ii).Ha, filts(ii).Hb] = parhsf(feq(ii),filts(ii).G,fs);
elseif strcmpi('peak',filts(ii).type)
[filts(ii).Ha, filts(ii).Hb] = parpeak(feq(ii),Q,filts(ii).G,fs);
else
error('Uknown filter type.');
end
end
end
% Read block of length bufLen
[f,flag] = blockread(bufLen);
% Do the filtering. Output of one filter is passed to the input of the
% following filter. Internal conditions are used and stored.
for ii=1:numel(filts)
[f,filts(ii).Z] = filter(filts(ii).Ha,filts(ii).Hb,f,filts(ii).Z);
end
% Play the block
blockplay(f);
end
blockdone(p);
function [Ha,Hb]=parlsf(fc,G,Fs)
% PARLSF Parametric Low-Shelwing filter
% Input parameters:
% fm : Cut-off frequency
% G : Gain in dB
% Fs : Sampling frequency
% Output parameters:
% Ha : Transfer function numerator coefficients.
% Hb : Transfer function denominator coefficients.
%
% For details see Table 5.4 in the reference.
Ha = zeros(3,1);
Hb = zeros(3,1);
%b0
Hb(1) = 1;
Ha(1) = 1;
K = tan(pi*fc/Fs);
if G>0
V0=10^(G/20);
den = 1 + sqrt(2)*K + K*K;
% a0
Ha(1) = (1+sqrt(2*V0)*K+V0*K*K)/den;
% a1
Ha(2) = 2*(V0*K*K-1)/den;
% a2
Ha(3) = (1-sqrt(2*V0)*K+V0*K*K)/den;
% b1
Hb(2) = 2*(K*K-1)/den;
% b2
Hb(3) = (1-sqrt(2)*K+K*K)/den;
elseif G<0
V0=10^(-G/20);
den = 1 + sqrt(2*V0)*K + V0*K*K;
% a0
Ha(1) = (1+sqrt(2)*K+K*K)/den;
% a1
Ha(2) = 2*(K*K-1)/den;
% a2
Ha(3) = (1-sqrt(2)*K+K*K)/den;
% b1
Hb(2) = 2*(V0*K*K-1)/den;
% b2
Hb(3) = (1-sqrt(2*V0)*K+V0*K*K)/den;
end
function [Ha,Hb]=parpeak(fc,Q,G,Fs)
% PARLSF Parametric Peaking filter
% Input parameters:
% fm : Cut-off frequency
% Q : Filter quality. Q=fc/B, where B is filter bandwidth.
% G : Gain in dB
% Fs : Sampling frequency
% Output parameters:
% Ha : Transfer function numerator coefficients.
% Hb : Transfer function denominator coefficients.
%
% For details see Table 5.3 in the reference.
Ha = zeros(3,1);
Hb = zeros(3,1);
%b0
Hb(1) = 1;
Ha(1) = 1;
K = tan(pi*fc/Fs);
if G>0
V0=10^(G/20);
den = 1 + K/Q + K*K;
% a0
Ha(1) = (1+V0*K/Q+K*K)/den;
% a1
Ha(2) = 2*(K*K-1)/den;
% a2
Ha(3) = (1-V0*K/Q+K*K)/den;
% b1
Hb(2) = 2*(K*K-1)/den;
% b2
Hb(3) = (1-K/Q+K*K)/den;
elseif G<0
V0=10^(-G/20);
den = 1 + V0*K/Q + K*K;
% a0
Ha(1) = (1+K/Q+K*K)/den;
% a1
Ha(2) = 2*(K*K-1)/den;
% a2
Ha(3) = (1-K/Q+K*K)/den;
% b1
Hb(2) = 2*(K*K-1)/den;
% b2
Hb(3) = (1-V0*K/Q+K*K)/den;
end
function [Ha,Hb]=parhsf(fm,G,Fs)
% PARLSF Parametric High-shelving filter
% Input parameters:
% fm : Cut-off frequency
% G : Gain in dB
% Fs : Sampling frequency
% Output parameters:
% Ha : Transfer function numerator coefficients.
% Hb : Transfer function denominator coefficients.
%
% For details see Table 5.3 in the reference.
Ha = zeros(3,1);
Hb = zeros(3,1);
%b0
Hb(1) = 1;
Ha(1) = 1;
K = tan(pi*fm/Fs);
if G>0
V0=10^(G/20);
den = 1 + sqrt(2)*K + K*K;
% a0
Ha(1) = (V0+sqrt(2*V0)*K+K*K)/den;
% a1
Ha(2) = 2*(K*K-V0)/den;
% a2
Ha(3) = (V0-sqrt(2*V0)*K+K*K)/den;
% b1
Hb(2) = 2*(K*K-1)/den;
% b2
Hb(3) = (1-sqrt(2)*K+K*K)/den;
elseif G<0
V0=10^(-G/20);
den = V0 + sqrt(2*V0)*K + K*K;
% a0
Ha(1) = (1+sqrt(2)*K+K*K)/den;
% a1
Ha(2) = 2*(K*K-1)/den;
% a2
Ha(3) = (1-sqrt(2)*K+K*K)/den;
% b1
Hb(2) = 2*(K*K/V0-1)/den;
% b2
Hb(3) = (1-sqrt(2/V0)*K+K*K/V0)/den;
end