-
Notifications
You must be signed in to change notification settings - Fork 14
/
Do_SLM.m
166 lines (148 loc) · 5.07 KB
/
Do_SLM.m
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
function [outsig_dB, dBFS] = Do_SLM(insig,fs,weight_freq,weight_time,dBFS)
% function [outsig_dB, dBFS] = Do_SLM(insig,fs,weight_freq,weight_time,dBFS)
%
% 1. Description:
% outsig is the weighted pressure in [Pa]
%
% 2. Stand-alone example:
% %%%%%%
% % Example 2.1:
% %%% Creating a sinuoid with an RMS of 60 dB SPL:
% fs = 44100;
% freq = 1000; % Hz
% dur = 1; % s
% t = 0:1/fs:dur-1/fs;
% dBFS = 94; % full scale convention
% target_lvl = 60; % 60 dB SPL
% cal_factor = 10^((target_lvl-dBFS)/20);
% A = 1*cal_factor*sqrt(2); % 1=full scale; sqrt(2)=relationship between RMS and peak value for a sinusoid
% insig = A*sin(2*pi*freq*t); % zero phase sinusoid centred at f=1000;
%
% %%% Obtaining its A-weighted amplitude, with a fast weighting:
% outsig_dB = Do_SLM(insig,fs,'A','f',dBFS); % A-weighting
% figure;
% plot(outsig_dB); grid on;
% xlabel('Time [samples]');
% ylabel('Amplitude [dB(A)]');
%
% %%%%%%
% % Example 2.2:
% %%% This example assumes that the file is found on disk and that the dB
% % full scale convention (dBFS) is as the default:
%
% file = 'D:\Databases\dir03-Speech\dutch\LISTman\jwz551.wav';
% [insig, fs] = audioread(file);
% Do_SLM(insig,fs,'Z','f'); % Z-weighting, fast response, with an automatic output figure
%
% 3. Additional info:
% Tested cross-platform: No
% See also: Get_Leq
%
% Programmed by Alejandro Osses, HTI, TU/e, the Netherlands, 2014-2016
% Created on : 12/07/2016
% Last update on: 12/07/2016
% : 22/03/2023, AO: Stylised output figure and independency
% of codes with respect to the LTFAT toolbox.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin < 3
weight_freq = 'A';
end
if nargin < 4
weight_time = 'f';
end
if nargin < 5
dBFS = 100;
end
if size(insig,2)~=1
if size(insig,1) == 1
fprintf('%s: Row array detected as an input to this function. The default is a column-wise array.\n', mfilename);
insig = insig(:);
end
end
[b,a] = Gen_weighting_filters(fs,weight_freq);
% same processing, but without AMT, as done in PsySound:
dBoffset = 0.93; % determined empirically on 13/07/2016 to obtain the same values
% with this implementation and the one in PsySound.
calCoeff = 10.^((dBFS+dBoffset-94)/20);
insig = calCoeff*insig; % same as: insig = setdbspl(insig,rmsdb(insig)+dBFS,'dboffset',94);
outsig = filter(b,a,insig);
outsig = il_integrator(outsig,fs,weight_time);
outsig_dB = 20*log10(abs(outsig)/2e-5);
try
idx = find(outsig_dB<0);
if ~isempty(idx)
fprintf('\t%s There were %.0f samples (out of %.0f) with levels below 0 dB SPL. They were set to 0 dB SPL\n',mfilename,length(idx),length(outsig_dB));
outsig_dB(idx) = 0;
end
end
if nargout == 0
Leq = Get_Leq(outsig_dB);
t = (1:length(outsig_dB))/fs;
figure;
plot(t, outsig_dB ); grid on;
switch weight_freq
case 'Z'
suff = '';
otherwise
suff = ['(' weight_freq ')'];
end
xlabel('Time [s]');
xlim([0 max(t)]);
unit = sprintf('[dB%s]',suff);
ylabel(sprintf('Amplitude %s',unit));
title(sprintf('Level Leq=%.1f %s',Leq,unit));
disp('')
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% EOF
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Inline functions:
function outsig = il_integrator(insig,fs, weightingType)
% function outsig = il_integrator(insig,fs, weightingType)
%
% 1. Description: This function generates and applies an integration filter
% to the input data. This code is based on an implementation taken from
% the PsySound toolbox by Matt Flax (January 2007) and Farhan Rizwi
% (July 2007).
%
% Inputs:
% insig - Incoming input signal, as a data vector
% fs - Sampling rate of the data
% weightingType - RC time constant is 'f' fast (125 ms), 's' slow
% (1 s), or 'i' impulsive. The time constant for the
% leaky integrator is tau. This is basically a low-pass
% filter whose transfer function is:
% 1
% H(s) = ---------------
% tau s + 1
%
% Code adapted by Alejandro Osses
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Filter coeffecients
switch weightingType
case 'f' % fast leak - time constant = 125 ms
tau = 125e-3;
case 's' % slow leak - time constant = 1 s
tau = 1;
case 'i'
tau = 35e-3; % impulse
% case 'p'
% tau = 50e-6;
% case 'l'
% tau = str2double(fastOrSlow(2:end));
% case 'r'
% tau = str2double(fastOrSlow(2:end));
otherwise
error(['integrator: unknown leak case ' char(fastOrSlow)]);
end
% State vector
Z = [];
% Exponential term
E = exp(-1/(tau*fs));
% Filter numerator - with gain adjustment
b = 1 - E;
% Filter denominator
a = [1 -E];
% Create run function handle
% Use filter to perform the integration
outsig = filter(b, a, abs(insig), Z, 1);