# How to assess perceptual volume from FFT

So far I could estimate signal volume from FFT using amplitude information, then adding all amplitudes together and divide this number by the number of frequencies. But I think this method does not apply for estimation of subjective perceptual volume.

If you equate perceptual volume to loudness, there are international standards.

This is an A-weighted Matlab FFT based implementation.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                  A-weighting Filter                  %
%              with MATLAB Implementation              %
%                                                      %
% Author: M.Sc. Eng. Hristo Zhivomirov        06/01/14 %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function xA = filterA(x, fs)

% function: xA = filterA(x, fs)
% x - signal in the time domain
% fs - sampling frequency, Hz
% xA - filtered signal in the time domain

% determine the signal size
sz = size(x);

% represent x as column-vector
x = x(:);

% signal length
xlen = length(x);

% number of unique points
NumUniquePts = ceil((xlen+1)/2);

% FFT
X = fft(x);

% fft is symmetric, throw away second half
X = X(1:NumUniquePts);

% frequency vector with NumUniquePts points
f = (0:NumUniquePts-1)*fs/xlen;

% A-weighting filter coefficients
c1 = 3.5041384e16;
c2 = 20.598997^2;
c3 = 107.65265^2;
c4 = 737.86223^2;
c5 = 12194.217^2;

% evaluate the A-weighting filter in the frequency domain
f = f.^2;
num = c1*f.^4;
den = ((c2+f).^2) .* (c3+f) .* (c4+f) .* ((c5+f).^2);
A = num./den;
A = A(:);

% filtering in the frequency domain
XA = X.*A;

% reconstruct the whole spectrum
if rem(xlen, 2)                     % odd xlen excludes the Nyquist point
XA = [XA; conj(XA(end:-1:2))];
else                                % even xlen includes the Nyquist point
XA = [XA; conj(XA(end-1:-1:2))];
end

% IFFT
xA = real(ifft(XA));

% represent the filtered signal in the form of the original one
xA = reshape(xA, sz);

end


The Mathwork will also sell you their Audio toolbox that has many types of weightings.

I find these standards a bit confusing because you don't know if they correct for the effective noise bandwidth of proportional bandwidth filters and if an FFT implementation should take that into account.

I don't vouch for the Matlab code above. It seems reasonable.

The Wikipedia article:

https://en.wikipedia.org/wiki/A-weighting

also gives the analog transfer functions, which can be converted to digital filters, but actual digital filters seem harder to find.

If your ultimate purpose is to use a standard where a professional signature is required, or one is exposed to liability, I would be inclined to use the Mathwork's product.

• i think the current ISO standard supports E-weighting over the anachronistic A-weighting. i have MATLAB code for it. i think it has something like 64 poles and zeros. – robert bristow-johnson Jun 26 '18 at 1:53
• @robertbristow-johnson so that's a filter followed by a squaring operation? – Marcus Müller Jun 26 '18 at 10:28
• yes, filter the audio first, then square that filtered output, then low-pass filter the squared output to get the "DC" value (that can change a little, so it's not exactly DC). then, since this is a squared value, apply $10 \log_{10}(\cdot)$ to that to get dB. – robert bristow-johnson Jun 26 '18 at 18:49