Skip to content

Instantly share code, notes, and snippets.

@pral2a
Created March 23, 2017 18:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pral2a/41f7a724c81965b4e36ef3ad97659884 to your computer and use it in GitHub Desktop.
Save pral2a/41f7a724c81965b4e36ef3ad97659884 to your computer and use it in GitHub Desktop.
Build A Weighting Table

Install

pkg install signal pkg load signal

Output

aweightingtableR.csv aweightingtableI.csv

% Build A-weighting filter gain table used to filter signal
%
% copyright (c) Davide Gironi, 2013
% copyright (c) Pral2a, 2016 (Ported to GNU Octave)
%
% Released under GPLv3.
% Please refer to LICENSE file for licensing information.
%clear matlab workspace
clear;
function aspec(B,A,Fs);
% ASPEC Plots a filter characteristics vs. A-weighting specifications.
% ASPEC(B,A,Fs) plots the attenuation of the filter defined by B and A
% with sampling frequency Fs against the specifications for class 1
% and class 2 A-weighting filters.
%
% See also ADSGN, CDSGN, CSPEC.
% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium)
% couvreur@thor.fpms.ac.be
% Last modification: Aug. 26, 1997, 10:00am.
% References:
% [1] IEC/CD 1672: Electroacoustics-Sound Level Meters, Nov. 1996.
if (nargin ~= 3)
error('Invalide number of arguments.');
end
N = 512;
W = 2*pi*logspace(log10(10),log10(Fs/2),N);
H = freqz(B,A,W/Fs);
fref = [10, 12.5 16 20, 25 31.5 40, 50 63 80, 100 125 160, 200 250 315, ...
400 500 630, 800 1000 1250, 1600 2000 2500, 3150 4000 5000, ...
6300 8000 10000, 12500 16000 20000 ];
Agoal = [-70.4, -63.4 -56.7 -50.5, -44.7 -39.4 -34.6, -30.2 -26.2 -22.5, ...
-19.1 -16.1 -13.4, -10.9 -8.6 -6.6, -4.8 -3.2 -1.9, -.8 0 .6, ...
1 1.2 1.3, 1.2, 1 .5, -.1 -1.1 -2.5, -4.3 -6.6 -9.3 ];
up1 = [ 3, .25 2 2, 2 1.5 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 0.7 1, ...
1 1 1, 1 1 1.5, 1.5 1.5 2, 2 2.5 3 ];
low1 = [ inf, inf 4 2, 1.5 1.5 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 0.7 1, ...
1 1 1, 1 1 1.5, 2 2.5 3, 5 8 inf ];
up2 = [ 5, 5 5 3, 3 3 2, 2 2 2, 1.5 1.5 1.5, 1.5 1.5 1.5, 1.5 1.5 1.5, ...
1.5 1 1.5, 2 2 2.5, 2.5 3 3.5, 4.5 5 5, 5 5 5 ];
low2 = [ inf, inf inf 3, 3 3 2, 2 2 2, 1.5 1.5 1.5, 1.5 1.5 1.5, ...
1.5 1.5 1.5, 1.5 1 1.5, 2,2 2.5, 2.5 3 3.5, 4.5 5 inf, inf inf inf ];
clf;
figure(1)
semilogx(W/2/pi,20*log10(abs(H)),'-',fref,Agoal+up1,'--',fref,Agoal+up2,':');
hold on
semilogx(W/2/pi,20*log10(abs(H)),'-',fref,Agoal-low1,'--',fref,Agoal-low2,':');
hold off
xlabel('Frequency [Hz]'); ylabel('Gain [dB]');
title(['A-weighting, Fs = ',int2str(Fs),' Hz']);
axis([fref(1) max(fref(34),Fs/2) -75 5]);
legend('Filter','Class 1','Class 2',0);
endfunction
function [B,A] = adsgn(Fs);
% ADSGN Design of a A-weighting filter.
% [B,A] = ADSGN(Fs) designs a digital A-weighting filter for
% sampling frequency Fs. Usage: Y = FILTER(B,A,X).
% Warning: Fs should normally be higher than 20 kHz. For example,
% Fs = 48000 yields a class 1-compliant filter.
%
% Requires the Signal Processing Toolbox.
%
% See also ASPEC, CDSGN, CSPEC.
% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium)
% couvreur@thor.fpms.ac.be
% Last modification: Aug. 20, 1997, 10:00am.
% References:
% [1] IEC/CD 1672: Electroacoustics-Sound Level Meters, Nov. 1996.
% Definition of analog A-weighting filter according to IEC/CD 1672.
f1 = 20.598997;
f2 = 107.65265;
f3 = 737.86223;
f4 = 12194.217;
A1000 = 1.9997;
pi = 3.14159265358979;
NUMs = [ (2*pi*f4)^2*(10^(A1000/20)) 0 0 0 0 ];
DENs = conv([1 +4*pi*f4 (2*pi*f4)^2],[1 +4*pi*f1 (2*pi*f1)^2]);
DENs = conv(conv(DENs,[1 2*pi*f3]),[1 2*pi*f2]);
% Use the bilinear transformation to get the digital filter.
[B,A] = bilinear(NUMs,DENs,1/Fs);
endfunction
function buildFilterGainTable(B, A, gaintablesize, Fs);
% Build a filter gain table used to filter signal
%
% copyright (c) Davide Gironi, 2013
%
% Released under GPLv3.
% Please refer to LICENSE file for licensing information.
%build filter gaintable
WindowSize = gaintablesize*2; %samples for gaintable creation / window length
filter_gaintable = freqz(B, A, WindowSize, 'whole'); %built for the sized window
filter_gaintableR = real(filter_gaintable);
filter_gaintableI = imag(filter_gaintable);
T = 1/Fs; %sample time
L = WindowSize*20; %length of signal (20 * window)
t = (0:L-1)*T; %time vector
y = 0.7*sin(2*pi*50*t) + sin(2*pi*2000*t) + 2*randn(size(t));
%sum of a 50Hz and a 2000 Hz sinusoid plus noise
signal = y';
%estimate signal level (within each windowed segment).
windowIntervals = [1:WindowSize:(length(signal)-WindowSize)];
windowTime = t(windowIntervals+round((WindowSize-1)/2));
%will contain the full signal
signalT = [];
filteredsignalT = [];
filteredsignalfreqrespT = [];
%will contain the dBA computations
dBA1 = zeros(length(windowIntervals),1);
dBA2 = zeros(length(windowIntervals),1);
dBA3 = zeros(length(windowIntervals),1);
for i = [1:length(windowIntervals)]
%take a part of the signal
signalP = signal(windowIntervals(i)-1+[1:WindowSize]);
%filter signal part by filter function
filteredsignalP = filter(B, A, signalP);
%filter signal part by frequency response
NFFTP = length(signalP);
fftsignalP = fft(signalP);
fftfilteredsignalP = fftsignalP .* filter_gaintable;
filteredsignalfreqrespP = ifft(fftfilteredsignalP, NFFTP);
%built the full signal
signalT = cat(1, signalT, signalP);
filteredsignalT = cat(1, filteredsignalT, filteredsignalP);
filteredsignalfreqrespT = cat(1, filteredsignalfreqrespT, filteredsignalfreqrespP);
%calcuatate rms of the signal part
rmssignalP = sqrt(mean(signalP.^2));
rmsfilteredsignalP = sqrt(mean(filteredsignalP.^2));
rmsfilteredsignalfreqrespP = sqrt(mean(filteredsignalfreqrespP.^2));
% Estimate dBA value using Parseval's relation.
dBA1(i) = 20*log10(rmssignalP);
dBA2(i) = 20*log10(rmsfilteredsignalP);
dBA3(i) = 20*log10(rmsfilteredsignalfreqrespP);
end
% %plot full signal, and filtered signal
% figure(2)
% plot([1:length(signalT)], signalT, '-', [1:length(filteredsignalT)], filteredsignalT, '-', [1:length(filteredsignalfreqrespT)], filteredsignalfreqrespT);
% title(['compare signal (1 window), to filtered signal']);
% legend('signal', 'filtered (using filter function)', 'filtered (using response table)');
% grid on
%plot out results
figure(3)
plot([1:length(dBA1)],dBA1,'-',[1:length(dBA2)],dBA2,'-',[1:length(dBA3)],dBA3);
legend('dBA signal','dBA filtered (using filter function)', 'dBA filtered (using weight table)',3);
grid on
%save gaintable to xls
CR(:,1) = filter_gaintableR(1:length(filter_gaintableR)/2); %retain frequencies below Nyquist rate
CI(:,1) = filter_gaintableI(1:length(filter_gaintableI)/2); %retain frequencies below Nyquist rate
csvwrite('aweightingtableR.csv', CR);
csvwrite('aweightingtableI.csv', CI);
endfunction
%frequency used for filter creation
Fsf = 22050;
%gaintable size
gaintablesize = 32;
%sampling frequency of signal
Fs = Fsf; %22050
%build A-Weight Filter
[B,A] = adsgn(Fsf);
%plot A-Weight and compare with Class I and Class II
aspec(B,A,Fsf);
%build the filter
buildFilterGainTable(B, A, gaintablesize, Fs);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment