image thumbnail
from t60.m by Christopher Brown
Returns an estimate of t60, a measure of reverberation time.

t60(impulse,S_Rate,flag)
function [rt,iidc] = t60(impulse,S_Rate,flag)

%[{rt,iidc}] = t60(impulse,S_Rate,{flag})
%
%Returns an estimate of t60, a measure of reverberation time 
%(in ms) and optionally, the integrated impulse decay curve 
%of the impulse response, using S_Rate as the sample rate
%
%Optional flag is 1 to plot. Default is no plot, unless no output
%arguments are specified
%
%Pass only the segment of the recording after the offset 
%of the impulse
%
%Reference:
%	Schroeder, M.R. (1965). New method of measuring reverberation
%time. Journal of the Acoustical Society of America, 37, 409-412.
%
%Version history:
%
%04-2001 First version
%05-2002 Fixed some bugs. Now accepts a column or row vector.
%			Also, fixed error in which the input vector was being
%			squared twice. Finally, fixed a bug that generated 
%			an error if the rt was longer than 1.5 s. 
%			Thanks to Olivier Deille for his helpful suggestions. 
%
%Christopher Brown, cbrown@phi.luc.edu

if nargin==2
	if nargout==0
		flag = 1;
	else
		flag = 0;
	end
elseif nargin==3
else
	error('Wrong number of input arguements. ''help t60'' for details');
end

if size(impulse,2)==1
impulse = impulse.';
end

begin = round(S_Rate * .05);	%assume slope extends to at least 50 ms
										%adjust this number if needed

if length(impulse)/S_Rate < 1.5	%if impulse is not at least 1.5 sec
   T = length(impulse);				%then use the whole waveform
   warning(['input vector less than 1.5 s in duration']);
else
   T = round(S_Rate * 1.5); 		%otherwise, use first 1.5 sec
end

iidc(length(impulse):-1:1) = cumsum(impulse(length(impulse):-1:1).^2);

y = iidc(1:T);
y = 10 * log10(y/max(abs(y)));	%generate y
xtime = linspace(1,(T/(S_Rate/1000)),T);	%generate x

%calculate r2's
sampsize = 1:length(xtime);
Exy2 = (cumsum(xtime.*y) - ((cumsum(xtime).*cumsum(y))./sampsize)).^2;
Ex2 = cumsum(xtime.^2) - (((cumsum(xtime)).^2)./sampsize);
totss = cumsum(y.^2) - (((cumsum(y)).^2)./sampsize);
regss = Exy2(begin:T)./Ex2(begin:T);
r2 = regss ./ totss(begin:T);

r3 = find(r2 == max(r2));		%find all of the points along slope where r2 is max
stop = begin + r3(length(r3));%stop is the largest r2 that's furthest from t0

mx = mean(xtime(1:stop)); my = mean(y(1:stop));
mx2 = mean(xtime(1:stop).^2); my2 = mean(y(1:stop).^2);
sdx = sqrt(mx2 - mx.^2); sdy = sqrt(my2 - my.^2);
mxy = mean(xtime(1:stop).*y(1:stop));
r = (mxy - (mx.*my))/(sdx.*sdy);
slope = (r * sdy)/sdx;
yintercept = -(slope * mx) + my;

rt = round(abs(60/slope(1))-yintercept);

if flag == 1

	clear xtime;
	xtime = linspace(1,rt,rt*(S_Rate/1000));	%regenerate x
	if length(y)<length(xtime)
		difference = length(xtime)-length(y);
		pad(1:difference) = nan;
		y = [y,pad];
	else
		y = y(1:length(xtime));
	end

	figure;
	plot(xtime,y,'b-','LineWidth',1.5);
	title('Integrated Impulse Decay Curve');
	ylim([-70 0]);
	xlim([0 rt*1.1]);
	xlabel('Time (ms)'), ylabel('dB')
	xlimits = xlim; ylimits = ylim;
	line([xlimits(1),xlimits(2)],[-60,-60],'Color',[.4,.4,.4],'LineWidth',.5);
	text(.6 * xlimits(2),-8,['T_6_0 (ms) = ',num2str(rt)],'FontSize',10,'color','k');
	linestart = (xlimits(1) * slope) + yintercept;
	line([xlimits(1),rt],[linestart,-60],'Color','r','LineWidth',.5);
end

Contact us at files@mathworks.com