-
Notifications
You must be signed in to change notification settings - Fork 13
/
EarlyDecayTime.m
153 lines (126 loc) · 4.18 KB
/
EarlyDecayTime.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
function [EDT,frq] = EarlyDecayTime(ImpRsp,smpFrq,bndOpt,pltEDT,pltSchCur)
%
% [EDT,frq] = EarlyDecayTime(ImpRsp,smpFrq,bndOpt,pltRvbTme,pltSchCur) ;
%
% Calculate the Early Decay Times from a set of impulse responses.
%
% Input: - ImpRsp is an impulse reponse ([Nx1] vector) or array of impulse
% responses ([NxM] matrix).
% - smpFrq is the sampling frequency.
% This parameter can be omitted, the default value is 48kHz.
%
% Output: - if ImpRsp is a vector, EDT is the vector of the EDTs for
% different frequency bands. If ImpRsp is a matrix, EDT is the
% matrix of the EDTs for each impulse response.
% - frq is the vector of the frequency band center frequencies.
%
% Options: - bndOpt can be set to 'oct' (default) to obtain the EDTs for 9
% octave bands with center frequency from 62.5 to 16kHz, or
% '3rdoct' in which case the EDTs are calculated for 25
% third-octave bands.
% - if pltEDT is set to true (default), the EDTs are plotted.
% - if pltSchCur is set to true, the Schroeder curves are plotted.
%
% Note: Requires MATLAB's Signal Processing Toolbox
%
% N.Epain, 2011
% Don't plot the Schroeder curve by default
if nargin < 5
pltSchCur = false ;
end
% Plot the EDTs by default
if nargin < 4
pltEDT = true ;
end
% Default "frequency band option": 'oct'
% (octave bands with center frequencies from 62.5 to 16 kHz)
if nargin < 3
bndOpt = 'oct' ;
end
bndOpt = lower(bndOpt) ;
% Default sampling frequency: 48kHz
if (nargin<2) || isempty(smpFrq)
smpFrq = 48e3 ;
end
% Length of the impulse responses
nmbSmp = size(ImpRsp,1) ;
% Number of impulse responses
nmbImp = size(ImpRsp,2) ;
% Vector of the center frequencies
switch bndOpt
case 'oct'
frq = 1000 * 2.^(-4:4)' ;
case '3rdoct'
frq = 1000 * 2.^(-4:1/3:4)' ;
end
nmbFrq = length(frq) ;
% Colors used for the reverb time and Schroeder curve plots
clr = lines(nmbImp) ;
% Initialise the output
EDT = zeros(nmbFrq,nmbImp) ;
% Create a new figure for the Schroeder curves
if pltSchCur == true
figure
end
% Calculate the Schroeder curves
SchCur = SchroederCurve(ImpRsp,smpFrq,bndOpt,false) ;
if nmbImp == 1
SchCur = permute(SchCur,[1 3 2]) ;
end
% Loop on the impulse responses
for J = 1 : nmbImp
% Loop on the center frequencies
for I = 1 : nmbFrq
% Estimate the slope of the Schroeder curve between -5 and -35dB
fst = find(SchCur(:,J,I)>=-1e-2,1,'last') ;
lst = find(SchCur(:,J,I)<=-10,1,'first') ;
coe = LinearRegression((fst:lst)'/smpFrq,SchCur(fst:lst,J,I)) ;
% Plot the Shroeder curve
if pltSchCur == true
switch bndOpt
case 'oct'
subplot(3,3,I), hold on
case '3rdoct'
subplot(5,5,I), hold on
end
plot((1:nmbSmp)/(smpFrq),SchCur(:,J,I), ...
'color',clr(J,:),'linewidth',2)
plot((1:nmbSmp)/(smpFrq), ...
coe(2)+coe(1)*(1:nmbSmp)/(smpFrq), ...
'color',clr(J,:))
title(['f = ' num2str(round(frq(I))) ' Hz']) ;
xlabel('Time [s]')
ylabel('Energy [dB]')
axis([0 1.05*nmbSmp/smpFrq -95 5])
grid on, box on
end
% EDT
EDT(I,J) = -60/coe(1) ;
end
end
% Plot the EDTs
if pltEDT == true
figure('color','white')
semilogx(frq,EDT,'-o','linewidth',2)
xlim([frq(1)*2^(-1/3) frq(end)*2^(1/3)])
title('Early Decay Time (EDT)','fontsize',14) ;
xlabel('Frequency [Hz]','fontsize',14)
ylabel('EDT [s]','fontsize',14)
set(gca,'YGrid','on')
set(gca,'Xtick',[],'fontsize',14)
switch lower(bndOpt)
case 'oct'
set(gca,'Xtick',[frq(1)/2;frq;frq(end)*2])
case '3rdoct'
set(gca,'Xtick',[frq(1)/2;frq(1:3:end);frq(end)*2])
end
box on
end
% Linear regression subroutine
function coe = LinearRegression(tme,eng)
% Number of points to fit
nmb = length(tme) ;
% Matrix we need to invert
Mat = [tme(:) ones(nmb,1)] ;
% Linear coefficients
coe = pinv(Mat) * eng ;